@galacean/effects-core 2.0.0-alpha.14 → 2.0.0-alpha.16

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 core for the web
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 燃然,飂兮,十弦,云垣,茂安,意绮
6
- * Version: v2.0.0-alpha.14
6
+ * Version: v2.0.0-alpha.16
7
7
  */
8
8
 
9
9
  'use strict';
@@ -597,6 +597,11 @@ function noop() {}
597
597
  */ function isObject(obj) {
598
598
  return Object.prototype.toString.call(obj) === '[object Object]';
599
599
  }
600
+ function isCanvas(canvas) {
601
+ var _canvas_tagName;
602
+ // 小程序 Canvas 无法使用 instanceof HTMLCanvasElement 判断
603
+ return typeof canvas === 'object' && canvas !== null && ((_canvas_tagName = canvas.tagName) == null ? void 0 : _canvas_tagName.toUpperCase()) === 'CANVAS';
604
+ }
600
605
  function deepClone(obj) {
601
606
  if (isArray(obj)) {
602
607
  return obj.map(deepClone);
@@ -624,6 +629,35 @@ function throwDestroyedError() {
624
629
  function generateGUID() {
625
630
  return v4().replace(/-/g, '');
626
631
  }
632
+ function base64ToFile(base64, filename = 'base64File', contentType = '') {
633
+ // 去掉 Base64 字符串的 Data URL 部分(如果存在)
634
+ const base64WithoutPrefix = base64.split(',')[1] || base64;
635
+ // 将 base64 编码的字符串转换为二进制字符串
636
+ const byteCharacters = atob(base64WithoutPrefix);
637
+ // 创建一个 8 位无符号整数值的数组,即“字节数组”
638
+ const byteArrays = [];
639
+ // 切割二进制字符串为多个片段,并将每个片段转换成一个字节数组
640
+ for(let offset = 0; offset < byteCharacters.length; offset += 512){
641
+ const slice = byteCharacters.slice(offset, offset + 512);
642
+ const byteNumbers = new Array(slice.length);
643
+ for(let i = 0; i < slice.length; i++){
644
+ byteNumbers[i] = slice.charCodeAt(i);
645
+ }
646
+ const byteArray = new Uint8Array(byteNumbers);
647
+ byteArrays.push(byteArray);
648
+ }
649
+ // 使用字节数组创建 Blob 对象
650
+ const blob = new Blob(byteArrays, {
651
+ type: contentType
652
+ });
653
+ // 创建 File 对象
654
+ const file = new File([
655
+ blob
656
+ ], filename, {
657
+ type: contentType
658
+ });
659
+ return file;
660
+ }
627
661
 
628
662
  function __decorate(decorators, target, key, desc) {
629
663
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -12744,13 +12778,16 @@ const tempColor = [
12744
12778
  let seed$3 = 0;
12745
12779
  class SpriteColorPlayable extends Playable {
12746
12780
  processFrame(context) {
12747
- const boundItem = context.output.getUserData();
12781
+ const boundObject = context.output.getUserData();
12782
+ if (!(boundObject instanceof VFXItem)) {
12783
+ return;
12784
+ }
12748
12785
  if (!this.spriteMaterial) {
12749
- this.spriteMaterial = boundItem.getComponent(SpriteComponent).material;
12786
+ this.spriteMaterial = boundObject.getComponent(SpriteComponent).material;
12750
12787
  }
12751
12788
  let colorInc = vecFill(tempColor, 1);
12752
12789
  let colorChanged;
12753
- const life = this.time / boundItem.duration;
12790
+ const life = this.time / boundObject.duration;
12754
12791
  const opacityOverLifetime = this.opacityOverLifetime;
12755
12792
  const colorOverLifetime = this.colorOverLifetime;
12756
12793
  if (colorOverLifetime) {
@@ -12849,7 +12886,6 @@ class SpriteComponent extends RendererComponent {
12849
12886
  renderer.drawGeometry(geo, material);
12850
12887
  }
12851
12888
  start() {
12852
- this.priority = this.item.listIndex;
12853
12889
  this.item.getHitTestParams = this.getHitTestParams;
12854
12890
  }
12855
12891
  update(dt) {
@@ -15218,7 +15254,7 @@ function getTrailMeshShader(trails, particleMaxCount, name, env = '', gpuCapabil
15218
15254
  * @internal
15219
15255
  */ class ParticleSystemRenderer extends RendererComponent {
15220
15256
  start() {
15221
- this._priority = this.item.listIndex;
15257
+ this._priority = this.item.renderOrder;
15222
15258
  this.particleMesh.gravityModifier.scaleXCoord(this.item.duration);
15223
15259
  for (const mesh of this.meshes){
15224
15260
  mesh.start();
@@ -16248,13 +16284,13 @@ function randomArrItem(arr, keepArr) {
16248
16284
  * @internal
16249
16285
  */ class ParticleBehaviourPlayable extends Playable {
16250
16286
  start(context) {
16251
- const binding = context.output.getUserData();
16252
- if (this.particleSystem) {
16287
+ const boundObject = context.output.getUserData();
16288
+ if (this.particleSystem || !(boundObject instanceof VFXItem)) {
16253
16289
  return;
16254
16290
  }
16255
- this.particleSystem = binding.getComponent(ParticleSystem);
16291
+ this.particleSystem = boundObject.getComponent(ParticleSystem);
16256
16292
  if (this.particleSystem) {
16257
- this.particleSystem.name = binding.name;
16293
+ this.particleSystem.name = boundObject.name;
16258
16294
  this.particleSystem.start();
16259
16295
  this.particleSystem.initEmitterTransform();
16260
16296
  }
@@ -17374,10 +17410,13 @@ const tempPos = new Vector3();
17374
17410
  }
17375
17411
  processFrame(context) {
17376
17412
  if (!this.binding) {
17377
- this.binding = context.output.getUserData();
17378
- this.start();
17413
+ const boundObject = context.output.getUserData();
17414
+ if (boundObject instanceof VFXItem) {
17415
+ this.binding = boundObject;
17416
+ this.start();
17417
+ }
17379
17418
  }
17380
- if (this.binding.composition) {
17419
+ if (this.binding && this.binding.composition) {
17381
17420
  this.sampleAnimation();
17382
17421
  }
17383
17422
  }
@@ -17545,24 +17584,26 @@ AnimationClip = __decorate([
17545
17584
  ], AnimationClip);
17546
17585
  class AnimationClipPlayable extends Playable {
17547
17586
  processFrame(context) {
17548
- const boundItem = context.output.getUserData();
17549
- if (boundItem.composition) {
17550
- this.clip.sampleAnimation(boundItem, this.time);
17587
+ const boundObject = context.output.getUserData();
17588
+ if (!(boundObject instanceof VFXItem)) {
17589
+ return;
17590
+ }
17591
+ if (boundObject.composition) {
17592
+ this.clip.sampleAnimation(boundObject, this.time);
17551
17593
  }
17552
17594
  }
17553
17595
  }
17554
17596
 
17555
17597
  class TrackAsset extends PlayableAsset {
17556
- initializeBinding(parentBinding) {
17557
- this.binding = parentBinding;
17598
+ /**
17599
+ * 重写该方法以获取自定义对象绑定
17600
+ */ resolveBinding(parentBinding) {
17601
+ return parentBinding;
17558
17602
  }
17559
17603
  /**
17560
- * @internal
17561
- */ initializeBindingRecursive(parentBinding) {
17562
- this.initializeBinding(parentBinding);
17563
- for (const subTrack of this.children){
17564
- subTrack.initializeBindingRecursive(this.binding);
17565
- }
17604
+ * 重写该方法以创建自定义混合器
17605
+ */ createTrackMixer(graph) {
17606
+ return new Playable(graph);
17566
17607
  }
17567
17608
  createOutput() {
17568
17609
  const output = new PlayableOutput();
@@ -17591,11 +17632,6 @@ class TrackAsset extends PlayableAsset {
17591
17632
  }
17592
17633
  return mixer;
17593
17634
  }
17594
- /**
17595
- * 重写该方法以创建自定义混合器
17596
- */ createTrackMixer(graph) {
17597
- return new Playable(graph);
17598
- }
17599
17635
  createPlayable(graph) {
17600
17636
  return new Playable(graph);
17601
17637
  }
@@ -17736,13 +17772,6 @@ class RuntimeClip {
17736
17772
  class ObjectBindingTrack extends TrackAsset {
17737
17773
  create(timelineAsset) {
17738
17774
  const boundItem = this.binding;
17739
- this.options = {
17740
- start: boundItem.start,
17741
- duration: boundItem.duration,
17742
- looping: boundItem.endBehavior === ItemEndBehavior.loop,
17743
- endBehavior: boundItem.endBehavior || ItemEndBehavior.destroy
17744
- };
17745
- this.name = boundItem.name;
17746
17775
  // 添加粒子动画 clip
17747
17776
  if (boundItem.getComponent(ParticleSystem)) {
17748
17777
  const particleTrack = timelineAsset.createTrack(TrackAsset, this, 'ParticleTrack');
@@ -17753,18 +17782,6 @@ class ObjectBindingTrack extends TrackAsset {
17753
17782
  particleClip.endBehaviour = boundItem.endBehavior;
17754
17783
  }
17755
17784
  }
17756
- toLocalTime(time) {
17757
- let localTime = time - this.options.start;
17758
- const duration = this.options.duration;
17759
- if (localTime - duration > 0.001) {
17760
- if (this.options.endBehavior === END_BEHAVIOR_RESTART) {
17761
- localTime = localTime % duration;
17762
- } else if (this.options.endBehavior === END_BEHAVIOR_FREEZE) {
17763
- localTime = Math.min(duration, localTime);
17764
- }
17765
- }
17766
- return localTime;
17767
- }
17768
17785
  fromData(data) {
17769
17786
  super.fromData(data);
17770
17787
  this.data = data;
@@ -17782,13 +17799,11 @@ TransformTrack = __decorate([
17782
17799
 
17783
17800
  class ActivationMixerPlayable extends Playable {
17784
17801
  processFrame(context) {
17785
- if (!this.bindingItem) {
17786
- this.bindingItem = context.output.getUserData();
17787
- }
17788
- if (!this.bindingItem) {
17802
+ const boundObject = context.output.getUserData();
17803
+ if (!(boundObject instanceof VFXItem)) {
17789
17804
  return;
17790
17805
  }
17791
- const bindingItem = this.bindingItem;
17806
+ const boundItem = boundObject;
17792
17807
  let hasInput = false;
17793
17808
  for(let i = 0; i < this.getInputCount(); i++){
17794
17809
  if (this.getInputWeight(i) > 0) {
@@ -17797,11 +17812,11 @@ class ActivationMixerPlayable extends Playable {
17797
17812
  }
17798
17813
  }
17799
17814
  if (hasInput) {
17800
- bindingItem.transform.setValid(true);
17801
- this.showRendererComponents(bindingItem);
17815
+ boundItem.transform.setValid(true);
17816
+ this.showRendererComponents(boundItem);
17802
17817
  } else {
17803
- bindingItem.transform.setValid(false);
17804
- this.hideRendererComponents(bindingItem);
17818
+ boundItem.transform.setValid(false);
17819
+ this.hideRendererComponents(boundItem);
17805
17820
  }
17806
17821
  }
17807
17822
  hideRendererComponents(item) {
@@ -17821,9 +17836,6 @@ class ActivationMixerPlayable extends Playable {
17821
17836
  }
17822
17837
 
17823
17838
  class ActivationTrack extends TrackAsset {
17824
- initializeBinding(parentBinding) {
17825
- this.binding = parentBinding;
17826
- }
17827
17839
  createTrackMixer(graph) {
17828
17840
  return new ActivationMixerPlayable(graph);
17829
17841
  }
@@ -17840,7 +17852,6 @@ SpriteColorTrack = __decorate([
17840
17852
 
17841
17853
  class TimelineAsset extends PlayableAsset {
17842
17854
  createPlayable(graph) {
17843
- this.graph = graph;
17844
17855
  const timelinePlayable = new TimelinePlayable(graph);
17845
17856
  timelinePlayable.setTraversalMode(PlayableTraversalMode.Passthrough);
17846
17857
  for (const track of this.tracks){
@@ -17951,179 +17962,415 @@ function compareTracks(a, b) {
17951
17962
  }
17952
17963
  }
17953
17964
 
17954
- class TextLayout {
17955
- getOffsetY(style) {
17956
- let offsetY = 0;
17957
- const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
17958
- switch(this.textBaseline){
17959
- case TextBaseline.top:
17960
- offsetY = offset;
17961
- break;
17962
- case TextBaseline.middle:
17963
- offsetY = (this.height + offset) / 2; // fonSize;
17964
- break;
17965
- case TextBaseline.bottom:
17966
- offsetY = this.height - offset / 2;
17967
- break;
17965
+ /**
17966
+ * @since 2.0.0
17967
+ * @internal
17968
+ */ class CompositionComponent extends ItemBehaviour {
17969
+ start() {
17970
+ const { startTime = 0 } = this.item.props;
17971
+ this.startTime = startTime;
17972
+ this.resolveBindings();
17973
+ this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
17974
+ this.timelinePlayable.play();
17975
+ // 重播不销毁元素
17976
+ if (this.item.endBehavior !== ItemEndBehavior.destroy) {
17977
+ this.setReusable(true);
17968
17978
  }
17969
- return offsetY;
17970
17979
  }
17971
- getOffsetX(style, maxWidth) {
17972
- let offsetX = 0;
17973
- switch(this.textAlign){
17974
- case TextAlignment.left:
17975
- offsetX = style.outlineWidth * style.fontScale;
17976
- break;
17977
- case TextAlignment.middle:
17978
- offsetX = (this.width * style.fontScale - maxWidth) / 2;
17979
- break;
17980
- case TextAlignment.right:
17981
- offsetX = this.width * style.fontScale - maxWidth;
17982
- break;
17980
+ setReusable(value) {
17981
+ for (const track of this.timelineAsset.tracks){
17982
+ const binding = track.binding;
17983
+ if (binding instanceof VFXItem) {
17984
+ if (track instanceof ObjectBindingTrack) {
17985
+ binding.reusable = value;
17986
+ }
17987
+ const subCompositionComponent = binding.getComponent(CompositionComponent);
17988
+ if (subCompositionComponent) {
17989
+ subCompositionComponent.setReusable(value);
17990
+ }
17991
+ }
17983
17992
  }
17984
- return offsetX;
17985
- }
17986
- /**
17987
- * 设置文本框的宽度和高度
17988
- * @param width 文本框宽度
17989
- * @param height 文本框高度
17990
- */ setSize(width, height) {
17991
- this.width = width;
17992
- this.height = height;
17993
17993
  }
17994
- constructor(options){
17995
- this.width = 0;
17996
- this.height = 0;
17997
- const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
17998
- const tempWidth = fontSize + letterSpace;
17999
- this.autoWidth = autoWidth;
18000
- this.maxTextWidth = text.length * tempWidth;
18001
- // if (autoWidth) {
18002
- // this.width = this.maxTextWidth + this.lineWidth;
18003
- // this.height = fontSize + this.lineHeight;
18004
- // } else {
18005
- // if (textWidth) {
18006
- // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18007
- // this.width = textWidth;
18008
- // } else {
18009
- // this.width = basicScale[0] * 100;
18010
- // }
18011
- // this.height = basicScale[1] * 100;
18012
- // }
18013
- this.width = textWidth;
18014
- this.height = textHeight;
18015
- this.letterSpace = letterSpace;
18016
- this.overFlow = textOverflow;
18017
- this.textBaseline = textBaseline;
18018
- this.textAlign = textAlign;
18019
- this.lineHeight = lineHeight;
17994
+ getReusable() {
17995
+ return this.reusable;
18020
17996
  }
18021
- }
18022
-
18023
- class TextStyle {
18024
- constructor(options){
18025
- /**
18026
- * 是否有下划线(暂时无效)
18027
- */ this.isUnderline = false // ttf
18028
- ;
18029
- /**
18030
- * 下划线高度(暂时无效)
18031
- */ this.underlineHeight = 1 // ttf
18032
- ;
18033
- /**
18034
- * 是否有外描边
18035
- */ this.isOutlined = false // both // ttf & char
18036
- ;
18037
- /**
18038
- * 外描边宽度
18039
- */ this.outlineWidth = 0 // both // ttf & char
18040
- ;
18041
- /**
18042
- * 是否有阴影
18043
- */ this.hasShadow = false // ttf
18044
- ;
18045
- this.fontDesc = '' // both
18046
- ;
18047
- /**
18048
- * 字体倍数
18049
- */ this.fontScale = 2;
18050
- this.fontOffset = 0;
18051
- const { textColor = [
18052
- 1,
18053
- 1,
18054
- 1,
18055
- 1
18056
- ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18057
- this.textColor = textColor;
18058
- //@ts-expect-error
18059
- this.textWeight = fontWeight;
18060
- //@ts-expect-error
18061
- this.fontStyle = fontStyle;
18062
- this.fontFamily = fontFamily;
18063
- this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18064
- if (outline) {
18065
- this.isOutlined = true;
18066
- var _outline_outlineColor;
18067
- this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18068
- 1,
18069
- 1,
18070
- 1,
18071
- 1
18072
- ];
18073
- var _outline_outlineWidth;
18074
- this.outlineWidth = (_outline_outlineWidth = outline.outlineWidth) != null ? _outline_outlineWidth : 1;
18075
- this.fontOffset += this.outlineWidth;
18076
- }
18077
- if (shadow) {
18078
- this.hasShadow = true;
18079
- var _shadow_shadowBlur;
18080
- this.shadowBlur = (_shadow_shadowBlur = shadow.shadowBlur) != null ? _shadow_shadowBlur : 2;
18081
- var _shadow_shadowColor;
18082
- this.shadowColor = (_shadow_shadowColor = shadow.shadowColor) != null ? _shadow_shadowColor : [
18083
- 0,
18084
- 0,
18085
- 0,
18086
- 1
18087
- ];
18088
- var _shadow_shadowOffsetX;
18089
- this.shadowOffsetX = (_shadow_shadowOffsetX = shadow.shadowOffsetX) != null ? _shadow_shadowOffsetX : 0;
18090
- var _shadow_shadowOffsetY;
18091
- this.shadowOffsetY = (_shadow_shadowOffsetY = shadow.shadowOffsetY) != null ? _shadow_shadowOffsetY : 0;
18092
- }
18093
- if (this.fontStyle !== FontStyle.normal) {
18094
- // 0.0174532925 = 3.141592653 / 180
18095
- this.fontOffset += this.fontSize * Math.tan(12 * 0.0174532925);
17997
+ update(dt) {
17998
+ const time = this.time;
17999
+ // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
18000
+ if (this.item.isEnded(this.time) && !this.item.parent) {
18001
+ this.item.ended = true;
18096
18002
  }
18003
+ this.timelinePlayable.setTime(time);
18004
+ this.graph.evaluate(dt);
18097
18005
  }
18098
- }
18099
-
18100
- class CanvasPool {
18101
- dispose() {
18102
- this.elements.forEach((e)=>e.remove());
18103
- // clearing the array
18104
- this.elements.length = 0;
18105
- }
18106
- getCanvas() {
18107
- if (this.elements.length !== 0) {
18108
- return this.elements.shift();
18109
- }
18110
- if (getConfig(TEMPLATE_USE_OFFSCREEN_CANVAS)) {
18111
- // @ts-expect-error
18112
- return window._createOffscreenCanvas(10, 10);
18113
- } else {
18114
- // in hongmeng system, create too many canvas will case render error
18115
- const defCanvas = document.createElement('canvas');
18116
- defCanvas.getContext('2d', {
18117
- willReadFrequently: true
18006
+ createContent() {
18007
+ const sceneBindings = [];
18008
+ for (const sceneBindingData of this.data.sceneBindings){
18009
+ sceneBindings.push({
18010
+ key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
18011
+ value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
18118
18012
  });
18119
- return defCanvas;
18120
18013
  }
18121
- }
18122
- saveCanvas(canvas) {
18123
- canvas.width = 1;
18124
- canvas.height = 1;
18125
- if (this.elements.length < 3) {
18126
- addItem(this.elements, canvas);
18014
+ this.sceneBindings = sceneBindings;
18015
+ const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
18016
+ this.timelineAsset = timelineAsset;
18017
+ const items = this.items;
18018
+ this.items.length = 0;
18019
+ if (this.item.composition) {
18020
+ const assetLoader = this.item.engine.assetLoader;
18021
+ const itemProps = this.item.props.items ? this.item.props.items : [];
18022
+ for(let i = 0; i < itemProps.length; i++){
18023
+ let item;
18024
+ const itemData = itemProps[i];
18025
+ // 设置预合成作为元素时的时长、结束行为和渲染延时
18026
+ if (exports.Item.isComposition(itemData)) {
18027
+ const refId = itemData.content.options.refId;
18028
+ const props = this.item.composition.refCompositionProps.get(refId);
18029
+ if (!props) {
18030
+ throw new Error(`引用的Id: ${refId} 的预合成不存在`);
18031
+ }
18032
+ // endBehaviour 类型需优化
18033
+ props.content = itemData.content;
18034
+ item = assetLoader.loadGUID(itemData.id);
18035
+ item.composition = this.item.composition;
18036
+ const compositionComponent = item.addComponent(CompositionComponent);
18037
+ compositionComponent.data = props;
18038
+ compositionComponent.refId = refId;
18039
+ item.transform.parentTransform = this.transform;
18040
+ this.item.composition.refContent.push(item);
18041
+ if (item.endBehavior === ItemEndBehavior.loop) {
18042
+ this.item.composition.autoRefTex = false;
18043
+ }
18044
+ compositionComponent.createContent();
18045
+ for (const vfxItem of compositionComponent.items){
18046
+ vfxItem.setInstanceId(generateGUID());
18047
+ for (const component of vfxItem.components){
18048
+ component.setInstanceId(generateGUID());
18049
+ }
18050
+ }
18051
+ } else {
18052
+ item = assetLoader.loadGUID(itemData.id);
18053
+ item.composition = this.item.composition;
18054
+ }
18055
+ item.parent = this.item;
18056
+ // 相机不跟随合成移动
18057
+ item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
18058
+ if (VFXItem.isExtraCamera(item)) {
18059
+ this.item.composition.extraCamera = item;
18060
+ }
18061
+ items.push(item);
18062
+ }
18063
+ }
18064
+ }
18065
+ onDestroy() {
18066
+ if (this.item.composition) {
18067
+ if (this.items) {
18068
+ this.items.forEach((item)=>item.dispose());
18069
+ this.items.length = 0;
18070
+ }
18071
+ }
18072
+ }
18073
+ hitTest(ray, x, y, regions, force, options) {
18074
+ const hitPositions = [];
18075
+ const stop = (options == null ? void 0 : options.stop) || noop;
18076
+ const skip = (options == null ? void 0 : options.skip) || noop;
18077
+ const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
18078
+ for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
18079
+ const item = this.items[i];
18080
+ if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
18081
+ const hitParams = item.getHitTestParams(force);
18082
+ if (hitParams) {
18083
+ let success = false;
18084
+ const intersectPoint = new Vector3();
18085
+ if (hitParams.type === exports.HitTestType.triangle) {
18086
+ const { triangles, backfaceCulling } = hitParams;
18087
+ for(let j = 0; j < triangles.length; j++){
18088
+ const triangle = triangles[j];
18089
+ if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
18090
+ success = true;
18091
+ hitPositions.push(intersectPoint);
18092
+ break;
18093
+ }
18094
+ }
18095
+ } else if (hitParams.type === exports.HitTestType.box) {
18096
+ const { center, size } = hitParams;
18097
+ const boxMin = center.clone().addScaledVector(size, 0.5);
18098
+ const boxMax = center.clone().addScaledVector(size, -0.5);
18099
+ if (ray.intersectBox({
18100
+ min: boxMin,
18101
+ max: boxMax
18102
+ }, intersectPoint)) {
18103
+ success = true;
18104
+ hitPositions.push(intersectPoint);
18105
+ }
18106
+ } else if (hitParams.type === exports.HitTestType.sphere) {
18107
+ const { center, radius } = hitParams;
18108
+ if (ray.intersectSphere({
18109
+ center,
18110
+ radius
18111
+ }, intersectPoint)) {
18112
+ success = true;
18113
+ hitPositions.push(intersectPoint);
18114
+ }
18115
+ } else if (hitParams.type === exports.HitTestType.custom) {
18116
+ const tempPosition = hitParams.collect(ray, new Vector2(x, y));
18117
+ if (tempPosition && tempPosition.length > 0) {
18118
+ tempPosition.forEach((pos)=>{
18119
+ hitPositions.push(pos);
18120
+ });
18121
+ success = true;
18122
+ }
18123
+ }
18124
+ if (success) {
18125
+ const region = {
18126
+ compContent: this.item,
18127
+ id: item.id,
18128
+ name: item.name,
18129
+ position: hitPositions[hitPositions.length - 1],
18130
+ parentId: item.parentId,
18131
+ hitPositions,
18132
+ behavior: hitParams.behavior
18133
+ };
18134
+ regions.push(region);
18135
+ if (stop(region)) {
18136
+ return regions;
18137
+ }
18138
+ }
18139
+ }
18140
+ }
18141
+ }
18142
+ return regions;
18143
+ }
18144
+ fromData(data) {}
18145
+ resolveBindings() {
18146
+ for (const sceneBinding of this.sceneBindings){
18147
+ sceneBinding.key.binding = sceneBinding.value;
18148
+ }
18149
+ for (const masterTrack of this.timelineAsset.tracks){
18150
+ this.resolveTrackBindingsWithRoot(masterTrack);
18151
+ }
18152
+ }
18153
+ resolveTrackBindingsWithRoot(track) {
18154
+ for (const subTrack of track.getChildTracks()){
18155
+ subTrack.binding = subTrack.resolveBinding(track.binding);
18156
+ this.resolveTrackBindingsWithRoot(subTrack);
18157
+ }
18158
+ }
18159
+ constructor(...args){
18160
+ super(...args);
18161
+ this.time = 0;
18162
+ this.startTime = 0;
18163
+ this.items = [] // 场景的所有元素
18164
+ ;
18165
+ this.reusable = false;
18166
+ this.sceneBindings = [];
18167
+ this.graph = new PlayableGraph();
18168
+ }
18169
+ }
18170
+
18171
+ class SubCompositionTrack extends TrackAsset {
18172
+ resolveBinding(parentBinding) {
18173
+ if (!(parentBinding instanceof VFXItem)) {
18174
+ throw new Error('SubCompositionTrack needs to be set under the VFXItem track');
18175
+ }
18176
+ return parentBinding.getComponent(CompositionComponent);
18177
+ }
18178
+ }
18179
+ SubCompositionTrack = __decorate([
18180
+ effectsClass('SubCompositionTrack')
18181
+ ], SubCompositionTrack);
18182
+
18183
+ class SubCompositionClipPlayable extends Playable {
18184
+ processFrame(context) {
18185
+ const boundObject = context.output.getUserData();
18186
+ if (boundObject instanceof CompositionComponent) {
18187
+ boundObject.time = this.getTime();
18188
+ }
18189
+ }
18190
+ }
18191
+
18192
+ class SubCompositionPlayableAsset extends PlayableAsset {
18193
+ createPlayable(graph) {
18194
+ return new SubCompositionClipPlayable(graph);
18195
+ }
18196
+ }
18197
+ SubCompositionPlayableAsset = __decorate([
18198
+ effectsClass('SubCompositionPlayableAsset')
18199
+ ], SubCompositionPlayableAsset);
18200
+
18201
+ class TextLayout {
18202
+ getOffsetY(style) {
18203
+ let offsetY = 0;
18204
+ const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
18205
+ switch(this.textBaseline){
18206
+ case TextBaseline.top:
18207
+ offsetY = offset;
18208
+ break;
18209
+ case TextBaseline.middle:
18210
+ offsetY = (this.height + offset) / 2; // fonSize;
18211
+ break;
18212
+ case TextBaseline.bottom:
18213
+ offsetY = this.height - offset / 2;
18214
+ break;
18215
+ }
18216
+ return offsetY;
18217
+ }
18218
+ getOffsetX(style, maxWidth) {
18219
+ let offsetX = 0;
18220
+ switch(this.textAlign){
18221
+ case TextAlignment.left:
18222
+ offsetX = style.outlineWidth * style.fontScale;
18223
+ break;
18224
+ case TextAlignment.middle:
18225
+ offsetX = (this.width * style.fontScale - maxWidth) / 2;
18226
+ break;
18227
+ case TextAlignment.right:
18228
+ offsetX = this.width * style.fontScale - maxWidth;
18229
+ break;
18230
+ }
18231
+ return offsetX;
18232
+ }
18233
+ /**
18234
+ * 设置文本框的宽度和高度
18235
+ * @param width 文本框宽度
18236
+ * @param height 文本框高度
18237
+ */ setSize(width, height) {
18238
+ this.width = width;
18239
+ this.height = height;
18240
+ }
18241
+ constructor(options){
18242
+ this.width = 0;
18243
+ this.height = 0;
18244
+ const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
18245
+ const tempWidth = fontSize + letterSpace;
18246
+ this.autoWidth = autoWidth;
18247
+ this.maxTextWidth = text.length * tempWidth;
18248
+ // if (autoWidth) {
18249
+ // this.width = this.maxTextWidth + this.lineWidth;
18250
+ // this.height = fontSize + this.lineHeight;
18251
+ // } else {
18252
+ // if (textWidth) {
18253
+ // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18254
+ // this.width = textWidth;
18255
+ // } else {
18256
+ // this.width = basicScale[0] * 100;
18257
+ // }
18258
+ // this.height = basicScale[1] * 100;
18259
+ // }
18260
+ this.width = textWidth;
18261
+ this.height = textHeight;
18262
+ this.letterSpace = letterSpace;
18263
+ this.overFlow = textOverflow;
18264
+ this.textBaseline = textBaseline;
18265
+ this.textAlign = textAlign;
18266
+ this.lineHeight = lineHeight;
18267
+ }
18268
+ }
18269
+
18270
+ class TextStyle {
18271
+ constructor(options){
18272
+ /**
18273
+ * 是否有下划线(暂时无效)
18274
+ */ this.isUnderline = false // ttf
18275
+ ;
18276
+ /**
18277
+ * 下划线高度(暂时无效)
18278
+ */ this.underlineHeight = 1 // ttf
18279
+ ;
18280
+ /**
18281
+ * 是否有外描边
18282
+ */ this.isOutlined = false // both // ttf & char
18283
+ ;
18284
+ /**
18285
+ * 外描边宽度
18286
+ */ this.outlineWidth = 0 // both // ttf & char
18287
+ ;
18288
+ /**
18289
+ * 是否有阴影
18290
+ */ this.hasShadow = false // ttf
18291
+ ;
18292
+ this.fontDesc = '' // both
18293
+ ;
18294
+ /**
18295
+ * 字体倍数
18296
+ */ this.fontScale = 2;
18297
+ this.fontOffset = 0;
18298
+ const { textColor = [
18299
+ 1,
18300
+ 1,
18301
+ 1,
18302
+ 1
18303
+ ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18304
+ this.textColor = textColor;
18305
+ //@ts-expect-error
18306
+ this.textWeight = fontWeight;
18307
+ //@ts-expect-error
18308
+ this.fontStyle = fontStyle;
18309
+ this.fontFamily = fontFamily;
18310
+ this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18311
+ if (outline) {
18312
+ this.isOutlined = true;
18313
+ var _outline_outlineColor;
18314
+ this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18315
+ 1,
18316
+ 1,
18317
+ 1,
18318
+ 1
18319
+ ];
18320
+ var _outline_outlineWidth;
18321
+ this.outlineWidth = (_outline_outlineWidth = outline.outlineWidth) != null ? _outline_outlineWidth : 1;
18322
+ this.fontOffset += this.outlineWidth;
18323
+ }
18324
+ if (shadow) {
18325
+ this.hasShadow = true;
18326
+ var _shadow_shadowBlur;
18327
+ this.shadowBlur = (_shadow_shadowBlur = shadow.shadowBlur) != null ? _shadow_shadowBlur : 2;
18328
+ var _shadow_shadowColor;
18329
+ this.shadowColor = (_shadow_shadowColor = shadow.shadowColor) != null ? _shadow_shadowColor : [
18330
+ 0,
18331
+ 0,
18332
+ 0,
18333
+ 1
18334
+ ];
18335
+ var _shadow_shadowOffsetX;
18336
+ this.shadowOffsetX = (_shadow_shadowOffsetX = shadow.shadowOffsetX) != null ? _shadow_shadowOffsetX : 0;
18337
+ var _shadow_shadowOffsetY;
18338
+ this.shadowOffsetY = (_shadow_shadowOffsetY = shadow.shadowOffsetY) != null ? _shadow_shadowOffsetY : 0;
18339
+ }
18340
+ if (this.fontStyle !== FontStyle.normal) {
18341
+ // 0.0174532925 = 3.141592653 / 180
18342
+ this.fontOffset += this.fontSize * Math.tan(12 * 0.0174532925);
18343
+ }
18344
+ }
18345
+ }
18346
+
18347
+ class CanvasPool {
18348
+ dispose() {
18349
+ this.elements.forEach((e)=>e.remove());
18350
+ // clearing the array
18351
+ this.elements.length = 0;
18352
+ }
18353
+ getCanvas() {
18354
+ if (this.elements.length !== 0) {
18355
+ return this.elements.shift();
18356
+ }
18357
+ if (getConfig(TEMPLATE_USE_OFFSCREEN_CANVAS)) {
18358
+ // @ts-expect-error
18359
+ return window._createOffscreenCanvas(10, 10);
18360
+ } else {
18361
+ // in hongmeng system, create too many canvas will case render error
18362
+ const defCanvas = document.createElement('canvas');
18363
+ defCanvas.getContext('2d', {
18364
+ willReadFrequently: true
18365
+ });
18366
+ return defCanvas;
18367
+ }
18368
+ }
18369
+ saveCanvas(canvas) {
18370
+ canvas.width = 1;
18371
+ canvas.height = 1;
18372
+ if (this.elements.length < 3) {
18373
+ addItem(this.elements, canvas);
18127
18374
  } else {
18128
18375
  canvas.remove();
18129
18376
  }
@@ -18663,6 +18910,19 @@ class VFXItem extends EffectsObject {
18663
18910
  return (_this_composition_reusable = (_this_composition = this.composition) == null ? void 0 : _this_composition.reusable) != null ? _this_composition_reusable : false;
18664
18911
  }
18665
18912
  /**
18913
+ * 元素在合成中的索引
18914
+ */ get renderOrder() {
18915
+ return this.listIndex;
18916
+ }
18917
+ set renderOrder(value) {
18918
+ if (this.listIndex !== value) {
18919
+ this.listIndex = value;
18920
+ for (const rendererComponent of this.rendererComponents){
18921
+ rendererComponent.priority = value;
18922
+ }
18923
+ }
18924
+ }
18925
+ /**
18666
18926
  * 设置元素的动画速度
18667
18927
  * @param speed - 速度
18668
18928
  */ setSpeed(speed) {
@@ -18919,7 +19179,7 @@ class VFXItem extends EffectsObject {
18919
19179
  this.parentId = parentId;
18920
19180
  this.duration = duration;
18921
19181
  this.endBehavior = endBehavior;
18922
- this.listIndex = listIndex;
19182
+ this.renderOrder = listIndex;
18923
19183
  //@ts-expect-error
18924
19184
  this.oldId = data.oldId;
18925
19185
  if (!data.content) {
@@ -19387,14 +19647,16 @@ class SerializationHelper {
19387
19647
  static checkGLTFNode(value) {
19388
19648
  return value instanceof Object && value.nodeIndex !== undefined && value.isJoint !== undefined;
19389
19649
  }
19650
+ static checkImageSource(value) {
19651
+ return isCanvas(value) || value instanceof HTMLImageElement;
19652
+ }
19390
19653
  static deserializeProperty(property, engine, level, type) {
19391
19654
  if (level > 14) {
19392
19655
  console.error('序列化数据的内嵌对象层数大于上限');
19393
19656
  return;
19394
19657
  }
19395
- if (typeof property === 'number' || typeof property === 'string' || typeof property === 'boolean') {
19396
- return property;
19397
- } else if (property instanceof Array) {
19658
+ // 加载并链接 DataPath 字段表示的 EffectsObject 引用。Class 对象 copy [key, value] 会丢失对象信息,因此只递归数组对象和普通 js Object 结构对象。
19659
+ if (property instanceof Array) {
19398
19660
  const res = [];
19399
19661
  for (const value of property){
19400
19662
  res.push(SerializationHelper.deserializeProperty(value, engine, level + 1, type));
@@ -19403,9 +19665,7 @@ class SerializationHelper {
19403
19665
  // TODO json 数据避免传 typedArray
19404
19666
  } else if (SerializationHelper.checkDataPath(property)) {
19405
19667
  return engine.assetLoader.loadGUID(property.id);
19406
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19407
- return property;
19408
- } else if (property instanceof Object) {
19668
+ } else if (property instanceof Object && property.constructor === Object) {
19409
19669
  let res;
19410
19670
  if (type) {
19411
19671
  const classConstructor = effectsClassStore[type];
@@ -19418,6 +19678,8 @@ class SerializationHelper {
19418
19678
  res[key] = SerializationHelper.deserializeProperty(property[key], engine, level + 1);
19419
19679
  }
19420
19680
  return res;
19681
+ } else {
19682
+ return property;
19421
19683
  }
19422
19684
  }
19423
19685
  static deserializePropertyAsync(property, engine, level, type) {
@@ -19426,9 +19688,7 @@ class SerializationHelper {
19426
19688
  console.error('序列化数据的内嵌对象层数大于上限');
19427
19689
  return;
19428
19690
  }
19429
- if (typeof property === 'number' || typeof property === 'string' || typeof property === 'boolean') {
19430
- return property;
19431
- } else if (property instanceof Array) {
19691
+ if (property instanceof Array) {
19432
19692
  const res = [];
19433
19693
  for (const value of property){
19434
19694
  res.push((yield SerializationHelper.deserializePropertyAsync(value, engine, level + 1, type)));
@@ -19438,9 +19698,7 @@ class SerializationHelper {
19438
19698
  } else if (SerializationHelper.checkDataPath(property)) {
19439
19699
  const res = yield engine.assetLoader.loadGUIDAsync(property.id);
19440
19700
  return res;
19441
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19442
- return property;
19443
- } else if (property instanceof Object) {
19701
+ } else if (property instanceof Object && property.constructor === Object) {
19444
19702
  let res;
19445
19703
  if (type) {
19446
19704
  const classConstructor = effectsClassStore[type];
@@ -19453,6 +19711,8 @@ class SerializationHelper {
19453
19711
  res[key] = SerializationHelper.deserializeProperty(property[key], engine, level + 1);
19454
19712
  }
19455
19713
  return res;
19714
+ } else {
19715
+ return property;
19456
19716
  }
19457
19717
  })();
19458
19718
  }
@@ -19542,9 +19802,8 @@ class SerializationHelper {
19542
19802
  effectsObject = Geometry.create(this.engine);
19543
19803
  break;
19544
19804
  case DataType.Texture:
19545
- // @ts-expect-error
19546
- effectsObject = Texture.create(this.engine, effectsObjectData);
19547
- return effectsObject;
19805
+ effectsObject = Texture.create(this.engine);
19806
+ break;
19548
19807
  default:
19549
19808
  {
19550
19809
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -19592,9 +19851,8 @@ class SerializationHelper {
19592
19851
  effectsObject = Geometry.create(_this.engine);
19593
19852
  break;
19594
19853
  case DataType.Texture:
19595
- // @ts-expect-error
19596
- effectsObject = Texture.create(_this.engine, effectsObjectData);
19597
- return effectsObject;
19854
+ effectsObject = Texture.create(_this.engine);
19855
+ break;
19598
19856
  default:
19599
19857
  {
19600
19858
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -20449,6 +20707,7 @@ function getStandardCameraContent(model) {
20449
20707
  _result;
20450
20708
  const result = _extends({}, json, {
20451
20709
  items: [],
20710
+ compositions: [],
20452
20711
  components: [],
20453
20712
  materials: [],
20454
20713
  shaders: [],
@@ -20539,8 +20798,15 @@ function getStandardCameraContent(model) {
20539
20798
  id: item.id
20540
20799
  };
20541
20800
  });
20801
+ const compositionData = _extends({}, composition, {
20802
+ timelineAsset: {
20803
+ id: ''
20804
+ },
20805
+ sceneBindings: []
20806
+ });
20807
+ result.compositions.push(compositionData);
20542
20808
  // 生成时间轴数据
20543
- convertTimelineAsset(composition, guidToItemMap, result);
20809
+ convertTimelineAsset(compositionData, guidToItemMap, result);
20544
20810
  }
20545
20811
  for (const item of result.items){
20546
20812
  // 原 texture 索引转为统一 guid 索引
@@ -20707,10 +20973,7 @@ function getStandardCameraContent(model) {
20707
20973
  item.type = 'orientation-transformer';
20708
20974
  }
20709
20975
  // item 的 content 转为 component data 加入 JSONScene.components
20710
- if (item.type === ItemType.sprite || item.type === ItemType.particle || item.type === ItemType.mesh || item.type === ItemType.skybox || item.type === ItemType.light || // @ts-expect-error
20711
- item.type === 'camera' || item.type === ItemType.tree || item.type === ItemType.interact || item.type === ItemType.camera || item.type === ItemType.text || item.type === ItemType.spine || // @ts-expect-error
20712
- item.type === 'editor-gizmo' || // @ts-expect-error
20713
- item.type === 'orientation-transformer') {
20976
+ if (item.type === ItemType.sprite || item.type === ItemType.particle || item.type === ItemType.mesh || item.type === ItemType.skybox || item.type === ItemType.light || item.type === 'camera' || item.type === ItemType.tree || item.type === ItemType.interact || item.type === ItemType.camera || item.type === ItemType.text || item.type === ItemType.spine || item.type === 'editor-gizmo' || item.type === 'orientation-transformer') {
20714
20977
  item.components = [];
20715
20978
  result.components.push(item.content);
20716
20979
  item.content.id = generateGUID();
@@ -20742,15 +21005,12 @@ function getStandardCameraContent(model) {
20742
21005
  case ItemType.light:
20743
21006
  item.content.dataType = DataType.LightComponent;
20744
21007
  break;
20745
- // @ts-expect-error
20746
21008
  case 'camera':
20747
21009
  item.content.dataType = DataType.CameraComponent;
20748
21010
  break;
20749
- // @ts-expect-error
20750
21011
  case 'editor-gizmo':
20751
21012
  item.content.dataType = 'GizmoComponent';
20752
21013
  break;
20753
- // @ts-expect-error
20754
21014
  case 'orientation-transformer':
20755
21015
  item.content.dataType = 'OrientationComponent';
20756
21016
  break;
@@ -20900,6 +21160,32 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20900
21160
  });
20901
21161
  trackDatas.push(newTrackData);
20902
21162
  }
21163
+ if (item.type === ItemType.composition) {
21164
+ const newSubCompositionPlayableAssetData = {
21165
+ id: generateGUID(),
21166
+ dataType: 'SubCompositionPlayableAsset'
21167
+ };
21168
+ playableAssetDatas.push(newSubCompositionPlayableAssetData);
21169
+ const newTrackData = {
21170
+ id: generateGUID(),
21171
+ dataType: 'SubCompositionTrack',
21172
+ children: [],
21173
+ clips: [
21174
+ {
21175
+ start: item.delay,
21176
+ duration: item.duration,
21177
+ endBehaviour: item.endBehavior,
21178
+ asset: {
21179
+ id: newSubCompositionPlayableAssetData.id
21180
+ }
21181
+ }
21182
+ ]
21183
+ };
21184
+ subTrackDatas.push({
21185
+ id: newTrackData.id
21186
+ });
21187
+ trackDatas.push(newTrackData);
21188
+ }
20903
21189
  const bindingTrackData = {
20904
21190
  id: generateGUID(),
20905
21191
  dataType: 'ObjectBindingTrack',
@@ -20925,11 +21211,9 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20925
21211
  id: trackData.id
20926
21212
  });
20927
21213
  }
20928
- //@ts-expect-error
20929
21214
  composition.timelineAsset = {
20930
21215
  id: timelineAssetData.id
20931
21216
  };
20932
- //@ts-expect-error
20933
21217
  composition.sceneBindings = sceneBindings;
20934
21218
  if (!jsonScene.animations) {
20935
21219
  jsonScene.animations = [];
@@ -21247,7 +21531,17 @@ function getStandardItem(item, opt = {}) {
21247
21531
  }
21248
21532
  }
21249
21533
 
21250
- const renderLevelPassSet = {
21534
+ /**
21535
+ * 机型和渲染等级对应表
21536
+ *
21537
+ * 机型:B-低端机、A-中端机、S-高端机
21538
+ * 渲染等级:B-低、A-中、S-高、A+-中高、B+-全部
21539
+ *
21540
+ * - S(高端机):高、全部、中高
21541
+ * - A(中端机):中、全部、中高
21542
+ * - B(低端机):低、全部
21543
+ * - undefined(全部机型)
21544
+ */ const renderLevelPassSet = {
21251
21545
  [RenderLevel.S]: [
21252
21546
  RenderLevel.S,
21253
21547
  RenderLevel.BPlus,
@@ -21796,40 +22090,6 @@ function createTextureOptionsBySource(image, sourceFrom) {
21796
22090
  }
21797
22091
  throw new Error('Invalid texture options');
21798
22092
  }
21799
- function base64ToFile(base64, filename = 'base64File', contentType = '') {
21800
- // 去掉 Base64 字符串的 Data URL 部分(如果存在)
21801
- const base64WithoutPrefix = base64.split(',')[1] || base64;
21802
- // 将 base64 编码的字符串转换为二进制字符串
21803
- const byteCharacters = atob(base64WithoutPrefix);
21804
- // 创建一个 8 位无符号整数值的数组,即“字节数组”
21805
- const byteArrays = [];
21806
- // 切割二进制字符串为多个片段,并将每个片段转换成一个字节数组
21807
- for(let offset = 0; offset < byteCharacters.length; offset += 512){
21808
- const slice = byteCharacters.slice(offset, offset + 512);
21809
- const byteNumbers = new Array(slice.length);
21810
- for(let i = 0; i < slice.length; i++){
21811
- byteNumbers[i] = slice.charCodeAt(i);
21812
- }
21813
- const byteArray = new Uint8Array(byteNumbers);
21814
- byteArrays.push(byteArray);
21815
- }
21816
- // 使用字节数组创建 Blob 对象
21817
- const blob = new Blob(byteArrays, {
21818
- type: contentType
21819
- });
21820
- // 创建 File 对象
21821
- const file = new File([
21822
- blob
21823
- ], filename, {
21824
- type: contentType
21825
- });
21826
- return file;
21827
- }
21828
- function isCanvas(canvas) {
21829
- var _canvas_tagName;
21830
- // 小程序 Canvas 无法使用 instanceof HTMLCanvasElement 判断
21831
- return typeof canvas === 'object' && canvas !== null && ((_canvas_tagName = canvas.tagName) == null ? void 0 : _canvas_tagName.toUpperCase()) === 'CANVAS';
21832
- }
21833
22093
 
21834
22094
  const tmpScale = new Vector3(1, 1, 1);
21835
22095
  /**
@@ -22083,217 +22343,173 @@ const tmpScale = new Vector3(1, 1, 1);
22083
22343
  this.dirty = true;
22084
22344
  this.updateMatrix();
22085
22345
  }
22086
- }
22087
-
22088
- /**
22089
- * @since 2.0.0
22090
- * @internal
22091
- */ class CompositionComponent extends ItemBehaviour {
22092
- start() {
22093
- const { startTime = 0 } = this.item.props;
22094
- this.startTime = startTime;
22095
- this.masterTracks = [];
22096
- for (const sceneBinding of this.sceneBindings){
22097
- sceneBinding.key.binding = sceneBinding.value;
22346
+ }
22347
+
22348
+ let listOrder = 0;
22349
+ /**
22350
+ * 合成资源管理
22351
+ */ class CompositionSourceManager {
22352
+ getContent(composition) {
22353
+ // TODO: specification 中补充 globalVolume 类型
22354
+ // @ts-expect-error
22355
+ const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0 } = composition;
22356
+ const items = this.assembleItems(composition);
22357
+ return _extends({}, composition, {
22358
+ id,
22359
+ duration,
22360
+ name,
22361
+ endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
22362
+ // looping,
22363
+ items,
22364
+ camera,
22365
+ startTime,
22366
+ globalVolume
22367
+ });
22368
+ }
22369
+ assembleItems(composition) {
22370
+ const items = [];
22371
+ this.mask++;
22372
+ const componentMap = {};
22373
+ //@ts-expect-error
22374
+ for (const component of this.jsonScene.components){
22375
+ componentMap[component.id] = component;
22098
22376
  }
22099
- this.initializeTrackBindings(this.timelineAsset.tracks);
22100
- this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
22101
- this.timelinePlayable.play();
22102
- for (const track of this.timelineAsset.tracks){
22103
- const binding = track.binding;
22104
- if (binding instanceof VFXItem) {
22105
- // 重播不销毁元素
22106
- if (this.item.endBehavior !== ItemEndBehavior.destroy || this.reusable) {
22107
- if (track instanceof ObjectBindingTrack) {
22108
- binding.reusable = true;
22377
+ for (const itemDataPath of composition.items){
22378
+ //@ts-expect-error
22379
+ const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
22380
+ const itemProps = sourceItemData;
22381
+ if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
22382
+ if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
22383
+ for (const componentPath of itemProps.components){
22384
+ const componentData = componentMap[componentPath.id];
22385
+ this.preProcessItemContent(componentData);
22386
+ }
22387
+ } else {
22388
+ const renderContent = itemProps.content;
22389
+ if (renderContent) {
22390
+ this.preProcessItemContent(renderContent);
22391
+ }
22392
+ }
22393
+ itemProps.listIndex = listOrder++;
22394
+ // 处理预合成的渲染顺序
22395
+ if (itemProps.type === ItemType.composition) {
22396
+ const refId = sourceItemData.content.options.refId;
22397
+ if (!this.refCompositions.get(refId)) {
22398
+ throw new Error('Invalid Ref Composition id: ' + refId);
22109
22399
  }
22110
- const subCompositionComponent = binding.getComponent(CompositionComponent);
22111
- if (subCompositionComponent) {
22112
- subCompositionComponent.reusable = true;
22400
+ const ref = this.getContent(this.refCompositions.get(refId));
22401
+ if (!this.refCompositionProps.has(refId)) {
22402
+ this.refCompositionProps.set(refId, ref);
22113
22403
  }
22404
+ ref.items.forEach((item)=>{
22405
+ this.processMask(item.content);
22406
+ });
22407
+ itemProps.items = ref.items;
22114
22408
  }
22409
+ items.push(itemProps);
22115
22410
  }
22116
- this.masterTracks.push(track);
22117
22411
  }
22412
+ return items;
22118
22413
  }
22119
- initializeTrackBindings(masterTracks) {
22120
- for (const track of masterTracks){
22121
- track.initializeBindingRecursive(track.binding);
22414
+ preProcessItemContent(renderContent) {
22415
+ if (renderContent.renderer) {
22416
+ renderContent.renderer = this.changeTex(renderContent.renderer);
22417
+ if (!renderContent.renderer.mask) {
22418
+ this.processMask(renderContent.renderer);
22419
+ }
22420
+ const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
22421
+ if (Number.isInteger(renderContent.renderer.shape)) {
22422
+ var _this_jsonScene;
22423
+ // TODO: scene.shapes 类型问题?
22424
+ renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
22425
+ } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
22426
+ renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
22427
+ }
22428
+ }
22429
+ if (renderContent.trails) {
22430
+ renderContent.trails = this.changeTex(renderContent.trails);
22122
22431
  }
22123
22432
  }
22124
- update(dt) {
22125
- const time = this.time;
22126
- // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
22127
- if (this.item.isEnded(this.time) && !this.item.parent) {
22128
- this.item.ended = true;
22433
+ changeTex(renderer) {
22434
+ if (!renderer.texture) {
22435
+ return renderer;
22129
22436
  }
22130
- this.timelinePlayable.setTime(time);
22131
- this.graph.evaluate(dt);
22132
- for(let i = 0; i < this.items.length; i++){
22133
- const item = this.items[i];
22134
- const subCompostionComponent = item.getComponent(CompositionComponent);
22135
- if (subCompostionComponent) {
22136
- const subCompositionTrack = this.masterTracks[i];
22137
- subCompostionComponent.time = subCompositionTrack.toLocalTime(time);
22138
- }
22437
+ //@ts-expect-error
22438
+ const texIdx = renderer.texture.id;
22439
+ if (texIdx !== undefined) {
22440
+ //@ts-expect-error
22441
+ this.addTextureUsage(texIdx) || texIdx;
22139
22442
  }
22443
+ return renderer;
22140
22444
  }
22141
- /**
22142
- * 重置元素状态属性
22143
- */ resetStatus() {
22144
- this.item.ended = false;
22145
- }
22146
- createContent() {
22147
- const sceneBindings = [];
22148
- for (const sceneBindingData of this.data.sceneBindings){
22149
- sceneBindings.push({
22150
- key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
22151
- value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
22152
- });
22153
- }
22154
- this.sceneBindings = sceneBindings;
22155
- const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
22156
- this.timelineAsset = timelineAsset;
22157
- const items = this.items;
22158
- this.items.length = 0;
22159
- if (this.item.composition) {
22160
- const assetLoader = this.item.engine.assetLoader;
22161
- const itemProps = this.item.props.items ? this.item.props.items : [];
22162
- for(let i = 0; i < itemProps.length; i++){
22163
- let item;
22164
- const itemData = itemProps[i];
22165
- // 设置预合成作为元素时的时长、结束行为和渲染延时
22166
- if (exports.Item.isComposition(itemData)) {
22167
- const refId = itemData.content.options.refId;
22168
- const props = this.item.composition.refCompositionProps.get(refId);
22169
- if (!props) {
22170
- throw new Error(`引用的Id: ${refId} 的预合成不存在`);
22171
- }
22172
- // endBehaviour 类型需优化
22173
- props.content = itemData.content;
22174
- item = assetLoader.loadGUID(itemData.id);
22175
- item.composition = this.item.composition;
22176
- const compositionComponent = item.addComponent(CompositionComponent);
22177
- compositionComponent.data = props;
22178
- compositionComponent.refId = refId;
22179
- item.transform.parentTransform = this.transform;
22180
- this.item.composition.refContent.push(item);
22181
- if (item.endBehavior === ItemEndBehavior.loop) {
22182
- this.item.composition.autoRefTex = false;
22183
- }
22184
- compositionComponent.createContent();
22185
- for (const vfxItem of compositionComponent.items){
22186
- vfxItem.setInstanceId(generateGUID());
22187
- for (const component of vfxItem.components){
22188
- component.setInstanceId(generateGUID());
22189
- }
22190
- }
22191
- } else {
22192
- item = assetLoader.loadGUID(itemData.id);
22193
- item.composition = this.item.composition;
22194
- }
22195
- item.parent = this.item;
22196
- // 相机不跟随合成移动
22197
- item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
22198
- if (VFXItem.isExtraCamera(item)) {
22199
- this.item.composition.extraCamera = item;
22200
- }
22201
- items.push(item);
22445
+ addTextureUsage(texIdx) {
22446
+ const texId = texIdx;
22447
+ var _this_imgUsage;
22448
+ // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
22449
+ const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
22450
+ if (texId && imageUsage) {
22451
+ // eslint-disable-next-line no-prototype-builtins
22452
+ if (!imageUsage.hasOwnProperty(texId)) {
22453
+ imageUsage[texId] = 0;
22202
22454
  }
22455
+ imageUsage[texId]++;
22203
22456
  }
22204
22457
  }
22205
- onDestroy() {
22206
- if (this.item.composition) {
22207
- if (this.items) {
22208
- this.items.forEach((item)=>item.dispose());
22209
- this.items.length = 0;
22458
+ /**
22459
+ * 处理蒙版和遮挡关系写入 stencil 的 ref 值
22460
+ */ processMask(renderer) {
22461
+ const maskMode = renderer.maskMode;
22462
+ if (maskMode === MaskMode.NONE) {
22463
+ return;
22464
+ }
22465
+ if (!renderer.mask) {
22466
+ if (maskMode === MaskMode.MASK) {
22467
+ renderer.mask = ++this.mask;
22468
+ } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
22469
+ renderer.mask = this.mask;
22210
22470
  }
22211
22471
  }
22212
22472
  }
22213
- hitTest(ray, x, y, regions, force, options) {
22214
- const hitPositions = [];
22215
- const stop = (options == null ? void 0 : options.stop) || noop;
22216
- const skip = (options == null ? void 0 : options.skip) || noop;
22217
- const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
22218
- for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
22219
- const item = this.items[i];
22220
- if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
22221
- const hitParams = item.getHitTestParams(force);
22222
- if (hitParams) {
22223
- let success = false;
22224
- const intersectPoint = new Vector3();
22225
- if (hitParams.type === exports.HitTestType.triangle) {
22226
- const { triangles, backfaceCulling } = hitParams;
22227
- for(let j = 0; j < triangles.length; j++){
22228
- const triangle = triangles[j];
22229
- if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
22230
- success = true;
22231
- hitPositions.push(intersectPoint);
22232
- break;
22233
- }
22234
- }
22235
- } else if (hitParams.type === exports.HitTestType.box) {
22236
- const { center, size } = hitParams;
22237
- const boxMin = center.clone().addScaledVector(size, 0.5);
22238
- const boxMax = center.clone().addScaledVector(size, -0.5);
22239
- if (ray.intersectBox({
22240
- min: boxMin,
22241
- max: boxMax
22242
- }, intersectPoint)) {
22243
- success = true;
22244
- hitPositions.push(intersectPoint);
22245
- }
22246
- } else if (hitParams.type === exports.HitTestType.sphere) {
22247
- const { center, radius } = hitParams;
22248
- if (ray.intersectSphere({
22249
- center,
22250
- radius
22251
- }, intersectPoint)) {
22252
- success = true;
22253
- hitPositions.push(intersectPoint);
22254
- }
22255
- } else if (hitParams.type === exports.HitTestType.custom) {
22256
- const tempPosition = hitParams.collect(ray, new Vector2(x, y));
22257
- if (tempPosition && tempPosition.length > 0) {
22258
- tempPosition.forEach((pos)=>{
22259
- hitPositions.push(pos);
22260
- });
22261
- success = true;
22262
- }
22263
- }
22264
- if (success) {
22265
- const region = {
22266
- compContent: this.item,
22267
- id: item.id,
22268
- name: item.name,
22269
- position: hitPositions[hitPositions.length - 1],
22270
- parentId: item.parentId,
22271
- hitPositions,
22272
- behavior: hitParams.behavior
22273
- };
22274
- regions.push(region);
22275
- if (stop(region)) {
22276
- return regions;
22277
- }
22278
- }
22279
- }
22473
+ dispose() {
22474
+ this.textures = [];
22475
+ this.composition = undefined;
22476
+ this.jsonScene = undefined;
22477
+ this.totalTime = 0;
22478
+ this.pluginSystem = undefined;
22479
+ this.sourceContent = undefined;
22480
+ this.refCompositions.clear();
22481
+ this.refCompositionProps.clear();
22482
+ }
22483
+ constructor(scene, engine){
22484
+ this.refCompositions = new Map();
22485
+ this.refCompositionProps = new Map();
22486
+ this.mask = 0;
22487
+ this.engine = engine;
22488
+ // 资源
22489
+ const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
22490
+ const { compositions, imgUsage, compositionId } = jsonScene;
22491
+ if (!textureOptions) {
22492
+ throw new Error('scene.textures expected');
22493
+ }
22494
+ const cachedTextures = textureOptions;
22495
+ for (const comp of compositions){
22496
+ if (comp.id === compositionId) {
22497
+ this.composition = comp;
22498
+ } else {
22499
+ this.refCompositions.set(comp.id, comp);
22280
22500
  }
22281
22501
  }
22282
- return regions;
22283
- }
22284
- fromData(data) {
22285
- // this.timelineAsset = data.timelineAsset;
22286
- }
22287
- constructor(...args){
22288
- super(...args);
22289
- this.time = 0;
22290
- this.startTime = 0;
22291
- this.items = [] // 场景的所有元素
22292
- ;
22293
- this.reusable = false;
22294
- this.sceneBindings = [];
22295
- this.masterTracks = [];
22296
- this.graph = new PlayableGraph();
22502
+ if (!this.composition) {
22503
+ throw new Error('Invalid composition id: ' + compositionId);
22504
+ }
22505
+ this.jsonScene = jsonScene;
22506
+ this.renderLevel = renderLevel;
22507
+ this.pluginSystem = pluginSystem;
22508
+ this.totalTime = totalTime != null ? totalTime : 0;
22509
+ this.imgUsage = imgUsage != null ? imgUsage : {};
22510
+ this.textures = cachedTextures;
22511
+ listOrder = 0;
22512
+ this.sourceContent = this.getContent(this.composition);
22297
22513
  }
22298
22514
  }
22299
22515
 
@@ -22303,6 +22519,11 @@ const tmpScale = new Vector3(1, 1, 1);
22303
22519
  * 也负责 Item 相关的动画播放控制,和持有渲染帧数据。
22304
22520
  */ class Composition {
22305
22521
  /**
22522
+ * 所有合成 Item 的根变换
22523
+ */ get transform() {
22524
+ return this.rootItem.transform;
22525
+ }
22526
+ /**
22306
22527
  * 获取场景中的纹理数组
22307
22528
  */ get textures() {
22308
22529
  return this.compositionSourceManager.textures;
@@ -22336,16 +22557,8 @@ const tmpScale = new Vector3(1, 1, 1);
22336
22557
  /**
22337
22558
  * 重新开始合成
22338
22559
  */ restart() {
22339
- // const contentItems = this.rootComposition.items;
22340
- // contentItems.forEach(item => item.dispose());
22341
- // contentItems.length = 0;
22342
- this.prepareRender();
22343
22560
  this.reset();
22344
- this.transform.setValid(true);
22345
- this.rootComposition.resetStatus();
22346
22561
  this.forwardTime(this.startTime);
22347
- // this.content.onUpdate(0);
22348
- // this.loaderData.spriteGroup.onUpdate(0);
22349
22562
  }
22350
22563
  /**
22351
22564
  * 设置当前合成的渲染顺序
@@ -22472,27 +22685,9 @@ const tmpScale = new Vector3(1, 1, 1);
22472
22685
  /**
22473
22686
  * 重置状态函数
22474
22687
  */ reset() {
22475
- const vfxItem = new VFXItem(this.getEngine(), this.compositionSourceManager.sourceContent);
22476
- // TODO 编辑器数据传入 composition type 后移除
22477
- vfxItem.type = ItemType.composition;
22478
- vfxItem.composition = this;
22479
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
22480
- this.rootComposition.data = this.compositionSourceManager.sourceContent;
22481
- this.transform = new Transform({
22482
- name: this.name
22483
- });
22484
- this.transform.engine = this.getEngine();
22485
- vfxItem.transform = this.transform;
22486
- this.rootItem = vfxItem;
22487
22688
  this.rendererOptions = null;
22488
22689
  this.globalTime = 0;
22489
- this.rootComposition.createContent();
22490
- this.buildItemTree(this.rootItem);
22491
- this.rootItem.onEnd = ()=>{
22492
- window.setTimeout(()=>{
22493
- this.onEnd == null ? void 0 : this.onEnd.call(this, this);
22494
- }, 0);
22495
- };
22690
+ this.rootItem.ended = false;
22496
22691
  this.pluginSystem.resetComposition(this, this.renderFrame);
22497
22692
  }
22498
22693
  prepareRender() {
@@ -22533,7 +22728,6 @@ const tmpScale = new Vector3(1, 1, 1);
22533
22728
  }
22534
22729
  const { ended, endBehavior } = this.rootItem;
22535
22730
  // TODO: 合成结束行为
22536
- // @ts-expect-error
22537
22731
  return ended && (!endBehavior || endBehavior === END_BEHAVIOR_PAUSE_AND_DESTROY);
22538
22732
  }
22539
22733
  /**
@@ -22622,7 +22816,7 @@ const tmpScale = new Vector3(1, 1, 1);
22622
22816
  for (const child of item.children){
22623
22817
  if (VFXItem.isComposition(child)) {
22624
22818
  if (child.ended && child.endBehavior === ItemEndBehavior.loop) {
22625
- child.getComponent(CompositionComponent).resetStatus();
22819
+ child.ended = false;
22626
22820
  // TODO K帧动画在元素重建后需要 tick ,否则会导致元素位置和 k 帧第一帧位置不一致
22627
22821
  this.callUpdate(child, 0);
22628
22822
  } else {
@@ -22989,46 +23183,48 @@ const tmpScale = new Vector3(1, 1, 1);
22989
23183
  * @param props - composition 的创建参数
22990
23184
  * @param scene
22991
23185
  * @param compositionSourceManager
22992
- */ constructor(props, scene, compositionSourceManager){
22993
- this.compositionSourceManager = compositionSourceManager;
22994
- this./**
23186
+ */ constructor(props, scene){
23187
+ /**
22995
23188
  * 动画播放速度
22996
- */ speed = 1;
22997
- this.loaderData = {};
22998
- this.refContent = [];
22999
- this./**
23189
+ */ this.speed = 1;
23190
+ /**
23191
+ * 用于保存与当前合成相关的插件数据
23192
+ */ this.loaderData = {};
23193
+ /**
23194
+ * 预合成数组
23195
+ */ this.refContent = [];
23196
+ /**
23000
23197
  * 预合成的合成属性,在 content 中会被其元素属性覆盖
23001
- */ refCompositionProps = new Map();
23198
+ */ this.refCompositionProps = new Map();
23002
23199
  this.editorScaleRatio = 1.0;
23200
+ // TODO: 待优化
23003
23201
  this.assigned = false;
23004
- this.destroyed = false;
23005
- this.paused = false;
23202
+ /**
23203
+ * 销毁状态位
23204
+ */ this.destroyed = false;
23205
+ /**
23206
+ * 合成暂停/播放 标识
23207
+ */ this.paused = false;
23006
23208
  this.lastVideoUpdateTime = 0;
23007
23209
  this.postLoaders = [];
23008
23210
  const { reusable = false, speed = 1, baseRenderOrder = 0, renderer, onPlayerPause, onMessageItem, onEnd, event, width, height } = props;
23211
+ this.compositionSourceManager = new CompositionSourceManager(scene, renderer.engine);
23009
23212
  scene.jsonScene.imgUsage = undefined;
23010
23213
  if (reusable) {
23011
23214
  this.keepResource = true;
23012
23215
  scene.textures = undefined;
23013
23216
  scene.consumed = true;
23014
23217
  }
23015
- const { sourceContent, pluginSystem, imgUsage, totalTime, renderLevel, refCompositionProps } = this.compositionSourceManager;
23218
+ const { sourceContent, pluginSystem, imgUsage, totalTime, refCompositionProps } = this.compositionSourceManager;
23016
23219
  assertExist(sourceContent);
23017
23220
  this.renderer = renderer;
23018
23221
  this.refCompositionProps = refCompositionProps;
23019
- const vfxItem = new VFXItem(this.getEngine(), sourceContent);
23020
- vfxItem.name = 'rootItem';
23021
- // TODO 编辑器数据传入 composition type 后移除
23022
- vfxItem.type = ItemType.composition;
23023
- vfxItem.composition = this;
23024
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
23222
+ this.rootItem = new VFXItem(this.getEngine(), sourceContent);
23223
+ this.rootItem.name = 'rootItem';
23224
+ this.rootItem.composition = this;
23225
+ this.rootComposition = this.rootItem.addComponent(CompositionComponent);
23025
23226
  this.rootComposition.data = sourceContent;
23026
23227
  const imageUsage = !reusable && imgUsage;
23027
- this.transform = new Transform({
23028
- name: this.name
23029
- });
23030
- this.transform.engine = this.getEngine();
23031
- vfxItem.transform = this.transform;
23032
23228
  this.globalVolume = sourceContent.globalVolume;
23033
23229
  this.width = width;
23034
23230
  this.height = height;
@@ -23045,9 +23241,7 @@ const tmpScale = new Vector3(1, 1, 1);
23045
23241
  };
23046
23242
  this.reusable = reusable;
23047
23243
  this.speed = speed;
23048
- this.renderLevel = renderLevel;
23049
- this.autoRefTex = !this.keepResource && imageUsage && vfxItem.endBehavior !== ItemEndBehavior.loop;
23050
- this.rootItem = vfxItem;
23244
+ this.autoRefTex = !this.keepResource && imageUsage && this.rootItem.endBehavior !== ItemEndBehavior.loop;
23051
23245
  this.name = sourceContent.name;
23052
23246
  this.pluginSystem = pluginSystem;
23053
23247
  this.pluginSystem.initializeComposition(this, scene);
@@ -23073,182 +23267,6 @@ const tmpScale = new Vector3(1, 1, 1);
23073
23267
  }
23074
23268
  }
23075
23269
 
23076
- let listOrder = 0;
23077
- /**
23078
- * 合成资源管理
23079
- */ class CompositionSourceManager {
23080
- getContent(composition) {
23081
- // TODO: specification 中补充 globalVolume 类型
23082
- // @ts-expect-error
23083
- const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0, timelineAsset } = composition;
23084
- const items = this.assembleItems(composition);
23085
- //@ts-expect-error
23086
- if (!composition.sceneBindings) {
23087
- //@ts-expect-error
23088
- composition.sceneBindings = [];
23089
- }
23090
- return {
23091
- id,
23092
- duration,
23093
- name,
23094
- endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
23095
- // looping,
23096
- items,
23097
- camera,
23098
- startTime,
23099
- globalVolume,
23100
- timelineAsset: timelineAsset,
23101
- //@ts-expect-error
23102
- sceneBindings: composition.sceneBindings
23103
- };
23104
- }
23105
- assembleItems(composition) {
23106
- const items = [];
23107
- this.mask++;
23108
- const componentMap = {};
23109
- //@ts-expect-error
23110
- for (const component of this.jsonScene.components){
23111
- componentMap[component.id] = component;
23112
- }
23113
- for (const itemDataPath of composition.items){
23114
- //@ts-expect-error
23115
- const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
23116
- const itemProps = sourceItemData;
23117
- if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
23118
- if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
23119
- for (const componentPath of itemProps.components){
23120
- const componentData = componentMap[componentPath.id];
23121
- this.preProcessItemContent(componentData);
23122
- }
23123
- } else {
23124
- const renderContent = itemProps.content;
23125
- if (renderContent) {
23126
- this.preProcessItemContent(renderContent);
23127
- }
23128
- }
23129
- itemProps.listIndex = listOrder++;
23130
- // 处理预合成的渲染顺序
23131
- if (itemProps.type === ItemType.composition) {
23132
- const refId = sourceItemData.content.options.refId;
23133
- if (!this.refCompositions.get(refId)) {
23134
- throw new Error('Invalid Ref Composition id: ' + refId);
23135
- }
23136
- const ref = this.getContent(this.refCompositions.get(refId));
23137
- if (!this.refCompositionProps.has(refId)) {
23138
- this.refCompositionProps.set(refId, ref);
23139
- }
23140
- ref.items.forEach((item)=>{
23141
- this.processMask(item.content);
23142
- });
23143
- itemProps.items = ref.items;
23144
- }
23145
- items.push(itemProps);
23146
- }
23147
- }
23148
- return items;
23149
- }
23150
- preProcessItemContent(renderContent) {
23151
- if (renderContent.renderer) {
23152
- renderContent.renderer = this.changeTex(renderContent.renderer);
23153
- if (!renderContent.renderer.mask) {
23154
- this.processMask(renderContent.renderer);
23155
- }
23156
- const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
23157
- if (Number.isInteger(renderContent.renderer.shape)) {
23158
- var _this_jsonScene;
23159
- // TODO: scene.shapes 类型问题?
23160
- renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
23161
- } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
23162
- renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
23163
- }
23164
- }
23165
- if (renderContent.trails) {
23166
- renderContent.trails = this.changeTex(renderContent.trails);
23167
- }
23168
- }
23169
- changeTex(renderer) {
23170
- if (!renderer.texture) {
23171
- return renderer;
23172
- }
23173
- //@ts-expect-error
23174
- const texIdx = renderer.texture.id;
23175
- if (texIdx !== undefined) {
23176
- //@ts-expect-error
23177
- this.addTextureUsage(texIdx) || texIdx;
23178
- }
23179
- return renderer;
23180
- }
23181
- addTextureUsage(texIdx) {
23182
- const texId = texIdx;
23183
- var _this_imgUsage;
23184
- // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
23185
- const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
23186
- if (texId && imageUsage) {
23187
- // eslint-disable-next-line no-prototype-builtins
23188
- if (!imageUsage.hasOwnProperty(texId)) {
23189
- imageUsage[texId] = 0;
23190
- }
23191
- imageUsage[texId]++;
23192
- }
23193
- }
23194
- /**
23195
- * 处理蒙版和遮挡关系写入 stencil 的 ref 值
23196
- */ processMask(renderer) {
23197
- const maskMode = renderer.maskMode;
23198
- if (maskMode === MaskMode.NONE) {
23199
- return;
23200
- }
23201
- if (!renderer.mask) {
23202
- if (maskMode === MaskMode.MASK) {
23203
- renderer.mask = ++this.mask;
23204
- } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
23205
- renderer.mask = this.mask;
23206
- }
23207
- }
23208
- }
23209
- dispose() {
23210
- this.textures = [];
23211
- this.composition = undefined;
23212
- this.jsonScene = undefined;
23213
- this.totalTime = 0;
23214
- this.pluginSystem = undefined;
23215
- this.sourceContent = undefined;
23216
- this.refCompositions.clear();
23217
- this.refCompositionProps.clear();
23218
- }
23219
- constructor(scene, engine){
23220
- this.refCompositions = new Map();
23221
- this.refCompositionProps = new Map();
23222
- this.mask = 0;
23223
- this.engine = engine;
23224
- // 资源
23225
- const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
23226
- const { compositions, imgUsage, compositionId } = jsonScene;
23227
- if (!textureOptions) {
23228
- throw new Error('scene.textures expected');
23229
- }
23230
- const cachedTextures = textureOptions;
23231
- for (const comp of compositions){
23232
- if (comp.id === compositionId) {
23233
- this.composition = comp;
23234
- } else {
23235
- this.refCompositions.set(comp.id, comp);
23236
- }
23237
- }
23238
- if (!this.composition) {
23239
- throw new Error('Invalid composition id: ' + compositionId);
23240
- }
23241
- this.jsonScene = jsonScene;
23242
- this.renderLevel = renderLevel;
23243
- this.pluginSystem = pluginSystem;
23244
- this.totalTime = totalTime != null ? totalTime : 0;
23245
- this.imgUsage = imgUsage != null ? imgUsage : {};
23246
- this.textures = cachedTextures;
23247
- listOrder = 0;
23248
- this.sourceContent = this.getContent(this.composition);
23249
- }
23250
- }
23251
-
23252
23270
  /**
23253
23271
  * Engine 基类,负责维护所有 GPU 资源的管理及销毁
23254
23272
  */ class Engine {
@@ -23272,65 +23290,48 @@ let listOrder = 0;
23272
23290
  delete this.objectInstance[id];
23273
23291
  }
23274
23292
  addPackageDatas(scene) {
23275
- const jsonScene = scene.jsonScene;
23276
- if (jsonScene.items) {
23277
- for (const vfxItemData of jsonScene.items){
23278
- this.addEffectsObjectData(vfxItemData);
23279
- }
23293
+ const { jsonScene, textureOptions = [] } = scene;
23294
+ const { items = [], materials = [], shaders = [], geometries = [], components = [], animations = [], bins = [] } = jsonScene;
23295
+ for (const vfxItemData of items){
23296
+ this.addEffectsObjectData(vfxItemData);
23280
23297
  }
23281
- if (jsonScene.materials) {
23282
- for (const materialData of jsonScene.materials){
23283
- this.addEffectsObjectData(materialData);
23284
- }
23298
+ for (const materialData of materials){
23299
+ this.addEffectsObjectData(materialData);
23285
23300
  }
23286
- if (jsonScene.shaders) {
23287
- for (const shaderData of jsonScene.shaders){
23288
- this.addEffectsObjectData(shaderData);
23289
- }
23301
+ for (const shaderData of shaders){
23302
+ this.addEffectsObjectData(shaderData);
23290
23303
  }
23291
- if (jsonScene.geometries) {
23292
- for (const geometryData of jsonScene.geometries){
23293
- this.addEffectsObjectData(geometryData);
23294
- }
23304
+ for (const geometryData of geometries){
23305
+ this.addEffectsObjectData(geometryData);
23295
23306
  }
23296
- if (jsonScene.components) {
23297
- for (const componentData of jsonScene.components){
23298
- this.addEffectsObjectData(componentData);
23299
- }
23307
+ for (const componentData of components){
23308
+ this.addEffectsObjectData(componentData);
23300
23309
  }
23301
- if (jsonScene.animations) {
23302
- for (const animationData of jsonScene.animations){
23303
- this.addEffectsObjectData(animationData);
23304
- }
23310
+ for (const animationData of animations){
23311
+ this.addEffectsObjectData(animationData);
23305
23312
  }
23306
- if (jsonScene.bins) {
23307
- for(let i = 0; i < jsonScene.bins.length; i++){
23308
- const binaryData = jsonScene.bins[i];
23309
- const binaryBuffer = scene.bins[i];
23310
- //@ts-expect-error
23311
- binaryData.buffer = binaryBuffer;
23313
+ for(let i = 0; i < bins.length; i++){
23314
+ const binaryData = bins[i];
23315
+ const binaryBuffer = scene.bins[i];
23316
+ //@ts-expect-error
23317
+ binaryData.buffer = binaryBuffer;
23318
+ //@ts-expect-error
23319
+ if (binaryData.id) {
23312
23320
  //@ts-expect-error
23313
- if (binaryData.id) {
23314
- //@ts-expect-error
23315
- this.addEffectsObjectData(binaryData);
23316
- }
23321
+ this.addEffectsObjectData(binaryData);
23317
23322
  }
23318
23323
  }
23319
- if (scene.textureOptions) {
23320
- for (const textureData of scene.textureOptions){
23321
- this.addEffectsObjectData(textureData);
23322
- }
23324
+ for (const textureData of textureOptions){
23325
+ this.addEffectsObjectData(textureData);
23323
23326
  }
23324
23327
  }
23325
23328
  createVFXItems(scene) {
23326
23329
  var _this = this;
23327
23330
  return _async_to_generator(function*() {
23328
- const jsonScene = scene.jsonScene;
23331
+ const { jsonScene } = scene;
23329
23332
  for (const itemData of jsonScene.items){
23330
23333
  const itemType = itemData.type;
23331
- if (!// @ts-expect-error
23332
- (itemType === 'ECS' || // @ts-expect-error
23333
- itemType === 'camera' || itemType === ItemType.sprite || itemType === ItemType.particle || itemType === ItemType.mesh || itemType === ItemType.skybox || itemType === ItemType.light || itemType === ItemType.tree || itemType === ItemType.interact || itemType === ItemType.camera)) {
23334
+ if (!(itemType === 'ECS' || itemType === 'camera' || itemType === ItemType.sprite || itemType === ItemType.particle || itemType === ItemType.mesh || itemType === ItemType.skybox || itemType === ItemType.light || itemType === ItemType.tree || itemType === ItemType.interact || itemType === ItemType.camera)) {
23334
23335
  continue;
23335
23336
  }
23336
23337
  if (_this.database) {
@@ -23428,21 +23429,11 @@ let listOrder = 0;
23428
23429
  if (info.length > 0) {
23429
23430
  logger.warn(`Release GPU memory: ${info.join(', ')}`);
23430
23431
  }
23431
- this.renderPasses.forEach((pass)=>{
23432
- pass.dispose();
23433
- });
23434
- this.meshes.forEach((mesh)=>{
23435
- mesh.dispose();
23436
- });
23437
- this.geometries.forEach((geo)=>{
23438
- geo.dispose();
23439
- });
23440
- this.materials.forEach((mat)=>{
23441
- mat.dispose();
23442
- });
23443
- this.textures.forEach((tex)=>{
23444
- tex.dispose();
23445
- });
23432
+ this.renderPasses.forEach((pass)=>pass.dispose());
23433
+ this.meshes.forEach((mesh)=>mesh.dispose());
23434
+ this.geometries.forEach((geo)=>geo.dispose());
23435
+ this.materials.forEach((mat)=>mat.dispose());
23436
+ this.textures.forEach((tex)=>tex.dispose());
23446
23437
  this.textures = [];
23447
23438
  this.materials = [];
23448
23439
  this.geometries = [];
@@ -23689,6 +23680,8 @@ exports.SpriteColorTrack = SpriteColorTrack;
23689
23680
  exports.SpriteComponent = SpriteComponent;
23690
23681
  exports.SpriteLoader = SpriteLoader;
23691
23682
  exports.StaticValue = StaticValue;
23683
+ exports.SubCompositionPlayableAsset = SubCompositionPlayableAsset;
23684
+ exports.SubCompositionTrack = SubCompositionTrack;
23692
23685
  exports.TEMPLATE_USE_OFFSCREEN_CANVAS = TEMPLATE_USE_OFFSCREEN_CANVAS;
23693
23686
  exports.TextComponent = TextComponent;
23694
23687
  exports.TextLoader = TextLoader;
@@ -23711,6 +23704,7 @@ exports.addItem = addItem;
23711
23704
  exports.addItemWithOrder = addItemWithOrder;
23712
23705
  exports.assertExist = assertExist;
23713
23706
  exports.asserts = asserts;
23707
+ exports.base64ToFile = base64ToFile;
23714
23708
  exports.blend = blend;
23715
23709
  exports.calculateTranslation = calculateTranslation;
23716
23710
  exports.canvasPool = canvasPool;
@@ -23779,6 +23773,7 @@ exports.interpolateColor = interpolateColor;
23779
23773
  exports.isAlipayMiniApp = isAlipayMiniApp;
23780
23774
  exports.isAndroid = isAndroid;
23781
23775
  exports.isArray = isArray;
23776
+ exports.isCanvas = isCanvas;
23782
23777
  exports.isFunction = isFunction;
23783
23778
  exports.isIOS = isIOS;
23784
23779
  exports.isObject = isObject;