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

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,15 @@ function resolveViewRef(game, go, ref) {
502
508
  }
503
509
  return null;
504
510
  }
511
+ function wrapBorrowedEntityView(childContainer, childName) {
512
+ const wrapper = new Container();
513
+ wrapper.label = childName ? `${childName}:view-ref` : 'plugin-ui-view-ref';
514
+ wrapper.addChild(childContainer);
515
+ return wrapper;
516
+ }
505
517
  /** 把 ViewRef 解析为已存在的 Texture(用于 ProgressBar/Slider/Input 的 nineSlice 路径) */
506
518
  function resolveTexture(game, key) {
507
- var _a, _b;
519
+ var _a, _b, _c;
508
520
  // 1) Eva resource pool
509
521
  const resourceModule = (_a = game === null || game === void 0 ? void 0 : game.resource) !== null && _a !== void 0 ? _a : null;
510
522
  if ((_b = resourceModule === null || resourceModule === void 0 ? void 0 : resourceModule.instances) === null || _b === void 0 ? void 0 : _b[key]) {
@@ -516,7 +528,7 @@ function resolveTexture(game, key) {
516
528
  }
517
529
  // 2) global asset cache (Texture.from)
518
530
  try {
519
- return Texture.from(key);
531
+ return (_c = Texture.from(key)) !== null && _c !== void 0 ? _c : null;
520
532
  }
521
533
  catch (_) {
522
534
  return null;
@@ -548,11 +560,20 @@ function drawInlineShape(shape) {
548
560
  if (style.fill !== undefined)
549
561
  g.fill(style.fill);
550
562
  if (style.stroke !== undefined && style.lineWidth !== undefined) {
551
- g.setStrokeStyle({ color: style.stroke, width: style.lineWidth });
552
- g.stroke();
563
+ g.stroke({ color: style.stroke, width: style.lineWidth });
564
+ }
565
+ else if (style.stroke !== undefined) {
566
+ g.stroke({ color: style.stroke, width: 1 });
553
567
  }
554
568
  if (style.alpha !== undefined)
555
569
  g.alpha = style.alpha;
570
+ try {
571
+ Object.defineProperty(g, 'clone', {
572
+ value: () => { var _a; return (_a = drawInlineShape(shape)) !== null && _a !== void 0 ? _a : new Graphics$1(); },
573
+ configurable: true,
574
+ });
575
+ }
576
+ catch (_) { }
556
577
  return g;
557
578
  }
558
579
  /**
@@ -605,12 +626,20 @@ class PixiUiComponent extends Component {
605
626
  /** runtime 计数,供 spec / debug 验证(toggleCount / pressCount / hoverCount / ...)*/
606
627
  this.toggleCount = 0;
607
628
  this.pressCount = 0;
629
+ this.downCount = 0;
630
+ this.upCount = 0;
608
631
  this.hoverCount = 0;
632
+ this.outCount = 0;
633
+ this.upOutCount = 0;
609
634
  this.changeCount = 0;
610
635
  this.updateCount = 0;
611
636
  this.selectCount = 0;
637
+ this.lastSignal = 'idle';
638
+ this.visualState = 'default';
612
639
  /** Input 私有 focused */
613
640
  this.focused = false;
641
+ /** DSL/constructor 中显式传入过的字段,用于区分 metadata default 与用户配置。 */
642
+ this.__evaExplicitFields = new Set();
614
643
  }
615
644
  init(p) {
616
645
  if (p)
@@ -630,6 +659,7 @@ class PixiUiComponent extends Component {
630
659
  const v = p[name];
631
660
  if (v === undefined)
632
661
  continue;
662
+ this.__evaExplicitFields.add(name);
633
663
  switch (spec.kind) {
634
664
  case 'scalar':
635
665
  this[name] = v;
@@ -750,6 +780,114 @@ function resolveViewsBySchema(game, go, component, schema) {
750
780
  }
751
781
  }
752
782
 
783
+ function readTransformRenderSize(go, options = {}) {
784
+ var _a;
785
+ const size = (_a = go === null || go === void 0 ? void 0 : go.transform) === null || _a === void 0 ? void 0 : _a.size;
786
+ if (!size)
787
+ return null;
788
+ const width = normalizeSizeValue(size.width, options.allowZero);
789
+ const height = normalizeSizeValue(size.height, options.allowZero);
790
+ if (width === undefined && height === undefined)
791
+ return null;
792
+ return { width, height };
793
+ }
794
+ function hasExplicitRenderSize(component) {
795
+ if (!component)
796
+ return false;
797
+ const explicitFields = component.__evaExplicitFields;
798
+ if (explicitFields && typeof explicitFields.has === 'function') {
799
+ return explicitFields.has('width') || explicitFields.has('height');
800
+ }
801
+ return component.width !== undefined || component.height !== undefined;
802
+ }
803
+ function applyTransformSizeToInstance(def, instance, component, go, source) {
804
+ const size = readTransformRenderSize(go, { allowZero: source === 'transform-change' });
805
+ if (!size)
806
+ return false;
807
+ const context = {
808
+ componentName: def.name,
809
+ component,
810
+ gameObject: go,
811
+ source,
812
+ };
813
+ if (def.applySize)
814
+ def.applySize(instance, size, component !== null && component !== void 0 ? component : {}, context);
815
+ else
816
+ applyRuntimeSize(instance, size);
817
+ return true;
818
+ }
819
+ function applyRuntimeSize(instance, size) {
820
+ if (!instance || !size)
821
+ return;
822
+ const width = normalizeSizeValue(size.width, true);
823
+ const height = normalizeSizeValue(size.height, true);
824
+ if (width === undefined && height === undefined)
825
+ return;
826
+ const nextWidth = width !== null && width !== void 0 ? width : getCurrentSize(instance, 'width');
827
+ const nextHeight = height !== null && height !== void 0 ? height : getCurrentSize(instance, 'height');
828
+ let applied = false;
829
+ if (typeof instance.setSize === 'function' && nextWidth !== undefined && nextHeight !== undefined) {
830
+ try {
831
+ instance.setSize(nextWidth, nextHeight);
832
+ applied = true;
833
+ }
834
+ catch (_) {
835
+ applied = false;
836
+ }
837
+ }
838
+ if (!applied) {
839
+ if (width !== undefined)
840
+ instance.width = width;
841
+ if (height !== undefined)
842
+ instance.height = height;
843
+ }
844
+ relayoutRuntimeInstance(instance);
845
+ }
846
+ function applyListLayoutSize(instance, size) {
847
+ const width = normalizeSizeValue(size.width, true);
848
+ const height = normalizeSizeValue(size.height, true);
849
+ if (width !== undefined) {
850
+ try {
851
+ instance.maxWidth = width;
852
+ }
853
+ catch (_) { }
854
+ }
855
+ if (height !== undefined) {
856
+ try {
857
+ instance.maxHeight = height;
858
+ }
859
+ catch (_) { }
860
+ }
861
+ relayoutRuntimeInstance(instance);
862
+ }
863
+ function relayoutRuntimeInstance(instance) {
864
+ var _a, _b, _c, _d;
865
+ try {
866
+ (_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);
867
+ }
868
+ catch (_) { }
869
+ try {
870
+ (_c = instance === null || instance === void 0 ? void 0 : instance.arrangeChildren) === null || _c === void 0 ? void 0 : _c.call(instance);
871
+ }
872
+ catch (_) { }
873
+ try {
874
+ (_d = instance === null || instance === void 0 ? void 0 : instance.resize) === null || _d === void 0 ? void 0 : _d.call(instance, true);
875
+ }
876
+ catch (_) { }
877
+ }
878
+ function normalizeSizeValue(value, allowZero = false) {
879
+ const n = Number(value);
880
+ if (!Number.isFinite(n))
881
+ return undefined;
882
+ if (allowZero ? n < 0 : n <= 0)
883
+ return undefined;
884
+ return n;
885
+ }
886
+ function getCurrentSize(instance, key) {
887
+ const n = Number(instance === null || instance === void 0 ? void 0 : instance[key]);
888
+ return Number.isFinite(n) && n >= 0 ? n : undefined;
889
+ }
890
+
753
891
  /**
754
892
  * @pixi/ui v2.x 包装层 — 14 个 ECS Component 由 metadata 驱动生成。
755
893
  *
@@ -797,8 +935,42 @@ const BUTTON_DEF = {
797
935
  optionsBuilder: (_c, v) => [v.single],
798
936
  postCreate: (inst, c) => { inst.enabled = c.enabled; },
799
937
  signalMap: (c) => ({
800
- press: () => { c.pressCount += 1; return {}; },
801
- down: true, up: true, hover: true,
938
+ press: () => {
939
+ c.pressCount += 1;
940
+ c.lastSignal = 'press';
941
+ c.visualState = 'default';
942
+ return { pressCount: c.pressCount, lastSignal: c.lastSignal, visualState: c.visualState };
943
+ },
944
+ down: () => {
945
+ c.downCount += 1;
946
+ c.lastSignal = 'down';
947
+ c.visualState = 'pressed';
948
+ return { downCount: c.downCount, lastSignal: c.lastSignal, visualState: c.visualState };
949
+ },
950
+ up: () => {
951
+ c.upCount += 1;
952
+ c.lastSignal = 'up';
953
+ c.visualState = 'default';
954
+ return { upCount: c.upCount, lastSignal: c.lastSignal, visualState: c.visualState };
955
+ },
956
+ hover: () => {
957
+ c.hoverCount += 1;
958
+ c.lastSignal = 'hover';
959
+ c.visualState = 'hover';
960
+ return { hoverCount: c.hoverCount, lastSignal: c.lastSignal, visualState: c.visualState };
961
+ },
962
+ out: () => {
963
+ c.outCount += 1;
964
+ c.lastSignal = 'out';
965
+ c.visualState = 'default';
966
+ return { outCount: c.outCount, lastSignal: c.lastSignal, visualState: c.visualState };
967
+ },
968
+ upOut: () => {
969
+ c.upOutCount += 1;
970
+ c.lastSignal = 'upOut';
971
+ c.visualState = 'default';
972
+ return { upOutCount: c.upOutCount, lastSignal: c.lastSignal, visualState: c.visualState };
973
+ },
802
974
  }),
803
975
  syncOnChange: (inst, c) => { inst.enabled = c.enabled; },
804
976
  };
@@ -816,10 +988,28 @@ const FANCY_BUTTON_DEF = {
816
988
  views: { kind: 'shallowMerge', default: {}, inspector: { name: 'views', type: 'object', isFolder: true, children: [
817
989
  { name: 'default', type: 'object' }, { name: 'hover', type: 'object' },
818
990
  { name: 'pressed', type: 'object' }, { name: 'disabled', type: 'object' },
991
+ { name: 'icon', type: 'object' },
819
992
  ] } },
820
993
  offset: { kind: 'shallowMerge', default: {} },
821
994
  textOffset: { kind: 'shallowMerge', default: {} },
995
+ iconOffset: { kind: 'shallowMerge', default: {} },
822
996
  nineSliceSprite: { kind: 'opaque' },
997
+ textStyle: { kind: 'shallowMerge', default: {} },
998
+ textClass: { kind: 'scalar', default: 'text' },
999
+ bitmapFontName: { kind: 'scalar', default: 'TitleFont' },
1000
+ defaultTextScale: { kind: 'opaque' },
1001
+ defaultIconScale: { kind: 'opaque' },
1002
+ defaultTextAnchor: { kind: 'opaque' },
1003
+ defaultIconAnchor: { kind: 'opaque' },
1004
+ anchor: { kind: 'scalar' },
1005
+ anchorX: { kind: 'scalar' },
1006
+ anchorY: { kind: 'scalar' },
1007
+ scale: { kind: 'scalar' },
1008
+ animations: { kind: 'opaque' },
1009
+ contentFittingMode: { kind: 'scalar' },
1010
+ ignoreRefitting: { kind: 'scalar' },
1011
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1012
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
823
1013
  },
824
1014
  views: {
825
1015
  kind: 'object', folder: 'views',
@@ -828,28 +1018,43 @@ const FANCY_BUTTON_DEF = {
828
1018
  { name: 'hover', required: false },
829
1019
  { name: 'pressed', required: false },
830
1020
  { name: 'disabled', required: false },
1021
+ { name: 'icon', required: false },
831
1022
  ],
832
1023
  },
833
1024
  optionsBuilder: (c, v) => {
834
- var _a, _b, _d, _e;
1025
+ var _a, _b, _d, _e, _f;
835
1026
  // FancyButton 内部 updateView 不接受 null;只把已 resolve 的 view 字段传过去
836
1027
  const opts = {
837
- text: c.text, padding: c.padding,
838
- offset: c.offset, textOffset: c.textOffset,
1028
+ text: makeFancyButtonText(c), padding: c.padding,
1029
+ offset: c.offset, textOffset: c.textOffset, iconOffset: c.iconOffset,
839
1030
  nineSliceSprite: c.nineSliceSprite,
1031
+ defaultTextScale: c.defaultTextScale,
1032
+ defaultIconScale: c.defaultIconScale,
1033
+ defaultTextAnchor: c.defaultTextAnchor,
1034
+ defaultIconAnchor: c.defaultIconAnchor,
1035
+ anchor: c.anchor, anchorX: c.anchorX, anchorY: c.anchorY,
1036
+ scale: c.scale, animations: c.animations,
1037
+ contentFittingMode: c.contentFittingMode,
1038
+ ignoreRefitting: c.ignoreRefitting,
840
1039
  };
841
1040
  if ((_a = v.object) === null || _a === void 0 ? void 0 : _a.default)
842
- opts.defaultView = v.object.default;
1041
+ opts.defaultView = getFancyButtonView(c, 'default', v.object.default);
843
1042
  if ((_b = v.object) === null || _b === void 0 ? void 0 : _b.hover)
844
- opts.hoverView = v.object.hover;
1043
+ opts.hoverView = getFancyButtonView(c, 'hover', v.object.hover);
845
1044
  if ((_d = v.object) === null || _d === void 0 ? void 0 : _d.pressed)
846
- opts.pressedView = v.object.pressed;
1045
+ opts.pressedView = getFancyButtonView(c, 'pressed', v.object.pressed);
847
1046
  if ((_e = v.object) === null || _e === void 0 ? void 0 : _e.disabled)
848
- opts.disabledView = v.object.disabled;
1047
+ opts.disabledView = getFancyButtonView(c, 'disabled', v.object.disabled);
1048
+ if ((_f = v.object) === null || _f === void 0 ? void 0 : _f.icon)
1049
+ opts.icon = v.object.icon;
849
1050
  return opts;
850
1051
  },
851
1052
  postCreate: (inst, c) => {
852
1053
  inst.enabled = c.enabled;
1054
+ if (c.state && typeof inst.setState === 'function')
1055
+ inst.setState(c.state, true);
1056
+ applyFancyButtonAnchor(inst, c);
1057
+ applyOptionalSize(inst, c);
853
1058
  if (c.selected)
854
1059
  applySelectedTint(inst, c);
855
1060
  },
@@ -864,9 +1069,84 @@ const FANCY_BUTTON_DEF = {
864
1069
  inst.text = c.text;
865
1070
  if (c.padding !== undefined && inst.padding !== c.padding)
866
1071
  inst.padding = c.padding;
1072
+ if (c.textOffset !== undefined)
1073
+ inst.textOffset = c.textOffset;
1074
+ if (c.iconOffset !== undefined)
1075
+ inst.iconOffset = c.iconOffset;
1076
+ if (c.defaultTextScale !== undefined)
1077
+ inst.defaultTextScale = c.defaultTextScale;
1078
+ if (c.defaultIconScale !== undefined)
1079
+ inst.defaultIconScale = c.defaultIconScale;
1080
+ if (c.defaultTextAnchor !== undefined)
1081
+ inst.defaultTextAnchor = c.defaultTextAnchor;
1082
+ if (c.defaultIconAnchor !== undefined)
1083
+ inst.defaultIconAnchor = c.defaultIconAnchor;
1084
+ if (c.contentFittingMode !== undefined)
1085
+ inst.contentFittingMode = c.contentFittingMode;
1086
+ if (c.ignoreRefitting !== undefined && inst.options)
1087
+ inst.options.ignoreRefitting = c.ignoreRefitting;
1088
+ if (c.state && typeof inst.setState === 'function')
1089
+ inst.setState(c.state, true);
1090
+ applyFancyButtonAnchor(inst, c);
1091
+ applyOptionalSize(inst, c);
867
1092
  applySelectedTint(inst, c);
868
1093
  },
869
1094
  };
1095
+ function applyFancyButtonAnchor(inst, c) {
1096
+ var _a, _b, _d, _e, _f, _g, _h;
1097
+ const hasAnchor = c.anchor !== undefined || c.anchorX !== undefined || c.anchorY !== undefined;
1098
+ if (!hasAnchor || !((_a = inst === null || inst === void 0 ? void 0 : inst.anchor) === null || _a === void 0 ? void 0 : _a.set))
1099
+ return;
1100
+ 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;
1101
+ 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;
1102
+ try {
1103
+ inst.anchor.set(x, y);
1104
+ }
1105
+ catch (_) { }
1106
+ }
1107
+ function makeFancyButtonText(c) {
1108
+ var _a, _b, _d;
1109
+ if (c.text === undefined)
1110
+ return undefined;
1111
+ const text = String(c.text);
1112
+ if (c.textClass === 'html') {
1113
+ return new HTMLText({ text, style: c.textStyle });
1114
+ }
1115
+ if (c.textClass === 'bitmap') {
1116
+ const fontFamily = (_a = c.bitmapFontName) !== null && _a !== void 0 ? _a : 'TitleFont';
1117
+ ensureBitmapFont(fontFamily, c.textStyle);
1118
+ return new BitmapText({
1119
+ text,
1120
+ style: {
1121
+ fontFamily,
1122
+ fontSize: (_d = (_b = c.textStyle) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _d !== void 0 ? _d : 40,
1123
+ },
1124
+ });
1125
+ }
1126
+ if (c.textStyle && Object.keys(c.textStyle).length > 0) {
1127
+ return new Text({ text, style: c.textStyle });
1128
+ }
1129
+ return c.text;
1130
+ }
1131
+ const installedBitmapFonts = new Set();
1132
+ function ensureBitmapFont(name, style) {
1133
+ if (installedBitmapFonts.has(name))
1134
+ return;
1135
+ try {
1136
+ BitmapFontManager.install({ name, style: (style !== null && style !== void 0 ? style : {}) });
1137
+ }
1138
+ catch (_) {
1139
+ // Reinstalling an existing font can throw in Pixi; rendering can still use the current font.
1140
+ }
1141
+ installedBitmapFonts.add(name);
1142
+ }
1143
+ function getFancyButtonView(c, key, resolved) {
1144
+ var _a;
1145
+ const ref = (_a = c.views) === null || _a === void 0 ? void 0 : _a[key];
1146
+ if (c.nineSliceSprite && ref && 'texture' in ref)
1147
+ return getTextureView(ref.texture);
1148
+ return resolved;
1149
+ }
870
1150
  function applySelectedTint(inst, c) {
871
1151
  try {
872
1152
  const dv = inst.defaultView;
@@ -875,6 +1155,22 @@ function applySelectedTint(inst, c) {
875
1155
  }
876
1156
  catch (_) { }
877
1157
  }
1158
+ function syncCheckBoxTextStyle(inst, c) {
1159
+ var _a, _b, _d;
1160
+ const style = inst.style;
1161
+ if (!style || (!c.textStyle && !c.textOffset))
1162
+ return;
1163
+ 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 });
1164
+ // @pixi/ui CheckBox.style rebuilds checked/unchecked views. If RadioGroup is
1165
+ // listening, that rebuild can emit onChange while only one view exists.
1166
+ inst._style = nextStyle;
1167
+ if (inst.labelText && c.textStyle)
1168
+ inst.labelText.style = c.textStyle;
1169
+ try {
1170
+ (_d = inst.alignText) === null || _d === void 0 ? void 0 : _d.call(inst);
1171
+ }
1172
+ catch (_) { }
1173
+ }
878
1174
  const CHECKBOX_DEF = {
879
1175
  name: 'CheckBox',
880
1176
  signalPrefix: 'checkbox',
@@ -887,6 +1183,8 @@ const CHECKBOX_DEF = {
887
1183
  views: { kind: 'shallowMerge', default: {}, inspector: { name: 'views', type: 'object', isFolder: true, children: [
888
1184
  { name: 'checked', type: 'object' }, { name: 'unchecked', type: 'object' },
889
1185
  ] } },
1186
+ textStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1187
+ textOffset: { kind: 'shallowMerge', default: {} },
890
1188
  disabledStyle: { kind: 'shallowMerge', default: { alpha: 0.4, scale: 1 } },
891
1189
  },
892
1190
  views: {
@@ -897,7 +1195,7 @@ const CHECKBOX_DEF = {
897
1195
  ],
898
1196
  },
899
1197
  optionsBuilder: (c, v) => ({
900
- style: { checked: v.object.checked, unchecked: v.object.unchecked },
1198
+ style: { checked: v.object.checked, unchecked: v.object.unchecked, text: c.textStyle, textOffset: c.textOffset },
901
1199
  text: c.text, checked: c.checked,
902
1200
  }),
903
1201
  signalMap: (c) => ({
@@ -906,6 +1204,9 @@ const CHECKBOX_DEF = {
906
1204
  syncOnChange: (inst, c) => {
907
1205
  if (inst.checked !== c.checked)
908
1206
  inst.checked = c.checked;
1207
+ if (c.text !== undefined && inst.text !== c.text)
1208
+ inst.text = c.text;
1209
+ syncCheckBoxTextStyle(inst, c);
909
1210
  },
910
1211
  };
911
1212
  const SWITCHER_DEF = {
@@ -932,6 +1233,8 @@ const SWITCHER_DEF = {
932
1233
  syncOnChange: (inst, c) => {
933
1234
  if (inst.active !== c.active)
934
1235
  inst.active = c.active;
1236
+ if (c.triggerEvent !== undefined)
1237
+ inst.triggerEvents = c.triggerEvent;
935
1238
  },
936
1239
  };
937
1240
  const SLIDER_DEF = {
@@ -947,6 +1250,12 @@ const SLIDER_DEF = {
947
1250
  orientation: { kind: 'scalar', default: 'horizontal', inspector: { name: 'orientation', type: 'string' } },
948
1251
  showValue: { kind: 'scalar', default: false, inspector: { name: 'showValue', type: 'boolean' } },
949
1252
  views: { kind: 'shallowMerge', default: {} },
1253
+ nineSliceSprite: { kind: 'opaque' },
1254
+ fillPaddings: { kind: 'shallowMerge', default: {} },
1255
+ valueTextStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1256
+ valueTextOffset: { kind: 'shallowMerge', default: {} },
1257
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1258
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
950
1259
  bindToStore: BIND_STORE,
951
1260
  },
952
1261
  views: {
@@ -958,12 +1267,20 @@ const SLIDER_DEF = {
958
1267
  ],
959
1268
  },
960
1269
  optionsBuilder: (c, v) => {
961
- centerThumbPivot(v.object.thumb);
1270
+ var _a, _b, _d;
1271
+ const bg = getSliderView((_a = c.views) === null || _a === void 0 ? void 0 : _a.bg, v.object.bg);
1272
+ const fill = getSliderView((_b = c.views) === null || _b === void 0 ? void 0 : _b.fill, v.object.fill);
1273
+ const thumb = getSliderView((_d = c.views) === null || _d === void 0 ? void 0 : _d.thumb, v.object.thumb);
962
1274
  return {
963
- bg: v.object.bg, fill: v.object.fill, slider: v.object.thumb,
1275
+ bg, fill, slider: thumb,
964
1276
  min: c.min, max: c.max, step: c.step, value: c.value, showValue: c.showValue,
1277
+ fillPaddings: c.fillPaddings,
1278
+ nineSliceSprite: c.nineSliceSprite,
1279
+ valueTextStyle: c.valueTextStyle,
1280
+ valueTextOffset: c.valueTextOffset,
965
1281
  };
966
1282
  },
1283
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
967
1284
  signalMap: (c) => ({
968
1285
  update: (vv) => { c.value = vv; c.updateCount += 1; return { value: vv }; },
969
1286
  change: (vv) => { c.value = vv; c.changeCount += 1; return { value: vv }; },
@@ -971,37 +1288,9 @@ const SLIDER_DEF = {
971
1288
  syncOnChange: (inst, c) => {
972
1289
  if (inst.value !== c.value)
973
1290
  inst.value = c.value;
1291
+ applyOptionalSize(inst, c);
974
1292
  },
975
1293
  };
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
1294
  const DOUBLE_SLIDER_DEF = {
1006
1295
  name: 'DoubleSlider',
1007
1296
  signalPrefix: 'doubleslider',
@@ -1015,6 +1304,12 @@ const DOUBLE_SLIDER_DEF = {
1015
1304
  step: { kind: 'scalar', default: 1 },
1016
1305
  showValue: { kind: 'scalar', default: false, inspector: { name: 'showValue', type: 'boolean' } },
1017
1306
  views: { kind: 'shallowMerge', default: {} },
1307
+ nineSliceSprite: { kind: 'opaque' },
1308
+ fillPaddings: { kind: 'shallowMerge', default: {} },
1309
+ valueTextStyle: { kind: 'shallowMerge', default: { fill: 0xffffff } },
1310
+ valueTextOffset: { kind: 'shallowMerge', default: {} },
1311
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1312
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1018
1313
  bindToStore1: { kind: 'scalar' },
1019
1314
  bindToStore2: { kind: 'scalar' },
1020
1315
  },
@@ -1026,14 +1321,22 @@ const DOUBLE_SLIDER_DEF = {
1026
1321
  ],
1027
1322
  },
1028
1323
  optionsBuilder: (c, v) => {
1029
- centerThumbPivot(v.object.slider1);
1030
- centerThumbPivot(v.object.slider2);
1324
+ var _a, _b, _d, _e;
1325
+ const bg = getSliderView((_a = c.views) === null || _a === void 0 ? void 0 : _a.bg, v.object.bg);
1326
+ const fill = getSliderView((_b = c.views) === null || _b === void 0 ? void 0 : _b.fill, v.object.fill);
1327
+ const slider1 = getSliderView((_d = c.views) === null || _d === void 0 ? void 0 : _d.slider1, v.object.slider1);
1328
+ const slider2 = getSliderView((_e = c.views) === null || _e === void 0 ? void 0 : _e.slider2, v.object.slider2);
1031
1329
  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,
1330
+ bg, fill,
1331
+ slider1, slider2,
1332
+ min: c.min, max: c.max, step: c.step, value1: c.value1, value2: c.value2, showValue: c.showValue,
1333
+ fillPaddings: c.fillPaddings,
1334
+ nineSliceSprite: c.nineSliceSprite,
1335
+ valueTextStyle: c.valueTextStyle,
1336
+ valueTextOffset: c.valueTextOffset,
1035
1337
  };
1036
1338
  },
1339
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
1037
1340
  signalMap: (c) => ({
1038
1341
  update: (v1, v2) => { c.value1 = v1; c.value2 = v2; c.updateCount += 1; return { value1: v1, value2: v2 }; },
1039
1342
  change: (v1, v2) => { c.value1 = v1; c.value2 = v2; c.changeCount += 1; return { value1: v1, value2: v2 }; },
@@ -1043,6 +1346,7 @@ const DOUBLE_SLIDER_DEF = {
1043
1346
  inst.value1 = c.value1;
1044
1347
  if (inst.value2 !== c.value2)
1045
1348
  inst.value2 = c.value2;
1349
+ applyOptionalSize(inst, c);
1046
1350
  },
1047
1351
  };
1048
1352
  const PROGRESS_BAR_DEF = {
@@ -1056,6 +1360,8 @@ const PROGRESS_BAR_DEF = {
1056
1360
  fillView: { kind: 'opaque' },
1057
1361
  nineSliceSprite: { kind: 'opaque' },
1058
1362
  fillPaddings: { kind: 'shallowMerge', default: {} },
1363
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1364
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1059
1365
  bindToStore: BIND_STORE,
1060
1366
  },
1061
1367
  views: {
@@ -1066,17 +1372,54 @@ const PROGRESS_BAR_DEF = {
1066
1372
  // 这里用 inline resolution(在 system.ts handleGeneric 里有 fast path 处理 views=undefined 的情形,
1067
1373
  // optionsBuilder 接受 raw component 自己 resolve)
1068
1374
  optionsBuilder: (c, _v) => ({
1069
- bg: c.__resolved_bg, fill: c.__resolved_fill,
1375
+ bg: c.__resolved_bg_view, fill: c.__resolved_fill_view,
1070
1376
  fillPaddings: c.fillPaddings,
1377
+ nineSliceSprite: c.nineSliceSprite,
1071
1378
  progress: computeProgressPct(c),
1072
1379
  }),
1380
+ postCreate: (inst, c) => applyOptionalSize(inst, c),
1073
1381
  syncOnChange: (inst, c) => {
1074
1382
  const pct = computeProgressPct(c);
1075
1383
  if (inst.progress !== pct)
1076
1384
  inst.progress = pct;
1385
+ applyOptionalSize(inst, c);
1077
1386
  },
1078
1387
  mixin: { getProgressPct: getProgressPctMixin },
1079
1388
  };
1389
+ function getSliderView(ref, resolved) {
1390
+ if (ref && 'texture' in ref) {
1391
+ return getTextureView(ref.texture);
1392
+ }
1393
+ return resolved;
1394
+ }
1395
+ function getProgressView(ref, resolved, nineSliceSprite) {
1396
+ if (nineSliceSprite && ref && 'texture' in ref) {
1397
+ return getTextureView(ref.texture);
1398
+ }
1399
+ return resolved;
1400
+ }
1401
+ function getTextureView(textureKey) {
1402
+ var _a;
1403
+ return (_a = resolveTexture(undefined, textureKey)) !== null && _a !== void 0 ? _a : textureKey;
1404
+ }
1405
+ function applyOptionalSize(inst, c) {
1406
+ var _a, _b;
1407
+ if (c.width === undefined && c.height === undefined)
1408
+ return;
1409
+ const width = (_a = c.width) !== null && _a !== void 0 ? _a : inst.width;
1410
+ const height = (_b = c.height) !== null && _b !== void 0 ? _b : inst.height;
1411
+ if (typeof inst.setSize === 'function') {
1412
+ try {
1413
+ inst.setSize(width, height);
1414
+ return;
1415
+ }
1416
+ catch (_) { }
1417
+ }
1418
+ if (c.width !== undefined)
1419
+ inst.width = c.width;
1420
+ if (c.height !== undefined)
1421
+ inst.height = c.height;
1422
+ }
1080
1423
  function computeProgressPct(c) {
1081
1424
  const [min, max] = c.valueRange;
1082
1425
  if (max <= min)
@@ -1098,21 +1441,36 @@ const CIRCULAR_PROGRESS_BAR_DEF = {
1098
1441
  fillColor: { kind: 'scalar', default: '#22c55e', inspector: { name: 'fillColor', type: 'color' } },
1099
1442
  backgroundAlpha: { kind: 'scalar', default: 1, inspector: { name: 'backgroundAlpha', type: 'number', step: 0.05 } },
1100
1443
  fillAlpha: { kind: 'scalar', default: 1, inspector: { name: 'fillAlpha', type: 'number', step: 0.05 } },
1444
+ cap: { kind: 'scalar', inspector: { name: 'cap', type: 'string' } },
1445
+ rotation: { kind: 'scalar', default: 0 },
1446
+ offset: { kind: 'shallowMerge', default: {} },
1101
1447
  bindToStore: BIND_STORE,
1102
1448
  },
1103
1449
  optionsBuilder: (c) => ({
1104
1450
  radius: c.radius, lineWidth: c.lineWidth,
1105
1451
  backgroundColor: c.backgroundColor, fillColor: c.fillColor,
1106
1452
  backgroundAlpha: c.backgroundAlpha, fillAlpha: c.fillAlpha,
1453
+ cap: c.cap,
1107
1454
  value: computeProgressPct(c),
1108
1455
  }),
1456
+ postCreate: (inst, c) => applyCircularProgressTransform(inst, c),
1109
1457
  syncOnChange: (inst, c) => {
1110
1458
  const pct = computeProgressPct(c);
1111
1459
  if (inst.progress !== pct)
1112
1460
  inst.progress = pct;
1461
+ applyCircularProgressTransform(inst, c);
1113
1462
  },
1114
1463
  mixin: { getProgressPct: getProgressPctMixin },
1115
1464
  };
1465
+ function applyCircularProgressTransform(inst, c) {
1466
+ var _a, _b;
1467
+ if (c.rotation !== undefined)
1468
+ inst.rotation = c.rotation;
1469
+ if (c.offset) {
1470
+ inst.x = (_a = c.offset.x) !== null && _a !== void 0 ? _a : 0;
1471
+ inst.y = (_b = c.offset.y) !== null && _b !== void 0 ? _b : 0;
1472
+ }
1473
+ }
1116
1474
  const INPUT_DEF = {
1117
1475
  name: 'Input',
1118
1476
  signalPrefix: 'input',
@@ -1130,15 +1488,18 @@ const INPUT_DEF = {
1130
1488
  nineSliceSprite: { kind: 'opaque' },
1131
1489
  cleanOnFocus: { kind: 'scalar', default: false, inspector: { name: 'cleanOnFocus', type: 'boolean' } },
1132
1490
  addMask: { kind: 'scalar', default: false, inspector: { name: 'addMask', type: 'boolean' } },
1491
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1492
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1133
1493
  bindToStore: BIND_STORE,
1134
1494
  },
1135
1495
  views: { kind: 'single', key: 'bgView', required: true },
1136
1496
  optionsBuilder: (c, v) => ({
1137
- bg: v.single, textStyle: c.textStyle,
1497
+ bg: getProgressView(c.bgView, v.single, c.nineSliceSprite), textStyle: c.textStyle,
1138
1498
  placeholder: c.placeholder, value: c.value, maxLength: c.maxLength, secure: c.secure,
1139
1499
  align: c.align, padding: c.padding,
1140
1500
  cleanOnFocus: c.cleanOnFocus, nineSliceSprite: c.nineSliceSprite, addMask: c.addMask,
1141
1501
  }),
1502
+ postCreate: (inst, c) => { inst.enabled = c.enabled; applyOptionalSize(inst, c); },
1142
1503
  signalMap: (c) => ({
1143
1504
  change: (text) => { c.value = text; c.changeCount += 1; return { value: text }; },
1144
1505
  enter: (text) => ({ value: text }),
@@ -1146,6 +1507,9 @@ const INPUT_DEF = {
1146
1507
  syncOnChange: (inst, c) => {
1147
1508
  if (inst.value !== c.value)
1148
1509
  inst.value = c.value;
1510
+ if (inst.enabled !== c.enabled)
1511
+ inst.enabled = c.enabled;
1512
+ applyOptionalSize(inst, c);
1149
1513
  },
1150
1514
  };
1151
1515
  const LIST_DEF = {
@@ -1167,18 +1531,25 @@ const LIST_DEF = {
1167
1531
  itemsChildName: { kind: 'scalar', default: 'items' },
1168
1532
  },
1169
1533
  // List 不走 ViewSchema,view 是 collectChildContainers 副作用,system.ts 处理
1170
- optionsBuilder: (c, _v) => {
1534
+ optionsBuilder: (c, _v) => ({
1535
+ type: c.type,
1536
+ elementsMargin: c.elementsMargin,
1537
+ padding: c.padding,
1538
+ vertPadding: c.vertPadding, horPadding: c.horPadding,
1539
+ topPadding: c.topPadding, bottomPadding: c.bottomPadding,
1540
+ leftPadding: c.leftPadding, rightPadding: c.rightPadding,
1541
+ maxWidth: c.maxWidth, maxHeight: c.maxHeight,
1542
+ }),
1543
+ postCreate: (inst, c) => {
1171
1544
  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
- });
1545
+ for (const item of (_a = c.__resolved_items) !== null && _a !== void 0 ? _a : []) {
1546
+ try {
1547
+ inst.addChild(item);
1548
+ }
1549
+ catch (_) { }
1550
+ }
1551
+ if (typeof inst.arrangeChildren === 'function')
1552
+ inst.arrangeChildren();
1182
1553
  },
1183
1554
  syncOnChange: (inst, c) => {
1184
1555
  if (inst.type !== c.type)
@@ -1188,6 +1559,7 @@ const LIST_DEF = {
1188
1559
  if (typeof inst.arrangeChildren === 'function')
1189
1560
  inst.arrangeChildren();
1190
1561
  },
1562
+ applySize: applyListLayoutSize,
1191
1563
  };
1192
1564
  const SCROLL_BOX_DEF = {
1193
1565
  name: 'ScrollBox',
@@ -1198,12 +1570,22 @@ const SCROLL_BOX_DEF = {
1198
1570
  height: { kind: 'scalar', default: 240, inspector: { name: 'height', type: 'number' } },
1199
1571
  direction: { kind: 'scalar', default: 'vertical', inspector: { name: 'direction', type: 'string' } },
1200
1572
  contentChildName: { kind: 'scalar', default: 'content' },
1201
- background: { kind: 'scalar', default: 0x111111, inspector: { name: 'background', type: 'color' } },
1573
+ background: { kind: 'scalar', inspector: { name: 'background', type: 'color' } },
1202
1574
  radius: { kind: 'scalar', default: 0, inspector: { name: 'radius', type: 'number' } },
1203
1575
  elementsMargin: { kind: 'scalar', default: 0 },
1204
1576
  disableDynamicRendering: { kind: 'scalar', default: false },
1205
1577
  disableEasing: { kind: 'scalar', default: false, inspector: { name: 'disableEasing', type: 'boolean' } },
1206
1578
  padding: { kind: 'scalar', default: 0 },
1579
+ vertPadding: { kind: 'scalar' },
1580
+ horPadding: { kind: 'scalar' },
1581
+ topPadding: { kind: 'scalar' },
1582
+ bottomPadding: { kind: 'scalar' },
1583
+ leftPadding: { kind: 'scalar' },
1584
+ rightPadding: { kind: 'scalar' },
1585
+ globalScroll: { kind: 'scalar', default: true },
1586
+ shiftScroll: { kind: 'scalar', default: false },
1587
+ proximityRange: { kind: 'scalar' },
1588
+ proximityDebounce: { kind: 'scalar' },
1207
1589
  // legacy fields(spec 兼容)
1208
1590
  inertia: { kind: 'scalar', default: true },
1209
1591
  inertiaDecay: { kind: 'scalar', default: 0.92 },
@@ -1215,7 +1597,7 @@ const SCROLL_BOX_DEF = {
1215
1597
  getBounds() { return { minX: 0, maxX: 0, minY: 0, maxY: 0 }; },
1216
1598
  },
1217
1599
  optionsBuilder: (c, _v) => {
1218
- var _a, _b;
1600
+ var _a;
1219
1601
  const typeMap = {
1220
1602
  horizontal: 'horizontal', vertical: 'vertical', both: 'bidirectional',
1221
1603
  };
@@ -1224,21 +1606,37 @@ const SCROLL_BOX_DEF = {
1224
1606
  type: (_a = typeMap[c.direction]) !== null && _a !== void 0 ? _a : 'vertical',
1225
1607
  background: c.background, radius: c.radius,
1226
1608
  elementsMargin: c.elementsMargin, padding: c.padding,
1609
+ vertPadding: c.vertPadding, horPadding: c.horPadding,
1610
+ topPadding: c.topPadding, bottomPadding: c.bottomPadding,
1611
+ leftPadding: c.leftPadding, rightPadding: c.rightPadding,
1227
1612
  disableEasing: c.disableEasing, disableDynamicRendering: c.disableDynamicRendering,
1228
- items: (_b = c.__resolved_items) !== null && _b !== void 0 ? _b : [],
1613
+ globalScroll: c.globalScroll, shiftScroll: c.shiftScroll,
1614
+ proximityRange: c.proximityRange, proximityDebounce: c.proximityDebounce,
1229
1615
  };
1230
1616
  },
1231
1617
  signalMap: () => ({
1232
1618
  scroll: (v) => ({ value: v }),
1233
1619
  }),
1234
- syncOnChange: (inst, c) => {
1620
+ postCreate: (inst, c) => {
1621
+ var _a, _b;
1622
+ if (typeof inst.addItems === 'function') {
1623
+ try {
1624
+ inst.addItems((_a = c.__resolved_items) !== null && _a !== void 0 ? _a : []);
1625
+ }
1626
+ catch (_) { }
1627
+ }
1628
+ if (typeof ((_b = inst.list) === null || _b === void 0 ? void 0 : _b.arrangeChildren) === 'function')
1629
+ inst.list.arrangeChildren();
1235
1630
  if (typeof inst.resize === 'function') {
1236
1631
  try {
1237
- inst.resize(c.width, c.height);
1632
+ inst.resize();
1238
1633
  }
1239
1634
  catch (_) { }
1240
1635
  }
1241
1636
  },
1637
+ syncOnChange: (inst, c) => {
1638
+ applyOptionalSize(inst, c);
1639
+ },
1242
1640
  };
1243
1641
  const SELECT_DEF = {
1244
1642
  name: 'Select',
@@ -1252,26 +1650,51 @@ const SELECT_DEF = {
1252
1650
  openView: { kind: 'opaque' },
1253
1651
  textStyle: { kind: 'shallowMerge', default: { fontFamily: 'Arial', fontSize: 14, fill: '#222' } },
1254
1652
  nineSliceSprite: { kind: 'opaque' },
1653
+ width: { kind: 'scalar', inspector: { name: 'width', type: 'number' } },
1654
+ height: { kind: 'scalar', inspector: { name: 'height', type: 'number' } },
1655
+ radius: { kind: 'scalar', default: 4 },
1656
+ visibleItems: { kind: 'scalar' },
1657
+ itemWidth: { kind: 'scalar' },
1658
+ itemHeight: { kind: 'scalar' },
1659
+ itemBackgroundColor: { kind: 'scalar', default: 0x000000 },
1660
+ itemHoverColor: { kind: 'scalar', default: 0x666666 },
1661
+ selectedTextOffset: { kind: 'shallowMerge', default: {} },
1662
+ scrollBox: { kind: 'shallowMerge', default: {} },
1663
+ textClass: { kind: 'scalar', default: 'text' },
1664
+ open: { kind: 'scalar', default: false },
1255
1665
  bindToStore: BIND_STORE,
1256
1666
  },
1257
1667
  views: {
1258
1668
  kind: 'object', folder: '__select_views__', keys: [],
1259
1669
  },
1260
1670
  optionsBuilder: (c) => {
1261
- var _a;
1671
+ var _a, _b, _d, _e, _f;
1262
1672
  return ({
1263
1673
  closedBG: c.__resolved_closedView,
1264
1674
  openBG: c.__resolved_openView,
1265
1675
  textStyle: c.textStyle,
1676
+ TextClass: c.textClass === 'html' ? HTMLText : undefined,
1677
+ selectedTextOffset: c.selectedTextOffset,
1266
1678
  items: {
1267
1679
  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,
1680
+ backgroundColor: c.itemBackgroundColor,
1681
+ hoverColor: c.itemHoverColor,
1682
+ width: (_d = (_b = c.itemWidth) !== null && _b !== void 0 ? _b : c.width) !== null && _d !== void 0 ? _d : 200,
1683
+ height: (_f = (_e = c.itemHeight) !== null && _e !== void 0 ? _e : c.height) !== null && _f !== void 0 ? _f : 30,
1684
+ textStyle: c.textStyle,
1685
+ TextClass: c.textClass === 'html' ? HTMLText : undefined,
1686
+ radius: c.radius,
1270
1687
  },
1271
1688
  selected: c.selectedIndex >= 0 ? c.selectedIndex : undefined,
1689
+ visibleItems: c.visibleItems,
1690
+ scrollBox: Object.assign({ width: c.width, height: c.height && c.visibleItems ? c.height * c.visibleItems : undefined, radius: c.radius }, c.scrollBox),
1272
1691
  nineSliceSprite: c.nineSliceSprite,
1273
1692
  });
1274
1693
  },
1694
+ postCreate: (inst, c) => {
1695
+ if (c.open && typeof inst.open === 'function')
1696
+ inst.open();
1697
+ },
1275
1698
  signalMap: (c) => ({
1276
1699
  select: (value, text) => {
1277
1700
  c.selectedIndex = value;
@@ -1279,6 +1702,12 @@ const SELECT_DEF = {
1279
1702
  return { index: value, text };
1280
1703
  },
1281
1704
  }),
1705
+ syncOnChange: (inst, c) => {
1706
+ if (c.open && typeof inst.open === 'function')
1707
+ inst.open();
1708
+ if (!c.open && typeof inst.close === 'function')
1709
+ inst.close();
1710
+ },
1282
1711
  };
1283
1712
  const DIALOG_DEF = {
1284
1713
  name: 'Dialog',
@@ -1297,36 +1726,340 @@ const DIALOG_DEF = {
1297
1726
  closeOnBackdropClick: { kind: 'scalar', default: true, inspector: { name: 'closeOnBackdropClick', type: 'boolean' } },
1298
1727
  contentChildName: { kind: 'scalar', default: 'content', inspector: { name: 'contentChildName', type: 'string' } },
1299
1728
  nineSliceSprite: { kind: 'opaque' },
1729
+ titleStyle: { kind: 'shallowMerge', default: {} },
1730
+ content: { kind: 'scalar' },
1731
+ contentStyle: { kind: 'shallowMerge', default: {} },
1732
+ contentButtons: { kind: 'arrayCopy', default: [] },
1733
+ contentCheckBoxes: { kind: 'arrayCopy', default: [] },
1734
+ buttons: { kind: 'arrayCopy', default: [] },
1735
+ buttonList: { kind: 'shallowMerge', default: {} },
1736
+ buttonListOffset: { kind: 'shallowMerge', default: {} },
1737
+ scrollBox: { kind: 'shallowMerge', default: {} },
1738
+ animations: { kind: 'opaque' },
1300
1739
  bindToStore: BIND_STORE,
1301
1740
  },
1302
1741
  optionsBuilder: (c) => {
1303
1742
  var _a;
1304
- return ({
1743
+ const background = c.nineSliceSprite && c.backgroundView && 'texture' in c.backgroundView
1744
+ ? c.backgroundView.texture
1745
+ : ((_a = c.__resolved_background_view) !== null && _a !== void 0 ? _a : new Container());
1746
+ return {
1305
1747
  backdrop: c.__resolved_backdropView,
1306
1748
  backdropColor: backdropColorToNumber(c.backdropColor),
1307
1749
  backdropAlpha: c.backdropAlpha,
1308
- background: (_a = c.__resolved_backgroundView) !== null && _a !== void 0 ? _a : new Container(),
1309
- title: c.title,
1750
+ background,
1751
+ title: makeDialogText(c.title, c.titleStyle),
1752
+ content: makeDialogContent(c),
1753
+ buttons: makeDialogButtons(c.buttons),
1754
+ buttonList: c.buttonList,
1755
+ scrollBox: c.scrollBox,
1310
1756
  width: c.width, height: c.height, padding: c.padding,
1311
1757
  closeOnBackdropClick: c.closeOnBackdropClick,
1312
1758
  nineSliceSprite: c.nineSliceSprite,
1313
- });
1759
+ animations: c.animations,
1760
+ };
1314
1761
  },
1315
1762
  postCreate: (inst, c) => {
1763
+ alignDialogAnchoredContent(inst, c);
1316
1764
  if (c.open && typeof inst.open === 'function')
1317
1765
  inst.open();
1318
1766
  },
1767
+ applySize: applyDialogSize,
1768
+ onAttachedExtra: (inst, c, go) => {
1769
+ wireDialogContentButtonPresses(inst, c, go);
1770
+ },
1319
1771
  signalMap: (c) => ({
1320
1772
  close: () => { c.open = false; return {}; },
1321
1773
  select: (idx, text) => ({ index: idx, text }),
1322
1774
  }),
1323
1775
  syncOnChange: (inst, c) => {
1776
+ alignDialogAnchoredContent(inst, c);
1324
1777
  if (c.open && !inst.isOpen && typeof inst.open === 'function')
1325
1778
  inst.open();
1326
1779
  else if (!c.open && inst.isOpen && typeof inst.close === 'function')
1327
1780
  inst.close();
1328
1781
  },
1329
1782
  };
1783
+ function applyDialogSize(inst, size, c) {
1784
+ var _a, _b, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _w, _x, _y;
1785
+ 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);
1786
+ 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);
1787
+ if (width === undefined && height === undefined)
1788
+ return;
1789
+ inst.options = (_h = inst.options) !== null && _h !== void 0 ? _h : {};
1790
+ if (width !== undefined)
1791
+ inst.options.width = width;
1792
+ if (height !== undefined)
1793
+ inst.options.height = height;
1794
+ 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);
1795
+ 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);
1796
+ const padding = Number((_m = (_l = c.padding) !== null && _l !== void 0 ? _l : inst.options.padding) !== null && _m !== void 0 ? _m : 20) || 20;
1797
+ if (inst.innerView) {
1798
+ if (width !== undefined)
1799
+ inst.innerView.width = width;
1800
+ if (height !== undefined)
1801
+ inst.innerView.height = height;
1802
+ if ('anchor' in inst.innerView && ((_o = inst.innerView.anchor) === null || _o === void 0 ? void 0 : _o.set)) {
1803
+ inst.innerView.anchor.set(0.5, 0.5);
1804
+ }
1805
+ else {
1806
+ try {
1807
+ (_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);
1808
+ }
1809
+ catch (_) { }
1810
+ }
1811
+ }
1812
+ if (inst.titleText) {
1813
+ inst.titleText.x = dialogWidth / 2;
1814
+ inst.titleText.y = padding;
1815
+ }
1816
+ const titleHeight = Number((_r = inst.titleText) === null || _r === void 0 ? void 0 : _r.height) || 0;
1817
+ const buttonHeight = Number((_s = inst.buttonContainer) === null || _s === void 0 ? void 0 : _s.height) || 0;
1818
+ if (inst.buttonContainer) {
1819
+ inst.buttonContainer.x = dialogWidth / 2 - ((Number(inst.buttonContainer.width) || 0) / 2);
1820
+ inst.buttonContainer.y = dialogHeight - padding - buttonHeight;
1821
+ }
1822
+ if (inst.scrollBox) {
1823
+ inst.scrollBox.x = padding;
1824
+ inst.scrollBox.y = padding + titleHeight;
1825
+ const overrideSize = (_t = c.scrollBox) === null || _t === void 0 ? void 0 : _t.size;
1826
+ const scrollWidth = (_u = readPositiveSize(overrideSize === null || overrideSize === void 0 ? void 0 : overrideSize.width)) !== null && _u !== void 0 ? _u : Math.max(0, dialogWidth - (padding * 2));
1827
+ 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);
1828
+ if (typeof inst.scrollBox.setSize === 'function')
1829
+ inst.scrollBox.setSize(scrollWidth, scrollHeight);
1830
+ else {
1831
+ inst.scrollBox.width = scrollWidth;
1832
+ inst.scrollBox.height = scrollHeight;
1833
+ }
1834
+ try {
1835
+ (_y = (_x = inst.scrollBox).resize) === null || _y === void 0 ? void 0 : _y.call(_x, true);
1836
+ }
1837
+ catch (_) { }
1838
+ }
1839
+ alignDialogAnchoredContent(inst, Object.assign(Object.assign({}, c), { width: dialogWidth, height: dialogHeight }));
1840
+ }
1841
+ function readPositiveSize(value) {
1842
+ const n = Number(value);
1843
+ return Number.isFinite(n) && n > 0 ? n : undefined;
1844
+ }
1845
+ function alignDialogAnchoredContent(inst, c) {
1846
+ var _a, _b;
1847
+ const innerView = inst === null || inst === void 0 ? void 0 : inst.innerView;
1848
+ const contentView = inst === null || inst === void 0 ? void 0 : inst.contentView;
1849
+ if ((innerView === null || innerView === void 0 ? void 0 : innerView.anchor) && contentView && c.width && c.height) {
1850
+ contentView.x = -c.width / 2;
1851
+ contentView.y = -c.height / 2;
1852
+ }
1853
+ applyDialogOffset(inst, 'buttonListOffset', inst.buttonContainer, c.buttonListOffset);
1854
+ applyDialogOffset(inst, 'scrollBoxOffset', inst.scrollBox, (_a = c.scrollBox) === null || _a === void 0 ? void 0 : _a.offset);
1855
+ applyDialogScrollBoxSize(inst, (_b = c.scrollBox) === null || _b === void 0 ? void 0 : _b.size);
1856
+ }
1857
+ function applyDialogOffset(inst, key, target, nextOffset) {
1858
+ var _a, _b, _d, _e;
1859
+ if (!target)
1860
+ return;
1861
+ const applied = (_a = inst.__evaDialogAppliedOffsets) !== null && _a !== void 0 ? _a : {};
1862
+ const prev = (_b = applied[key]) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
1863
+ 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 };
1864
+ target.x += next.x - prev.x;
1865
+ target.y += next.y - prev.y;
1866
+ inst.__evaDialogAppliedOffsets = Object.assign(Object.assign({}, applied), { [key]: next });
1867
+ }
1868
+ function applyDialogScrollBoxSize(inst, nextSize) {
1869
+ var _a, _b, _d;
1870
+ const scrollBox = inst === null || inst === void 0 ? void 0 : inst.scrollBox;
1871
+ if (!scrollBox)
1872
+ return;
1873
+ const base = (_a = inst.__evaDialogBaseScrollBoxSize) !== null && _a !== void 0 ? _a : {
1874
+ width: scrollBox.width,
1875
+ height: scrollBox.height,
1876
+ };
1877
+ inst.__evaDialogBaseScrollBoxSize = base;
1878
+ const wasApplied = inst.__evaDialogAppliedScrollBoxSize;
1879
+ if (!nextSize && !wasApplied)
1880
+ return;
1881
+ const width = (_b = nextSize === null || nextSize === void 0 ? void 0 : nextSize.width) !== null && _b !== void 0 ? _b : base.width;
1882
+ const height = (_d = nextSize === null || nextSize === void 0 ? void 0 : nextSize.height) !== null && _d !== void 0 ? _d : base.height;
1883
+ if (typeof scrollBox.setSize === 'function')
1884
+ scrollBox.setSize(width, height);
1885
+ else {
1886
+ scrollBox.width = width;
1887
+ scrollBox.height = height;
1888
+ }
1889
+ if (typeof scrollBox.resize === 'function')
1890
+ scrollBox.resize(true);
1891
+ inst.__evaDialogAppliedScrollBoxSize = !!nextSize;
1892
+ }
1893
+ function makeDialogText(text, style) {
1894
+ if (text === undefined)
1895
+ return undefined;
1896
+ if (style && Object.keys(style).length > 0) {
1897
+ return new Text({ text, style: style });
1898
+ }
1899
+ return text;
1900
+ }
1901
+ function makeDialogContent(c) {
1902
+ var _a, _b;
1903
+ if ((_a = c.contentButtons) === null || _a === void 0 ? void 0 : _a.length) {
1904
+ const records = [];
1905
+ const buttons = c.contentButtons.map((button, index) => {
1906
+ const pixiButton = new FancyButton$1(makeDialogButtonOptions(button));
1907
+ applyOptionalSize(pixiButton, button);
1908
+ if (button.disabled !== undefined)
1909
+ pixiButton.enabled = !button.disabled;
1910
+ records.push({ button: pixiButton, params: button, index });
1911
+ return pixiButton;
1912
+ });
1913
+ c.__dialogContentButtons = records;
1914
+ return buttons;
1915
+ }
1916
+ if ((_b = c.contentCheckBoxes) === null || _b === void 0 ? void 0 : _b.length) {
1917
+ return c.contentCheckBoxes.map((checkBox) => new CheckBox$1(makeDialogCheckBoxOptions(checkBox)));
1918
+ }
1919
+ return makeDialogText(c.content, c.contentStyle);
1920
+ }
1921
+ function wireDialogContentButtonPresses(inst, c, go) {
1922
+ const records = c.__dialogContentButtons;
1923
+ if (!Array.isArray(records) || records.length === 0 || inst.__evaDialogContentButtonPressesWired)
1924
+ return;
1925
+ inst.__evaDialogContentButtonPressesWired = true;
1926
+ inst.__evaDialogContentButtonPressCleanups = records.map((record) => {
1927
+ var _a;
1928
+ const signal = (_a = record.button) === null || _a === void 0 ? void 0 : _a.onPress;
1929
+ if (!signal || typeof signal.connect !== 'function')
1930
+ return undefined;
1931
+ const conn = signal.connect(() => {
1932
+ var _a, _b, _d, _e;
1933
+ const value = (_b = (_a = record.params.value) !== null && _a !== void 0 ? _a : record.params.text) !== null && _b !== void 0 ? _b : record.index;
1934
+ c.selectedContentIndex = record.index;
1935
+ c.selectedContentValue = value;
1936
+ c.selectCount = ((_d = c.selectCount) !== null && _d !== void 0 ? _d : 0) + 1;
1937
+ c.lastSignal = 'select';
1938
+ emitDialogSelection(go, { index: record.index, text: String((_e = record.params.text) !== null && _e !== void 0 ? _e : ''), value });
1939
+ if (record.params.closeOnPress && typeof inst.close === 'function')
1940
+ inst.close();
1941
+ const reopenDelay = Number(record.params.reopenDelay);
1942
+ if (Number.isFinite(reopenDelay) && reopenDelay >= 0 && typeof inst.open === 'function') {
1943
+ setTimeout(() => {
1944
+ try {
1945
+ inst.open();
1946
+ }
1947
+ catch (_) { }
1948
+ }, reopenDelay);
1949
+ }
1950
+ });
1951
+ return () => { try {
1952
+ conn.disconnect();
1953
+ }
1954
+ catch (_) { } };
1955
+ }).filter(Boolean);
1956
+ }
1957
+ function emitDialogSelection(go, payload) {
1958
+ var _a, _b, _d;
1959
+ const eventPayload = Object.assign({ entityName: go === null || go === void 0 ? void 0 : go.name }, payload);
1960
+ try {
1961
+ (_a = go === null || go === void 0 ? void 0 : go.emit) === null || _a === void 0 ? void 0 : _a.call(go, 'select', eventPayload);
1962
+ }
1963
+ catch (_) { }
1964
+ try {
1965
+ (_b = go === null || go === void 0 ? void 0 : go.emit) === null || _b === void 0 ? void 0 : _b.call(go, 'dialog:select', eventPayload);
1966
+ }
1967
+ catch (_) { }
1968
+ const mx = (typeof globalThis !== 'undefined' ? globalThis.mx : undefined);
1969
+ if ((_d = mx === null || mx === void 0 ? void 0 : mx.event) === null || _d === void 0 ? void 0 : _d.emit) {
1970
+ try {
1971
+ mx.event.emit('dialog:select', eventPayload);
1972
+ }
1973
+ catch (_) { }
1974
+ }
1975
+ }
1976
+ function makeDialogButtons(buttons) {
1977
+ if (!(buttons === null || buttons === void 0 ? void 0 : buttons.length))
1978
+ return undefined;
1979
+ return buttons.map((button) => {
1980
+ const options = makeDialogButtonOptions(button);
1981
+ const shouldMaterialize = button.disabled !== undefined
1982
+ || !!(button.nineSliceSprite && (button.width !== undefined || button.height !== undefined));
1983
+ if (button.kind === 'button' || !shouldMaterialize)
1984
+ return options;
1985
+ const pixiButton = new FancyButton$1(options);
1986
+ applyOptionalSize(pixiButton, button);
1987
+ pixiButton.enabled = !button.disabled;
1988
+ return pixiButton;
1989
+ });
1990
+ }
1991
+ function makeDialogButtonOptions(button) {
1992
+ var _a, _b, _d, _e, _f, _g, _h, _j, _k, _l;
1993
+ if (button.kind === 'button')
1994
+ return makeDialogBareButton(button);
1995
+ const width = (_a = button.width) !== null && _a !== void 0 ? _a : 110;
1996
+ const height = (_b = button.height) !== null && _b !== void 0 ? _b : 48;
1997
+ const radius = (_d = button.radius) !== null && _d !== void 0 ? _d : 12;
1998
+ const color = (_e = button.color) !== null && _e !== void 0 ? _e : pixiStoryDefaultButtonColor;
1999
+ return {
2000
+ text: makeDialogText(button.text, button.textStyle),
2001
+ defaultView: (_f = resolveDialogButtonView(button.defaultView)) !== null && _f !== void 0 ? _f : makeDialogButtonView(width, height, radius, color),
2002
+ hoverView: (_g = resolveDialogButtonView(button.hoverView)) !== null && _g !== void 0 ? _g : makeDialogButtonView(width, height, radius, (_h = button.hoverColor) !== null && _h !== void 0 ? _h : color),
2003
+ pressedView: (_j = resolveDialogButtonView(button.pressedView)) !== null && _j !== void 0 ? _j : makeDialogButtonView(width, height, radius, (_k = button.pressedColor) !== null && _k !== void 0 ? _k : color),
2004
+ disabledView: (_l = resolveDialogButtonView(button.disabledView)) !== null && _l !== void 0 ? _l : (button.disabledColor ? makeDialogButtonView(width, height, radius, button.disabledColor) : undefined),
2005
+ nineSliceSprite: button.nineSliceSprite,
2006
+ enabled: button.disabled === undefined ? undefined : !button.disabled,
2007
+ animations: button.animations,
2008
+ };
2009
+ }
2010
+ function resolveDialogButtonView(view) {
2011
+ return view ? getTextureView(view) : undefined;
2012
+ }
2013
+ const pixiStoryDefaultButtonColor = '#e91e63';
2014
+ const pixiStoryDefaultTextColor = '#ffffff';
2015
+ function makeDialogButtonView(width, height, radius, color) {
2016
+ return new Graphics$1()
2017
+ .roundRect(0, 0, width, height, radius)
2018
+ .fill(color);
2019
+ }
2020
+ function makeDialogBareButton(button) {
2021
+ var _a, _b, _d, _e, _f, _g;
2022
+ const width = (_a = button.width) !== null && _a !== void 0 ? _a : 110;
2023
+ const height = (_b = button.height) !== null && _b !== void 0 ? _b : 48;
2024
+ const radius = (_d = button.radius) !== null && _d !== void 0 ? _d : 12;
2025
+ const view = makeDialogButtonView(width, height, radius, (_e = button.color) !== null && _e !== void 0 ? _e : pixiStoryDefaultButtonColor);
2026
+ const label = makeDialogText(button.text, button.textStyle);
2027
+ if (label) {
2028
+ label.x = width / 2;
2029
+ label.y = height / 2;
2030
+ try {
2031
+ (_g = (_f = label.anchor) === null || _f === void 0 ? void 0 : _f.set) === null || _g === void 0 ? void 0 : _g.call(_f, 0.5);
2032
+ }
2033
+ catch (_) { }
2034
+ view.addChild(label);
2035
+ }
2036
+ const pixiButton = new Button$1(view);
2037
+ if (button.disabled !== undefined)
2038
+ pixiButton.enabled = !button.disabled;
2039
+ return pixiButton;
2040
+ }
2041
+ function makeDialogCheckBoxOptions(checkBox) {
2042
+ var _a, _b, _d, _e, _f, _g;
2043
+ const size = (_a = checkBox.size) !== null && _a !== void 0 ? _a : 30;
2044
+ const radius = (_b = checkBox.radius) !== null && _b !== void 0 ? _b : 5;
2045
+ const strokeColor = (_d = checkBox.strokeColor) !== null && _d !== void 0 ? _d : pixiStoryDefaultTextColor;
2046
+ const strokeWidth = (_e = checkBox.strokeWidth) !== null && _e !== void 0 ? _e : 2;
2047
+ return {
2048
+ style: {
2049
+ unchecked: new Graphics$1()
2050
+ .roundRect(0, 0, size, size, radius)
2051
+ .fill(((_f = checkBox.uncheckedColor) !== null && _f !== void 0 ? _f : '#3e3f40'))
2052
+ .stroke({ color: strokeColor, width: strokeWidth }),
2053
+ checked: new Graphics$1()
2054
+ .roundRect(0, 0, size, size, radius)
2055
+ .fill(((_g = checkBox.checkedColor) !== null && _g !== void 0 ? _g : pixiStoryDefaultButtonColor))
2056
+ .stroke({ color: strokeColor, width: strokeWidth }),
2057
+ text: checkBox.textStyle,
2058
+ },
2059
+ text: checkBox.text,
2060
+ checked: checkBox.checked,
2061
+ };
2062
+ }
1330
2063
  const MASKED_FRAME_DEF = {
1331
2064
  name: 'MaskedFrame',
1332
2065
  signalPrefix: 'maskedframe',
@@ -1335,12 +2068,14 @@ const MASKED_FRAME_DEF = {
1335
2068
  targetView: { kind: 'opaque' },
1336
2069
  maskView: { kind: 'opaque' },
1337
2070
  borderView: { kind: 'opaque' },
2071
+ borderWidth: { kind: 'scalar', default: 0, inspector: { name: 'borderWidth', type: 'number' } },
2072
+ borderColor: { kind: 'scalar', default: 0x000000, inspector: { name: 'borderColor', type: 'color' } },
1338
2073
  },
1339
2074
  optionsBuilder: (c) => ({
1340
- target: c.__resolved_targetView,
1341
- mask: c.__resolved_maskView,
1342
- borderWidth: 0,
1343
- borderColor: 0,
2075
+ target: c.__resolved_target_view,
2076
+ mask: c.__resolved_mask_view,
2077
+ borderWidth: c.borderWidth,
2078
+ borderColor: c.borderColor,
1344
2079
  }),
1345
2080
  };
1346
2081
  // ============================================================
@@ -1537,13 +2272,16 @@ function safeProject(projector, args) {
1537
2272
  /**
1538
2273
  * UISystem - generic handler driven by COMPONENT_DEFINITIONS metadata.
1539
2274
  *
1540
- * 16 个 ECS 组件(UI 自渲染 + 14 个 @pixi/ui factory wrapper + RadioGroup 独立)由本 system 统一驱动。
2275
+ * 16 个 ECS 组件(Shape 自渲染 + 14 个 @pixi/ui factory wrapper + RadioGroup 独立)由本 system 统一驱动。
1541
2276
  * 不再为每个组件写独立 handler 方法 - 14 个 @pixi/ui 组件走 handleGeneric,RadioGroup 单独处理。
1542
2277
  */
1543
2278
  // observer schema:把 COMPONENT_DEFINITIONS.fields 转成 componentObserver decorator 参数
1544
2279
  function buildObserverSchema() {
1545
2280
  const out = {
2281
+ Transform: [{ prop: ['size'], deep: true }],
2282
+ Shape: [{ prop: ['shapes'], deep: true }],
1546
2283
  UI: [{ prop: ['shapes'], deep: true }],
2284
+ UIComponent: [{ prop: ['shapes'], deep: true }],
1547
2285
  RadioGroup: [
1548
2286
  { prop: ['selectedId'], deep: false },
1549
2287
  { prop: ['direction'], deep: false },
@@ -1560,6 +2298,9 @@ function buildObserverSchema() {
1560
2298
  }
1561
2299
  return out;
1562
2300
  }
2301
+ function isShapeComponentName(name) {
2302
+ return name === 'Shape' || name === 'UI' || name === 'UIComponent';
2303
+ }
1563
2304
  let UISystem = class UISystem extends System {
1564
2305
  constructor() {
1565
2306
  super(...arguments);
@@ -1567,6 +2308,7 @@ let UISystem = class UISystem extends System {
1567
2308
  /** componentName -> instance map(generic 共享一份) */
1568
2309
  this.instances = new Map();
1569
2310
  this.signalCleanups = new Map();
2311
+ this.transformSizeAuthorities = new Set();
1570
2312
  this.radioGroupInstances = new Map();
1571
2313
  }
1572
2314
  /** 给 RadioGroup 反查 PixiCheckBox 实例用 */
@@ -1590,8 +2332,10 @@ let UISystem = class UISystem extends System {
1590
2332
  }
1591
2333
  componentChanged(changed) {
1592
2334
  const name = changed.componentName;
1593
- if (name === 'UI')
1594
- return this.handleUI(changed);
2335
+ if (name === 'Transform')
2336
+ return this.handleTransformSizeChanged(changed);
2337
+ if (isShapeComponentName(name))
2338
+ return this.handleShape(changed);
1595
2339
  if (name === 'RadioGroup')
1596
2340
  return this.handleRadioGroup(changed);
1597
2341
  const def = COMPONENT_DEFINITIONS[name];
@@ -1599,13 +2343,13 @@ let UISystem = class UISystem extends System {
1599
2343
  return this.handleGeneric(def, changed);
1600
2344
  }
1601
2345
  // ============================================================
1602
- // UI(自渲染,无 @pixi/ui 实例)
2346
+ // Shape(自渲染,无 @pixi/ui 实例)
1603
2347
  // ============================================================
1604
- handleUI(changed) {
2348
+ handleShape(changed) {
1605
2349
  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();
2350
+ const shape = changed.component;
2351
+ if (typeof shape.redraw === 'function')
2352
+ shape.redraw();
1609
2353
  }
1610
2354
  }
1611
2355
  // ============================================================
@@ -1629,13 +2373,16 @@ let UISystem = class UISystem extends System {
1629
2373
  return;
1630
2374
  }
1631
2375
  (_a = def.syncOnChange) === null || _a === void 0 ? void 0 : _a.call(def, inst, c);
2376
+ if (this.transformSizeAuthorities.has(go.id)) {
2377
+ applyTransformSizeToInstance(def, inst, c, go, 'component-change');
2378
+ }
1632
2379
  }
1633
2380
  else if (changed.type === OBSERVER_TYPE.REMOVE) {
1634
2381
  this.detachGeneric(go.id, instMap, go);
1635
2382
  }
1636
2383
  }
1637
2384
  attachGeneric(def, c, go, instMap) {
1638
- var _a, _b, _c, _d, _f, _g, _h;
2385
+ var _a, _b, _c, _d, _f, _g, _h, _j, _k;
1639
2386
  if (instMap.has(go.id))
1640
2387
  return;
1641
2388
  const game = this.gameRef(go);
@@ -1652,25 +2399,39 @@ let UISystem = class UISystem extends System {
1652
2399
  if (def.name === 'List' || def.name === 'ScrollBox') {
1653
2400
  const childName = def.name === 'List' ? c.itemsChildName : c.contentChildName;
1654
2401
  c.__resolved_items = collectChildContainers(game, go, childName);
2402
+ const expectedCount = getCollectedChildCount(go, childName);
2403
+ if (expectedCount > 0 && c.__resolved_items.length < expectedCount && ((_a = c.__collect_retry) !== null && _a !== void 0 ? _a : 0) < 10) {
2404
+ c.__collect_retry = ((_b = c.__collect_retry) !== null && _b !== void 0 ? _b : 0) + 1;
2405
+ requestAnimationFrame(() => this.attachGeneric(def, c, go, instMap));
2406
+ return;
2407
+ }
1655
2408
  }
1656
2409
  // 4) 构造 PIXI 实例
2410
+ const restoreTransientSize = this.applyTransientTransformSize(c, go);
1657
2411
  const built = def.optionsBuilder(c, views !== null && views !== void 0 ? views : {});
1658
2412
  const inst = def.positional
1659
2413
  ? new def.pixiClass(...built)
1660
2414
  : new def.pixiClass(built);
1661
2415
  // 5) postCreate(enabled / selected tint 等)
1662
- (_a = def.postCreate) === null || _a === void 0 ? void 0 : _a.call(def, inst, c);
2416
+ (_c = def.postCreate) === null || _c === void 0 ? void 0 : _c.call(def, inst, c);
2417
+ // 5.5) 新 DSL 以 Transform.size 作为 plugin-ui 渲染尺寸来源。
2418
+ // 历史 DSL 若显式写了组件 width/height,初次 attach 保持旧行为;之后 Transform.size change 会接管。
2419
+ if (this.transformSizeAuthorities.has(go.id) || !hasExplicitRenderSize(c)) {
2420
+ const applied = applyTransformSizeToInstance(def, inst, c, go, 'initial-transform');
2421
+ if (applied)
2422
+ this.transformSizeAuthorities.add(go.id);
2423
+ }
1663
2424
  // 6) 注册 + attach
1664
2425
  instMap.set(go.id, inst);
1665
2426
  attachToGameObject(game, go, inst);
1666
2427
  // 7) onAttachedExtra(Dialog 挂 contentChild)
1667
2428
  if (def.name === 'Dialog') {
1668
- const contentChild = findChildEntity(go, (_b = c.contentChildName) !== null && _b !== void 0 ? _b : 'content');
2429
+ const contentChild = findChildEntity(go, (_d = c.contentChildName) !== null && _d !== void 0 ? _d : 'content');
1669
2430
  if (contentChild) {
1670
2431
  const cc = getEvaContainer(game, contentChild);
1671
2432
  if (cc) {
1672
2433
  try {
1673
- (_d = (_c = inst).addChild) === null || _d === void 0 ? void 0 : _d.call(_c, cc);
2434
+ (_g = (_f = inst).addChild) === null || _g === void 0 ? void 0 : _g.call(_f, cc);
1674
2435
  }
1675
2436
  catch (_) { }
1676
2437
  }
@@ -1681,7 +2442,7 @@ let UISystem = class UISystem extends System {
1681
2442
  const border = resolveViewRef(game, go, c.borderView);
1682
2443
  if (border) {
1683
2444
  try {
1684
- (_g = (_f = inst).addChild) === null || _g === void 0 ? void 0 : _g.call(_f, border);
2445
+ (_j = (_h = inst).addChild) === null || _j === void 0 ? void 0 : _j.call(_h, border);
1685
2446
  }
1686
2447
  catch (_) { }
1687
2448
  }
@@ -1691,7 +2452,8 @@ let UISystem = class UISystem extends System {
1691
2452
  const offs = bridgeSignals(inst, { go, prefix: def.signalPrefix }, def.signalMap(c));
1692
2453
  this.signalCleanups.set(go.id, offs);
1693
2454
  }
1694
- (_h = def.onAttachedExtra) === null || _h === void 0 ? void 0 : _h.call(def, inst, c, go, game);
2455
+ (_k = def.onAttachedExtra) === null || _k === void 0 ? void 0 : _k.call(def, inst, c, go, game);
2456
+ restoreTransientSize();
1695
2457
  }
1696
2458
  detachGeneric(id, instMap, go) {
1697
2459
  const inst = instMap.get(id);
@@ -1768,6 +2530,11 @@ let UISystem = class UISystem extends System {
1768
2530
  items, type: (_f = typeMap[c.direction]) !== null && _f !== void 0 ? _f : 'vertical',
1769
2531
  elementsMargin: c.elementsMargin, selectedItem: initialIndex,
1770
2532
  });
2533
+ if (this.transformSizeAuthorities.has(go.id)) {
2534
+ const size = readTransformRenderSize(go, { allowZero: true });
2535
+ if (size)
2536
+ applyRuntimeSize(inst, size);
2537
+ }
1771
2538
  this.radioGroupInstances.set(go.id, inst);
1772
2539
  attachToGameObject(game, go, inst);
1773
2540
  const offs = bridgeSignals(inst, { go, prefix: 'radiogroup' }, {
@@ -1803,6 +2570,74 @@ let UISystem = class UISystem extends System {
1803
2570
  }
1804
2571
  return null;
1805
2572
  }
2573
+ // ============================================================
2574
+ // Transform.size -> plugin-ui runtime size
2575
+ // ============================================================
2576
+ handleTransformSizeChanged(changed) {
2577
+ var _a, _b;
2578
+ if (changed.type !== OBSERVER_TYPE.CHANGE)
2579
+ return;
2580
+ const transform = changed.component;
2581
+ const go = (_a = changed.gameObject) !== null && _a !== void 0 ? _a : transform === null || transform === void 0 ? void 0 : transform.gameObject;
2582
+ if (!go)
2583
+ return;
2584
+ let applied = false;
2585
+ for (const [componentName, def] of Object.entries(COMPONENT_DEFINITIONS)) {
2586
+ const inst = (_b = this.instances.get(componentName)) === null || _b === void 0 ? void 0 : _b.get(go.id);
2587
+ if (!inst)
2588
+ continue;
2589
+ const component = getComponentSafe(go, componentName);
2590
+ if (applyTransformSizeToInstance(def, inst, component, go, 'transform-change')) {
2591
+ applied = true;
2592
+ }
2593
+ }
2594
+ const radioGroup = this.radioGroupInstances.get(go.id);
2595
+ if (radioGroup) {
2596
+ const size = readTransformRenderSize(go, { allowZero: true });
2597
+ if (size) {
2598
+ applyRuntimeSize(radioGroup, size);
2599
+ applied = true;
2600
+ }
2601
+ }
2602
+ if (applied)
2603
+ this.transformSizeAuthorities.add(go.id);
2604
+ this.relayoutLayoutInstances();
2605
+ }
2606
+ relayoutLayoutInstances() {
2607
+ for (const name of ['List', 'ScrollBox']) {
2608
+ const instMap = this.instances.get(name);
2609
+ if (!instMap)
2610
+ continue;
2611
+ for (const inst of instMap.values()) {
2612
+ relayoutRuntimeInstance(inst);
2613
+ }
2614
+ }
2615
+ }
2616
+ applyTransientTransformSize(c, go) {
2617
+ if (hasExplicitRenderSize(c))
2618
+ return () => { };
2619
+ const size = readTransformRenderSize(go);
2620
+ if (!size)
2621
+ return () => { };
2622
+ const hadWidth = Object.prototype.hasOwnProperty.call(c, 'width');
2623
+ const hadHeight = Object.prototype.hasOwnProperty.call(c, 'height');
2624
+ const prevWidth = c.width;
2625
+ const prevHeight = c.height;
2626
+ if (size.width !== undefined)
2627
+ c.width = size.width;
2628
+ if (size.height !== undefined)
2629
+ c.height = size.height;
2630
+ return () => {
2631
+ if (hadWidth)
2632
+ c.width = prevWidth;
2633
+ else
2634
+ delete c.width;
2635
+ if (hadHeight)
2636
+ c.height = prevHeight;
2637
+ else
2638
+ delete c.height;
2639
+ };
2640
+ }
1806
2641
  };
1807
2642
  UISystem.systemName = 'UISystem';
1808
2643
  UISystem = __decorate([
@@ -1826,6 +2661,8 @@ function inlineResolveSpecialViews(name, c, game, go) {
1826
2661
  case 'ProgressBar':
1827
2662
  c.__resolved_bg = resolveViewRef(game, go, c.bgView);
1828
2663
  c.__resolved_fill = resolveViewRef(game, go, c.fillView);
2664
+ c.__resolved_bg_view = c.nineSliceSprite && c.bgView && 'texture' in c.bgView ? c.bgView.texture : c.__resolved_bg;
2665
+ c.__resolved_fill_view = c.nineSliceSprite && c.fillView && 'texture' in c.fillView ? c.fillView.texture : c.__resolved_fill;
1829
2666
  break;
1830
2667
  case 'Select':
1831
2668
  c.__resolved_closedView = resolveViewRef(game, go, c.closedView);
@@ -1834,10 +2671,15 @@ function inlineResolveSpecialViews(name, c, game, go) {
1834
2671
  case 'Dialog':
1835
2672
  c.__resolved_backdropView = resolveViewRef(game, go, c.backdropView);
1836
2673
  c.__resolved_backgroundView = resolveViewRef(game, go, c.backgroundView);
2674
+ c.__resolved_background_view = c.nineSliceSprite && c.backgroundView && 'texture' in c.backgroundView
2675
+ ? c.backgroundView.texture
2676
+ : c.__resolved_backgroundView;
1837
2677
  break;
1838
2678
  case 'MaskedFrame':
1839
2679
  c.__resolved_targetView = resolveViewRef(game, go, c.targetView);
1840
2680
  c.__resolved_maskView = resolveViewRef(game, go, c.maskView);
2681
+ c.__resolved_target_view = c.targetView && 'texture' in c.targetView ? c.targetView.texture : c.__resolved_targetView;
2682
+ c.__resolved_mask_view = c.maskView && 'texture' in c.maskView ? c.maskView.texture : c.__resolved_maskView;
1841
2683
  break;
1842
2684
  }
1843
2685
  }
@@ -1845,14 +2687,14 @@ function inlineResolveSpecialViews(name, c, game, go) {
1845
2687
  function validateInlineResolved(name, c) {
1846
2688
  switch (name) {
1847
2689
  case 'ProgressBar':
1848
- return !!(c.__resolved_bg && c.__resolved_fill);
2690
+ return !!(c.__resolved_bg_view && c.__resolved_fill_view);
1849
2691
  case 'Select':
1850
2692
  return !!(c.__resolved_closedView && c.__resolved_openView);
1851
2693
  case 'Dialog':
1852
2694
  // backgroundView 可 fallback PixiContainer,backdropView 也可 null
1853
2695
  return true;
1854
2696
  case 'MaskedFrame':
1855
- return !!(c.__resolved_targetView && c.__resolved_maskView);
2697
+ return !!(c.__resolved_target_view && c.__resolved_mask_view);
1856
2698
  default:
1857
2699
  return true;
1858
2700
  }
@@ -1870,15 +2712,47 @@ function collectChildContainers(game, go, childName) {
1870
2712
  continue;
1871
2713
  const childContainer = getEvaContainer(game, child);
1872
2714
  if (childContainer) {
2715
+ if (childContainer.width <= 0 || childContainer.height <= 0)
2716
+ continue;
1873
2717
  try {
1874
2718
  (_c = (_b = childContainer.parent) === null || _b === void 0 ? void 0 : _b.removeChild) === null || _c === void 0 ? void 0 : _c.call(_b, childContainer);
1875
2719
  }
1876
2720
  catch (_) { }
1877
- result.push(childContainer);
2721
+ result.push(wrapLayoutItem(childContainer, child));
1878
2722
  }
1879
2723
  }
1880
2724
  return result;
1881
2725
  }
2726
+ function wrapLayoutItem(childContainer, child) {
2727
+ const wrapper = new Container();
2728
+ const childName = child === null || child === void 0 ? void 0 : child.name;
2729
+ wrapper.label = childName ? `${childName}:layout-item` : 'plugin-ui-layout-item';
2730
+ wrapper.addChild(childContainer);
2731
+ Object.defineProperty(wrapper, 'width', {
2732
+ get: () => resolveLayoutItemSize(child, childContainer, 'width'),
2733
+ set: () => { },
2734
+ configurable: true,
2735
+ });
2736
+ Object.defineProperty(wrapper, 'height', {
2737
+ get: () => resolveLayoutItemSize(child, childContainer, 'height'),
2738
+ set: () => { },
2739
+ configurable: true,
2740
+ });
2741
+ return wrapper;
2742
+ }
2743
+ function resolveLayoutItemSize(child, childContainer, key) {
2744
+ var _a, _b;
2745
+ 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]);
2746
+ if (Number.isFinite(transformSize) && transformSize > 0)
2747
+ return transformSize;
2748
+ const containerSize = Number(childContainer === null || childContainer === void 0 ? void 0 : childContainer[key]);
2749
+ return Number.isFinite(containerSize) ? containerSize : 0;
2750
+ }
2751
+ function getCollectedChildCount(go, childName) {
2752
+ var _a, _b, _c;
2753
+ const contentChild = findChildEntity(go, childName);
2754
+ 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;
2755
+ }
1882
2756
  function findChildEntity(go, name) {
1883
2757
  var _a, _b;
1884
2758
  if (!go)
@@ -1897,6 +2771,15 @@ function findChildEntity(go, name) {
1897
2771
  return tf.gameObject;
1898
2772
  }
1899
2773
  return null;
2774
+ }
2775
+ function getComponentSafe(go, componentName) {
2776
+ var _a;
2777
+ try {
2778
+ return (_a = go === null || go === void 0 ? void 0 : go.getComponent) === null || _a === void 0 ? void 0 : _a.call(go, componentName);
2779
+ }
2780
+ catch (_) {
2781
+ return undefined;
2782
+ }
1900
2783
  }
1901
2784
 
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 };
2785
+ 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 };