@eva/plugin-ui 2.1.0-beta.1 → 2.1.0-beta.11

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,28 +1,30 @@
1
1
  import { Component, System, OBSERVER_TYPE, decorators } from '@eva/eva.js';
2
2
  import { Graphics } from '@eva/plugin-renderer-graphics';
3
- import { FillGradient, Sprite, Graphics as Graphics$1, Texture, Container } from 'pixi.js';
4
- import { ButtonContainer, FancyButton as FancyButton$1, CheckBox as CheckBox$1, Switcher as Switcher$1, Slider as Slider$1, DoubleSlider as DoubleSlider$1, ProgressBar as ProgressBar$1, CircularProgressBar as CircularProgressBar$1, Input as Input$1, List as List$1, ScrollBox as ScrollBox$1, Select as Select$1, Dialog as Dialog$1, MaskedFrame as MaskedFrame$1, RadioGroup as RadioGroup$1 } from '@pixi/ui';
3
+ import { FillGradient, Sprite, Graphics as Graphics$1, Container, Texture, HTMLText, BitmapText, Text, BitmapFontManager } from 'pixi.js';
4
+ import { ButtonContainer, FancyButton as FancyButton$1, CheckBox as CheckBox$1, Switcher as Switcher$1, Slider as Slider$1, DoubleSlider as DoubleSlider$1, ProgressBar as ProgressBar$1, CircularProgressBar as CircularProgressBar$1, Input as Input$1, List as List$1, ScrollBox as ScrollBox$1, Select as Select$1, Dialog as Dialog$1, Button as Button$1, MaskedFrame as MaskedFrame$1, RadioGroup as RadioGroup$1 } from '@pixi/ui';
5
5
 
6
- /** UI 形状类型枚举 */
7
- var UIShapeType;
8
- (function (UIShapeType) {
9
- UIShapeType["RECT"] = "rect";
10
- UIShapeType["CIRCLE"] = "circle";
11
- UIShapeType["ELLIPSE"] = "ellipse";
12
- UIShapeType["ROUNDED_RECT"] = "roundedRect";
13
- })(UIShapeType || (UIShapeType = {}));
6
+ /** Shape primitive type enum */
7
+ var ShapeType;
8
+ (function (ShapeType) {
9
+ ShapeType["RECT"] = "rect";
10
+ ShapeType["CIRCLE"] = "circle";
11
+ ShapeType["ELLIPSE"] = "ellipse";
12
+ ShapeType["ROUNDED_RECT"] = "roundedRect";
13
+ })(ShapeType || (ShapeType = {}));
14
+ /** Backward-compatible enum value alias for existing TypeScript consumers. */
15
+ const UIShapeType = ShapeType;
14
16
  /**
15
- * UI 组件
17
+ * Shape 组件
16
18
  *
17
19
  * 基于 `@eva/plugin-renderer-graphics` 实现 rect/circle/ellipse/roundedRect 的
18
20
  * 矢量绘制,支持纯色 / linear-gradient 填充与描边。`shapes` 数组允许在同一个
19
21
  * GameObject 上层叠多个形状。
20
22
  */
21
- class UI extends Component {
23
+ class Shape extends Component {
22
24
  constructor() {
23
25
  super(...arguments);
24
26
  /** 实例侧 componentName,DSL 序列化时使用 */
25
- this.componentName = 'UI';
27
+ this.componentName = 'Shape';
26
28
  this.shapes = [];
27
29
  }
28
30
  /** 编辑器 Inspector 元数据,主仓 ComponentInspector 通过静态方法读取 */
@@ -39,7 +41,7 @@ class UI extends Component {
39
41
  { name: 'radius', type: 'number', isArray: false },
40
42
  ];
41
43
  return {
42
- name: UI.componentName,
44
+ name: Shape.componentName,
43
45
  type: 'object',
44
46
  isArray: false,
45
47
  isFolder: true,
@@ -172,12 +174,12 @@ class UI extends Component {
172
174
  const x = style.x || 0;
173
175
  const y = style.y || 0;
174
176
  switch (type) {
175
- case UIShapeType.RECT:
176
- case UIShapeType.ROUNDED_RECT:
177
+ case ShapeType.RECT:
178
+ case ShapeType.ROUNDED_RECT:
177
179
  return { width: style.width, height: style.height, x, y };
178
- case UIShapeType.CIRCLE:
180
+ case ShapeType.CIRCLE:
179
181
  return { width: style.radius * 2, height: style.radius * 2, x, y };
180
- case UIShapeType.ELLIPSE:
182
+ case ShapeType.ELLIPSE:
181
183
  return { width: style.width, height: style.height, x, y };
182
184
  default:
183
185
  return { width: 100, height: 100, x, y };
@@ -203,32 +205,27 @@ class UI extends Component {
203
205
  }
204
206
  /** 绘制单个形状 */
205
207
  drawShape(graphics, type, style) {
208
+ var _a;
206
209
  if (style.alpha !== undefined) {
207
210
  graphics.alpha = style.alpha;
208
211
  }
209
- if (style.stroke && style.lineWidth !== undefined) {
210
- graphics.setStrokeStyle({ color: style.stroke, width: style.lineWidth });
211
- }
212
- else if (style.stroke) {
213
- graphics.setStrokeStyle({ color: style.stroke, width: 1 });
214
- }
215
212
  switch (type) {
216
- case UIShapeType.RECT:
213
+ case ShapeType.RECT:
217
214
  this.drawRect(graphics, style);
218
215
  break;
219
- case UIShapeType.CIRCLE:
216
+ case ShapeType.CIRCLE:
220
217
  this.drawCircle(graphics, style);
221
218
  break;
222
- case UIShapeType.ELLIPSE:
219
+ case ShapeType.ELLIPSE:
223
220
  this.drawEllipse(graphics, style);
224
221
  break;
225
- case UIShapeType.ROUNDED_RECT:
222
+ case ShapeType.ROUNDED_RECT:
226
223
  this.drawRoundedRect(graphics, style);
227
224
  break;
228
225
  default:
229
226
  console.warn(`Unknown shape type: ${type}`);
230
227
  }
231
- if (style.fill) {
228
+ if (style.fill !== undefined) {
232
229
  if (typeof style.fill === 'string' && style.fill.includes('linear-gradient')) {
233
230
  const gradientInfo = this.parseLinearGradient(style.fill);
234
231
  if (gradientInfo) {
@@ -245,6 +242,12 @@ class UI extends Component {
245
242
  graphics.fill(style.fill);
246
243
  }
247
244
  }
245
+ if (style.stroke !== undefined) {
246
+ graphics.stroke({
247
+ color: style.stroke,
248
+ width: (_a = style.lineWidth) !== null && _a !== void 0 ? _a : 1,
249
+ });
250
+ }
248
251
  }
249
252
  drawRect(graphics, style) {
250
253
  const x = style.x || 0;
@@ -326,7 +329,7 @@ class UI extends Component {
326
329
  }
327
330
  }
328
331
  /** 组件名称 */
329
- UI.componentName = 'UI';
332
+ Shape.componentName = 'Shape';
330
333
 
331
334
  /**
332
335
  * Eva GameObject -> PIXI.Container resolver.
@@ -450,7 +453,7 @@ function whenContainerReady(game, go, fn, attempts = 4) {
450
453
  * @returns PIXI 显示对象,失败返回 null
451
454
  */
452
455
  function resolveViewRef(game, go, ref) {
453
- var _a;
456
+ var _a, _b;
454
457
  if (!ref)
455
458
  return null;
456
459
  if ('entityName' in ref) {
@@ -465,15 +468,18 @@ function resolveViewRef(game, go, ref) {
465
468
  }
466
469
  }
467
470
  catch (_) { }
468
- return childContainer;
471
+ return wrapBorrowedEntityView(childContainer, child.name);
469
472
  }
470
473
  }
471
474
  if (ref.fallback)
472
475
  return resolveViewRef(game, go, ref.fallback);
473
476
  return null;
474
477
  }
478
+ if ('shape' in ref) {
479
+ return (_a = drawInlineShape(ref.shape)) !== null && _a !== void 0 ? _a : (ref.fallback ? resolveViewRef(game, go, ref.fallback) : null);
480
+ }
475
481
  if ('ui' in ref) {
476
- return (_a = drawInlineShape(ref.ui)) !== null && _a !== void 0 ? _a : (ref.fallback ? resolveViewRef(game, go, ref.fallback) : null);
482
+ return (_b = drawInlineShape(ref.ui)) !== null && _b !== void 0 ? _b : (ref.fallback ? resolveViewRef(game, go, ref.fallback) : null);
477
483
  }
478
484
  if ('texture' in ref) {
479
485
  const tex = resolveTexture(game, ref.texture);
@@ -502,9 +508,46 @@ function resolveViewRef(game, go, ref) {
502
508
  }
503
509
  return null;
504
510
  }
511
+ /**
512
+ * @pixi/ui ProgressBar 的非 nine-slice fillPaddings 只移动 fill.x/y,
513
+ * 不会自动把 fill view 缩成内层尺寸。DSL 常用的 inline color/shape
514
+ * 需要先扣除 padding,否则 fill 会向下或向右溢出,造成上下层偏差。
515
+ */
516
+ function normalizeProgressFillViewRef(ref, fillPaddings, fallbackSize) {
517
+ if (!ref)
518
+ return ref;
519
+ const paddings = normalizePaddings(fillPaddings);
520
+ if (paddings.top === 0 && paddings.right === 0 && paddings.bottom === 0 && paddings.left === 0) {
521
+ return ref;
522
+ }
523
+ const fallback = ref.fallback
524
+ ? normalizeProgressFillViewRef(ref.fallback, paddings, fallbackSize)
525
+ : undefined;
526
+ if ('color' in ref) {
527
+ const width = shrinkSize(ref.width, paddings.left + paddings.right);
528
+ const height = shrinkSize(ref.height, paddings.top + paddings.bottom);
529
+ return Object.assign(Object.assign(Object.assign({}, ref), { width,
530
+ height, radius: shrinkRadius(ref.radius, width, height) }), (fallback ? { fallback } : {}));
531
+ }
532
+ if ('shape' in ref) {
533
+ return Object.assign(Object.assign(Object.assign({}, ref), { shape: shrinkInlineShape(ref.shape, paddings, fallbackSize) }), (fallback ? { fallback } : {}));
534
+ }
535
+ if ('ui' in ref) {
536
+ return Object.assign(Object.assign(Object.assign({}, ref), { ui: shrinkInlineShape(ref.ui, paddings, fallbackSize) }), (fallback ? { fallback } : {}));
537
+ }
538
+ if (fallback)
539
+ return Object.assign(Object.assign({}, ref), { fallback });
540
+ return ref;
541
+ }
542
+ function wrapBorrowedEntityView(childContainer, childName) {
543
+ const wrapper = new Container();
544
+ wrapper.label = childName ? `${childName}:view-ref` : 'plugin-ui-view-ref';
545
+ wrapper.addChild(childContainer);
546
+ return wrapper;
547
+ }
505
548
  /** 把 ViewRef 解析为已存在的 Texture(用于 ProgressBar/Slider/Input 的 nineSlice 路径) */
506
549
  function resolveTexture(game, key) {
507
- var _a, _b;
550
+ var _a, _b, _c;
508
551
  // 1) Eva resource pool
509
552
  const resourceModule = (_a = game === null || game === void 0 ? void 0 : game.resource) !== null && _a !== void 0 ? _a : null;
510
553
  if ((_b = resourceModule === null || resourceModule === void 0 ? void 0 : resourceModule.instances) === null || _b === void 0 ? void 0 : _b[key]) {
@@ -516,45 +559,129 @@ function resolveTexture(game, key) {
516
559
  }
517
560
  // 2) global asset cache (Texture.from)
518
561
  try {
519
- return Texture.from(key);
562
+ return (_c = Texture.from(key)) !== null && _c !== void 0 ? _c : null;
520
563
  }
521
564
  catch (_) {
522
565
  return null;
523
566
  }
524
567
  }
525
568
  function drawInlineShape(shape) {
526
- var _a, _b, _c;
569
+ var _a, _b, _c, _d, _e;
527
570
  if (!shape || !shape.type)
528
571
  return null;
529
572
  const g = new Graphics$1();
530
573
  const { style } = shape;
531
- const w = (_a = style.width) !== null && _a !== void 0 ? _a : 0;
532
- const h = (_b = style.height) !== null && _b !== void 0 ? _b : 0;
533
- const r = (_c = style.radius) !== null && _c !== void 0 ? _c : 0;
574
+ const x = (_a = style.x) !== null && _a !== void 0 ? _a : 0;
575
+ const y = (_b = style.y) !== null && _b !== void 0 ? _b : 0;
576
+ const w = (_c = style.width) !== null && _c !== void 0 ? _c : 0;
577
+ const h = (_d = style.height) !== null && _d !== void 0 ? _d : 0;
578
+ const r = (_e = style.radius) !== null && _e !== void 0 ? _e : 0;
534
579
  switch (shape.type) {
535
580
  case 'rect':
536
- g.rect(0, 0, w, h);
581
+ drawRect(g, x, y, w, h);
537
582
  break;
538
583
  case 'roundedRect':
539
- g.roundRect(0, 0, w, h, r);
584
+ drawRoundedRect(g, x, y, w, h, r);
540
585
  break;
541
586
  case 'circle':
542
- g.circle(r, r, r);
587
+ drawCircle(g, x + r, y + r, r);
543
588
  break;
544
589
  case 'ellipse':
545
- g.ellipse(w / 2, h / 2, w / 2, h / 2);
590
+ drawEllipse(g, x + w / 2, y + h / 2, w / 2, h / 2);
546
591
  break;
547
592
  }
548
593
  if (style.fill !== undefined)
549
594
  g.fill(style.fill);
550
595
  if (style.stroke !== undefined && style.lineWidth !== undefined) {
551
- g.setStrokeStyle({ color: style.stroke, width: style.lineWidth });
552
- g.stroke();
596
+ g.stroke({ color: style.stroke, width: style.lineWidth });
597
+ }
598
+ else if (style.stroke !== undefined) {
599
+ g.stroke({ color: style.stroke, width: 1 });
553
600
  }
554
601
  if (style.alpha !== undefined)
555
602
  g.alpha = style.alpha;
603
+ try {
604
+ Object.defineProperty(g, 'clone', {
605
+ value: () => { var _a; return (_a = drawInlineShape(shape)) !== null && _a !== void 0 ? _a : new Graphics$1(); },
606
+ configurable: true,
607
+ });
608
+ }
609
+ catch (_) { }
556
610
  return g;
557
611
  }
612
+ function drawRect(g, x, y, width, height) {
613
+ const anyGraphics = g;
614
+ if (typeof anyGraphics.rect === 'function') {
615
+ anyGraphics.rect(x, y, width, height);
616
+ return;
617
+ }
618
+ anyGraphics.drawRect(x, y, width, height);
619
+ }
620
+ function drawRoundedRect(g, x, y, width, height, radius) {
621
+ const anyGraphics = g;
622
+ if (typeof anyGraphics.roundRect === 'function') {
623
+ anyGraphics.roundRect(x, y, width, height, radius);
624
+ return;
625
+ }
626
+ anyGraphics.drawRoundedRect(x, y, width, height, radius);
627
+ }
628
+ function drawCircle(g, x, y, radius) {
629
+ const anyGraphics = g;
630
+ if (typeof anyGraphics.circle === 'function') {
631
+ anyGraphics.circle(x, y, radius);
632
+ return;
633
+ }
634
+ anyGraphics.drawCircle(x, y, radius);
635
+ }
636
+ function drawEllipse(g, x, y, halfWidth, halfHeight) {
637
+ const anyGraphics = g;
638
+ if (typeof anyGraphics.ellipse === 'function') {
639
+ anyGraphics.ellipse(x, y, halfWidth, halfHeight);
640
+ return;
641
+ }
642
+ anyGraphics.drawEllipse(x, y, halfWidth, halfHeight);
643
+ }
644
+ function normalizePaddings(fillPaddings) {
645
+ return {
646
+ top: readPadding(fillPaddings === null || fillPaddings === void 0 ? void 0 : fillPaddings.top),
647
+ right: readPadding(fillPaddings === null || fillPaddings === void 0 ? void 0 : fillPaddings.right),
648
+ bottom: readPadding(fillPaddings === null || fillPaddings === void 0 ? void 0 : fillPaddings.bottom),
649
+ left: readPadding(fillPaddings === null || fillPaddings === void 0 ? void 0 : fillPaddings.left),
650
+ };
651
+ }
652
+ function readPadding(value) {
653
+ if (typeof value !== 'number' || !Number.isFinite(value))
654
+ return 0;
655
+ return Math.max(0, value);
656
+ }
657
+ function shrinkSize(value, inset) {
658
+ return Math.max(0, value - inset);
659
+ }
660
+ function shrinkOptionalSize(value, fallback, inset) {
661
+ if (typeof value === 'number')
662
+ return shrinkSize(value, inset);
663
+ if (typeof fallback === 'number')
664
+ return shrinkSize(fallback, inset);
665
+ return value;
666
+ }
667
+ function shrinkRadius(radius, width, height) {
668
+ if (typeof radius !== 'number' || !Number.isFinite(radius))
669
+ return radius;
670
+ const limits = [radius];
671
+ if (typeof width === 'number')
672
+ limits.push(width / 2);
673
+ if (typeof height === 'number')
674
+ limits.push(height / 2);
675
+ return Math.max(0, Math.min(...limits));
676
+ }
677
+ function shrinkInlineShape(shape, paddings, fallbackSize) {
678
+ var _a;
679
+ const style = (_a = shape.style) !== null && _a !== void 0 ? _a : {};
680
+ const width = shrinkOptionalSize(style.width, fallbackSize === null || fallbackSize === void 0 ? void 0 : fallbackSize.width, paddings.left + paddings.right);
681
+ const height = shrinkOptionalSize(style.height, fallbackSize === null || fallbackSize === void 0 ? void 0 : fallbackSize.height, paddings.top + paddings.bottom);
682
+ const radius = shrinkRadius(style.radius, width, height);
683
+ return Object.assign(Object.assign({}, shape), { style: Object.assign(Object.assign(Object.assign(Object.assign({}, style), (width !== undefined ? { width } : {})), (height !== undefined ? { height } : {})), (radius !== undefined ? { radius } : {})) });
684
+ }
558
685
  /**
559
686
  * 在 GameObject 的 transform.children 中查找指定名字的子 entity。
560
687
  * 不递归 — plugin-ui 的视觉子项语义只允许直接子节点。
@@ -605,12 +732,20 @@ class PixiUiComponent extends Component {
605
732
  /** runtime 计数,供 spec / debug 验证(toggleCount / pressCount / hoverCount / ...)*/
606
733
  this.toggleCount = 0;
607
734
  this.pressCount = 0;
735
+ this.downCount = 0;
736
+ this.upCount = 0;
608
737
  this.hoverCount = 0;
738
+ this.outCount = 0;
739
+ this.upOutCount = 0;
609
740
  this.changeCount = 0;
610
741
  this.updateCount = 0;
611
742
  this.selectCount = 0;
743
+ this.lastSignal = 'idle';
744
+ this.visualState = 'default';
612
745
  /** Input 私有 focused */
613
746
  this.focused = false;
747
+ /** DSL/constructor 中显式传入过的字段,用于区分 metadata default 与用户配置。 */
748
+ this.__evaExplicitFields = new Set();
614
749
  }
615
750
  init(p) {
616
751
  if (p)
@@ -630,6 +765,7 @@ class PixiUiComponent extends Component {
630
765
  const v = p[name];
631
766
  if (v === undefined)
632
767
  continue;
768
+ this.__evaExplicitFields.add(name);
633
769
  switch (spec.kind) {
634
770
  case 'scalar':
635
771
  this[name] = v;
@@ -750,6 +886,114 @@ function resolveViewsBySchema(game, go, component, schema) {
750
886
  }
751
887
  }
752
888
 
889
+ function readTransformRenderSize(go, options = {}) {
890
+ var _a;
891
+ const size = (_a = go === null || go === void 0 ? void 0 : go.transform) === null || _a === void 0 ? void 0 : _a.size;
892
+ if (!size)
893
+ return null;
894
+ const width = normalizeSizeValue(size.width, options.allowZero);
895
+ const height = normalizeSizeValue(size.height, options.allowZero);
896
+ if (width === undefined && height === undefined)
897
+ return null;
898
+ return { width, height };
899
+ }
900
+ function hasExplicitRenderSize(component) {
901
+ if (!component)
902
+ return false;
903
+ const explicitFields = component.__evaExplicitFields;
904
+ if (explicitFields && typeof explicitFields.has === 'function') {
905
+ return explicitFields.has('width') || explicitFields.has('height');
906
+ }
907
+ return component.width !== undefined || component.height !== undefined;
908
+ }
909
+ function applyTransformSizeToInstance(def, instance, component, go, source) {
910
+ const size = readTransformRenderSize(go, { allowZero: source === 'transform-change' });
911
+ if (!size)
912
+ return false;
913
+ const context = {
914
+ componentName: def.name,
915
+ component,
916
+ gameObject: go,
917
+ source,
918
+ };
919
+ if (def.applySize)
920
+ def.applySize(instance, size, component !== null && component !== void 0 ? component : {}, context);
921
+ else
922
+ applyRuntimeSize(instance, size);
923
+ return true;
924
+ }
925
+ function applyRuntimeSize(instance, size) {
926
+ if (!instance || !size)
927
+ return;
928
+ const width = normalizeSizeValue(size.width, true);
929
+ const height = normalizeSizeValue(size.height, true);
930
+ if (width === undefined && height === undefined)
931
+ return;
932
+ const nextWidth = width !== null && width !== void 0 ? width : getCurrentSize(instance, 'width');
933
+ const nextHeight = height !== null && height !== void 0 ? height : getCurrentSize(instance, 'height');
934
+ let applied = false;
935
+ if (typeof instance.setSize === 'function' && nextWidth !== undefined && nextHeight !== undefined) {
936
+ try {
937
+ instance.setSize(nextWidth, nextHeight);
938
+ applied = true;
939
+ }
940
+ catch (_) {
941
+ applied = false;
942
+ }
943
+ }
944
+ if (!applied) {
945
+ if (width !== undefined)
946
+ instance.width = width;
947
+ if (height !== undefined)
948
+ instance.height = height;
949
+ }
950
+ relayoutRuntimeInstance(instance);
951
+ }
952
+ function applyListLayoutSize(instance, size) {
953
+ const width = normalizeSizeValue(size.width, true);
954
+ const height = normalizeSizeValue(size.height, true);
955
+ if (width !== undefined) {
956
+ try {
957
+ instance.maxWidth = width;
958
+ }
959
+ catch (_) { }
960
+ }
961
+ if (height !== undefined) {
962
+ try {
963
+ instance.maxHeight = height;
964
+ }
965
+ catch (_) { }
966
+ }
967
+ relayoutRuntimeInstance(instance);
968
+ }
969
+ function relayoutRuntimeInstance(instance) {
970
+ var _a, _b, _c, _d;
971
+ try {
972
+ (_b = (_a = instance === null || instance === void 0 ? void 0 : instance.list) === null || _a === void 0 ? void 0 : _a.arrangeChildren) === null || _b === void 0 ? void 0 : _b.call(_a);
973
+ }
974
+ catch (_) { }
975
+ try {
976
+ (_c = instance === null || instance === void 0 ? void 0 : instance.arrangeChildren) === null || _c === void 0 ? void 0 : _c.call(instance);
977
+ }
978
+ catch (_) { }
979
+ try {
980
+ (_d = instance === null || instance === void 0 ? void 0 : instance.resize) === null || _d === void 0 ? void 0 : _d.call(instance, true);
981
+ }
982
+ catch (_) { }
983
+ }
984
+ function normalizeSizeValue(value, allowZero = false) {
985
+ const n = Number(value);
986
+ if (!Number.isFinite(n))
987
+ return undefined;
988
+ if (allowZero ? n < 0 : n <= 0)
989
+ return undefined;
990
+ return n;
991
+ }
992
+ function getCurrentSize(instance, key) {
993
+ const n = Number(instance === null || instance === void 0 ? void 0 : instance[key]);
994
+ return Number.isFinite(n) && n >= 0 ? n : undefined;
995
+ }
996
+
753
997
  /**
754
998
  * @pixi/ui v2.x 包装层 — 14 个 ECS Component 由 metadata 驱动生成。
755
999
  *
@@ -797,8 +1041,42 @@ const BUTTON_DEF = {
797
1041
  optionsBuilder: (_c, v) => [v.single],
798
1042
  postCreate: (inst, c) => { inst.enabled = c.enabled; },
799
1043
  signalMap: (c) => ({
800
- press: () => { c.pressCount += 1; return {}; },
801
- down: true, up: true, hover: true,
1044
+ press: () => {
1045
+ c.pressCount += 1;
1046
+ c.lastSignal = 'press';
1047
+ c.visualState = 'default';
1048
+ return { pressCount: c.pressCount, lastSignal: c.lastSignal, visualState: c.visualState };
1049
+ },
1050
+ down: () => {
1051
+ c.downCount += 1;
1052
+ c.lastSignal = 'down';
1053
+ c.visualState = 'pressed';
1054
+ return { downCount: c.downCount, lastSignal: c.lastSignal, visualState: c.visualState };
1055
+ },
1056
+ up: () => {
1057
+ c.upCount += 1;
1058
+ c.lastSignal = 'up';
1059
+ c.visualState = 'default';
1060
+ return { upCount: c.upCount, lastSignal: c.lastSignal, visualState: c.visualState };
1061
+ },
1062
+ hover: () => {
1063
+ c.hoverCount += 1;
1064
+ c.lastSignal = 'hover';
1065
+ c.visualState = 'hover';
1066
+ return { hoverCount: c.hoverCount, lastSignal: c.lastSignal, visualState: c.visualState };
1067
+ },
1068
+ out: () => {
1069
+ c.outCount += 1;
1070
+ c.lastSignal = 'out';
1071
+ c.visualState = 'default';
1072
+ return { outCount: c.outCount, lastSignal: c.lastSignal, visualState: c.visualState };
1073
+ },
1074
+ upOut: () => {
1075
+ c.upOutCount += 1;
1076
+ c.lastSignal = 'upOut';
1077
+ c.visualState = 'default';
1078
+ return { upOutCount: c.upOutCount, lastSignal: c.lastSignal, visualState: c.visualState };
1079
+ },
802
1080
  }),
803
1081
  syncOnChange: (inst, c) => { inst.enabled = c.enabled; },
804
1082
  };
@@ -816,10 +1094,28 @@ const FANCY_BUTTON_DEF = {
816
1094
  views: { kind: 'shallowMerge', default: {}, inspector: { name: 'views', type: 'object', isFolder: true, children: [
817
1095
  { name: 'default', type: 'object' }, { name: 'hover', type: 'object' },
818
1096
  { name: 'pressed', type: 'object' }, { name: 'disabled', type: 'object' },
1097
+ { name: 'icon', type: 'object' },
819
1098
  ] } },
820
1099
  offset: { kind: 'shallowMerge', default: {} },
821
1100
  textOffset: { kind: 'shallowMerge', default: {} },
1101
+ iconOffset: { kind: 'shallowMerge', default: {} },
822
1102
  nineSliceSprite: { kind: 'opaque' },
1103
+ textStyle: { kind: 'shallowMerge', default: {} },
1104
+ textClass: { kind: 'scalar', default: 'text' },
1105
+ bitmapFontName: { kind: 'scalar', default: 'TitleFont' },
1106
+ defaultTextScale: { kind: 'opaque' },
1107
+ defaultIconScale: { kind: 'opaque' },
1108
+ defaultTextAnchor: { kind: 'opaque' },
1109
+ defaultIconAnchor: { kind: 'opaque' },
1110
+ anchor: { kind: 'scalar' },
1111
+ anchorX: { kind: 'scalar' },
1112
+ anchorY: { kind: 'scalar' },
1113
+ scale: { kind: 'scalar' },
1114
+ animations: { kind: 'opaque' },
1115
+ contentFittingMode: { kind: 'scalar' },
1116
+ ignoreRefitting: { kind: 'scalar' },
1117
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1118
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
823
1119
  },
824
1120
  views: {
825
1121
  kind: 'object', folder: 'views',
@@ -828,28 +1124,43 @@ const FANCY_BUTTON_DEF = {
828
1124
  { name: 'hover', required: false },
829
1125
  { name: 'pressed', required: false },
830
1126
  { name: 'disabled', required: false },
1127
+ { name: 'icon', required: false },
831
1128
  ],
832
1129
  },
833
1130
  optionsBuilder: (c, v) => {
834
- var _a, _b, _d, _e;
1131
+ var _a, _b, _d, _e, _f;
835
1132
  // FancyButton 内部 updateView 不接受 null;只把已 resolve 的 view 字段传过去
836
1133
  const opts = {
837
- text: c.text, padding: c.padding,
838
- offset: c.offset, textOffset: c.textOffset,
1134
+ text: makeFancyButtonText(c), padding: c.padding,
1135
+ offset: c.offset, textOffset: c.textOffset, iconOffset: c.iconOffset,
839
1136
  nineSliceSprite: c.nineSliceSprite,
1137
+ defaultTextScale: c.defaultTextScale,
1138
+ defaultIconScale: c.defaultIconScale,
1139
+ defaultTextAnchor: c.defaultTextAnchor,
1140
+ defaultIconAnchor: c.defaultIconAnchor,
1141
+ anchor: c.anchor, anchorX: c.anchorX, anchorY: c.anchorY,
1142
+ scale: c.scale, animations: c.animations,
1143
+ contentFittingMode: c.contentFittingMode,
1144
+ ignoreRefitting: c.ignoreRefitting,
840
1145
  };
841
1146
  if ((_a = v.object) === null || _a === void 0 ? void 0 : _a.default)
842
- opts.defaultView = v.object.default;
1147
+ opts.defaultView = getFancyButtonView(c, 'default', v.object.default);
843
1148
  if ((_b = v.object) === null || _b === void 0 ? void 0 : _b.hover)
844
- opts.hoverView = v.object.hover;
1149
+ opts.hoverView = getFancyButtonView(c, 'hover', v.object.hover);
845
1150
  if ((_d = v.object) === null || _d === void 0 ? void 0 : _d.pressed)
846
- opts.pressedView = v.object.pressed;
1151
+ opts.pressedView = getFancyButtonView(c, 'pressed', v.object.pressed);
847
1152
  if ((_e = v.object) === null || _e === void 0 ? void 0 : _e.disabled)
848
- opts.disabledView = v.object.disabled;
1153
+ opts.disabledView = getFancyButtonView(c, 'disabled', v.object.disabled);
1154
+ if ((_f = v.object) === null || _f === void 0 ? void 0 : _f.icon)
1155
+ opts.icon = v.object.icon;
849
1156
  return opts;
850
1157
  },
851
1158
  postCreate: (inst, c) => {
852
1159
  inst.enabled = c.enabled;
1160
+ if (c.state && typeof inst.setState === 'function')
1161
+ inst.setState(c.state, true);
1162
+ applyFancyButtonAnchor(inst, c);
1163
+ applyOptionalSize(inst, c);
853
1164
  if (c.selected)
854
1165
  applySelectedTint(inst, c);
855
1166
  },
@@ -864,9 +1175,84 @@ const FANCY_BUTTON_DEF = {
864
1175
  inst.text = c.text;
865
1176
  if (c.padding !== undefined && inst.padding !== c.padding)
866
1177
  inst.padding = c.padding;
1178
+ if (c.textOffset !== undefined)
1179
+ inst.textOffset = c.textOffset;
1180
+ if (c.iconOffset !== undefined)
1181
+ inst.iconOffset = c.iconOffset;
1182
+ if (c.defaultTextScale !== undefined)
1183
+ inst.defaultTextScale = c.defaultTextScale;
1184
+ if (c.defaultIconScale !== undefined)
1185
+ inst.defaultIconScale = c.defaultIconScale;
1186
+ if (c.defaultTextAnchor !== undefined)
1187
+ inst.defaultTextAnchor = c.defaultTextAnchor;
1188
+ if (c.defaultIconAnchor !== undefined)
1189
+ inst.defaultIconAnchor = c.defaultIconAnchor;
1190
+ if (c.contentFittingMode !== undefined)
1191
+ inst.contentFittingMode = c.contentFittingMode;
1192
+ if (c.ignoreRefitting !== undefined && inst.options)
1193
+ inst.options.ignoreRefitting = c.ignoreRefitting;
1194
+ if (c.state && typeof inst.setState === 'function')
1195
+ inst.setState(c.state, true);
1196
+ applyFancyButtonAnchor(inst, c);
1197
+ applyOptionalSize(inst, c);
867
1198
  applySelectedTint(inst, c);
868
1199
  },
869
1200
  };
1201
+ function applyFancyButtonAnchor(inst, c) {
1202
+ var _a, _b, _d, _e, _f, _g, _h;
1203
+ const hasAnchor = c.anchor !== undefined || c.anchorX !== undefined || c.anchorY !== undefined;
1204
+ if (!hasAnchor || !((_a = inst === null || inst === void 0 ? void 0 : inst.anchor) === null || _a === void 0 ? void 0 : _a.set))
1205
+ return;
1206
+ const x = (_e = (_d = (_b = c.anchorX) !== null && _b !== void 0 ? _b : c.anchor) !== null && _d !== void 0 ? _d : inst.anchor.x) !== null && _e !== void 0 ? _e : 0;
1207
+ const y = (_h = (_g = (_f = c.anchorY) !== null && _f !== void 0 ? _f : c.anchor) !== null && _g !== void 0 ? _g : inst.anchor.y) !== null && _h !== void 0 ? _h : 0;
1208
+ try {
1209
+ inst.anchor.set(x, y);
1210
+ }
1211
+ catch (_) { }
1212
+ }
1213
+ function makeFancyButtonText(c) {
1214
+ var _a, _b, _d;
1215
+ if (c.text === undefined)
1216
+ return undefined;
1217
+ const text = String(c.text);
1218
+ if (c.textClass === 'html') {
1219
+ return new HTMLText({ text, style: c.textStyle });
1220
+ }
1221
+ if (c.textClass === 'bitmap') {
1222
+ const fontFamily = (_a = c.bitmapFontName) !== null && _a !== void 0 ? _a : 'TitleFont';
1223
+ ensureBitmapFont(fontFamily, c.textStyle);
1224
+ return new BitmapText({
1225
+ text,
1226
+ style: {
1227
+ fontFamily,
1228
+ fontSize: (_d = (_b = c.textStyle) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _d !== void 0 ? _d : 40,
1229
+ },
1230
+ });
1231
+ }
1232
+ if (c.textStyle && Object.keys(c.textStyle).length > 0) {
1233
+ return new Text({ text, style: c.textStyle });
1234
+ }
1235
+ return c.text;
1236
+ }
1237
+ const installedBitmapFonts = new Set();
1238
+ function ensureBitmapFont(name, style) {
1239
+ if (installedBitmapFonts.has(name))
1240
+ return;
1241
+ try {
1242
+ BitmapFontManager.install({ name, style: (style !== null && style !== void 0 ? style : {}) });
1243
+ }
1244
+ catch (_) {
1245
+ // Reinstalling an existing font can throw in Pixi; rendering can still use the current font.
1246
+ }
1247
+ installedBitmapFonts.add(name);
1248
+ }
1249
+ function getFancyButtonView(c, key, resolved) {
1250
+ var _a;
1251
+ const ref = (_a = c.views) === null || _a === void 0 ? void 0 : _a[key];
1252
+ if (c.nineSliceSprite && ref && 'texture' in ref)
1253
+ return getTextureView(ref.texture);
1254
+ return resolved;
1255
+ }
870
1256
  function applySelectedTint(inst, c) {
871
1257
  try {
872
1258
  const dv = inst.defaultView;
@@ -875,6 +1261,22 @@ function applySelectedTint(inst, c) {
875
1261
  }
876
1262
  catch (_) { }
877
1263
  }
1264
+ function syncCheckBoxTextStyle(inst, c) {
1265
+ var _a, _b, _d;
1266
+ const style = inst.style;
1267
+ if (!style || (!c.textStyle && !c.textOffset))
1268
+ return;
1269
+ const nextStyle = Object.assign(Object.assign({}, style), { text: (_a = c.textStyle) !== null && _a !== void 0 ? _a : style.text, textOffset: (_b = c.textOffset) !== null && _b !== void 0 ? _b : style.textOffset });
1270
+ // @pixi/ui CheckBox.style rebuilds checked/unchecked views. If RadioGroup is
1271
+ // listening, that rebuild can emit onChange while only one view exists.
1272
+ inst._style = nextStyle;
1273
+ if (inst.labelText && c.textStyle)
1274
+ inst.labelText.style = c.textStyle;
1275
+ try {
1276
+ (_d = inst.alignText) === null || _d === void 0 ? void 0 : _d.call(inst);
1277
+ }
1278
+ catch (_) { }
1279
+ }
878
1280
  const CHECKBOX_DEF = {
879
1281
  name: 'CheckBox',
880
1282
  signalPrefix: 'checkbox',
@@ -887,6 +1289,8 @@ const CHECKBOX_DEF = {
887
1289
  views: { kind: 'shallowMerge', default: {}, inspector: { name: 'views', type: 'object', isFolder: true, children: [
888
1290
  { name: 'checked', type: 'object' }, { name: 'unchecked', type: 'object' },
889
1291
  ] } },
1292
+ textStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1293
+ textOffset: { kind: 'shallowMerge', default: {} },
890
1294
  disabledStyle: { kind: 'shallowMerge', default: { alpha: 0.4, scale: 1 } },
891
1295
  },
892
1296
  views: {
@@ -897,7 +1301,7 @@ const CHECKBOX_DEF = {
897
1301
  ],
898
1302
  },
899
1303
  optionsBuilder: (c, v) => ({
900
- style: { checked: v.object.checked, unchecked: v.object.unchecked },
1304
+ style: { checked: v.object.checked, unchecked: v.object.unchecked, text: c.textStyle, textOffset: c.textOffset },
901
1305
  text: c.text, checked: c.checked,
902
1306
  }),
903
1307
  signalMap: (c) => ({
@@ -906,6 +1310,9 @@ const CHECKBOX_DEF = {
906
1310
  syncOnChange: (inst, c) => {
907
1311
  if (inst.checked !== c.checked)
908
1312
  inst.checked = c.checked;
1313
+ if (c.text !== undefined && inst.text !== c.text)
1314
+ inst.text = c.text;
1315
+ syncCheckBoxTextStyle(inst, c);
909
1316
  },
910
1317
  };
911
1318
  const SWITCHER_DEF = {
@@ -932,6 +1339,8 @@ const SWITCHER_DEF = {
932
1339
  syncOnChange: (inst, c) => {
933
1340
  if (inst.active !== c.active)
934
1341
  inst.active = c.active;
1342
+ if (c.triggerEvent !== undefined)
1343
+ inst.triggerEvents = c.triggerEvent;
935
1344
  },
936
1345
  };
937
1346
  const SLIDER_DEF = {
@@ -947,6 +1356,12 @@ const SLIDER_DEF = {
947
1356
  orientation: { kind: 'scalar', default: 'horizontal', inspector: { name: 'orientation', type: 'string' } },
948
1357
  showValue: { kind: 'scalar', default: false, inspector: { name: 'showValue', type: 'boolean' } },
949
1358
  views: { kind: 'shallowMerge', default: {} },
1359
+ nineSliceSprite: { kind: 'opaque' },
1360
+ fillPaddings: { kind: 'shallowMerge', default: {} },
1361
+ valueTextStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1362
+ valueTextOffset: { kind: 'shallowMerge', default: {} },
1363
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1364
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
950
1365
  bindToStore: BIND_STORE,
951
1366
  },
952
1367
  views: {
@@ -958,12 +1373,20 @@ const SLIDER_DEF = {
958
1373
  ],
959
1374
  },
960
1375
  optionsBuilder: (c, v) => {
961
- centerThumbPivot(v.object.thumb);
1376
+ var _a, _b, _d;
1377
+ const bg = getSliderView((_a = c.views) === null || _a === void 0 ? void 0 : _a.bg, v.object.bg);
1378
+ const fill = getSliderView((_b = c.views) === null || _b === void 0 ? void 0 : _b.fill, v.object.fill);
1379
+ const thumb = getSliderView((_d = c.views) === null || _d === void 0 ? void 0 : _d.thumb, v.object.thumb);
962
1380
  return {
963
- bg: v.object.bg, fill: v.object.fill, slider: v.object.thumb,
1381
+ bg, fill, slider: thumb,
964
1382
  min: c.min, max: c.max, step: c.step, value: c.value, showValue: c.showValue,
1383
+ fillPaddings: c.fillPaddings,
1384
+ nineSliceSprite: c.nineSliceSprite,
1385
+ valueTextStyle: c.valueTextStyle,
1386
+ valueTextOffset: c.valueTextOffset,
965
1387
  };
966
1388
  },
1389
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
967
1390
  signalMap: (c) => ({
968
1391
  update: (vv) => { c.value = vv; c.updateCount += 1; return { value: vv }; },
969
1392
  change: (vv) => { c.value = vv; c.changeCount += 1; return { value: vv }; },
@@ -971,37 +1394,9 @@ const SLIDER_DEF = {
971
1394
  syncOnChange: (inst, c) => {
972
1395
  if (inst.value !== c.value)
973
1396
  inst.value = c.value;
1397
+ applyOptionalSize(inst, c);
974
1398
  },
975
1399
  };
976
- /**
977
- * @pixi/ui Slider 的 update 逻辑:
978
- * slider.x = (bg.width/100 * progress) - (slider.width / 2) // x 已居中
979
- * slider.y = bg.height / 2 // y 未居中(bug)
980
- *
981
- * 因 y 维度 @pixi/ui 假设 thumb anchor / pivot 在中心(对 Sprite 自动 anchor.set(0.5),
982
- * 但 Graphics 没 anchor),Graphics 渲染时左上角对齐 bg 中线,thumb 中心落到中线下方。
983
- *
984
- * 修法:只设 pivot.y = h/2 让 thumb 沿 y 居中。pivot.x 保持 0(x 在 update
985
- * 里已用 -width/2 居中过,再设 pivot.x 会双倍偏移)。
986
- */
987
- function centerThumbPivot(thumb) {
988
- var _a, _b, _d, _e;
989
- if (!thumb)
990
- return;
991
- if (thumb.anchor)
992
- return; // Sprite — @pixi/ui 自己 anchor.set(0.5)
993
- let h = 0;
994
- try {
995
- const b = (_a = thumb.getBounds) === null || _a === void 0 ? void 0 : _a.call(thumb);
996
- h = (_d = (_b = b === null || b === void 0 ? void 0 : b.height) !== null && _b !== void 0 ? _b : thumb.height) !== null && _d !== void 0 ? _d : 0;
997
- }
998
- catch (_) {
999
- h = (_e = thumb.height) !== null && _e !== void 0 ? _e : 0;
1000
- }
1001
- if (h > 0 && thumb.pivot) {
1002
- thumb.pivot.set(0, h / 2);
1003
- }
1004
- }
1005
1400
  const DOUBLE_SLIDER_DEF = {
1006
1401
  name: 'DoubleSlider',
1007
1402
  signalPrefix: 'doubleslider',
@@ -1015,6 +1410,12 @@ const DOUBLE_SLIDER_DEF = {
1015
1410
  step: { kind: 'scalar', default: 1 },
1016
1411
  showValue: { kind: 'scalar', default: false, inspector: { name: 'showValue', type: 'boolean' } },
1017
1412
  views: { kind: 'shallowMerge', default: {} },
1413
+ nineSliceSprite: { kind: 'opaque' },
1414
+ fillPaddings: { kind: 'shallowMerge', default: {} },
1415
+ valueTextStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1416
+ valueTextOffset: { kind: 'shallowMerge', default: {} },
1417
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1418
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1018
1419
  bindToStore1: { kind: 'scalar' },
1019
1420
  bindToStore2: { kind: 'scalar' },
1020
1421
  },
@@ -1026,14 +1427,22 @@ const DOUBLE_SLIDER_DEF = {
1026
1427
  ],
1027
1428
  },
1028
1429
  optionsBuilder: (c, v) => {
1029
- centerThumbPivot(v.object.slider1);
1030
- centerThumbPivot(v.object.slider2);
1430
+ var _a, _b, _d, _e;
1431
+ const bg = getSliderView((_a = c.views) === null || _a === void 0 ? void 0 : _a.bg, v.object.bg);
1432
+ const fill = getSliderView((_b = c.views) === null || _b === void 0 ? void 0 : _b.fill, v.object.fill);
1433
+ const slider1 = getSliderView((_d = c.views) === null || _d === void 0 ? void 0 : _d.slider1, v.object.slider1);
1434
+ const slider2 = getSliderView((_e = c.views) === null || _e === void 0 ? void 0 : _e.slider2, v.object.slider2);
1031
1435
  return {
1032
- bg: v.object.bg, fill: v.object.fill,
1033
- slider1: v.object.slider1, slider2: v.object.slider2,
1034
- min: c.min, max: c.max, value1: c.value1, value2: c.value2, showValue: c.showValue,
1436
+ bg, fill,
1437
+ slider1, slider2,
1438
+ min: c.min, max: c.max, step: c.step, value1: c.value1, value2: c.value2, showValue: c.showValue,
1439
+ fillPaddings: c.fillPaddings,
1440
+ nineSliceSprite: c.nineSliceSprite,
1441
+ valueTextStyle: c.valueTextStyle,
1442
+ valueTextOffset: c.valueTextOffset,
1035
1443
  };
1036
1444
  },
1445
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
1037
1446
  signalMap: (c) => ({
1038
1447
  update: (v1, v2) => { c.value1 = v1; c.value2 = v2; c.updateCount += 1; return { value1: v1, value2: v2 }; },
1039
1448
  change: (v1, v2) => { c.value1 = v1; c.value2 = v2; c.changeCount += 1; return { value1: v1, value2: v2 }; },
@@ -1043,6 +1452,7 @@ const DOUBLE_SLIDER_DEF = {
1043
1452
  inst.value1 = c.value1;
1044
1453
  if (inst.value2 !== c.value2)
1045
1454
  inst.value2 = c.value2;
1455
+ applyOptionalSize(inst, c);
1046
1456
  },
1047
1457
  };
1048
1458
  const PROGRESS_BAR_DEF = {
@@ -1056,6 +1466,8 @@ const PROGRESS_BAR_DEF = {
1056
1466
  fillView: { kind: 'opaque' },
1057
1467
  nineSliceSprite: { kind: 'opaque' },
1058
1468
  fillPaddings: { kind: 'shallowMerge', default: {} },
1469
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1470
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1059
1471
  bindToStore: BIND_STORE,
1060
1472
  },
1061
1473
  views: {
@@ -1066,17 +1478,54 @@ const PROGRESS_BAR_DEF = {
1066
1478
  // 这里用 inline resolution(在 system.ts handleGeneric 里有 fast path 处理 views=undefined 的情形,
1067
1479
  // optionsBuilder 接受 raw component 自己 resolve)
1068
1480
  optionsBuilder: (c, _v) => ({
1069
- bg: c.__resolved_bg, fill: c.__resolved_fill,
1481
+ bg: c.__resolved_bg_view, fill: c.__resolved_fill_view,
1070
1482
  fillPaddings: c.fillPaddings,
1483
+ nineSliceSprite: c.nineSliceSprite,
1071
1484
  progress: computeProgressPct(c),
1072
1485
  }),
1486
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
1073
1487
  syncOnChange: (inst, c) => {
1074
1488
  const pct = computeProgressPct(c);
1075
1489
  if (inst.progress !== pct)
1076
1490
  inst.progress = pct;
1491
+ applyOptionalSize(inst, c);
1077
1492
  },
1078
1493
  mixin: { getProgressPct: getProgressPctMixin },
1079
1494
  };
1495
+ function getSliderView(ref, resolved) {
1496
+ if (ref && 'texture' in ref) {
1497
+ return getTextureView(ref.texture);
1498
+ }
1499
+ return resolved;
1500
+ }
1501
+ function getProgressView(ref, resolved, nineSliceSprite) {
1502
+ if (nineSliceSprite && ref && 'texture' in ref) {
1503
+ return getTextureView(ref.texture);
1504
+ }
1505
+ return resolved;
1506
+ }
1507
+ function getTextureView(textureKey) {
1508
+ var _a;
1509
+ return (_a = resolveTexture(undefined, textureKey)) !== null && _a !== void 0 ? _a : textureKey;
1510
+ }
1511
+ function applyOptionalSize(inst, c) {
1512
+ var _a, _b;
1513
+ if (c.width === undefined && c.height === undefined)
1514
+ return;
1515
+ const width = (_a = c.width) !== null && _a !== void 0 ? _a : inst.width;
1516
+ const height = (_b = c.height) !== null && _b !== void 0 ? _b : inst.height;
1517
+ if (typeof inst.setSize === 'function') {
1518
+ try {
1519
+ inst.setSize(width, height);
1520
+ return;
1521
+ }
1522
+ catch (_) { }
1523
+ }
1524
+ if (c.width !== undefined)
1525
+ inst.width = c.width;
1526
+ if (c.height !== undefined)
1527
+ inst.height = c.height;
1528
+ }
1080
1529
  function computeProgressPct(c) {
1081
1530
  const [min, max] = c.valueRange;
1082
1531
  if (max <= min)
@@ -1098,21 +1547,36 @@ const CIRCULAR_PROGRESS_BAR_DEF = {
1098
1547
  fillColor: { kind: 'scalar', default: '#22c55e', inspector: { name: 'fillColor', type: 'color' } },
1099
1548
  backgroundAlpha: { kind: 'scalar', default: 1, inspector: { name: 'backgroundAlpha', type: 'number', step: 0.05 } },
1100
1549
  fillAlpha: { kind: 'scalar', default: 1, inspector: { name: 'fillAlpha', type: 'number', step: 0.05 } },
1550
+ cap: { kind: 'scalar', inspector: { name: 'cap', type: 'string' } },
1551
+ rotation: { kind: 'scalar', default: 0 },
1552
+ offset: { kind: 'shallowMerge', default: {} },
1101
1553
  bindToStore: BIND_STORE,
1102
1554
  },
1103
1555
  optionsBuilder: (c) => ({
1104
1556
  radius: c.radius, lineWidth: c.lineWidth,
1105
1557
  backgroundColor: c.backgroundColor, fillColor: c.fillColor,
1106
1558
  backgroundAlpha: c.backgroundAlpha, fillAlpha: c.fillAlpha,
1559
+ cap: c.cap,
1107
1560
  value: computeProgressPct(c),
1108
1561
  }),
1562
+ postCreate: (inst, c) => applyCircularProgressTransform(inst, c),
1109
1563
  syncOnChange: (inst, c) => {
1110
1564
  const pct = computeProgressPct(c);
1111
1565
  if (inst.progress !== pct)
1112
1566
  inst.progress = pct;
1567
+ applyCircularProgressTransform(inst, c);
1113
1568
  },
1114
1569
  mixin: { getProgressPct: getProgressPctMixin },
1115
1570
  };
1571
+ function applyCircularProgressTransform(inst, c) {
1572
+ var _a, _b;
1573
+ if (c.rotation !== undefined)
1574
+ inst.rotation = c.rotation;
1575
+ if (c.offset) {
1576
+ inst.x = (_a = c.offset.x) !== null && _a !== void 0 ? _a : 0;
1577
+ inst.y = (_b = c.offset.y) !== null && _b !== void 0 ? _b : 0;
1578
+ }
1579
+ }
1116
1580
  const INPUT_DEF = {
1117
1581
  name: 'Input',
1118
1582
  signalPrefix: 'input',
@@ -1130,15 +1594,18 @@ const INPUT_DEF = {
1130
1594
  nineSliceSprite: { kind: 'opaque' },
1131
1595
  cleanOnFocus: { kind: 'scalar', default: false, inspector: { name: 'cleanOnFocus', type: 'boolean' } },
1132
1596
  addMask: { kind: 'scalar', default: false, inspector: { name: 'addMask', type: 'boolean' } },
1597
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1598
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1133
1599
  bindToStore: BIND_STORE,
1134
1600
  },
1135
1601
  views: { kind: 'single', key: 'bgView', required: true },
1136
1602
  optionsBuilder: (c, v) => ({
1137
- bg: v.single, textStyle: c.textStyle,
1603
+ bg: getProgressView(c.bgView, v.single, c.nineSliceSprite), textStyle: c.textStyle,
1138
1604
  placeholder: c.placeholder, value: c.value, maxLength: c.maxLength, secure: c.secure,
1139
1605
  align: c.align, padding: c.padding,
1140
1606
  cleanOnFocus: c.cleanOnFocus, nineSliceSprite: c.nineSliceSprite, addMask: c.addMask,
1141
1607
  }),
1608
+ postCreate: (inst, c) => { inst.enabled = c.enabled; applyOptionalSize(inst, c); },
1142
1609
  signalMap: (c) => ({
1143
1610
  change: (text) => { c.value = text; c.changeCount += 1; return { value: text }; },
1144
1611
  enter: (text) => ({ value: text }),
@@ -1146,6 +1613,9 @@ const INPUT_DEF = {
1146
1613
  syncOnChange: (inst, c) => {
1147
1614
  if (inst.value !== c.value)
1148
1615
  inst.value = c.value;
1616
+ if (inst.enabled !== c.enabled)
1617
+ inst.enabled = c.enabled;
1618
+ applyOptionalSize(inst, c);
1149
1619
  },
1150
1620
  };
1151
1621
  const LIST_DEF = {
@@ -1167,18 +1637,25 @@ const LIST_DEF = {
1167
1637
  itemsChildName: { kind: 'scalar', default: 'items' },
1168
1638
  },
1169
1639
  // List 不走 ViewSchema,view 是 collectChildContainers 副作用,system.ts 处理
1170
- optionsBuilder: (c, _v) => {
1640
+ optionsBuilder: (c, _v) => ({
1641
+ type: c.type,
1642
+ elementsMargin: c.elementsMargin,
1643
+ padding: c.padding,
1644
+ vertPadding: c.vertPadding, horPadding: c.horPadding,
1645
+ topPadding: c.topPadding, bottomPadding: c.bottomPadding,
1646
+ leftPadding: c.leftPadding, rightPadding: c.rightPadding,
1647
+ maxWidth: c.maxWidth, maxHeight: c.maxHeight,
1648
+ }),
1649
+ postCreate: (inst, c) => {
1171
1650
  var _a;
1172
- return ({
1173
- type: c.type,
1174
- elementsMargin: c.elementsMargin,
1175
- padding: c.padding,
1176
- vertPadding: c.vertPadding, horPadding: c.horPadding,
1177
- topPadding: c.topPadding, bottomPadding: c.bottomPadding,
1178
- leftPadding: c.leftPadding, rightPadding: c.rightPadding,
1179
- maxWidth: c.maxWidth, maxHeight: c.maxHeight,
1180
- children: (_a = c.__resolved_items) !== null && _a !== void 0 ? _a : [],
1181
- });
1651
+ for (const item of (_a = c.__resolved_items) !== null && _a !== void 0 ? _a : []) {
1652
+ try {
1653
+ inst.addChild(item);
1654
+ }
1655
+ catch (_) { }
1656
+ }
1657
+ if (typeof inst.arrangeChildren === 'function')
1658
+ inst.arrangeChildren();
1182
1659
  },
1183
1660
  syncOnChange: (inst, c) => {
1184
1661
  if (inst.type !== c.type)
@@ -1188,6 +1665,7 @@ const LIST_DEF = {
1188
1665
  if (typeof inst.arrangeChildren === 'function')
1189
1666
  inst.arrangeChildren();
1190
1667
  },
1668
+ applySize: applyListLayoutSize,
1191
1669
  };
1192
1670
  const SCROLL_BOX_DEF = {
1193
1671
  name: 'ScrollBox',
@@ -1198,12 +1676,22 @@ const SCROLL_BOX_DEF = {
1198
1676
  height: { kind: 'scalar', default: 240, inspector: { name: 'height', type: 'number' } },
1199
1677
  direction: { kind: 'scalar', default: 'vertical', inspector: { name: 'direction', type: 'string' } },
1200
1678
  contentChildName: { kind: 'scalar', default: 'content' },
1201
- background: { kind: 'scalar', default: 0x111111, inspector: { name: 'background', type: 'color' } },
1679
+ background: { kind: 'scalar', inspector: { name: 'background', type: 'color' } },
1202
1680
  radius: { kind: 'scalar', default: 0, inspector: { name: 'radius', type: 'number' } },
1203
1681
  elementsMargin: { kind: 'scalar', default: 0 },
1204
1682
  disableDynamicRendering: { kind: 'scalar', default: false },
1205
1683
  disableEasing: { kind: 'scalar', default: false, inspector: { name: 'disableEasing', type: 'boolean' } },
1206
1684
  padding: { kind: 'scalar', default: 0 },
1685
+ vertPadding: { kind: 'scalar' },
1686
+ horPadding: { kind: 'scalar' },
1687
+ topPadding: { kind: 'scalar' },
1688
+ bottomPadding: { kind: 'scalar' },
1689
+ leftPadding: { kind: 'scalar' },
1690
+ rightPadding: { kind: 'scalar' },
1691
+ globalScroll: { kind: 'scalar', default: true },
1692
+ shiftScroll: { kind: 'scalar', default: false },
1693
+ proximityRange: { kind: 'scalar' },
1694
+ proximityDebounce: { kind: 'scalar' },
1207
1695
  // legacy fields(spec 兼容)
1208
1696
  inertia: { kind: 'scalar', default: true },
1209
1697
  inertiaDecay: { kind: 'scalar', default: 0.92 },
@@ -1215,7 +1703,7 @@ const SCROLL_BOX_DEF = {
1215
1703
  getBounds() { return { minX: 0, maxX: 0, minY: 0, maxY: 0 }; },
1216
1704
  },
1217
1705
  optionsBuilder: (c, _v) => {
1218
- var _a, _b;
1706
+ var _a;
1219
1707
  const typeMap = {
1220
1708
  horizontal: 'horizontal', vertical: 'vertical', both: 'bidirectional',
1221
1709
  };
@@ -1224,21 +1712,37 @@ const SCROLL_BOX_DEF = {
1224
1712
  type: (_a = typeMap[c.direction]) !== null && _a !== void 0 ? _a : 'vertical',
1225
1713
  background: c.background, radius: c.radius,
1226
1714
  elementsMargin: c.elementsMargin, padding: c.padding,
1715
+ vertPadding: c.vertPadding, horPadding: c.horPadding,
1716
+ topPadding: c.topPadding, bottomPadding: c.bottomPadding,
1717
+ leftPadding: c.leftPadding, rightPadding: c.rightPadding,
1227
1718
  disableEasing: c.disableEasing, disableDynamicRendering: c.disableDynamicRendering,
1228
- items: (_b = c.__resolved_items) !== null && _b !== void 0 ? _b : [],
1719
+ globalScroll: c.globalScroll, shiftScroll: c.shiftScroll,
1720
+ proximityRange: c.proximityRange, proximityDebounce: c.proximityDebounce,
1229
1721
  };
1230
1722
  },
1231
1723
  signalMap: () => ({
1232
1724
  scroll: (v) => ({ value: v }),
1233
1725
  }),
1234
- syncOnChange: (inst, c) => {
1726
+ postCreate: (inst, c) => {
1727
+ var _a, _b;
1728
+ if (typeof inst.addItems === 'function') {
1729
+ try {
1730
+ inst.addItems((_a = c.__resolved_items) !== null && _a !== void 0 ? _a : []);
1731
+ }
1732
+ catch (_) { }
1733
+ }
1734
+ if (typeof ((_b = inst.list) === null || _b === void 0 ? void 0 : _b.arrangeChildren) === 'function')
1735
+ inst.list.arrangeChildren();
1235
1736
  if (typeof inst.resize === 'function') {
1236
1737
  try {
1237
- inst.resize(c.width, c.height);
1738
+ inst.resize();
1238
1739
  }
1239
1740
  catch (_) { }
1240
1741
  }
1241
1742
  },
1743
+ syncOnChange: (inst, c) => {
1744
+ applyOptionalSize(inst, c);
1745
+ },
1242
1746
  };
1243
1747
  const SELECT_DEF = {
1244
1748
  name: 'Select',
@@ -1252,26 +1756,51 @@ const SELECT_DEF = {
1252
1756
  openView: { kind: 'opaque' },
1253
1757
  textStyle: { kind: 'shallowMerge', default: { fontFamily: 'Arial', fontSize: 14, fill: '#222' } },
1254
1758
  nineSliceSprite: { kind: 'opaque' },
1759
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1760
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1761
+ radius: { kind: 'scalar', default: 4 },
1762
+ visibleItems: { kind: 'scalar' },
1763
+ itemWidth: { kind: 'scalar' },
1764
+ itemHeight: { kind: 'scalar' },
1765
+ itemBackgroundColor: { kind: 'scalar', default: 0x000000 },
1766
+ itemHoverColor: { kind: 'scalar', default: 0x666666 },
1767
+ selectedTextOffset: { kind: 'shallowMerge', default: {} },
1768
+ scrollBox: { kind: 'shallowMerge', default: {} },
1769
+ textClass: { kind: 'scalar', default: 'text' },
1770
+ open: { kind: 'scalar', default: false },
1255
1771
  bindToStore: BIND_STORE,
1256
1772
  },
1257
1773
  views: {
1258
1774
  kind: 'object', folder: '__select_views__', keys: [],
1259
1775
  },
1260
1776
  optionsBuilder: (c) => {
1261
- var _a;
1777
+ var _a, _b, _d, _e, _f;
1262
1778
  return ({
1263
1779
  closedBG: c.__resolved_closedView,
1264
1780
  openBG: c.__resolved_openView,
1265
1781
  textStyle: c.textStyle,
1782
+ TextClass: c.textClass === 'html' ? HTMLText : undefined,
1783
+ selectedTextOffset: c.selectedTextOffset,
1266
1784
  items: {
1267
1785
  items: ((_a = c.items) !== null && _a !== void 0 ? _a : []).map((it) => it.text),
1268
- backgroundColor: 0x000000, hoverColor: 0x666666,
1269
- width: 200, height: 30, textStyle: c.textStyle, radius: 4,
1786
+ backgroundColor: c.itemBackgroundColor,
1787
+ hoverColor: c.itemHoverColor,
1788
+ width: (_d = (_b = c.itemWidth) !== null && _b !== void 0 ? _b : c.width) !== null && _d !== void 0 ? _d : 200,
1789
+ height: (_f = (_e = c.itemHeight) !== null && _e !== void 0 ? _e : c.height) !== null && _f !== void 0 ? _f : 30,
1790
+ textStyle: c.textStyle,
1791
+ TextClass: c.textClass === 'html' ? HTMLText : undefined,
1792
+ radius: c.radius,
1270
1793
  },
1271
1794
  selected: c.selectedIndex >= 0 ? c.selectedIndex : undefined,
1795
+ visibleItems: c.visibleItems,
1796
+ scrollBox: Object.assign({ width: c.width, height: c.height && c.visibleItems ? c.height * c.visibleItems : undefined, radius: c.radius }, c.scrollBox),
1272
1797
  nineSliceSprite: c.nineSliceSprite,
1273
1798
  });
1274
1799
  },
1800
+ postCreate: (inst, c) => {
1801
+ if (c.open && typeof inst.open === 'function')
1802
+ inst.open();
1803
+ },
1275
1804
  signalMap: (c) => ({
1276
1805
  select: (value, text) => {
1277
1806
  c.selectedIndex = value;
@@ -1279,6 +1808,12 @@ const SELECT_DEF = {
1279
1808
  return { index: value, text };
1280
1809
  },
1281
1810
  }),
1811
+ syncOnChange: (inst, c) => {
1812
+ if (c.open && typeof inst.open === 'function')
1813
+ inst.open();
1814
+ if (!c.open && typeof inst.close === 'function')
1815
+ inst.close();
1816
+ },
1282
1817
  };
1283
1818
  const DIALOG_DEF = {
1284
1819
  name: 'Dialog',
@@ -1297,36 +1832,340 @@ const DIALOG_DEF = {
1297
1832
  closeOnBackdropClick: { kind: 'scalar', default: true, inspector: { name: 'closeOnBackdropClick', type: 'boolean' } },
1298
1833
  contentChildName: { kind: 'scalar', default: 'content', inspector: { name: 'contentChildName', type: 'string' } },
1299
1834
  nineSliceSprite: { kind: 'opaque' },
1835
+ titleStyle: { kind: 'shallowMerge', default: {} },
1836
+ content: { kind: 'scalar' },
1837
+ contentStyle: { kind: 'shallowMerge', default: {} },
1838
+ contentButtons: { kind: 'arrayCopy', default: [] },
1839
+ contentCheckBoxes: { kind: 'arrayCopy', default: [] },
1840
+ buttons: { kind: 'arrayCopy', default: [] },
1841
+ buttonList: { kind: 'shallowMerge', default: {} },
1842
+ buttonListOffset: { kind: 'shallowMerge', default: {} },
1843
+ scrollBox: { kind: 'shallowMerge', default: {} },
1844
+ animations: { kind: 'opaque' },
1300
1845
  bindToStore: BIND_STORE,
1301
1846
  },
1302
1847
  optionsBuilder: (c) => {
1303
1848
  var _a;
1304
- return ({
1849
+ const background = c.nineSliceSprite && c.backgroundView && 'texture' in c.backgroundView
1850
+ ? c.backgroundView.texture
1851
+ : ((_a = c.__resolved_background_view) !== null && _a !== void 0 ? _a : new Container());
1852
+ return {
1305
1853
  backdrop: c.__resolved_backdropView,
1306
1854
  backdropColor: backdropColorToNumber(c.backdropColor),
1307
1855
  backdropAlpha: c.backdropAlpha,
1308
- background: (_a = c.__resolved_backgroundView) !== null && _a !== void 0 ? _a : new Container(),
1309
- title: c.title,
1856
+ background,
1857
+ title: makeDialogText(c.title, c.titleStyle),
1858
+ content: makeDialogContent(c),
1859
+ buttons: makeDialogButtons(c.buttons),
1860
+ buttonList: c.buttonList,
1861
+ scrollBox: c.scrollBox,
1310
1862
  width: c.width, height: c.height, padding: c.padding,
1311
1863
  closeOnBackdropClick: c.closeOnBackdropClick,
1312
1864
  nineSliceSprite: c.nineSliceSprite,
1313
- });
1865
+ animations: c.animations,
1866
+ };
1314
1867
  },
1315
1868
  postCreate: (inst, c) => {
1869
+ alignDialogAnchoredContent(inst, c);
1316
1870
  if (c.open && typeof inst.open === 'function')
1317
1871
  inst.open();
1318
1872
  },
1873
+ applySize: applyDialogSize,
1874
+ onAttachedExtra: (inst, c, go) => {
1875
+ wireDialogContentButtonPresses(inst, c, go);
1876
+ },
1319
1877
  signalMap: (c) => ({
1320
1878
  close: () => { c.open = false; return {}; },
1321
1879
  select: (idx, text) => ({ index: idx, text }),
1322
1880
  }),
1323
1881
  syncOnChange: (inst, c) => {
1882
+ alignDialogAnchoredContent(inst, c);
1324
1883
  if (c.open && !inst.isOpen && typeof inst.open === 'function')
1325
1884
  inst.open();
1326
1885
  else if (!c.open && inst.isOpen && typeof inst.close === 'function')
1327
1886
  inst.close();
1328
1887
  },
1329
1888
  };
1889
+ function applyDialogSize(inst, size, c) {
1890
+ var _a, _b, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _w, _x, _y;
1891
+ const width = readPositiveSize((_b = (_a = size.width) !== null && _a !== void 0 ? _a : c.width) !== null && _b !== void 0 ? _b : (_d = inst === null || inst === void 0 ? void 0 : inst.options) === null || _d === void 0 ? void 0 : _d.width);
1892
+ const height = readPositiveSize((_f = (_e = size.height) !== null && _e !== void 0 ? _e : c.height) !== null && _f !== void 0 ? _f : (_g = inst === null || inst === void 0 ? void 0 : inst.options) === null || _g === void 0 ? void 0 : _g.height);
1893
+ if (width === undefined && height === undefined)
1894
+ return;
1895
+ inst.options = (_h = inst.options) !== null && _h !== void 0 ? _h : {};
1896
+ if (width !== undefined)
1897
+ inst.options.width = width;
1898
+ if (height !== undefined)
1899
+ inst.options.height = height;
1900
+ const dialogWidth = width !== null && width !== void 0 ? width : (Number(inst.options.width) || Number((_j = inst.innerView) === null || _j === void 0 ? void 0 : _j.width) || 0);
1901
+ const dialogHeight = height !== null && height !== void 0 ? height : (Number(inst.options.height) || Number((_k = inst.innerView) === null || _k === void 0 ? void 0 : _k.height) || 0);
1902
+ const padding = Number((_m = (_l = c.padding) !== null && _l !== void 0 ? _l : inst.options.padding) !== null && _m !== void 0 ? _m : 20) || 20;
1903
+ if (inst.innerView) {
1904
+ if (width !== undefined)
1905
+ inst.innerView.width = width;
1906
+ if (height !== undefined)
1907
+ inst.innerView.height = height;
1908
+ if ('anchor' in inst.innerView && ((_o = inst.innerView.anchor) === null || _o === void 0 ? void 0 : _o.set)) {
1909
+ inst.innerView.anchor.set(0.5, 0.5);
1910
+ }
1911
+ else {
1912
+ try {
1913
+ (_q = (_p = inst.innerView.pivot) === null || _p === void 0 ? void 0 : _p.set) === null || _q === void 0 ? void 0 : _q.call(_p, dialogWidth / 2, dialogHeight / 2);
1914
+ }
1915
+ catch (_) { }
1916
+ }
1917
+ }
1918
+ if (inst.titleText) {
1919
+ inst.titleText.x = dialogWidth / 2;
1920
+ inst.titleText.y = padding;
1921
+ }
1922
+ const titleHeight = Number((_r = inst.titleText) === null || _r === void 0 ? void 0 : _r.height) || 0;
1923
+ const buttonHeight = Number((_s = inst.buttonContainer) === null || _s === void 0 ? void 0 : _s.height) || 0;
1924
+ if (inst.buttonContainer) {
1925
+ inst.buttonContainer.x = dialogWidth / 2 - ((Number(inst.buttonContainer.width) || 0) / 2);
1926
+ inst.buttonContainer.y = dialogHeight - padding - buttonHeight;
1927
+ }
1928
+ if (inst.scrollBox) {
1929
+ inst.scrollBox.x = padding;
1930
+ inst.scrollBox.y = padding + titleHeight;
1931
+ const overrideSize = (_t = c.scrollBox) === null || _t === void 0 ? void 0 : _t.size;
1932
+ const scrollWidth = (_u = readPositiveSize(overrideSize === null || overrideSize === void 0 ? void 0 : overrideSize.width)) !== null && _u !== void 0 ? _u : Math.max(0, dialogWidth - (padding * 2));
1933
+ const scrollHeight = (_w = readPositiveSize(overrideSize === null || overrideSize === void 0 ? void 0 : overrideSize.height)) !== null && _w !== void 0 ? _w : Math.max(0, dialogHeight - (padding * 2) - titleHeight - buttonHeight);
1934
+ if (typeof inst.scrollBox.setSize === 'function')
1935
+ inst.scrollBox.setSize(scrollWidth, scrollHeight);
1936
+ else {
1937
+ inst.scrollBox.width = scrollWidth;
1938
+ inst.scrollBox.height = scrollHeight;
1939
+ }
1940
+ try {
1941
+ (_y = (_x = inst.scrollBox).resize) === null || _y === void 0 ? void 0 : _y.call(_x, true);
1942
+ }
1943
+ catch (_) { }
1944
+ }
1945
+ alignDialogAnchoredContent(inst, Object.assign(Object.assign({}, c), { width: dialogWidth, height: dialogHeight }));
1946
+ }
1947
+ function readPositiveSize(value) {
1948
+ const n = Number(value);
1949
+ return Number.isFinite(n) && n > 0 ? n : undefined;
1950
+ }
1951
+ function alignDialogAnchoredContent(inst, c) {
1952
+ var _a, _b;
1953
+ const innerView = inst === null || inst === void 0 ? void 0 : inst.innerView;
1954
+ const contentView = inst === null || inst === void 0 ? void 0 : inst.contentView;
1955
+ if ((innerView === null || innerView === void 0 ? void 0 : innerView.anchor) && contentView && c.width && c.height) {
1956
+ contentView.x = -c.width / 2;
1957
+ contentView.y = -c.height / 2;
1958
+ }
1959
+ applyDialogOffset(inst, 'buttonListOffset', inst.buttonContainer, c.buttonListOffset);
1960
+ applyDialogOffset(inst, 'scrollBoxOffset', inst.scrollBox, (_a = c.scrollBox) === null || _a === void 0 ? void 0 : _a.offset);
1961
+ applyDialogScrollBoxSize(inst, (_b = c.scrollBox) === null || _b === void 0 ? void 0 : _b.size);
1962
+ }
1963
+ function applyDialogOffset(inst, key, target, nextOffset) {
1964
+ var _a, _b, _d, _e;
1965
+ if (!target)
1966
+ return;
1967
+ const applied = (_a = inst.__evaDialogAppliedOffsets) !== null && _a !== void 0 ? _a : {};
1968
+ const prev = (_b = applied[key]) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
1969
+ const next = { x: (_d = nextOffset === null || nextOffset === void 0 ? void 0 : nextOffset.x) !== null && _d !== void 0 ? _d : 0, y: (_e = nextOffset === null || nextOffset === void 0 ? void 0 : nextOffset.y) !== null && _e !== void 0 ? _e : 0 };
1970
+ target.x += next.x - prev.x;
1971
+ target.y += next.y - prev.y;
1972
+ inst.__evaDialogAppliedOffsets = Object.assign(Object.assign({}, applied), { [key]: next });
1973
+ }
1974
+ function applyDialogScrollBoxSize(inst, nextSize) {
1975
+ var _a, _b, _d;
1976
+ const scrollBox = inst === null || inst === void 0 ? void 0 : inst.scrollBox;
1977
+ if (!scrollBox)
1978
+ return;
1979
+ const base = (_a = inst.__evaDialogBaseScrollBoxSize) !== null && _a !== void 0 ? _a : {
1980
+ width: scrollBox.width,
1981
+ height: scrollBox.height,
1982
+ };
1983
+ inst.__evaDialogBaseScrollBoxSize = base;
1984
+ const wasApplied = inst.__evaDialogAppliedScrollBoxSize;
1985
+ if (!nextSize && !wasApplied)
1986
+ return;
1987
+ const width = (_b = nextSize === null || nextSize === void 0 ? void 0 : nextSize.width) !== null && _b !== void 0 ? _b : base.width;
1988
+ const height = (_d = nextSize === null || nextSize === void 0 ? void 0 : nextSize.height) !== null && _d !== void 0 ? _d : base.height;
1989
+ if (typeof scrollBox.setSize === 'function')
1990
+ scrollBox.setSize(width, height);
1991
+ else {
1992
+ scrollBox.width = width;
1993
+ scrollBox.height = height;
1994
+ }
1995
+ if (typeof scrollBox.resize === 'function')
1996
+ scrollBox.resize(true);
1997
+ inst.__evaDialogAppliedScrollBoxSize = !!nextSize;
1998
+ }
1999
+ function makeDialogText(text, style) {
2000
+ if (text === undefined)
2001
+ return undefined;
2002
+ if (style && Object.keys(style).length > 0) {
2003
+ return new Text({ text, style: style });
2004
+ }
2005
+ return text;
2006
+ }
2007
+ function makeDialogContent(c) {
2008
+ var _a, _b;
2009
+ if ((_a = c.contentButtons) === null || _a === void 0 ? void 0 : _a.length) {
2010
+ const records = [];
2011
+ const buttons = c.contentButtons.map((button, index) => {
2012
+ const pixiButton = new FancyButton$1(makeDialogButtonOptions(button));
2013
+ applyOptionalSize(pixiButton, button);
2014
+ if (button.disabled !== undefined)
2015
+ pixiButton.enabled = !button.disabled;
2016
+ records.push({ button: pixiButton, params: button, index });
2017
+ return pixiButton;
2018
+ });
2019
+ c.__dialogContentButtons = records;
2020
+ return buttons;
2021
+ }
2022
+ if ((_b = c.contentCheckBoxes) === null || _b === void 0 ? void 0 : _b.length) {
2023
+ return c.contentCheckBoxes.map((checkBox) => new CheckBox$1(makeDialogCheckBoxOptions(checkBox)));
2024
+ }
2025
+ return makeDialogText(c.content, c.contentStyle);
2026
+ }
2027
+ function wireDialogContentButtonPresses(inst, c, go) {
2028
+ const records = c.__dialogContentButtons;
2029
+ if (!Array.isArray(records) || records.length === 0 || inst.__evaDialogContentButtonPressesWired)
2030
+ return;
2031
+ inst.__evaDialogContentButtonPressesWired = true;
2032
+ inst.__evaDialogContentButtonPressCleanups = records.map((record) => {
2033
+ var _a;
2034
+ const signal = (_a = record.button) === null || _a === void 0 ? void 0 : _a.onPress;
2035
+ if (!signal || typeof signal.connect !== 'function')
2036
+ return undefined;
2037
+ const conn = signal.connect(() => {
2038
+ var _a, _b, _d, _e;
2039
+ const value = (_b = (_a = record.params.value) !== null && _a !== void 0 ? _a : record.params.text) !== null && _b !== void 0 ? _b : record.index;
2040
+ c.selectedContentIndex = record.index;
2041
+ c.selectedContentValue = value;
2042
+ c.selectCount = ((_d = c.selectCount) !== null && _d !== void 0 ? _d : 0) + 1;
2043
+ c.lastSignal = 'select';
2044
+ emitDialogSelection(go, { index: record.index, text: String((_e = record.params.text) !== null && _e !== void 0 ? _e : ''), value });
2045
+ if (record.params.closeOnPress && typeof inst.close === 'function')
2046
+ inst.close();
2047
+ const reopenDelay = Number(record.params.reopenDelay);
2048
+ if (Number.isFinite(reopenDelay) && reopenDelay >= 0 && typeof inst.open === 'function') {
2049
+ setTimeout(() => {
2050
+ try {
2051
+ inst.open();
2052
+ }
2053
+ catch (_) { }
2054
+ }, reopenDelay);
2055
+ }
2056
+ });
2057
+ return () => { try {
2058
+ conn.disconnect();
2059
+ }
2060
+ catch (_) { } };
2061
+ }).filter(Boolean);
2062
+ }
2063
+ function emitDialogSelection(go, payload) {
2064
+ var _a, _b, _d;
2065
+ const eventPayload = Object.assign({ entityName: go === null || go === void 0 ? void 0 : go.name }, payload);
2066
+ try {
2067
+ (_a = go === null || go === void 0 ? void 0 : go.emit) === null || _a === void 0 ? void 0 : _a.call(go, 'select', eventPayload);
2068
+ }
2069
+ catch (_) { }
2070
+ try {
2071
+ (_b = go === null || go === void 0 ? void 0 : go.emit) === null || _b === void 0 ? void 0 : _b.call(go, 'dialog:select', eventPayload);
2072
+ }
2073
+ catch (_) { }
2074
+ const mx = (typeof globalThis !== 'undefined' ? globalThis.mx : undefined);
2075
+ if ((_d = mx === null || mx === void 0 ? void 0 : mx.event) === null || _d === void 0 ? void 0 : _d.emit) {
2076
+ try {
2077
+ mx.event.emit('dialog:select', eventPayload);
2078
+ }
2079
+ catch (_) { }
2080
+ }
2081
+ }
2082
+ function makeDialogButtons(buttons) {
2083
+ if (!(buttons === null || buttons === void 0 ? void 0 : buttons.length))
2084
+ return undefined;
2085
+ return buttons.map((button) => {
2086
+ const options = makeDialogButtonOptions(button);
2087
+ const shouldMaterialize = button.disabled !== undefined
2088
+ || !!(button.nineSliceSprite && (button.width !== undefined || button.height !== undefined));
2089
+ if (button.kind === 'button' || !shouldMaterialize)
2090
+ return options;
2091
+ const pixiButton = new FancyButton$1(options);
2092
+ applyOptionalSize(pixiButton, button);
2093
+ pixiButton.enabled = !button.disabled;
2094
+ return pixiButton;
2095
+ });
2096
+ }
2097
+ function makeDialogButtonOptions(button) {
2098
+ var _a, _b, _d, _e, _f, _g, _h, _j, _k, _l;
2099
+ if (button.kind === 'button')
2100
+ return makeDialogBareButton(button);
2101
+ const width = (_a = button.width) !== null && _a !== void 0 ? _a : 110;
2102
+ const height = (_b = button.height) !== null && _b !== void 0 ? _b : 48;
2103
+ const radius = (_d = button.radius) !== null && _d !== void 0 ? _d : 12;
2104
+ const color = (_e = button.color) !== null && _e !== void 0 ? _e : pixiStoryDefaultButtonColor;
2105
+ return {
2106
+ text: makeDialogText(button.text, button.textStyle),
2107
+ defaultView: (_f = resolveDialogButtonView(button.defaultView)) !== null && _f !== void 0 ? _f : makeDialogButtonView(width, height, radius, color),
2108
+ hoverView: (_g = resolveDialogButtonView(button.hoverView)) !== null && _g !== void 0 ? _g : makeDialogButtonView(width, height, radius, (_h = button.hoverColor) !== null && _h !== void 0 ? _h : color),
2109
+ pressedView: (_j = resolveDialogButtonView(button.pressedView)) !== null && _j !== void 0 ? _j : makeDialogButtonView(width, height, radius, (_k = button.pressedColor) !== null && _k !== void 0 ? _k : color),
2110
+ disabledView: (_l = resolveDialogButtonView(button.disabledView)) !== null && _l !== void 0 ? _l : (button.disabledColor ? makeDialogButtonView(width, height, radius, button.disabledColor) : undefined),
2111
+ nineSliceSprite: button.nineSliceSprite,
2112
+ enabled: button.disabled === undefined ? undefined : !button.disabled,
2113
+ animations: button.animations,
2114
+ };
2115
+ }
2116
+ function resolveDialogButtonView(view) {
2117
+ return view ? getTextureView(view) : undefined;
2118
+ }
2119
+ const pixiStoryDefaultButtonColor = '#e91e63';
2120
+ const pixiStoryDefaultTextColor = '#ffffff';
2121
+ function makeDialogButtonView(width, height, radius, color) {
2122
+ return new Graphics$1()
2123
+ .roundRect(0, 0, width, height, radius)
2124
+ .fill(color);
2125
+ }
2126
+ function makeDialogBareButton(button) {
2127
+ var _a, _b, _d, _e, _f, _g;
2128
+ const width = (_a = button.width) !== null && _a !== void 0 ? _a : 110;
2129
+ const height = (_b = button.height) !== null && _b !== void 0 ? _b : 48;
2130
+ const radius = (_d = button.radius) !== null && _d !== void 0 ? _d : 12;
2131
+ const view = makeDialogButtonView(width, height, radius, (_e = button.color) !== null && _e !== void 0 ? _e : pixiStoryDefaultButtonColor);
2132
+ const label = makeDialogText(button.text, button.textStyle);
2133
+ if (label) {
2134
+ label.x = width / 2;
2135
+ label.y = height / 2;
2136
+ try {
2137
+ (_g = (_f = label.anchor) === null || _f === void 0 ? void 0 : _f.set) === null || _g === void 0 ? void 0 : _g.call(_f, 0.5);
2138
+ }
2139
+ catch (_) { }
2140
+ view.addChild(label);
2141
+ }
2142
+ const pixiButton = new Button$1(view);
2143
+ if (button.disabled !== undefined)
2144
+ pixiButton.enabled = !button.disabled;
2145
+ return pixiButton;
2146
+ }
2147
+ function makeDialogCheckBoxOptions(checkBox) {
2148
+ var _a, _b, _d, _e, _f, _g;
2149
+ const size = (_a = checkBox.size) !== null && _a !== void 0 ? _a : 30;
2150
+ const radius = (_b = checkBox.radius) !== null && _b !== void 0 ? _b : 5;
2151
+ const strokeColor = (_d = checkBox.strokeColor) !== null && _d !== void 0 ? _d : pixiStoryDefaultTextColor;
2152
+ const strokeWidth = (_e = checkBox.strokeWidth) !== null && _e !== void 0 ? _e : 2;
2153
+ return {
2154
+ style: {
2155
+ unchecked: new Graphics$1()
2156
+ .roundRect(0, 0, size, size, radius)
2157
+ .fill(((_f = checkBox.uncheckedColor) !== null && _f !== void 0 ? _f : '#3e3f40'))
2158
+ .stroke({ color: strokeColor, width: strokeWidth }),
2159
+ checked: new Graphics$1()
2160
+ .roundRect(0, 0, size, size, radius)
2161
+ .fill(((_g = checkBox.checkedColor) !== null && _g !== void 0 ? _g : pixiStoryDefaultButtonColor))
2162
+ .stroke({ color: strokeColor, width: strokeWidth }),
2163
+ text: checkBox.textStyle,
2164
+ },
2165
+ text: checkBox.text,
2166
+ checked: checkBox.checked,
2167
+ };
2168
+ }
1330
2169
  const MASKED_FRAME_DEF = {
1331
2170
  name: 'MaskedFrame',
1332
2171
  signalPrefix: 'maskedframe',
@@ -1335,12 +2174,14 @@ const MASKED_FRAME_DEF = {
1335
2174
  targetView: { kind: 'opaque' },
1336
2175
  maskView: { kind: 'opaque' },
1337
2176
  borderView: { kind: 'opaque' },
2177
+ borderWidth: { kind: 'scalar', default: 0, inspector: { name: 'borderWidth', type: 'number' } },
2178
+ borderColor: { kind: 'scalar', default: 0x000000, inspector: { name: 'borderColor', type: 'color' } },
1338
2179
  },
1339
2180
  optionsBuilder: (c) => ({
1340
- target: c.__resolved_targetView,
1341
- mask: c.__resolved_maskView,
1342
- borderWidth: 0,
1343
- borderColor: 0,
2181
+ target: c.__resolved_target_view,
2182
+ mask: c.__resolved_mask_view,
2183
+ borderWidth: c.borderWidth,
2184
+ borderColor: c.borderColor,
1344
2185
  }),
1345
2186
  };
1346
2187
  // ============================================================
@@ -1390,6 +2231,12 @@ class RadioGroup extends Component {
1390
2231
  constructor() {
1391
2232
  super(...arguments);
1392
2233
  this.componentName = 'RadioGroup';
2234
+ // 显式 `= undefined`:被 UISystem 的 `@componentObserver({ RadioGroup: ['selectedId', ...] })`
2235
+ // 观察;applyParams 里 `if (typeof p.selectedId === 'string')` 是条件赋值,
2236
+ // 默认 RadioGroup 无选中时 own property 不存在,observer.ts:236 会打
2237
+ // "prop selectedId not in component: RadioGroup, Can not observer" 并跳过
2238
+ // 响应式挂载,后续 `radioGroup.selectedId = 'xxx'` 也不会经 UISystem 同步子 CheckBox。
2239
+ this.selectedId = undefined;
1393
2240
  this.direction = 'vertical';
1394
2241
  this.elementsMargin = 4;
1395
2242
  /** runtime: 已绑定的子 CheckBox(System 填充) */
@@ -1537,13 +2384,16 @@ function safeProject(projector, args) {
1537
2384
  /**
1538
2385
  * UISystem - generic handler driven by COMPONENT_DEFINITIONS metadata.
1539
2386
  *
1540
- * 16 个 ECS 组件(UI 自渲染 + 14 个 @pixi/ui factory wrapper + RadioGroup 独立)由本 system 统一驱动。
2387
+ * 16 个 ECS 组件(Shape 自渲染 + 14 个 @pixi/ui factory wrapper + RadioGroup 独立)由本 system 统一驱动。
1541
2388
  * 不再为每个组件写独立 handler 方法 - 14 个 @pixi/ui 组件走 handleGeneric,RadioGroup 单独处理。
1542
2389
  */
1543
2390
  // observer schema:把 COMPONENT_DEFINITIONS.fields 转成 componentObserver decorator 参数
1544
2391
  function buildObserverSchema() {
1545
2392
  const out = {
2393
+ Transform: [{ prop: ['size'], deep: true }],
2394
+ Shape: [{ prop: ['shapes'], deep: true }],
1546
2395
  UI: [{ prop: ['shapes'], deep: true }],
2396
+ UIComponent: [{ prop: ['shapes'], deep: true }],
1547
2397
  RadioGroup: [
1548
2398
  { prop: ['selectedId'], deep: false },
1549
2399
  { prop: ['direction'], deep: false },
@@ -1560,6 +2410,9 @@ function buildObserverSchema() {
1560
2410
  }
1561
2411
  return out;
1562
2412
  }
2413
+ function isShapeComponentName(name) {
2414
+ return name === 'Shape' || name === 'UI' || name === 'UIComponent';
2415
+ }
1563
2416
  let UISystem = class UISystem extends System {
1564
2417
  constructor() {
1565
2418
  super(...arguments);
@@ -1567,6 +2420,7 @@ let UISystem = class UISystem extends System {
1567
2420
  /** componentName -> instance map(generic 共享一份) */
1568
2421
  this.instances = new Map();
1569
2422
  this.signalCleanups = new Map();
2423
+ this.transformSizeAuthorities = new Set();
1570
2424
  this.radioGroupInstances = new Map();
1571
2425
  }
1572
2426
  /** 给 RadioGroup 反查 PixiCheckBox 实例用 */
@@ -1590,8 +2444,10 @@ let UISystem = class UISystem extends System {
1590
2444
  }
1591
2445
  componentChanged(changed) {
1592
2446
  const name = changed.componentName;
1593
- if (name === 'UI')
1594
- return this.handleUI(changed);
2447
+ if (name === 'Transform')
2448
+ return this.handleTransformSizeChanged(changed);
2449
+ if (isShapeComponentName(name))
2450
+ return this.handleShape(changed);
1595
2451
  if (name === 'RadioGroup')
1596
2452
  return this.handleRadioGroup(changed);
1597
2453
  const def = COMPONENT_DEFINITIONS[name];
@@ -1599,13 +2455,13 @@ let UISystem = class UISystem extends System {
1599
2455
  return this.handleGeneric(def, changed);
1600
2456
  }
1601
2457
  // ============================================================
1602
- // UI(自渲染,无 @pixi/ui 实例)
2458
+ // Shape(自渲染,无 @pixi/ui 实例)
1603
2459
  // ============================================================
1604
- handleUI(changed) {
2460
+ handleShape(changed) {
1605
2461
  if (changed.type === OBSERVER_TYPE.ADD || changed.type === OBSERVER_TYPE.CHANGE) {
1606
- const ui = changed.component;
1607
- if (typeof ui.redraw === 'function')
1608
- ui.redraw();
2462
+ const shape = changed.component;
2463
+ if (typeof shape.redraw === 'function')
2464
+ shape.redraw();
1609
2465
  }
1610
2466
  }
1611
2467
  // ============================================================
@@ -1629,13 +2485,16 @@ let UISystem = class UISystem extends System {
1629
2485
  return;
1630
2486
  }
1631
2487
  (_a = def.syncOnChange) === null || _a === void 0 ? void 0 : _a.call(def, inst, c);
2488
+ if (this.transformSizeAuthorities.has(go.id)) {
2489
+ applyTransformSizeToInstance(def, inst, c, go, 'component-change');
2490
+ }
1632
2491
  }
1633
2492
  else if (changed.type === OBSERVER_TYPE.REMOVE) {
1634
2493
  this.detachGeneric(go.id, instMap, go);
1635
2494
  }
1636
2495
  }
1637
2496
  attachGeneric(def, c, go, instMap) {
1638
- var _a, _b, _c, _d, _f, _g, _h;
2497
+ var _a, _b, _c, _d, _f, _g, _h, _j, _k;
1639
2498
  if (instMap.has(go.id))
1640
2499
  return;
1641
2500
  const game = this.gameRef(go);
@@ -1652,25 +2511,39 @@ let UISystem = class UISystem extends System {
1652
2511
  if (def.name === 'List' || def.name === 'ScrollBox') {
1653
2512
  const childName = def.name === 'List' ? c.itemsChildName : c.contentChildName;
1654
2513
  c.__resolved_items = collectChildContainers(game, go, childName);
2514
+ const expectedCount = getCollectedChildCount(go, childName);
2515
+ if (expectedCount > 0 && c.__resolved_items.length < expectedCount && ((_a = c.__collect_retry) !== null && _a !== void 0 ? _a : 0) < 10) {
2516
+ c.__collect_retry = ((_b = c.__collect_retry) !== null && _b !== void 0 ? _b : 0) + 1;
2517
+ requestAnimationFrame(() => this.attachGeneric(def, c, go, instMap));
2518
+ return;
2519
+ }
1655
2520
  }
1656
2521
  // 4) 构造 PIXI 实例
2522
+ const restoreTransientSize = this.applyTransientTransformSize(c, go);
1657
2523
  const built = def.optionsBuilder(c, views !== null && views !== void 0 ? views : {});
1658
2524
  const inst = def.positional
1659
2525
  ? new def.pixiClass(...built)
1660
2526
  : new def.pixiClass(built);
1661
2527
  // 5) postCreate(enabled / selected tint 等)
1662
- (_a = def.postCreate) === null || _a === void 0 ? void 0 : _a.call(def, inst, c);
2528
+ (_c = def.postCreate) === null || _c === void 0 ? void 0 : _c.call(def, inst, c);
2529
+ // 5.5) 新 DSL 以 Transform.size 作为 plugin-ui 渲染尺寸来源。
2530
+ // 历史 DSL 若显式写了组件 width/height,初次 attach 保持旧行为;之后 Transform.size change 会接管。
2531
+ if (this.transformSizeAuthorities.has(go.id) || !hasExplicitRenderSize(c)) {
2532
+ const applied = applyTransformSizeToInstance(def, inst, c, go, 'initial-transform');
2533
+ if (applied)
2534
+ this.transformSizeAuthorities.add(go.id);
2535
+ }
1663
2536
  // 6) 注册 + attach
1664
2537
  instMap.set(go.id, inst);
1665
2538
  attachToGameObject(game, go, inst);
1666
2539
  // 7) onAttachedExtra(Dialog 挂 contentChild)
1667
2540
  if (def.name === 'Dialog') {
1668
- const contentChild = findChildEntity(go, (_b = c.contentChildName) !== null && _b !== void 0 ? _b : 'content');
2541
+ const contentChild = findChildEntity(go, (_d = c.contentChildName) !== null && _d !== void 0 ? _d : 'content');
1669
2542
  if (contentChild) {
1670
2543
  const cc = getEvaContainer(game, contentChild);
1671
2544
  if (cc) {
1672
2545
  try {
1673
- (_d = (_c = inst).addChild) === null || _d === void 0 ? void 0 : _d.call(_c, cc);
2546
+ (_g = (_f = inst).addChild) === null || _g === void 0 ? void 0 : _g.call(_f, cc);
1674
2547
  }
1675
2548
  catch (_) { }
1676
2549
  }
@@ -1681,7 +2554,7 @@ let UISystem = class UISystem extends System {
1681
2554
  const border = resolveViewRef(game, go, c.borderView);
1682
2555
  if (border) {
1683
2556
  try {
1684
- (_g = (_f = inst).addChild) === null || _g === void 0 ? void 0 : _g.call(_f, border);
2557
+ (_j = (_h = inst).addChild) === null || _j === void 0 ? void 0 : _j.call(_h, border);
1685
2558
  }
1686
2559
  catch (_) { }
1687
2560
  }
@@ -1691,7 +2564,8 @@ let UISystem = class UISystem extends System {
1691
2564
  const offs = bridgeSignals(inst, { go, prefix: def.signalPrefix }, def.signalMap(c));
1692
2565
  this.signalCleanups.set(go.id, offs);
1693
2566
  }
1694
- (_h = def.onAttachedExtra) === null || _h === void 0 ? void 0 : _h.call(def, inst, c, go, game);
2567
+ (_k = def.onAttachedExtra) === null || _k === void 0 ? void 0 : _k.call(def, inst, c, go, game);
2568
+ restoreTransientSize();
1695
2569
  }
1696
2570
  detachGeneric(id, instMap, go) {
1697
2571
  const inst = instMap.get(id);
@@ -1768,6 +2642,11 @@ let UISystem = class UISystem extends System {
1768
2642
  items, type: (_f = typeMap[c.direction]) !== null && _f !== void 0 ? _f : 'vertical',
1769
2643
  elementsMargin: c.elementsMargin, selectedItem: initialIndex,
1770
2644
  });
2645
+ if (this.transformSizeAuthorities.has(go.id)) {
2646
+ const size = readTransformRenderSize(go, { allowZero: true });
2647
+ if (size)
2648
+ applyRuntimeSize(inst, size);
2649
+ }
1771
2650
  this.radioGroupInstances.set(go.id, inst);
1772
2651
  attachToGameObject(game, go, inst);
1773
2652
  const offs = bridgeSignals(inst, { go, prefix: 'radiogroup' }, {
@@ -1803,6 +2682,74 @@ let UISystem = class UISystem extends System {
1803
2682
  }
1804
2683
  return null;
1805
2684
  }
2685
+ // ============================================================
2686
+ // Transform.size -> plugin-ui runtime size
2687
+ // ============================================================
2688
+ handleTransformSizeChanged(changed) {
2689
+ var _a, _b;
2690
+ if (changed.type !== OBSERVER_TYPE.CHANGE)
2691
+ return;
2692
+ const transform = changed.component;
2693
+ const go = (_a = changed.gameObject) !== null && _a !== void 0 ? _a : transform === null || transform === void 0 ? void 0 : transform.gameObject;
2694
+ if (!go)
2695
+ return;
2696
+ let applied = false;
2697
+ for (const [componentName, def] of Object.entries(COMPONENT_DEFINITIONS)) {
2698
+ const inst = (_b = this.instances.get(componentName)) === null || _b === void 0 ? void 0 : _b.get(go.id);
2699
+ if (!inst)
2700
+ continue;
2701
+ const component = getComponentSafe(go, componentName);
2702
+ if (applyTransformSizeToInstance(def, inst, component, go, 'transform-change')) {
2703
+ applied = true;
2704
+ }
2705
+ }
2706
+ const radioGroup = this.radioGroupInstances.get(go.id);
2707
+ if (radioGroup) {
2708
+ const size = readTransformRenderSize(go, { allowZero: true });
2709
+ if (size) {
2710
+ applyRuntimeSize(radioGroup, size);
2711
+ applied = true;
2712
+ }
2713
+ }
2714
+ if (applied)
2715
+ this.transformSizeAuthorities.add(go.id);
2716
+ this.relayoutLayoutInstances();
2717
+ }
2718
+ relayoutLayoutInstances() {
2719
+ for (const name of ['List', 'ScrollBox']) {
2720
+ const instMap = this.instances.get(name);
2721
+ if (!instMap)
2722
+ continue;
2723
+ for (const inst of instMap.values()) {
2724
+ relayoutRuntimeInstance(inst);
2725
+ }
2726
+ }
2727
+ }
2728
+ applyTransientTransformSize(c, go) {
2729
+ if (hasExplicitRenderSize(c))
2730
+ return () => { };
2731
+ const size = readTransformRenderSize(go);
2732
+ if (!size)
2733
+ return () => { };
2734
+ const hadWidth = Object.prototype.hasOwnProperty.call(c, 'width');
2735
+ const hadHeight = Object.prototype.hasOwnProperty.call(c, 'height');
2736
+ const prevWidth = c.width;
2737
+ const prevHeight = c.height;
2738
+ if (size.width !== undefined)
2739
+ c.width = size.width;
2740
+ if (size.height !== undefined)
2741
+ c.height = size.height;
2742
+ return () => {
2743
+ if (hadWidth)
2744
+ c.width = prevWidth;
2745
+ else
2746
+ delete c.width;
2747
+ if (hadHeight)
2748
+ c.height = prevHeight;
2749
+ else
2750
+ delete c.height;
2751
+ };
2752
+ }
1806
2753
  };
1807
2754
  UISystem.systemName = 'UISystem';
1808
2755
  UISystem = __decorate([
@@ -1823,10 +2770,16 @@ var UISystem$1 = UISystem;
1823
2770
  */
1824
2771
  function inlineResolveSpecialViews(name, c, game, go) {
1825
2772
  switch (name) {
1826
- case 'ProgressBar':
2773
+ case 'ProgressBar': {
2774
+ const fillView = c.nineSliceSprite
2775
+ ? c.fillView
2776
+ : normalizeProgressFillViewRef(c.fillView, c.fillPaddings, { width: c.width, height: c.height });
1827
2777
  c.__resolved_bg = resolveViewRef(game, go, c.bgView);
1828
- c.__resolved_fill = resolveViewRef(game, go, c.fillView);
2778
+ c.__resolved_fill = resolveViewRef(game, go, fillView);
2779
+ c.__resolved_bg_view = c.nineSliceSprite && c.bgView && 'texture' in c.bgView ? c.bgView.texture : c.__resolved_bg;
2780
+ c.__resolved_fill_view = c.nineSliceSprite && c.fillView && 'texture' in c.fillView ? c.fillView.texture : c.__resolved_fill;
1829
2781
  break;
2782
+ }
1830
2783
  case 'Select':
1831
2784
  c.__resolved_closedView = resolveViewRef(game, go, c.closedView);
1832
2785
  c.__resolved_openView = resolveViewRef(game, go, c.openView);
@@ -1834,10 +2787,15 @@ function inlineResolveSpecialViews(name, c, game, go) {
1834
2787
  case 'Dialog':
1835
2788
  c.__resolved_backdropView = resolveViewRef(game, go, c.backdropView);
1836
2789
  c.__resolved_backgroundView = resolveViewRef(game, go, c.backgroundView);
2790
+ c.__resolved_background_view = c.nineSliceSprite && c.backgroundView && 'texture' in c.backgroundView
2791
+ ? c.backgroundView.texture
2792
+ : c.__resolved_backgroundView;
1837
2793
  break;
1838
2794
  case 'MaskedFrame':
1839
2795
  c.__resolved_targetView = resolveViewRef(game, go, c.targetView);
1840
2796
  c.__resolved_maskView = resolveViewRef(game, go, c.maskView);
2797
+ c.__resolved_target_view = c.targetView && 'texture' in c.targetView ? c.targetView.texture : c.__resolved_targetView;
2798
+ c.__resolved_mask_view = c.maskView && 'texture' in c.maskView ? c.maskView.texture : c.__resolved_maskView;
1841
2799
  break;
1842
2800
  }
1843
2801
  }
@@ -1845,14 +2803,14 @@ function inlineResolveSpecialViews(name, c, game, go) {
1845
2803
  function validateInlineResolved(name, c) {
1846
2804
  switch (name) {
1847
2805
  case 'ProgressBar':
1848
- return !!(c.__resolved_bg && c.__resolved_fill);
2806
+ return !!(c.__resolved_bg_view && c.__resolved_fill_view);
1849
2807
  case 'Select':
1850
2808
  return !!(c.__resolved_closedView && c.__resolved_openView);
1851
2809
  case 'Dialog':
1852
2810
  // backgroundView 可 fallback PixiContainer,backdropView 也可 null
1853
2811
  return true;
1854
2812
  case 'MaskedFrame':
1855
- return !!(c.__resolved_targetView && c.__resolved_maskView);
2813
+ return !!(c.__resolved_target_view && c.__resolved_mask_view);
1856
2814
  default:
1857
2815
  return true;
1858
2816
  }
@@ -1870,15 +2828,47 @@ function collectChildContainers(game, go, childName) {
1870
2828
  continue;
1871
2829
  const childContainer = getEvaContainer(game, child);
1872
2830
  if (childContainer) {
2831
+ if (childContainer.width <= 0 || childContainer.height <= 0)
2832
+ continue;
1873
2833
  try {
1874
2834
  (_c = (_b = childContainer.parent) === null || _b === void 0 ? void 0 : _b.removeChild) === null || _c === void 0 ? void 0 : _c.call(_b, childContainer);
1875
2835
  }
1876
2836
  catch (_) { }
1877
- result.push(childContainer);
2837
+ result.push(wrapLayoutItem(childContainer, child));
1878
2838
  }
1879
2839
  }
1880
2840
  return result;
1881
2841
  }
2842
+ function wrapLayoutItem(childContainer, child) {
2843
+ const wrapper = new Container();
2844
+ const childName = child === null || child === void 0 ? void 0 : child.name;
2845
+ wrapper.label = childName ? `${childName}:layout-item` : 'plugin-ui-layout-item';
2846
+ wrapper.addChild(childContainer);
2847
+ Object.defineProperty(wrapper, 'width', {
2848
+ get: () => resolveLayoutItemSize(child, childContainer, 'width'),
2849
+ set: () => { },
2850
+ configurable: true,
2851
+ });
2852
+ Object.defineProperty(wrapper, 'height', {
2853
+ get: () => resolveLayoutItemSize(child, childContainer, 'height'),
2854
+ set: () => { },
2855
+ configurable: true,
2856
+ });
2857
+ return wrapper;
2858
+ }
2859
+ function resolveLayoutItemSize(child, childContainer, key) {
2860
+ var _a, _b;
2861
+ const transformSize = Number((_b = (_a = child === null || child === void 0 ? void 0 : child.transform) === null || _a === void 0 ? void 0 : _a.size) === null || _b === void 0 ? void 0 : _b[key]);
2862
+ if (Number.isFinite(transformSize) && transformSize > 0)
2863
+ return transformSize;
2864
+ const containerSize = Number(childContainer === null || childContainer === void 0 ? void 0 : childContainer[key]);
2865
+ return Number.isFinite(containerSize) ? containerSize : 0;
2866
+ }
2867
+ function getCollectedChildCount(go, childName) {
2868
+ var _a, _b, _c;
2869
+ const contentChild = findChildEntity(go, childName);
2870
+ return (_c = (_b = (_a = contentChild === null || contentChild === void 0 ? void 0 : contentChild.transform) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
2871
+ }
1882
2872
  function findChildEntity(go, name) {
1883
2873
  var _a, _b;
1884
2874
  if (!go)
@@ -1897,6 +2887,15 @@ function findChildEntity(go, name) {
1897
2887
  return tf.gameObject;
1898
2888
  }
1899
2889
  return null;
2890
+ }
2891
+ function getComponentSafe(go, componentName) {
2892
+ var _a;
2893
+ try {
2894
+ return (_a = go === null || go === void 0 ? void 0 : go.getComponent) === null || _a === void 0 ? void 0 : _a.call(go, componentName);
2895
+ }
2896
+ catch (_) {
2897
+ return undefined;
2898
+ }
1900
2899
  }
1901
2900
 
1902
- export { Button, COMPONENT_DEFINITIONS, CheckBox, CircularProgressBar, Dialog, DoubleSlider, FancyButton, Input, List, MaskedFrame, PixiUiComponent, UISystem$1 as PluginUiSystem, ProgressBar, RadioGroup, ScrollBox, Select, Slider, Switcher, UI, UIShapeType, UISystem$1 as UISystem, defineUiComponent };
2901
+ export { Button, COMPONENT_DEFINITIONS, CheckBox, CircularProgressBar, Dialog, DoubleSlider, FancyButton, Input, List, MaskedFrame, PixiUiComponent, UISystem$1 as PluginUiSystem, ProgressBar, RadioGroup, ScrollBox, Select, Shape, ShapeType, Slider, Switcher, Shape as UI, UIShapeType, UISystem$1 as UISystem, defineUiComponent };