@galacean/effects-threejs 2.9.0-alpha.1 → 2.9.0-alpha.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.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Description: Galacean Effects runtime threejs plugin for the web
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 燃然,飂兮,十弦,云垣,茂安,意绮
6
- * Version: v2.9.0-alpha.1
6
+ * Version: v2.9.0-alpha.2
7
7
  */
8
8
 
9
9
  'use strict';
@@ -4119,7 +4119,7 @@ function getDirectStore(target) {
4119
4119
  function EffectsObject(engine) {
4120
4120
  this.engine = engine;
4121
4121
  this.guid = generateGUID();
4122
- this.defination = {};
4122
+ this.definition = {};
4123
4123
  this.engine.addInstance(this);
4124
4124
  }
4125
4125
  var _proto = EffectsObject.prototype;
@@ -7023,6 +7023,11 @@ function _create_class(Constructor, protoProps, staticProps) {
7023
7023
  // OVERRIDE
7024
7024
  };
7025
7025
  /**
7026
+ * 当父级或间接父级发生改变时调用
7027
+ */ _proto.onParentChanged = function onParentChanged() {
7028
+ // OVERRIDE
7029
+ };
7030
+ /**
7026
7031
  * @internal
7027
7032
  */ _proto.enable = function enable() {
7028
7033
  if (this.item.composition) {
@@ -9253,7 +9258,6 @@ exports.MaterialRenderType = void 0;
9253
9258
  for(var _iterator4 = _create_for_of_iterator_helper_loose(frameClipMasks), _step4; !(_step4 = _iterator4()).done;){
9254
9259
  var frameClipMask1 = _step4.value;
9255
9260
  this.removeMaskReference(frameClipMask1);
9256
- maskedComponent.frameClipMasks = [];
9257
9261
  }
9258
9262
  };
9259
9263
  /**
@@ -10691,7 +10695,6 @@ BoundingBox.tempVector2 = new Vector3();
10691
10695
  _this.materials = [];
10692
10696
  /**
10693
10697
  * @hidden
10694
- * @internal
10695
10698
  * Internal utility.
10696
10699
  * Not part of the public API — do not rely on this in your code.
10697
10700
  */ _this.frameClipMasks = [];
@@ -10715,6 +10718,9 @@ BoundingBox.tempVector2 = new Vector3();
10715
10718
  var _this_item_composition;
10716
10719
  (_this_item_composition = this.item.composition) == null ? void 0 : _this_item_composition.renderFrame.removeMeshFromDefaultRenderPass(this);
10717
10720
  };
10721
+ _proto.onParentChanged = function onParentChanged() {
10722
+ this.frameClipMasks = [];
10723
+ };
10718
10724
  /**
10719
10725
  * 获取包围盒信息
10720
10726
  */ _proto.getBoundingBoxInfo = function getBoundingBoxInfo() {
@@ -13233,6 +13239,7 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13233
13239
  if (!this.composition && vfxItem.composition) {
13234
13240
  this.composition = vfxItem.composition;
13235
13241
  }
13242
+ this.onParentChanged();
13236
13243
  if (!this.isDuringPlay && vfxItem.isDuringPlay) {
13237
13244
  this.awake();
13238
13245
  this.beginPlay();
@@ -13365,6 +13372,122 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13365
13372
  // OVERRIDE
13366
13373
  };
13367
13374
  /**
13375
+ * 对当前元素及其子节点进行射线命中测试
13376
+ *
13377
+ * @param ray - 射线
13378
+ * @param x - 归一化屏幕坐标 x
13379
+ * @param y - 归一化屏幕坐标 y
13380
+ * @param regions - 命中结果收集数组
13381
+ * @param hitPositions - 共享的命中位置数组,所有 region 共享同一引用
13382
+ * @param force - 是否强制测试无交互信息的元素
13383
+ * @param options - 额外选项(maxCount、stop、skip)
13384
+ * @returns 是否有任何命中
13385
+ */ _proto.hitTest = function hitTest(ray, x, y, regions, hitPositions, force, options) {
13386
+ var _this_composition;
13387
+ if (!this.isActive) {
13388
+ return false;
13389
+ }
13390
+ var hitTestSuccess = false;
13391
+ var maxCount = options == null ? void 0 : options.maxCount;
13392
+ var hitParams = this.getHitTestParams(force);
13393
+ // 1. 测试自身
13394
+ if (hitParams) {
13395
+ var clipMasks = hitParams.clipMasks;
13396
+ var clipPassed = true;
13397
+ if (clipMasks.length > 0 && !hitTestMask(ray, clipMasks)) {
13398
+ clipPassed = false;
13399
+ }
13400
+ if (clipPassed) {
13401
+ var success = false;
13402
+ var intersectPoint = new Vector3();
13403
+ if (hitParams.type === exports.HitTestType.triangle) {
13404
+ var triangles = hitParams.triangles, backfaceCulling = hitParams.backfaceCulling;
13405
+ for(var j = 0; j < triangles.length; j++){
13406
+ if (ray.intersectTriangle(triangles[j], intersectPoint, backfaceCulling)) {
13407
+ success = true;
13408
+ hitPositions.push(intersectPoint);
13409
+ break;
13410
+ }
13411
+ }
13412
+ } else if (hitParams.type === exports.HitTestType.box) {
13413
+ var center = hitParams.center, size = hitParams.size;
13414
+ var boxMin = center.clone().addScaledVector(size, 0.5);
13415
+ var boxMax = center.clone().addScaledVector(size, -0.5);
13416
+ if (ray.intersectBox({
13417
+ min: boxMin,
13418
+ max: boxMax
13419
+ }, intersectPoint)) {
13420
+ success = true;
13421
+ hitPositions.push(intersectPoint);
13422
+ }
13423
+ } else if (hitParams.type === exports.HitTestType.sphere) {
13424
+ var center1 = hitParams.center, radius = hitParams.radius;
13425
+ if (ray.intersectSphere({
13426
+ center: center1,
13427
+ radius: radius
13428
+ }, intersectPoint)) {
13429
+ success = true;
13430
+ hitPositions.push(intersectPoint);
13431
+ }
13432
+ } else if (hitParams.type === exports.HitTestType.custom) {
13433
+ var tempPosition = hitParams.collect(ray, new Vector2(x, y));
13434
+ if (tempPosition && tempPosition.length > 0) {
13435
+ tempPosition.forEach(function(pos) {
13436
+ hitPositions.push(pos);
13437
+ });
13438
+ success = true;
13439
+ }
13440
+ }
13441
+ if (success) {
13442
+ var _options_stop;
13443
+ var region = {
13444
+ id: this.getInstanceId(),
13445
+ name: this.name,
13446
+ position: hitPositions[hitPositions.length - 1],
13447
+ parentId: this.parentId,
13448
+ hitPositions: hitPositions,
13449
+ behavior: hitParams.behavior,
13450
+ item: this,
13451
+ composition: this.composition
13452
+ };
13453
+ regions.push(region);
13454
+ hitTestSuccess = true;
13455
+ if (options == null ? void 0 : (_options_stop = options.stop) == null ? void 0 : _options_stop.call(options, region)) {
13456
+ return true;
13457
+ }
13458
+ }
13459
+ }
13460
+ }
13461
+ // 2. 递归测试子节点
13462
+ for(var _iterator = _create_for_of_iterator_helper_loose(this.children), _step; !(_step = _iterator()).done;){
13463
+ var child = _step.value;
13464
+ var _options_skip;
13465
+ if (maxCount !== undefined && regions.length >= maxCount) {
13466
+ break;
13467
+ }
13468
+ if (options == null ? void 0 : (_options_skip = options.skip) == null ? void 0 : _options_skip.call(options, child)) {
13469
+ continue;
13470
+ }
13471
+ if (child.hitTest(ray, x, y, regions, hitPositions, force, options)) {
13472
+ hitTestSuccess = true;
13473
+ }
13474
+ }
13475
+ // 3. composition 元素:子元素命中时,将自身也加入结果(根元素除外)
13476
+ if (VFXItem.isComposition(this) && hitTestSuccess && this !== ((_this_composition = this.composition) == null ? void 0 : _this_composition.rootItem)) {
13477
+ regions.push({
13478
+ id: this.getInstanceId(),
13479
+ name: this.name,
13480
+ position: hitPositions[hitPositions.length - 1],
13481
+ parentId: this.parentId,
13482
+ hitPositions: hitPositions,
13483
+ behavior: InteractBehavior.NONE,
13484
+ item: this,
13485
+ composition: this.composition
13486
+ });
13487
+ }
13488
+ return hitTestSuccess;
13489
+ };
13490
+ /**
13368
13491
  * 获取元素当前世界坐标
13369
13492
  */ _proto.getCurrentPosition = function getCurrentPosition() {
13370
13493
  var pos = new Vector3();
@@ -13400,7 +13523,7 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13400
13523
  // 重新设置当前元素和组件的 ID 以及子元素和子元素组件的 ID,避免实例化新的对象时产生碰撞
13401
13524
  this.refreshGUIDRecursive();
13402
13525
  var newItem = this.engine.findObject({
13403
- id: this.defination.id
13526
+ id: this.definition.id
13404
13527
  });
13405
13528
  newItem.refreshGUIDRecursive();
13406
13529
  this.refreshGUIDRecursive(previousObjectIDMap);
@@ -13476,6 +13599,16 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13476
13599
  }
13477
13600
  }
13478
13601
  };
13602
+ _proto.onParentChanged = function onParentChanged() {
13603
+ for(var _iterator = _create_for_of_iterator_helper_loose(this.components), _step; !(_step = _iterator()).done;){
13604
+ var component = _step.value;
13605
+ component.onParentChanged();
13606
+ }
13607
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(this.children), _step1; !(_step1 = _iterator1()).done;){
13608
+ var child = _step1.value;
13609
+ child.onParentChanged();
13610
+ }
13611
+ };
13479
13612
  /**
13480
13613
  * @internal
13481
13614
  */ _proto.setRendererComponentOrder = function setRendererComponentOrder(renderOrder) {
@@ -13495,7 +13628,7 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13495
13628
  this.parentId = parentId;
13496
13629
  this.components.length = 0;
13497
13630
  if (VFXItem.isComposition(this)) {
13498
- var refId = this.defination.content.options.refId;
13631
+ var refId = this.definition.content.options.refId;
13499
13632
  var compositionData = this.engine.findEffectsObjectData(refId);
13500
13633
  if (!compositionData) {
13501
13634
  throw new Error("Referenced precomposition with Id: " + refId + " does not exist.");
@@ -13542,24 +13675,24 @@ exports.VFXItem = /*#__PURE__*/ function(EffectsObject) {
13542
13675
  };
13543
13676
  _proto.toData = function toData() {
13544
13677
  var _this_parent;
13545
- this.defination.id = this.guid;
13546
- this.defination.transform = this.transform.toData();
13547
- this.defination.dataType = DataType.VFXItemData;
13678
+ this.definition.id = this.guid;
13679
+ this.definition.transform = this.transform.toData();
13680
+ this.definition.dataType = DataType.VFXItemData;
13548
13681
  if (((_this_parent = this.parent) == null ? void 0 : _this_parent.name) !== "rootItem") {
13549
13682
  var _this_parent1;
13550
- this.defination.parentId = (_this_parent1 = this.parent) == null ? void 0 : _this_parent1.guid;
13683
+ this.definition.parentId = (_this_parent1 = this.parent) == null ? void 0 : _this_parent1.guid;
13551
13684
  }
13552
13685
  // TODO 统一 sprite 等其他组件的序列化逻辑
13553
- if (!this.defination.components) {
13554
- this.defination.components = [];
13686
+ if (!this.definition.components) {
13687
+ this.definition.components = [];
13555
13688
  for(var _iterator = _create_for_of_iterator_helper_loose(this.components), _step; !(_step = _iterator()).done;){
13556
13689
  var component = _step.value;
13557
13690
  if (_instanceof1(component, exports.EffectComponent)) {
13558
- this.defination.components.push(component);
13691
+ this.definition.components.push(component);
13559
13692
  }
13560
13693
  }
13561
13694
  }
13562
- this.defination.content = {};
13695
+ this.definition.content = {};
13563
13696
  };
13564
13697
  /**
13565
13698
  * 销毁元素
@@ -13816,6 +13949,47 @@ exports.Item = void 0;
13816
13949
  }
13817
13950
  Item.isNull = isNull;
13818
13951
  })(exports.Item || (exports.Item = {}));
13952
+ /**
13953
+ * 遮罩命中测试:检查射线是否通过所有遮罩区域
13954
+ * 根据每个遮罩的 transform(size、scale、position、rotation、anchor)构建世界空间矩形,
13955
+ * 然后检测射线是否与该矩形相交。所有遮罩都必须通过才算测试通过。
13956
+ * @param ray - 射线
13957
+ * @param clipMasks - 遮罩列表
13958
+ * @returns 射线是否通过所有遮罩测试
13959
+ */ function hitTestMask(ray, clipMasks) {
13960
+ for(var _iterator = _create_for_of_iterator_helper_loose(clipMasks), _step; !(_step = _iterator()).done;){
13961
+ var mask = _step.value;
13962
+ var item = mask.item;
13963
+ if (!item.isActive || !item.transform.getValid()) {
13964
+ continue;
13965
+ }
13966
+ var transform = item.transform;
13967
+ var worldMatrix = transform.getWorldMatrix();
13968
+ var sx = transform.size.x;
13969
+ var sy = transform.size.y;
13970
+ // 将遮罩矩形的四个顶点从本地空间变换到世界空间
13971
+ // 本地空间顶点为单位矩形 (-0.5, -0.5) 到 (0.5, 0.5),按 size 缩放
13972
+ var p0 = new Vector3(-0.5 * sx, 0.5 * sy, 0).applyMatrix(worldMatrix);
13973
+ var p1 = new Vector3(-0.5 * sx, -0.5 * sy, 0).applyMatrix(worldMatrix);
13974
+ var p2 = new Vector3(0.5 * sx, 0.5 * sy, 0).applyMatrix(worldMatrix);
13975
+ var p3 = new Vector3(0.5 * sx, -0.5 * sy, 0).applyMatrix(worldMatrix);
13976
+ // 矩形由两个三角形组成,检测射线与任一三角形的相交
13977
+ var triangle1 = {
13978
+ p0: p0,
13979
+ p1: p1,
13980
+ p2: p2
13981
+ };
13982
+ var triangle2 = {
13983
+ p0: p2,
13984
+ p1: p1,
13985
+ p2: p3
13986
+ };
13987
+ if (!ray.intersectTriangle(triangle1) && !ray.intersectTriangle(triangle2)) {
13988
+ return false;
13989
+ }
13990
+ }
13991
+ return true;
13992
+ }
13819
13993
 
13820
13994
  var toHalf = function() {
13821
13995
  var floatView = new Float32Array(1);
@@ -17423,7 +17597,7 @@ function triangulate(contours) {
17423
17597
  */ _proto.getY = function getY() {
17424
17598
  return this.points[this.points.length - 1];
17425
17599
  };
17426
- _proto.build = function build(points) {
17600
+ _proto.build = function build(points, screenScale) {
17427
17601
  for(var i = 0; i < this.points.length; i++){
17428
17602
  points[i] = this.points[i];
17429
17603
  }
@@ -17525,11 +17699,10 @@ var RECURSION_LIMIT = 8;
17525
17699
  var FLT_EPSILON = 1.19209290e-7;
17526
17700
  var PATH_DISTANCE_EPSILON = 1.0;
17527
17701
  var defaultBezierSmoothness = 0.5;
17528
- function buildAdaptiveBezier(points, sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, smoothness) {
17529
- // TODO expose as a parameter
17530
- var scale = 5;
17702
+ function buildAdaptiveBezier(points, sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, smoothness, scale) {
17703
+ var s = scale != null ? scale : 1;
17531
17704
  var smoothing = Math.min(0.99, Math.max(0, smoothness != null ? smoothness : defaultBezierSmoothness));
17532
- var distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
17705
+ var distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / s;
17533
17706
  distanceTolerance *= distanceTolerance;
17534
17707
  begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);
17535
17708
  return points;
@@ -17719,7 +17892,7 @@ function recursive(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, le
17719
17892
  _proto.getY = function getY() {
17720
17893
  return this.y;
17721
17894
  };
17722
- _proto.build = function build(points) {
17895
+ _proto.build = function build(points, screenScale) {
17723
17896
  var x = this.x;
17724
17897
  var y = this.y;
17725
17898
  var rx = this.halfWidth;
@@ -17729,9 +17902,10 @@ function recursive(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, le
17729
17902
  if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
17730
17903
  return points;
17731
17904
  }
17732
- // Choose a number of segments such that the maximum absolute deviation from the circle is approximately 0.029
17733
- var sampleDensity = 5;
17734
- var n = Math.ceil(sampleDensity * Math.sqrt(rx + ry));
17905
+ // n 个等分段逼近四分之一椭圆弧,最大弦高误差 ε = R·π²/(8n²)
17906
+ // 屏幕误差 = ε × ppu = ppu·R·π²/(8n²),令 n = √(ppu·(rx+ry)),则误差 ≈ π²/8 ≈ 1.2px
17907
+ var ppu = screenScale != null ? screenScale : 1;
17908
+ var n = Math.ceil(Math.sqrt(ppu * (rx + ry)));
17735
17909
  var m = n * 8 + (0) + (0);
17736
17910
  if (m === 0) {
17737
17911
  return points;
@@ -17866,7 +18040,7 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
17866
18040
  _proto.copyTo = function copyTo(destination) {
17867
18041
  destination.copyFrom(this);
17868
18042
  };
17869
- _proto.build = function build(points) {
18043
+ _proto.build = function build(points, screenScale) {
17870
18044
  switch(this.starType){
17871
18045
  case 0:
17872
18046
  {
@@ -17879,13 +18053,13 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
17879
18053
  break;
17880
18054
  }
17881
18055
  }
17882
- var smoothness = 1;
18056
+ var ppu = screenScale != null ? screenScale : 1;
17883
18057
  for(var i = 0; i < this.v.length - 2; i += 2){
17884
- buildAdaptiveBezier(points, this.v[i], this.v[i + 1], this.out[i], this.out[i + 1], this.in[i + 2], this.in[i + 3], this.v[i + 2], this.v[i + 3], smoothness);
18058
+ buildAdaptiveBezier(points, this.v[i], this.v[i + 1], this.out[i], this.out[i + 1], this.in[i + 2], this.in[i + 3], this.v[i + 2], this.v[i + 3], undefined, ppu);
17885
18059
  }
17886
18060
  // draw last curve
17887
18061
  var lastIndex = this.v.length - 1;
17888
- buildAdaptiveBezier(points, this.v[lastIndex - 1], this.v[lastIndex], this.out[lastIndex - 1], this.out[lastIndex], this.in[0], this.in[1], this.v[0], this.v[1], smoothness);
18062
+ buildAdaptiveBezier(points, this.v[lastIndex - 1], this.v[lastIndex], this.out[lastIndex - 1], this.out[lastIndex], this.in[0], this.in[1], this.v[0], this.v[1], undefined, ppu);
17889
18063
  };
17890
18064
  _proto.triangulate = function triangulate1(points, vertices, verticesOffset, indices, indicesOffset) {
17891
18065
  var triangles = triangulate([
@@ -18030,7 +18204,7 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
18030
18204
  rectangle.copyFrom(this);
18031
18205
  return rectangle;
18032
18206
  };
18033
- _proto.build = function build(points) {
18207
+ _proto.build = function build(points, screenScale) {
18034
18208
  var ry;
18035
18209
  var halfWidth = this.width / 2;
18036
18210
  var halfHeight = this.height / 2;
@@ -18042,10 +18216,10 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
18042
18216
  if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
18043
18217
  return;
18044
18218
  }
18045
- // 控制边缘的平滑程度
18046
- var densityScale = 5;
18047
- // Choose a number of segments such that the maximum absolute deviation from the circle is approximately 0.029
18048
- var n = densityScale * Math.ceil(2.3 * Math.sqrt(rx + ry));
18219
+ // n 个等分段逼近四分之一圆角弧,最大弦高误差 ε = R·π²/(8n²)
18220
+ // 屏幕误差 = ε × ppu,令 n = √(ppu·(rx+ry)),则误差 ≈ π²/8 ≈ 1.2px
18221
+ var ppu = screenScale != null ? screenScale : 1;
18222
+ var n = Math.ceil(Math.sqrt(ppu * (rx + ry)));
18049
18223
  var m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
18050
18224
  if (m === 0) {
18051
18225
  return;
@@ -18254,7 +18428,7 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
18254
18428
  _proto.getY = function getY() {
18255
18429
  return this.y;
18256
18430
  };
18257
- _proto.build = function build(points) {
18431
+ _proto.build = function build(points, screenScale) {
18258
18432
  points[0] = this.x;
18259
18433
  points[1] = this.y;
18260
18434
  points[2] = this.x2;
@@ -18471,7 +18645,7 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
18471
18645
  circle.copyFrom(this);
18472
18646
  return circle;
18473
18647
  };
18474
- _proto.build = function build(points) {
18648
+ _proto.build = function build(points, screenScale) {
18475
18649
  var x = this.x;
18476
18650
  var y = this.y;
18477
18651
  var dx = 0;
@@ -18481,8 +18655,10 @@ var PolyStar = /*#__PURE__*/ function(ShapePrimitive) {
18481
18655
  if (rx <= 0) {
18482
18656
  return;
18483
18657
  }
18484
- // Choose a number of segments such that the maximum absolute deviation from the circle is approximately 0.029
18485
- var n = Math.ceil(2.3 * Math.sqrt(rx + ry));
18658
+ // n 个等分段逼近四分之一圆弧,最大弦高误差 ε = R·π²/(8n²)
18659
+ // 屏幕误差 = ε × ppu = ppu·R·π²/(8n²),令 n = √(ppu·(rx+ry)),则误差 ≈ π²/8 ≈ 1.2px
18660
+ var ppu = screenScale != null ? screenScale : 1;
18661
+ var n = Math.ceil(Math.sqrt(ppu * (rx + ry)));
18486
18662
  var m = n * 8 + (0) + (0);
18487
18663
  if (m === 0) {
18488
18664
  return;
@@ -18592,7 +18768,7 @@ var ShapePath = /*#__PURE__*/ function() {
18592
18768
  switch(action){
18593
18769
  case "bezierCurveTo":
18594
18770
  {
18595
- this.bezierCurveTo(data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
18771
+ this.bezierCurveTo(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
18596
18772
  break;
18597
18773
  }
18598
18774
  case "moveTo":
@@ -18651,10 +18827,10 @@ var ShapePath = /*#__PURE__*/ function() {
18651
18827
  * @param y - The y-coordinate of the end point.
18652
18828
  * @param smoothness - Optional parameter to adjust the smoothness of the curve.
18653
18829
  * @returns The instance of the current object for chaining.
18654
- */ _proto.bezierCurveTo = function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
18830
+ */ _proto.bezierCurveTo = function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness, scale) {
18655
18831
  this.ensurePoly();
18656
18832
  var currentPoly = this.currentPoly;
18657
- buildAdaptiveBezier(currentPoly.points, currentPoly.lastX, currentPoly.lastY, cp1x, cp1y, cp2x, cp2y, x, y, smoothness);
18833
+ buildAdaptiveBezier(currentPoly.points, currentPoly.lastX, currentPoly.lastY, cp1x, cp1y, cp2x, cp2y, x, y, smoothness, scale);
18658
18834
  return this;
18659
18835
  };
18660
18836
  _proto.moveTo = function moveTo(x, y) {
@@ -18819,7 +18995,7 @@ var GraphicsPath = /*#__PURE__*/ function() {
18819
18995
  * @param y - The y-coordinate of the end point.
18820
18996
  * @param smoothness - Optional parameter to adjust the smoothness of the curve.
18821
18997
  * @returns The instance of the current object for chaining.
18822
- */ _proto.bezierCurveTo = function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
18998
+ */ _proto.bezierCurveTo = function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness, scale) {
18823
18999
  this.instructions.push({
18824
19000
  action: "bezierCurveTo",
18825
19001
  data: [
@@ -18829,7 +19005,8 @@ var GraphicsPath = /*#__PURE__*/ function() {
18829
19005
  cp2y,
18830
19006
  x,
18831
19007
  y,
18832
- smoothness
19008
+ smoothness,
19009
+ scale
18833
19010
  ]
18834
19011
  });
18835
19012
  this.dirty = true;
@@ -19130,28 +19307,6 @@ exports.CompositionComponent = /*#__PURE__*/ function(Component) {
19130
19307
  return item.dispose();
19131
19308
  });
19132
19309
  };
19133
- _proto.hitTest = function hitTest(ray, x, y, regions, force, options) {
19134
- var _this_item_composition;
19135
- var isHitTestSuccess = hitTestRecursive(this.item, ray, x, y, regions, force, options);
19136
- // 子元素碰撞测试成功加入当前预合成元素,判断是否是合成根元素,根元素不加入
19137
- if (isHitTestSuccess && this.item !== ((_this_item_composition = this.item.composition) == null ? void 0 : _this_item_composition.rootItem)) {
19138
- var item = this.item;
19139
- var lastRegion = regions[regions.length - 1];
19140
- var hitPositions = lastRegion.hitPositions;
19141
- var region = {
19142
- id: item.getInstanceId(),
19143
- name: item.name,
19144
- position: hitPositions[hitPositions.length - 1],
19145
- parentId: item.parentId,
19146
- hitPositions: hitPositions,
19147
- behavior: InteractBehavior.NONE,
19148
- item: item,
19149
- composition: item.composition
19150
- };
19151
- regions.push(region);
19152
- }
19153
- return isHitTestSuccess;
19154
- };
19155
19310
  /**
19156
19311
  * 设置当前合成子元素的渲染顺序
19157
19312
  *
@@ -19261,98 +19416,6 @@ __decorate([
19261
19416
  exports.CompositionComponent = __decorate([
19262
19417
  effectsClass("CompositionComponent")
19263
19418
  ], exports.CompositionComponent);
19264
- function hitTestRecursive(item, ray, x, y, regions, force, options) {
19265
- var _loop = function() {
19266
- var hitTestItem = _step.value;
19267
- if (hitTestItem.isActive && hitTestItem.transform.getValid() && !skip(hitTestItem)) {
19268
- var hitParams = hitTestItem.getHitTestParams(force);
19269
- if (hitParams) {
19270
- var success = false;
19271
- var intersectPoint = new Vector3();
19272
- if (hitParams.type === exports.HitTestType.triangle) {
19273
- var triangles = hitParams.triangles, backfaceCulling = hitParams.backfaceCulling;
19274
- for(var j = 0; j < triangles.length; j++){
19275
- var triangle = triangles[j];
19276
- if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
19277
- success = true;
19278
- hitPositions.push(intersectPoint);
19279
- break;
19280
- }
19281
- }
19282
- } else if (hitParams.type === exports.HitTestType.box) {
19283
- var center = hitParams.center, size = hitParams.size;
19284
- var boxMin = center.clone().addScaledVector(size, 0.5);
19285
- var boxMax = center.clone().addScaledVector(size, -0.5);
19286
- if (ray.intersectBox({
19287
- min: boxMin,
19288
- max: boxMax
19289
- }, intersectPoint)) {
19290
- success = true;
19291
- hitPositions.push(intersectPoint);
19292
- }
19293
- } else if (hitParams.type === exports.HitTestType.sphere) {
19294
- var center1 = hitParams.center, radius = hitParams.radius;
19295
- if (ray.intersectSphere({
19296
- center: center1,
19297
- radius: radius
19298
- }, intersectPoint)) {
19299
- success = true;
19300
- hitPositions.push(intersectPoint);
19301
- }
19302
- } else if (hitParams.type === exports.HitTestType.custom) {
19303
- var tempPosition = hitParams.collect(ray, new Vector2(x, y));
19304
- if (tempPosition && tempPosition.length > 0) {
19305
- tempPosition.forEach(function(pos) {
19306
- hitPositions.push(pos);
19307
- });
19308
- success = true;
19309
- }
19310
- }
19311
- if (success) {
19312
- var region = {
19313
- id: hitTestItem.getInstanceId(),
19314
- name: hitTestItem.name,
19315
- position: hitPositions[hitPositions.length - 1],
19316
- parentId: hitTestItem.parentId,
19317
- hitPositions: hitPositions,
19318
- behavior: hitParams.behavior,
19319
- item: hitTestItem,
19320
- composition: hitTestItem.composition
19321
- };
19322
- regions.push(region);
19323
- hitTestSuccess = true;
19324
- if (stop(region)) {
19325
- return {
19326
- v: true
19327
- };
19328
- }
19329
- }
19330
- }
19331
- }
19332
- if (exports.VFXItem.isComposition(hitTestItem)) {
19333
- if (hitTestItem.getComponent(exports.CompositionComponent).hitTest(ray, x, y, regions, force, options)) {
19334
- hitTestSuccess = true;
19335
- }
19336
- } else {
19337
- if (hitTestRecursive(hitTestItem, ray, x, y, regions, force, options)) {
19338
- hitTestSuccess = true;
19339
- }
19340
- }
19341
- };
19342
- var hitPositions = [];
19343
- var stop = (options == null ? void 0 : options.stop) || noop;
19344
- var skip = (options == null ? void 0 : options.skip) || noop;
19345
- var maxCount = options == null ? void 0 : options.maxCount;
19346
- if (maxCount !== undefined && regions.length >= maxCount) {
19347
- return false;
19348
- }
19349
- var hitTestSuccess = false;
19350
- for(var _iterator = _create_for_of_iterator_helper_loose(item.children), _step; !(_step = _iterator()).done;){
19351
- var _ret = _loop();
19352
- if (_type_of(_ret) === "object") return _ret.v;
19353
- }
19354
- return hitTestSuccess;
19355
- }
19356
19419
 
19357
19420
  /**
19358
19421
  * Mesh 组件
@@ -19369,7 +19432,8 @@ function hitTestRecursive(item, ray, x, y, regions, force, options) {
19369
19432
  if (area) {
19370
19433
  return {
19371
19434
  type: area.type,
19372
- triangles: area.area
19435
+ triangles: area.area,
19436
+ clipMasks: _this.frameClipMasks
19373
19437
  };
19374
19438
  }
19375
19439
  };
@@ -21508,7 +21572,8 @@ var Graphics = /*#__PURE__*/ function() {
21508
21572
  behavior: ((_this_interaction = _this.interaction) == null ? void 0 : _this_interaction.behavior) || 0,
21509
21573
  type: area.type,
21510
21574
  triangles: area.area,
21511
- backfaceCulling: _this.renderer.side === SideMode.FRONT
21575
+ backfaceCulling: _this.renderer.side === SideMode.FRONT,
21576
+ clipMasks: _this.frameClipMasks
21512
21577
  };
21513
21578
  }
21514
21579
  }
@@ -21807,7 +21872,8 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
21807
21872
  behavior: 0,
21808
21873
  type: area.type,
21809
21874
  triangles: area.area,
21810
- backfaceCulling: _this.rendererOptions.side === SideMode.FRONT
21875
+ backfaceCulling: _this.rendererOptions.side === SideMode.FRONT,
21876
+ clipMasks: _this.frameClipMasks
21811
21877
  };
21812
21878
  }
21813
21879
  }
@@ -21910,8 +21976,9 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
21910
21976
  };
21911
21977
  _proto.onUpdate = function onUpdate(dt) {
21912
21978
  if (this.shapeDirty) {
21913
- this.buildPath(this.shapeAttributes);
21914
- this.buildGeometryFromPath(this.graphicsPath.shapePath);
21979
+ var screenScale = this.computeScreenScale();
21980
+ this.buildPath(this.shapeAttributes, screenScale);
21981
+ this.buildGeometryFromPath(this.graphicsPath.shapePath, screenScale);
21915
21982
  this.shapeDirty = false;
21916
21983
  }
21917
21984
  if (this.materialDirty) {
@@ -21962,7 +22029,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
21962
22029
  }
21963
22030
  return this.boundingBoxInfo;
21964
22031
  };
21965
- _proto.buildGeometryFromPath = function buildGeometryFromPath(shapePath) {
22032
+ _proto.buildGeometryFromPath = function buildGeometryFromPath(shapePath, screenScale) {
21966
22033
  var shapePrimitives = shapePath.shapePrimitives;
21967
22034
  var vertices = [];
21968
22035
  var indices = [];
@@ -21974,7 +22041,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
21974
22041
  var points = [];
21975
22042
  var indexOffset = indices.length;
21976
22043
  var vertOffset = vertices.length / 2;
21977
- shape.build(points);
22044
+ shape.build(points, screenScale);
21978
22045
  shape.triangulate(points, vertices, vertOffset, indices, indexOffset);
21979
22046
  }
21980
22047
  }
@@ -21994,7 +22061,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
21994
22061
  if (this.shapeAttributes.type === ShapePrimitiveType.Custom) {
21995
22062
  close = shape1.closePath;
21996
22063
  }
21997
- shape1.build(points1);
22064
+ shape1.build(points1, screenScale);
21998
22065
  buildLine(points1, lineStyle, false, close, vertices, 2, vertOffset1, indices);
21999
22066
  }
22000
22067
  }
@@ -22054,8 +22121,40 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
22054
22121
  strokeSubMesh.offset = fillIndexCount * u16Size;
22055
22122
  strokeSubMesh.indexCount = strokeIndexCount;
22056
22123
  };
22057
- _proto.buildPath = function buildPath(shapeAttribute) {
22124
+ _proto.computeScreenScale = function computeScreenScale() {
22125
+ var defaultPpu = 1;
22126
+ var composition = this.item.composition;
22127
+ if (!composition) {
22128
+ return defaultPpu;
22129
+ }
22130
+ var camera = composition.camera;
22131
+ if (!camera) {
22132
+ return defaultPpu;
22133
+ }
22134
+ var mvp = camera.getModelViewProjection(ShapeComponent.tempMVP, this.transform.getWorldMatrix());
22135
+ var e = mvp.elements;
22136
+ // 列优先:col0=[e[0],e[1]], col1=[e[4],e[5]]
22137
+ // 透视投影下 MVP 不含 w-divide,cols 0-1 的长度是 clip-space 缩放
22138
+ // 需要除以物体中心的 w 值才能得到 NDC 缩放
22139
+ // 物体局部原点 [0,0,0,1] 经 MVP 后 w = e[15](≈ 物体到相机距离)
22140
+ var w = Math.abs(e[15]) || 1;
22141
+ var sx = Math.sqrt(e[0] * e[0] + e[1] * e[1]) / w;
22142
+ var sy = Math.sqrt(e[4] * e[4] + e[5] * e[5]) / w;
22143
+ var maxNdcScale = Math.max(sx, sy);
22144
+ // NDC -> 像素: canvasSize / 2
22145
+ var canvasRect = this.engine.canvas.getBoundingClientRect();
22146
+ var ndcToPixels = Math.max(canvasRect.width, canvasRect.height) / 2;
22147
+ // pixelsPerUnit: 1个局部空间单位在屏幕上对应多少像素
22148
+ // 椭圆/圆/矩形中使用 n = ceil(√(ppu × (rx+ry))) 确保圆弧误差 ≈ 1.2px
22149
+ var pixelsPerUnit = maxNdcScale * ndcToPixels * this.engine.pixelRatio;
22150
+ var minPpu = 1;
22151
+ var maxPpu = 2000;
22152
+ return Math.max(minPpu, Math.min(maxPpu, pixelsPerUnit));
22153
+ };
22154
+ _proto.buildPath = function buildPath(shapeAttribute, screenScale) {
22155
+ if (screenScale === void 0) screenScale = 1;
22058
22156
  this.graphicsPath.clear();
22157
+ var ppu = screenScale;
22059
22158
  switch(shapeAttribute.type){
22060
22159
  case ShapePrimitiveType.Custom:
22061
22160
  {
@@ -22075,7 +22174,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
22075
22174
  var lastPoint = points[lastPointIndex.point];
22076
22175
  var control1 = easingOuts[lastPointIndex.easingOut];
22077
22176
  var control2 = easingIns[pointIndex.easingIn];
22078
- this.graphicsPath.bezierCurveTo(control1.x + lastPoint.x, control1.y + lastPoint.y, control2.x + point.x, control2.y + point.y, point.x, point.y, 1);
22177
+ this.graphicsPath.bezierCurveTo(control1.x + lastPoint.x, control1.y + lastPoint.y, control2.x + point.x, control2.y + point.y, point.x, point.y, undefined, ppu);
22079
22178
  }
22080
22179
  if (shape.close) {
22081
22180
  var pointIndex1 = indices[0];
@@ -22084,7 +22183,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
22084
22183
  var lastPoint1 = points[lastPointIndex1.point];
22085
22184
  var control11 = easingOuts[lastPointIndex1.easingOut];
22086
22185
  var control21 = easingIns[pointIndex1.easingIn];
22087
- this.graphicsPath.bezierCurveTo(control11.x + lastPoint1.x, control11.y + lastPoint1.y, control21.x + point1.x, control21.y + point1.y, point1.x, point1.y, 1);
22186
+ this.graphicsPath.bezierCurveTo(control11.x + lastPoint1.x, control11.y + lastPoint1.y, control21.x + point1.x, control21.y + point1.y, point1.x, point1.y, undefined, ppu);
22088
22187
  this.graphicsPath.closePath();
22089
22188
  }
22090
22189
  }
@@ -22379,6 +22478,7 @@ exports.ShapeComponent = /*#__PURE__*/ function(RendererComponent) {
22379
22478
  ]);
22380
22479
  return ShapeComponent;
22381
22480
  }(RendererComponent);
22481
+ exports.ShapeComponent.tempMVP = Matrix4.fromIdentity();
22382
22482
  exports.ShapeComponent = __decorate([
22383
22483
  effectsClass("ShapeComponent")
22384
22484
  ], exports.ShapeComponent);
@@ -22525,7 +22625,8 @@ exports.FrameComponent = /*#__PURE__*/ function(RendererComponent1) {
22525
22625
  if (area) {
22526
22626
  return {
22527
22627
  type: area.type,
22528
- triangles: area.area
22628
+ triangles: area.area,
22629
+ clipMasks: _this.frameClipMasks
22529
22630
  };
22530
22631
  }
22531
22632
  }
@@ -22638,7 +22739,7 @@ exports.FrameComponent = /*#__PURE__*/ function(RendererComponent1) {
22638
22739
  var child = _step.value;
22639
22740
  var childFrameComponent = child.getComponent(RendererComponent);
22640
22741
  if (childFrameComponent) {
22641
- childFrameComponent.frameClipMasks.push(this);
22742
+ addItem(childFrameComponent.frameClipMasks, this);
22642
22743
  }
22643
22744
  this.setClipRectangleRecursive(child);
22644
22745
  }
@@ -23175,7 +23276,8 @@ exports.InteractComponent = /*#__PURE__*/ function(RendererComponent) {
23175
23276
  return {
23176
23277
  type: area.type,
23177
23278
  triangles: area.area,
23178
- behavior: behavior
23279
+ behavior: behavior,
23280
+ clipMasks: _this.frameClipMasks
23179
23281
  };
23180
23282
  }
23181
23283
  };
@@ -27579,6 +27681,7 @@ exports.ParticleSystem = /*#__PURE__*/ function(Component) {
27579
27681
  if (force || interactParams) {
27580
27682
  return {
27581
27683
  type: exports.HitTestType.custom,
27684
+ clipMasks: _this.renderer.frameClipMasks,
27582
27685
  collect: function(ray) {
27583
27686
  return _this.raycast({
27584
27687
  radius: (interactParams == null ? void 0 : interactParams.radius) || 0.4,
@@ -29314,13 +29417,14 @@ var TextLayout = /*#__PURE__*/ function() {
29314
29417
  }
29315
29418
  var _proto = TextLayout.prototype;
29316
29419
  _proto.update = function update(options) {
29317
- var _options_textHeight = options.textHeight, textHeight = _options_textHeight === void 0 ? 100 : _options_textHeight, _options_textWidth = options.textWidth, textWidth = _options_textWidth === void 0 ? 100 : _options_textWidth, _options_textOverflow = options.textOverflow, textOverflow = _options_textOverflow === void 0 ? TextOverflow.clip : _options_textOverflow, _options_textVerticalAlign = options.textVerticalAlign, textVerticalAlign = _options_textVerticalAlign === void 0 ? TextVerticalAlign.top : _options_textVerticalAlign, _options_textAlign = options.textAlign, textAlign = _options_textAlign === void 0 ? TextAlignment.left : _options_textAlign, _options_letterSpace = options.letterSpace, letterSpace = _options_letterSpace === void 0 ? 0 : _options_letterSpace, fontSize = options.fontSize, _options_lineHeight = options.lineHeight, lineHeight = _options_lineHeight === void 0 ? fontSize : _options_lineHeight;
29420
+ var _options_textHeight = options.textHeight, textHeight = _options_textHeight === void 0 ? 100 : _options_textHeight, _options_textWidth = options.textWidth, textWidth = _options_textWidth === void 0 ? 100 : _options_textWidth, _options_textOverflow = options.textOverflow, textOverflow = _options_textOverflow === void 0 ? TextOverflow.clip : _options_textOverflow, _options_textVerticalAlign = options.textVerticalAlign, textVerticalAlign = _options_textVerticalAlign === void 0 ? TextVerticalAlign.top : _options_textVerticalAlign, _options_textAlign = options.textAlign, textAlign = _options_textAlign === void 0 ? TextAlignment.left : _options_textAlign, _options_letterSpace = options.letterSpace, letterSpace = _options_letterSpace === void 0 ? 0 : _options_letterSpace, fontSize = options.fontSize, _options_lineHeight = options.lineHeight, lineHeight = _options_lineHeight === void 0 ? fontSize : _options_lineHeight, _options_autoResize = options.autoResize, autoResize = _options_autoResize === void 0 ? TextSizeMode.fixed : _options_autoResize;
29318
29421
  this.letterSpace = letterSpace;
29319
29422
  this.overflow = textOverflow;
29320
29423
  this.textVerticalAlign = textVerticalAlign;
29321
29424
  this.textAlign = textAlign;
29322
29425
  this.width = textWidth;
29323
29426
  this.height = textHeight;
29427
+ this.autoResize = autoResize;
29324
29428
  this.lineHeight = lineHeight;
29325
29429
  };
29326
29430
  /**
@@ -29332,7 +29436,6 @@ var TextLayout = /*#__PURE__*/ function() {
29332
29436
  * @param totalLineHeight - 可选的实际总行高,用于替代默认计算
29333
29437
  * @returns - 行高偏移值
29334
29438
  */ _proto.getOffsetY = function getOffsetY(style, lineCount, lineHeight, fontSize, totalLineHeight) {
29335
- var fontScale = style.fontScale;
29336
29439
  // /3 计算Y轴偏移量,以匹配编辑器行为
29337
29440
  var offsetY = (lineHeight - fontSize) / 3;
29338
29441
  // 计算基础偏移量
@@ -29344,10 +29447,10 @@ var TextLayout = /*#__PURE__*/ function() {
29344
29447
  offsetResult = baseOffset + offsetY;
29345
29448
  break;
29346
29449
  case TextVerticalAlign.middle:
29347
- offsetResult = (this.height * fontScale - commonCalculation + baseOffset) / 2;
29450
+ offsetResult = (this.height - commonCalculation + baseOffset) / 2;
29348
29451
  break;
29349
29452
  case TextVerticalAlign.bottom:
29350
- offsetResult = this.height * fontScale - commonCalculation - offsetY;
29453
+ offsetResult = this.height - commonCalculation - offsetY;
29351
29454
  break;
29352
29455
  }
29353
29456
  return offsetResult;
@@ -29364,10 +29467,10 @@ var TextLayout = /*#__PURE__*/ function() {
29364
29467
  offsetX = 0;
29365
29468
  break;
29366
29469
  case TextAlignment.middle:
29367
- offsetX = (this.width * style.fontScale - maxWidth) / 2;
29470
+ offsetX = (this.width - maxWidth) / 2;
29368
29471
  break;
29369
29472
  case TextAlignment.right:
29370
- offsetX = this.width * style.fontScale - maxWidth;
29473
+ offsetX = this.width - maxWidth;
29371
29474
  break;
29372
29475
  }
29373
29476
  return offsetX;
@@ -29620,8 +29723,8 @@ var TextStyle = /*#__PURE__*/ function() {
29620
29723
  };
29621
29724
  // 通用工具方法
29622
29725
  _proto.getFontDesc = function getFontDesc(size) {
29623
- var _this_textStyle = this.textStyle, fontSize = _this_textStyle.fontSize, fontScale = _this_textStyle.fontScale, fontFamily = _this_textStyle.fontFamily, textWeight = _this_textStyle.textWeight, fontStyle = _this_textStyle.fontStyle;
29624
- var fontDesc = "" + (size || fontSize * fontScale).toString() + "px ";
29726
+ var _this_textStyle = this.textStyle, fontSize = _this_textStyle.fontSize, fontFamily = _this_textStyle.fontFamily, textWeight = _this_textStyle.textWeight, fontStyle = _this_textStyle.fontStyle;
29727
+ var fontDesc = "" + (size || fontSize).toString() + "px ";
29625
29728
  if (![
29626
29729
  "serif",
29627
29730
  "sans-serif",
@@ -29651,13 +29754,13 @@ var TextStyle = /*#__PURE__*/ function() {
29651
29754
  };
29652
29755
  _proto.setupShadow = function setupShadow() {
29653
29756
  var context = this.context;
29654
- var _this_textStyle = this.textStyle, shadowColor = _this_textStyle.shadowColor, shadowBlur = _this_textStyle.shadowBlur, shadowOffsetX = _this_textStyle.shadowOffsetX, shadowOffsetY = _this_textStyle.shadowOffsetY;
29757
+ var _this_textStyle = this.textStyle, shadowColor = _this_textStyle.shadowColor, shadowBlur = _this_textStyle.shadowBlur, shadowOffsetX = _this_textStyle.shadowOffsetX, shadowOffsetY = _this_textStyle.shadowOffsetY, fontScale = _this_textStyle.fontScale;
29655
29758
  var r = shadowColor[0], g = shadowColor[1], b = shadowColor[2], a = shadowColor[3];
29656
29759
  if (context) {
29657
29760
  context.shadowColor = "rgba(" + r * 255 + ", " + g * 255 + ", " + b * 255 + ", " + a + ")";
29658
- context.shadowBlur = shadowBlur;
29659
- context.shadowOffsetX = shadowOffsetX;
29660
- context.shadowOffsetY = -shadowOffsetY;
29761
+ context.shadowBlur = shadowBlur * fontScale;
29762
+ context.shadowOffsetX = shadowOffsetX * fontScale;
29763
+ context.shadowOffsetY = -shadowOffsetY * fontScale;
29661
29764
  }
29662
29765
  };
29663
29766
  // 通用纹理生命周期管理
@@ -29902,30 +30005,40 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
29902
30005
  layout.width = this.getTextWidth();
29903
30006
  this.lineCount = this.getLineCount(this.text);
29904
30007
  layout.height = layout.lineHeight * this.lineCount;
30008
+ } else if (layout.autoResize === TextSizeMode.autoHeight) {
30009
+ this.lineCount = this.getLineCount(this.text);
30010
+ layout.height = layout.lineHeight * this.lineCount;
29905
30011
  } else {
29906
30012
  this.lineCount = this.getLineCount(this.text);
29907
30013
  }
29908
- var baseWidth = (layout.width + style.fontOffset) * fontScale;
29909
- var baseHeight = layout.height * fontScale;
29910
- var fontSize = style.fontSize * fontScale;
29911
- var lineHeight = layout.lineHeight * fontScale;
30014
+ var baseWidth = layout.width + style.fontOffset;
30015
+ var baseHeight = layout.height;
30016
+ var fontSize = style.fontSize;
30017
+ var lineHeight = layout.lineHeight;
29912
30018
  style.fontDesc = this.getFontDesc(fontSize);
29913
30019
  // 使用 Array.from 正确分割 Unicode 字符(包括 emoji)
29914
30020
  var char = Array.from(this.text || "");
29915
30021
  var _this_getEffectPadding = this.getEffectPadding(), padL = _this_getEffectPadding.padL, padR = _this_getEffectPadding.padR, padT = _this_getEffectPadding.padT, padB = _this_getEffectPadding.padB;
29916
30022
  var hasEffect = (padL | padR | padT | padB) !== 0;
29917
- var texWidth = hasEffect ? Math.ceil(baseWidth + padL + padR) : baseWidth;
29918
- var texHeight = hasEffect ? Math.ceil(baseHeight + padT + padB) : baseHeight;
30023
+ // 限制 fontScale,确保纹理尺寸不超过 maxTextureSize / 2
30024
+ var maxTexSize = this.engine.gpuCapability.detail.maxTextureSize / 2;
30025
+ var logicalWidth = hasEffect ? baseWidth + padL + padR : baseWidth;
30026
+ var logicalHeight = hasEffect ? baseHeight + padT + padB : baseHeight;
30027
+ var maxLogical = Math.max(logicalWidth, logicalHeight, 1);
30028
+ fontScale = Math.min(fontScale, maxTexSize / maxLogical);
30029
+ var texWidth = Math.ceil(logicalWidth * fontScale);
30030
+ var texHeight = Math.ceil(logicalHeight * fontScale);
29919
30031
  var shiftX = hasEffect ? padL : 0;
29920
30032
  var shiftY = hasEffect ? flipY ? padT : padB : 0;
29921
30033
  // 给渲染层用:扩容比例
29922
- this.effectScaleX = baseWidth > 0 ? texWidth / baseWidth : 1;
29923
- this.effectScaleY = baseHeight > 0 ? texHeight / baseHeight : 1;
30034
+ this.effectScaleX = baseWidth > 0 ? texWidth / (baseWidth * fontScale) : 1;
30035
+ this.effectScaleY = baseHeight > 0 ? texHeight / (baseHeight * fontScale) : 1;
29924
30036
  // 默认 camera 下的 world per pixel
29925
30037
  var scaleFactor = 0.11092565;
29926
30038
  var scaleFactor2 = scaleFactor * scaleFactor;
29927
- this.transform.setSize(baseWidth * scaleFactor2 / fontScale, baseHeight * scaleFactor2 / fontScale);
30039
+ this.transform.setSize(baseWidth * scaleFactor2, baseHeight * scaleFactor2);
29928
30040
  this.renderToTexture(texWidth, texHeight, flipY, function(context) {
30041
+ context.scale(fontScale, fontScale);
29929
30042
  // canvas size 变化后重新刷新 context
29930
30043
  if (_this.maxLineWidth > baseWidth && layout.overflow === TextOverflow.display) {
29931
30044
  context.font = _this.getFontDesc(fontSize * baseWidth / _this.maxLineWidth);
@@ -29946,7 +30059,7 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
29946
30059
  // 和浏览器行为保持一致
29947
30060
  // 字符间距只应用在字符之间,每行第一个字符不加间距
29948
30061
  if (charsArray.length > 0) {
29949
- x += layout.letterSpace * fontScale;
30062
+ x += layout.letterSpace;
29950
30063
  }
29951
30064
  if (x + textMetrics.width > baseWidth && i > 0 || str === "\n") {
29952
30065
  charsInfo.push({
@@ -30031,9 +30144,9 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
30031
30144
  */ _proto.getEffectPadding = function getEffectPadding() {
30032
30145
  var style = this.textStyle;
30033
30146
  var hasDrawOutline = style.isOutlined && style.outlineWidth > 0;
30034
- var outlinePad = hasDrawOutline ? Math.ceil(style.outlineWidth * 2 * style.fontScale) : 0;
30147
+ var outlinePad = hasDrawOutline ? Math.ceil(style.outlineWidth * 2) : 0;
30035
30148
  var hasShadow = style.hasShadow && (style.shadowBlur > 0 || style.shadowOffsetX !== 0 || style.shadowOffsetY !== 0);
30036
- var shadowPad = hasShadow ? Math.ceil((Math.abs(style.shadowOffsetX) + Math.abs(style.shadowOffsetY) + style.shadowBlur) * style.fontScale) : 0;
30149
+ var shadowPad = hasShadow ? Math.ceil(Math.abs(style.shadowOffsetX) + Math.abs(style.shadowOffsetY) + style.shadowBlur) : 0;
30037
30150
  var pad = outlinePad + shadowPad;
30038
30151
  return {
30039
30152
  padL: pad,
@@ -30058,11 +30171,13 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
30058
30171
  var width = Math.max(0, Number(value) || 0);
30059
30172
  var layout = this.textLayout;
30060
30173
  // 宽度没变且已是非 autoWidth 模式,直接返回
30061
- if (layout.width === width && layout.autoResize === TextSizeMode.autoWidth) {
30174
+ if (layout.width === width) {
30062
30175
  return;
30063
30176
  }
30064
30177
  // 手动设置宽度时关闭 autoWidth
30065
- layout.autoResize = TextSizeMode.autoHeight;
30178
+ if (layout.autoResize === TextSizeMode.autoWidth) {
30179
+ layout.autoResize = TextSizeMode.autoHeight;
30180
+ }
30066
30181
  layout.width = width;
30067
30182
  // 按当前 overflow 模式重新计算 maxLineWidth
30068
30183
  this.isDirty = true;
@@ -30175,7 +30290,7 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
30175
30290
  *
30176
30291
  * 说明:
30177
30292
  * - 使用 Canvas 2D 的 measureText,并按当前实现的逐字符排版规则累加宽度(与 updateTexture 保持一致)。
30178
- * - 结果为"逻辑宽度"(已除去 fontScale,并扣除 fontOffset),可直接写回 options.textWidth。
30293
+ * - 结果为"逻辑宽度"(扣除 fontOffset),可直接写回 options.textWidth。,可直接写回 options.textWidth
30179
30294
  * - 通过 padding 追加少量冗余像素,用于降低边缘裁切风险。
30180
30295
  *
30181
30296
  * @returns 文本宽度(>= 0)
@@ -30190,10 +30305,8 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
30190
30305
  var text = ((_this_text = this.text) != null ? _this_text : "").toString();
30191
30306
  var layout = this.textLayout;
30192
30307
  var style = this.textStyle;
30193
- var fontScale = style.fontScale || 1;
30194
- var renderFontSize = style.fontSize * fontScale;
30195
- // 与 updateTexture 一致:用 render 字号测量
30196
- ctx.font = this.getFontDesc(renderFontSize);
30308
+ // updateTexture 一致:用逻辑字号测量
30309
+ ctx.font = this.getFontDesc(style.fontSize);
30197
30310
  var maxLineWidthRender = 0;
30198
30311
  var x = 0;
30199
30312
  for(var i = 0; i < text.length; i++){
@@ -30203,17 +30316,14 @@ exports.TextComponent = /*#__PURE__*/ function(MaskableGraphic) {
30203
30316
  x = 0;
30204
30317
  continue;
30205
30318
  }
30206
- // 与 updateTexture 一致:每个字符前加一次 letterSpace * fontScale
30207
- x += (layout.letterSpace || 0) * fontScale;
30319
+ // 与 updateTexture 一致:每个字符前加一次 letterSpace
30320
+ x += layout.letterSpace || 0;
30208
30321
  x += ctx.measureText(ch).width;
30209
30322
  }
30210
30323
  maxLineWidthRender = Math.max(maxLineWidthRender, x);
30211
- // render -> 逻辑宽度
30212
- var logicalMax = maxLineWidthRender / fontScale;
30213
- // 反推 layout.width:renderWidth = (layout.width + fontOffset) * fontScale
30214
30324
  var padding = 2;
30215
30325
  var EPS = 1e-4;
30216
- var w = Math.ceil(logicalMax - (style.fontOffset || 0) - EPS) + padding;
30326
+ var w = Math.ceil(maxLineWidthRender - (style.fontOffset || 0) - EPS) + padding;
30217
30327
  return Math.max(0, w);
30218
30328
  };
30219
30329
  _proto.getDefaultProps = function getDefaultProps() {
@@ -30325,9 +30435,9 @@ var SerializationHelper = /*#__PURE__*/ function() {
30325
30435
  }
30326
30436
  }
30327
30437
  // TODO 待移除 tagggedProperties 为没有装饰器的临时方案
30328
- for(var _iterator1 = _create_for_of_iterator_helper_loose(Object.keys(effectsObject.defination)), _step1; !(_step1 = _iterator1()).done;){
30438
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(Object.keys(effectsObject.definition)), _step1; !(_step1 = _iterator1()).done;){
30329
30439
  var key1 = _step1.value;
30330
- var value1 = effectsObject.defination[key1];
30440
+ var value1 = effectsObject.definition[key1];
30331
30441
  if (typeof value1 === "number" || typeof value1 === "string" || typeof value1 === "boolean" || SerializationHelper.checkTypedArray(value1)) {
30332
30442
  // TODO json 数据避免传 typedArray
30333
30443
  serializedData[key1] = value1;
@@ -30351,7 +30461,7 @@ var SerializationHelper = /*#__PURE__*/ function() {
30351
30461
  return serializedData;
30352
30462
  };
30353
30463
  SerializationHelper.deserialize = function deserialize(serializedData, effectsObject) {
30354
- effectsObject.defination = serializedData;
30464
+ effectsObject.definition = serializedData;
30355
30465
  var serializedProperties = getMergedStore(effectsObject);
30356
30466
  var engine = effectsObject.engine;
30357
30467
  if (serializedProperties) {
@@ -30366,7 +30476,7 @@ var SerializationHelper = /*#__PURE__*/ function() {
30366
30476
  effectsObject[key] = SerializationHelper.deserializeProperty(value, engine, 0, propertyType);
30367
30477
  }
30368
30478
  }
30369
- effectsObject.fromData(effectsObject.defination);
30479
+ effectsObject.fromData(effectsObject.definition);
30370
30480
  };
30371
30481
  SerializationHelper.checkTypedArray = function checkTypedArray(obj) {
30372
30482
  return _instanceof1(obj, Int8Array) || _instanceof1(obj, Uint8Array) || _instanceof1(obj, Uint8ClampedArray) || _instanceof1(obj, Int16Array) || _instanceof1(obj, Uint16Array) || _instanceof1(obj, Int32Array) || _instanceof1(obj, Uint32Array) || _instanceof1(obj, Float32Array) || _instanceof1(obj, Float64Array) || _instanceof1(obj, ArrayBuffer);
@@ -30497,7 +30607,7 @@ var SerializationHelper = /*#__PURE__*/ function() {
30497
30607
  var effectsObjectData = this.findData(guid);
30498
30608
  var effectsObject;
30499
30609
  if (!effectsObjectData) {
30500
- console.error("Object data with uuid: " + guid + " not found.");
30610
+ console.warn("Object data with uuid: " + guid + " not found.");
30501
30611
  return undefined;
30502
30612
  }
30503
30613
  switch(effectsObjectData.dataType){
@@ -30519,7 +30629,7 @@ var SerializationHelper = /*#__PURE__*/ function() {
30519
30629
  }
30520
30630
  }
30521
30631
  if (!effectsObject) {
30522
- console.error("Constructor for DataType: " + effectsObjectData.dataType + " not found.");
30632
+ console.warn("Constructor for DataType: " + effectsObjectData.dataType + " not found.");
30523
30633
  return undefined;
30524
30634
  }
30525
30635
  effectsObject.setInstanceId(effectsObjectData.id);
@@ -32361,7 +32471,7 @@ function getStandardSpriteContent(sprite, transform) {
32361
32471
  return ret;
32362
32472
  }
32363
32473
 
32364
- var version$2 = "2.9.0-alpha.1";
32474
+ var version$2 = "2.9.0-alpha.2";
32365
32475
  var v0 = /^(\d+)\.(\d+)\.(\d+)(-(\w+)\.\d+)?$/;
32366
32476
  var standardVersion = /^(\d+)\.(\d+)$/;
32367
32477
  var reverseParticle = false;
@@ -34680,7 +34790,9 @@ var PreRenderTickData = /*#__PURE__*/ function(TickData) {
34680
34790
  }
34681
34791
  var regions = [];
34682
34792
  var ray = this.getHitTestRay(x, y);
34683
- this.rootComposition.hitTest(ray, x, y, regions, force, options);
34793
+ // 所有命中的元素共享同一个 hitPositions 数组,保持与原有行为一致
34794
+ var hitPositions = [];
34795
+ this.rootItem.hitTest(ray, x, y, regions, hitPositions, force, options);
34684
34796
  return regions;
34685
34797
  };
34686
34798
  /**
@@ -37248,10 +37360,6 @@ var PassTextureCache = /*#__PURE__*/ function() {
37248
37360
  height: renderer.getHeight(),
37249
37361
  event: engine.eventSystem
37250
37362
  }), scene);
37251
- // 中低端设备降帧到 30fps·
37252
- if (engine.ticker && options.renderLevel === RenderLevel.B) {
37253
- engine.ticker.setFPS(Math.min(engine.ticker.getFPS(), 30));
37254
- }
37255
37363
  // TODO 目前编辑器会每帧调用 loadScene, 在这编译会导致闪帧,待编辑器渲染逻辑优化后移除。
37256
37364
  if (engine.env !== PLAYER_OPTIONS_ENV_EDITOR) {
37257
37365
  engine.assetService.createShaderVariant();
@@ -37316,7 +37424,7 @@ registerPlugin("text", TextLoader);
37316
37424
  registerPlugin("sprite", SpriteLoader);
37317
37425
  registerPlugin("particle", ParticleLoader);
37318
37426
  registerPlugin("interact", InteractLoader);
37319
- var version$1 = "2.9.0-alpha.1";
37427
+ var version$1 = "2.9.0-alpha.2";
37320
37428
  logger.info("Core version: " + version$1 + ".");
37321
37429
 
37322
37430
  var _obj;
@@ -38474,11 +38582,21 @@ var seed = 1;
38474
38582
  }
38475
38583
  var _proto = ThreeComposition.prototype;
38476
38584
  _proto.prepareRender = function prepareRender() {
38477
- var _this_rootItem_getComponent;
38478
38585
  var render = this.renderer;
38479
38586
  var frame = this.renderFrame;
38480
38587
  frame.renderPasses[0].meshes.length = 0;
38481
- (_this_rootItem_getComponent = this.rootItem.getComponent(RendererComponent)) == null ? void 0 : _this_rootItem_getComponent.render(render);
38588
+ var items = this.rootItem.getDescendants();
38589
+ // 主合成元素
38590
+ for(var _iterator = _create_for_of_iterator_helper_loose(items), _step; !(_step = _iterator()).done;){
38591
+ var vfxItem = _step.value;
38592
+ var rendererComponents = vfxItem.getComponents(RendererComponent);
38593
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(rendererComponents), _step1; !(_step1 = _iterator1()).done;){
38594
+ var rendererComponent = _step1.value;
38595
+ if (rendererComponent.isActiveAndEnabled) {
38596
+ rendererComponent.render(render);
38597
+ }
38598
+ }
38599
+ }
38482
38600
  };
38483
38601
  return ThreeComposition;
38484
38602
  }(Composition);
@@ -38882,7 +39000,7 @@ applyMixins(exports.ThreeTextComponent, [
38882
39000
  */ Mesh.create = function(engine, props) {
38883
39001
  return new ThreeMesh(engine, props);
38884
39002
  };
38885
- var version = "2.9.0-alpha.1";
39003
+ var version = "2.9.0-alpha.2";
38886
39004
  logger.info("THREEJS plugin version: " + version + ".");
38887
39005
 
38888
39006
  exports.ActivationMixerPlayable = ActivationMixerPlayable;