@galacean/effects-core 2.0.0-alpha.13 → 2.0.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs 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.13
6
+ * Version: v2.0.0-alpha.15
7
7
  */
8
8
 
9
9
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -593,6 +593,11 @@ function noop() {}
593
593
  */ function isObject(obj) {
594
594
  return Object.prototype.toString.call(obj) === '[object Object]';
595
595
  }
596
+ function isCanvas(canvas) {
597
+ var _canvas_tagName;
598
+ // 小程序 Canvas 无法使用 instanceof HTMLCanvasElement 判断
599
+ return typeof canvas === 'object' && canvas !== null && ((_canvas_tagName = canvas.tagName) == null ? void 0 : _canvas_tagName.toUpperCase()) === 'CANVAS';
600
+ }
596
601
  function deepClone(obj) {
597
602
  if (isArray(obj)) {
598
603
  return obj.map(deepClone);
@@ -620,6 +625,35 @@ function throwDestroyedError() {
620
625
  function generateGUID() {
621
626
  return v4().replace(/-/g, '');
622
627
  }
628
+ function base64ToFile(base64, filename = 'base64File', contentType = '') {
629
+ // 去掉 Base64 字符串的 Data URL 部分(如果存在)
630
+ const base64WithoutPrefix = base64.split(',')[1] || base64;
631
+ // 将 base64 编码的字符串转换为二进制字符串
632
+ const byteCharacters = atob(base64WithoutPrefix);
633
+ // 创建一个 8 位无符号整数值的数组,即“字节数组”
634
+ const byteArrays = [];
635
+ // 切割二进制字符串为多个片段,并将每个片段转换成一个字节数组
636
+ for(let offset = 0; offset < byteCharacters.length; offset += 512){
637
+ const slice = byteCharacters.slice(offset, offset + 512);
638
+ const byteNumbers = new Array(slice.length);
639
+ for(let i = 0; i < slice.length; i++){
640
+ byteNumbers[i] = slice.charCodeAt(i);
641
+ }
642
+ const byteArray = new Uint8Array(byteNumbers);
643
+ byteArrays.push(byteArray);
644
+ }
645
+ // 使用字节数组创建 Blob 对象
646
+ const blob = new Blob(byteArrays, {
647
+ type: contentType
648
+ });
649
+ // 创建 File 对象
650
+ const file = new File([
651
+ blob
652
+ ], filename, {
653
+ type: contentType
654
+ });
655
+ return file;
656
+ }
623
657
 
624
658
  function __decorate(decorators, target, key, desc) {
625
659
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -17448,6 +17482,9 @@ class ActivationPlayableAsset extends PlayableAsset {
17448
17482
  return new ActivationPlayable(graph);
17449
17483
  }
17450
17484
  }
17485
+ ActivationPlayableAsset = __decorate([
17486
+ effectsClass('ActivationPlayableAsset')
17487
+ ], ActivationPlayableAsset);
17451
17488
  class AnimationClip extends EffectsObject {
17452
17489
  sampleAnimation(vfxItem, time) {
17453
17490
  const duration = vfxItem.duration;
@@ -17546,16 +17583,15 @@ class AnimationClipPlayable extends Playable {
17546
17583
  }
17547
17584
 
17548
17585
  class TrackAsset extends PlayableAsset {
17549
- initializeBinding(parentBinding) {
17550
- this.binding = parentBinding;
17586
+ /**
17587
+ * 重写该方法以获取自定义对象绑定
17588
+ */ resolveBinding(parentBinding) {
17589
+ return parentBinding;
17551
17590
  }
17552
17591
  /**
17553
- * @internal
17554
- */ initializeBindingRecursive(parentBinding) {
17555
- this.initializeBinding(parentBinding);
17556
- for (const subTrack of this.children){
17557
- subTrack.initializeBindingRecursive(this.binding);
17558
- }
17592
+ * 重写该方法以创建自定义混合器
17593
+ */ createTrackMixer(graph) {
17594
+ return new Playable(graph);
17559
17595
  }
17560
17596
  createOutput() {
17561
17597
  const output = new PlayableOutput();
@@ -17584,17 +17620,15 @@ class TrackAsset extends PlayableAsset {
17584
17620
  }
17585
17621
  return mixer;
17586
17622
  }
17587
- /**
17588
- * 重写该方法以创建自定义混合器
17589
- */ createTrackMixer(graph) {
17590
- return new Playable(graph);
17591
- }
17592
17623
  createPlayable(graph) {
17593
17624
  return new Playable(graph);
17594
17625
  }
17595
17626
  getChildTracks() {
17596
17627
  return this.children;
17597
17628
  }
17629
+ addChild(child) {
17630
+ this.children.push(child);
17631
+ }
17598
17632
  createClip(classConstructor, name) {
17599
17633
  const newClip = new TimelineClip();
17600
17634
  newClip.asset = new classConstructor(this.engine);
@@ -17676,9 +17710,10 @@ class RuntimeClip {
17676
17710
  let weight = 1.0;
17677
17711
  let ended = false;
17678
17712
  let started = false;
17713
+ const boundItem = this.track.binding;
17679
17714
  if (localTime > clip.start + clip.duration + 0.001 && clip.endBehaviour === ItemEndBehavior.destroy) {
17680
- var _this_track_binding_getComponent;
17681
- if (VFXItem.isParticle(this.track.binding) && !((_this_track_binding_getComponent = this.track.binding.getComponent(ParticleSystem)) == null ? void 0 : _this_track_binding_getComponent.destroyed)) {
17715
+ var _boundItem_getComponent;
17716
+ if (VFXItem.isParticle(boundItem) && !((_boundItem_getComponent = boundItem.getComponent(ParticleSystem)) == null ? void 0 : _boundItem_getComponent.destroyed)) {
17682
17717
  weight = 1.0;
17683
17718
  } else {
17684
17719
  weight = 0.0;
@@ -17694,7 +17729,6 @@ class RuntimeClip {
17694
17729
  this.playable.play();
17695
17730
  }
17696
17731
  this.parentMixer.setInputWeight(this.playable, weight);
17697
- const boundItem = this.track.binding;
17698
17732
  // 判断动画是否结束
17699
17733
  if (ended && !boundItem.ended) {
17700
17734
  boundItem.ended = true;
@@ -17723,6 +17757,34 @@ class RuntimeClip {
17723
17757
  }
17724
17758
  }
17725
17759
 
17760
+ class ObjectBindingTrack extends TrackAsset {
17761
+ create(timelineAsset) {
17762
+ const boundItem = this.binding;
17763
+ // 添加粒子动画 clip
17764
+ if (boundItem.getComponent(ParticleSystem)) {
17765
+ const particleTrack = timelineAsset.createTrack(TrackAsset, this, 'ParticleTrack');
17766
+ particleTrack.binding = this.binding;
17767
+ const particleClip = particleTrack.createClip(ParticleBehaviourPlayableAsset);
17768
+ particleClip.start = boundItem.start;
17769
+ particleClip.duration = boundItem.duration;
17770
+ particleClip.endBehaviour = boundItem.endBehavior;
17771
+ }
17772
+ }
17773
+ fromData(data) {
17774
+ super.fromData(data);
17775
+ this.data = data;
17776
+ }
17777
+ }
17778
+ ObjectBindingTrack = __decorate([
17779
+ effectsClass('ObjectBindingTrack')
17780
+ ], ObjectBindingTrack);
17781
+
17782
+ class TransformTrack extends TrackAsset {
17783
+ }
17784
+ TransformTrack = __decorate([
17785
+ effectsClass('TransformTrack')
17786
+ ], TransformTrack);
17787
+
17726
17788
  class ActivationMixerPlayable extends Playable {
17727
17789
  processFrame(context) {
17728
17790
  if (!this.bindingItem) {
@@ -17772,73 +17834,6 @@ ActivationTrack = __decorate([
17772
17834
  effectsClass('ActivationTrack')
17773
17835
  ], ActivationTrack);
17774
17836
 
17775
- class ObjectBindingTrack extends TrackAsset {
17776
- create() {
17777
- this.options = {
17778
- start: this.binding.start,
17779
- duration: this.binding.duration,
17780
- looping: this.binding.endBehavior === ItemEndBehavior.loop,
17781
- endBehavior: this.binding.endBehavior || ItemEndBehavior.destroy
17782
- };
17783
- this.id = this.binding.id;
17784
- this.name = this.binding.name;
17785
- const activationTrack = this.createTrack(ActivationTrack, 'ActivationTrack');
17786
- activationTrack.binding = this.binding;
17787
- activationTrack.createClip(ActivationPlayableAsset, 'ActivationTimelineClip');
17788
- // 添加粒子动画 clip
17789
- if (this.binding.getComponent(ParticleSystem)) {
17790
- const particleTrack = this.createTrack(TrackAsset, 'ParticleTrack');
17791
- particleTrack.binding = this.binding;
17792
- particleTrack.createClip(ParticleBehaviourPlayableAsset);
17793
- }
17794
- // TODO TimelineClip 需要传入 start 和 duration 数据
17795
- for (const track of this.children){
17796
- for (const clip of track.getClips()){
17797
- clip.start = this.binding.start;
17798
- clip.duration = this.binding.duration;
17799
- clip.endBehaviour = this.binding.endBehavior;
17800
- }
17801
- }
17802
- }
17803
- toLocalTime(time) {
17804
- let localTime = time - this.options.start;
17805
- const duration = this.options.duration;
17806
- if (localTime - duration > 0.001) {
17807
- if (this.options.endBehavior === END_BEHAVIOR_RESTART) {
17808
- localTime = localTime % duration;
17809
- } else if (this.options.endBehavior === END_BEHAVIOR_FREEZE) {
17810
- localTime = Math.min(duration, localTime);
17811
- }
17812
- }
17813
- return localTime;
17814
- }
17815
- createTrack(classConstructor, name) {
17816
- const newTrack = new classConstructor(this.engine);
17817
- newTrack.binding = this.binding;
17818
- newTrack.id = (this.trackSeed++).toString();
17819
- newTrack.name = name ? name : 'Track' + newTrack.id;
17820
- this.children.push(newTrack);
17821
- return newTrack;
17822
- }
17823
- fromData(data) {
17824
- super.fromData(data);
17825
- this.data = data;
17826
- }
17827
- constructor(...args){
17828
- super(...args);
17829
- this.trackSeed = 0;
17830
- }
17831
- }
17832
- ObjectBindingTrack = __decorate([
17833
- effectsClass('ObjectBindingTrack')
17834
- ], ObjectBindingTrack);
17835
-
17836
- class TransformTrack extends TrackAsset {
17837
- }
17838
- TransformTrack = __decorate([
17839
- effectsClass('TransformTrack')
17840
- ], TransformTrack);
17841
-
17842
17837
  class SpriteColorTrack extends TrackAsset {
17843
17838
  }
17844
17839
  SpriteColorTrack = __decorate([
@@ -17847,20 +17842,31 @@ SpriteColorTrack = __decorate([
17847
17842
 
17848
17843
  class TimelineAsset extends PlayableAsset {
17849
17844
  createPlayable(graph) {
17850
- this.graph = graph;
17851
17845
  const timelinePlayable = new TimelinePlayable(graph);
17852
17846
  timelinePlayable.setTraversalMode(PlayableTraversalMode.Passthrough);
17847
+ for (const track of this.tracks){
17848
+ if (track instanceof ObjectBindingTrack) {
17849
+ track.create(this);
17850
+ }
17851
+ }
17853
17852
  timelinePlayable.compileTracks(graph, this.tracks);
17854
17853
  return timelinePlayable;
17855
17854
  }
17856
- fromData(data) {
17857
- this.tracks = data.tracks;
17855
+ createTrack(classConstructor, parent, name) {
17856
+ const newTrack = new classConstructor(this.engine);
17857
+ newTrack.name = name ? name : classConstructor.name;
17858
+ parent.addChild(newTrack);
17859
+ return newTrack;
17858
17860
  }
17861
+ fromData(data) {}
17859
17862
  constructor(...args){
17860
17863
  super(...args);
17861
17864
  this.tracks = [];
17862
17865
  }
17863
17866
  }
17867
+ __decorate([
17868
+ serialize()
17869
+ ], TimelineAsset.prototype, "tracks", void 0);
17864
17870
  TimelineAsset = __decorate([
17865
17871
  effectsClass('TimelineAsset')
17866
17872
  ], TimelineAsset);
@@ -17877,12 +17883,6 @@ class TimelinePlayable extends Playable {
17877
17883
  }
17878
17884
  compileTracks(graph, tracks) {
17879
17885
  this.sortTracks(tracks);
17880
- for (const track of tracks){
17881
- if (track instanceof ObjectBindingTrack) {
17882
- track.create();
17883
- }
17884
- this.masterTracks.push(track);
17885
- }
17886
17886
  const outputTrack = [];
17887
17887
  for (const masterTrack of tracks){
17888
17888
  outputTrack.push(masterTrack);
@@ -17919,7 +17919,6 @@ class TimelinePlayable extends Playable {
17919
17919
  constructor(...args){
17920
17920
  super(...args);
17921
17921
  this.clips = [];
17922
- this.masterTracks = [];
17923
17922
  }
17924
17923
  }
17925
17924
  class TrackSortWrapper {
@@ -17939,134 +17938,373 @@ function isAncestor(ancestorCandidate, descendantCandidate) {
17939
17938
  return false;
17940
17939
  }
17941
17940
  function compareTracks(a, b) {
17942
- if (isAncestor(a.track.binding, b.track.binding)) {
17941
+ const bindingA = a.track.binding;
17942
+ const bindingB = b.track.binding;
17943
+ if (!(bindingA instanceof VFXItem) || !(bindingB instanceof VFXItem)) {
17944
+ return a.originalIndex - b.originalIndex;
17945
+ }
17946
+ if (isAncestor(bindingA, bindingB)) {
17943
17947
  return -1;
17944
- } else if (isAncestor(b.track.binding, a.track.binding)) {
17948
+ } else if (isAncestor(bindingB, bindingA)) {
17945
17949
  return 1;
17946
17950
  } else {
17947
17951
  return a.originalIndex - b.originalIndex; // 非父子关系的元素保持原始顺序
17948
17952
  }
17949
17953
  }
17950
17954
 
17951
- class TextLayout {
17952
- getOffsetY(style) {
17953
- let offsetY = 0;
17954
- const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
17955
- switch(this.textBaseline){
17956
- case TextBaseline.top:
17957
- offsetY = offset;
17958
- break;
17959
- case TextBaseline.middle:
17960
- offsetY = (this.height + offset) / 2; // fonSize;
17961
- break;
17962
- case TextBaseline.bottom:
17963
- offsetY = this.height - offset / 2;
17964
- break;
17955
+ /**
17956
+ * @since 2.0.0
17957
+ * @internal
17958
+ */ class CompositionComponent extends ItemBehaviour {
17959
+ start() {
17960
+ const { startTime = 0 } = this.item.props;
17961
+ this.startTime = startTime;
17962
+ this.resolveBindings();
17963
+ this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
17964
+ this.timelinePlayable.play();
17965
+ // 重播不销毁元素
17966
+ if (this.item.endBehavior !== ItemEndBehavior.destroy) {
17967
+ this.setReusable(true);
17965
17968
  }
17966
- return offsetY;
17967
17969
  }
17968
- getOffsetX(style, maxWidth) {
17969
- let offsetX = 0;
17970
- switch(this.textAlign){
17971
- case TextAlignment.left:
17972
- offsetX = style.outlineWidth * style.fontScale;
17973
- break;
17974
- case TextAlignment.middle:
17975
- offsetX = (this.width * style.fontScale - maxWidth) / 2;
17976
- break;
17977
- case TextAlignment.right:
17978
- offsetX = this.width * style.fontScale - maxWidth;
17979
- break;
17970
+ setReusable(value) {
17971
+ for (const track of this.timelineAsset.tracks){
17972
+ const binding = track.binding;
17973
+ if (binding instanceof VFXItem) {
17974
+ if (track instanceof ObjectBindingTrack) {
17975
+ binding.reusable = value;
17976
+ }
17977
+ const subCompositionComponent = binding.getComponent(CompositionComponent);
17978
+ if (subCompositionComponent) {
17979
+ subCompositionComponent.setReusable(value);
17980
+ }
17981
+ }
17980
17982
  }
17981
- return offsetX;
17982
17983
  }
17983
- /**
17984
- * 设置文本框的宽度和高度
17985
- * @param width 文本框宽度
17986
- * @param height 文本框高度
17987
- */ setSize(width, height) {
17988
- this.width = width;
17989
- this.height = height;
17984
+ getReusable() {
17985
+ return this.reusable;
17990
17986
  }
17991
- constructor(options){
17992
- this.width = 0;
17993
- this.height = 0;
17994
- const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
17995
- const tempWidth = fontSize + letterSpace;
17996
- this.autoWidth = autoWidth;
17997
- this.maxTextWidth = text.length * tempWidth;
17998
- // if (autoWidth) {
17999
- // this.width = this.maxTextWidth + this.lineWidth;
18000
- // this.height = fontSize + this.lineHeight;
18001
- // } else {
18002
- // if (textWidth) {
18003
- // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18004
- // this.width = textWidth;
18005
- // } else {
18006
- // this.width = basicScale[0] * 100;
18007
- // }
18008
- // this.height = basicScale[1] * 100;
18009
- // }
18010
- this.width = textWidth;
18011
- this.height = textHeight;
18012
- this.letterSpace = letterSpace;
18013
- this.overFlow = textOverflow;
18014
- this.textBaseline = textBaseline;
18015
- this.textAlign = textAlign;
18016
- this.lineHeight = lineHeight;
17987
+ update(dt) {
17988
+ const time = this.time;
17989
+ // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
17990
+ if (this.item.isEnded(this.time) && !this.item.parent) {
17991
+ this.item.ended = true;
17992
+ }
17993
+ this.timelinePlayable.setTime(time);
17994
+ this.graph.evaluate(dt);
18017
17995
  }
18018
- }
18019
-
18020
- class TextStyle {
18021
- constructor(options){
18022
- /**
18023
- * 是否有下划线(暂时无效)
18024
- */ this.isUnderline = false // ttf
18025
- ;
18026
- /**
18027
- * 下划线高度(暂时无效)
18028
- */ this.underlineHeight = 1 // ttf
18029
- ;
18030
- /**
18031
- * 是否有外描边
18032
- */ this.isOutlined = false // both // ttf & char
18033
- ;
18034
- /**
18035
- * 外描边宽度
18036
- */ this.outlineWidth = 0 // both // ttf & char
18037
- ;
18038
- /**
18039
- * 是否有阴影
18040
- */ this.hasShadow = false // ttf
18041
- ;
18042
- this.fontDesc = '' // both
18043
- ;
18044
- /**
18045
- * 字体倍数
18046
- */ this.fontScale = 2;
18047
- this.fontOffset = 0;
18048
- const { textColor = [
18049
- 1,
18050
- 1,
18051
- 1,
18052
- 1
18053
- ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18054
- this.textColor = textColor;
18055
- //@ts-expect-error
18056
- this.textWeight = fontWeight;
18057
- //@ts-expect-error
18058
- this.fontStyle = fontStyle;
18059
- this.fontFamily = fontFamily;
18060
- this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18061
- if (outline) {
18062
- this.isOutlined = true;
18063
- var _outline_outlineColor;
18064
- this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18065
- 1,
18066
- 1,
18067
- 1,
18068
- 1
18069
- ];
17996
+ createContent() {
17997
+ const sceneBindings = [];
17998
+ for (const sceneBindingData of this.data.sceneBindings){
17999
+ sceneBindings.push({
18000
+ key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
18001
+ value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
18002
+ });
18003
+ }
18004
+ this.sceneBindings = sceneBindings;
18005
+ const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
18006
+ this.timelineAsset = timelineAsset;
18007
+ const items = this.items;
18008
+ this.items.length = 0;
18009
+ if (this.item.composition) {
18010
+ const assetLoader = this.item.engine.assetLoader;
18011
+ const itemProps = this.item.props.items ? this.item.props.items : [];
18012
+ for(let i = 0; i < itemProps.length; i++){
18013
+ let item;
18014
+ const itemData = itemProps[i];
18015
+ // 设置预合成作为元素时的时长、结束行为和渲染延时
18016
+ if (Item.isComposition(itemData)) {
18017
+ const refId = itemData.content.options.refId;
18018
+ const props = this.item.composition.refCompositionProps.get(refId);
18019
+ if (!props) {
18020
+ throw new Error(`引用的Id: ${refId} 的预合成不存在`);
18021
+ }
18022
+ // endBehaviour 类型需优化
18023
+ props.content = itemData.content;
18024
+ item = assetLoader.loadGUID(itemData.id);
18025
+ item.composition = this.item.composition;
18026
+ const compositionComponent = item.addComponent(CompositionComponent);
18027
+ compositionComponent.data = props;
18028
+ compositionComponent.refId = refId;
18029
+ item.transform.parentTransform = this.transform;
18030
+ this.item.composition.refContent.push(item);
18031
+ if (item.endBehavior === ItemEndBehavior.loop) {
18032
+ this.item.composition.autoRefTex = false;
18033
+ }
18034
+ compositionComponent.createContent();
18035
+ for (const vfxItem of compositionComponent.items){
18036
+ vfxItem.setInstanceId(generateGUID());
18037
+ for (const component of vfxItem.components){
18038
+ component.setInstanceId(generateGUID());
18039
+ }
18040
+ }
18041
+ } else {
18042
+ item = assetLoader.loadGUID(itemData.id);
18043
+ item.composition = this.item.composition;
18044
+ }
18045
+ item.parent = this.item;
18046
+ // 相机不跟随合成移动
18047
+ item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
18048
+ if (VFXItem.isExtraCamera(item)) {
18049
+ this.item.composition.extraCamera = item;
18050
+ }
18051
+ items.push(item);
18052
+ }
18053
+ }
18054
+ }
18055
+ onDestroy() {
18056
+ if (this.item.composition) {
18057
+ if (this.items) {
18058
+ this.items.forEach((item)=>item.dispose());
18059
+ this.items.length = 0;
18060
+ }
18061
+ }
18062
+ }
18063
+ hitTest(ray, x, y, regions, force, options) {
18064
+ const hitPositions = [];
18065
+ const stop = (options == null ? void 0 : options.stop) || noop;
18066
+ const skip = (options == null ? void 0 : options.skip) || noop;
18067
+ const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
18068
+ for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
18069
+ const item = this.items[i];
18070
+ if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
18071
+ const hitParams = item.getHitTestParams(force);
18072
+ if (hitParams) {
18073
+ let success = false;
18074
+ const intersectPoint = new Vector3();
18075
+ if (hitParams.type === HitTestType.triangle) {
18076
+ const { triangles, backfaceCulling } = hitParams;
18077
+ for(let j = 0; j < triangles.length; j++){
18078
+ const triangle = triangles[j];
18079
+ if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
18080
+ success = true;
18081
+ hitPositions.push(intersectPoint);
18082
+ break;
18083
+ }
18084
+ }
18085
+ } else if (hitParams.type === HitTestType.box) {
18086
+ const { center, size } = hitParams;
18087
+ const boxMin = center.clone().addScaledVector(size, 0.5);
18088
+ const boxMax = center.clone().addScaledVector(size, -0.5);
18089
+ if (ray.intersectBox({
18090
+ min: boxMin,
18091
+ max: boxMax
18092
+ }, intersectPoint)) {
18093
+ success = true;
18094
+ hitPositions.push(intersectPoint);
18095
+ }
18096
+ } else if (hitParams.type === HitTestType.sphere) {
18097
+ const { center, radius } = hitParams;
18098
+ if (ray.intersectSphere({
18099
+ center,
18100
+ radius
18101
+ }, intersectPoint)) {
18102
+ success = true;
18103
+ hitPositions.push(intersectPoint);
18104
+ }
18105
+ } else if (hitParams.type === HitTestType.custom) {
18106
+ const tempPosition = hitParams.collect(ray, new Vector2(x, y));
18107
+ if (tempPosition && tempPosition.length > 0) {
18108
+ tempPosition.forEach((pos)=>{
18109
+ hitPositions.push(pos);
18110
+ });
18111
+ success = true;
18112
+ }
18113
+ }
18114
+ if (success) {
18115
+ const region = {
18116
+ compContent: this.item,
18117
+ id: item.id,
18118
+ name: item.name,
18119
+ position: hitPositions[hitPositions.length - 1],
18120
+ parentId: item.parentId,
18121
+ hitPositions,
18122
+ behavior: hitParams.behavior
18123
+ };
18124
+ regions.push(region);
18125
+ if (stop(region)) {
18126
+ return regions;
18127
+ }
18128
+ }
18129
+ }
18130
+ }
18131
+ }
18132
+ return regions;
18133
+ }
18134
+ fromData(data) {}
18135
+ resolveBindings() {
18136
+ for (const sceneBinding of this.sceneBindings){
18137
+ sceneBinding.key.binding = sceneBinding.value;
18138
+ }
18139
+ for (const masterTrack of this.timelineAsset.tracks){
18140
+ this.resolveTrackBindingsWithRoot(masterTrack);
18141
+ }
18142
+ }
18143
+ resolveTrackBindingsWithRoot(track) {
18144
+ for (const subTrack of track.getChildTracks()){
18145
+ subTrack.binding = subTrack.resolveBinding(track.binding);
18146
+ this.resolveTrackBindingsWithRoot(subTrack);
18147
+ }
18148
+ }
18149
+ constructor(...args){
18150
+ super(...args);
18151
+ this.time = 0;
18152
+ this.startTime = 0;
18153
+ this.items = [] // 场景的所有元素
18154
+ ;
18155
+ this.reusable = false;
18156
+ this.sceneBindings = [];
18157
+ this.graph = new PlayableGraph();
18158
+ }
18159
+ }
18160
+
18161
+ class SubCompositionTrack extends TrackAsset {
18162
+ resolveBinding(parentBinding) {
18163
+ if (!(parentBinding instanceof VFXItem)) {
18164
+ throw new Error('SubCompositionTrack needs to be set under the VFXItem track');
18165
+ }
18166
+ return parentBinding.getComponent(CompositionComponent);
18167
+ }
18168
+ }
18169
+ SubCompositionTrack = __decorate([
18170
+ effectsClass('SubCompositionTrack')
18171
+ ], SubCompositionTrack);
18172
+
18173
+ class SubCompositionClipPlayable extends Playable {
18174
+ processFrame(context) {
18175
+ const boundObject = context.output.getUserData();
18176
+ boundObject.time = this.getTime();
18177
+ }
18178
+ }
18179
+
18180
+ class SubCompositionPlayableAsset extends PlayableAsset {
18181
+ createPlayable(graph) {
18182
+ return new SubCompositionClipPlayable(graph);
18183
+ }
18184
+ }
18185
+ SubCompositionPlayableAsset = __decorate([
18186
+ effectsClass('SubCompositionPlayableAsset')
18187
+ ], SubCompositionPlayableAsset);
18188
+
18189
+ class TextLayout {
18190
+ getOffsetY(style) {
18191
+ let offsetY = 0;
18192
+ const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
18193
+ switch(this.textBaseline){
18194
+ case TextBaseline.top:
18195
+ offsetY = offset;
18196
+ break;
18197
+ case TextBaseline.middle:
18198
+ offsetY = (this.height + offset) / 2; // fonSize;
18199
+ break;
18200
+ case TextBaseline.bottom:
18201
+ offsetY = this.height - offset / 2;
18202
+ break;
18203
+ }
18204
+ return offsetY;
18205
+ }
18206
+ getOffsetX(style, maxWidth) {
18207
+ let offsetX = 0;
18208
+ switch(this.textAlign){
18209
+ case TextAlignment.left:
18210
+ offsetX = style.outlineWidth * style.fontScale;
18211
+ break;
18212
+ case TextAlignment.middle:
18213
+ offsetX = (this.width * style.fontScale - maxWidth) / 2;
18214
+ break;
18215
+ case TextAlignment.right:
18216
+ offsetX = this.width * style.fontScale - maxWidth;
18217
+ break;
18218
+ }
18219
+ return offsetX;
18220
+ }
18221
+ /**
18222
+ * 设置文本框的宽度和高度
18223
+ * @param width 文本框宽度
18224
+ * @param height 文本框高度
18225
+ */ setSize(width, height) {
18226
+ this.width = width;
18227
+ this.height = height;
18228
+ }
18229
+ constructor(options){
18230
+ this.width = 0;
18231
+ this.height = 0;
18232
+ const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
18233
+ const tempWidth = fontSize + letterSpace;
18234
+ this.autoWidth = autoWidth;
18235
+ this.maxTextWidth = text.length * tempWidth;
18236
+ // if (autoWidth) {
18237
+ // this.width = this.maxTextWidth + this.lineWidth;
18238
+ // this.height = fontSize + this.lineHeight;
18239
+ // } else {
18240
+ // if (textWidth) {
18241
+ // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18242
+ // this.width = textWidth;
18243
+ // } else {
18244
+ // this.width = basicScale[0] * 100;
18245
+ // }
18246
+ // this.height = basicScale[1] * 100;
18247
+ // }
18248
+ this.width = textWidth;
18249
+ this.height = textHeight;
18250
+ this.letterSpace = letterSpace;
18251
+ this.overFlow = textOverflow;
18252
+ this.textBaseline = textBaseline;
18253
+ this.textAlign = textAlign;
18254
+ this.lineHeight = lineHeight;
18255
+ }
18256
+ }
18257
+
18258
+ class TextStyle {
18259
+ constructor(options){
18260
+ /**
18261
+ * 是否有下划线(暂时无效)
18262
+ */ this.isUnderline = false // ttf
18263
+ ;
18264
+ /**
18265
+ * 下划线高度(暂时无效)
18266
+ */ this.underlineHeight = 1 // ttf
18267
+ ;
18268
+ /**
18269
+ * 是否有外描边
18270
+ */ this.isOutlined = false // both // ttf & char
18271
+ ;
18272
+ /**
18273
+ * 外描边宽度
18274
+ */ this.outlineWidth = 0 // both // ttf & char
18275
+ ;
18276
+ /**
18277
+ * 是否有阴影
18278
+ */ this.hasShadow = false // ttf
18279
+ ;
18280
+ this.fontDesc = '' // both
18281
+ ;
18282
+ /**
18283
+ * 字体倍数
18284
+ */ this.fontScale = 2;
18285
+ this.fontOffset = 0;
18286
+ const { textColor = [
18287
+ 1,
18288
+ 1,
18289
+ 1,
18290
+ 1
18291
+ ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18292
+ this.textColor = textColor;
18293
+ //@ts-expect-error
18294
+ this.textWeight = fontWeight;
18295
+ //@ts-expect-error
18296
+ this.fontStyle = fontStyle;
18297
+ this.fontFamily = fontFamily;
18298
+ this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18299
+ if (outline) {
18300
+ this.isOutlined = true;
18301
+ var _outline_outlineColor;
18302
+ this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18303
+ 1,
18304
+ 1,
18305
+ 1,
18306
+ 1
18307
+ ];
18070
18308
  var _outline_outlineWidth;
18071
18309
  this.outlineWidth = (_outline_outlineWidth = outline.outlineWidth) != null ? _outline_outlineWidth : 1;
18072
18310
  this.fontOffset += this.outlineWidth;
@@ -19384,6 +19622,9 @@ class SerializationHelper {
19384
19622
  static checkGLTFNode(value) {
19385
19623
  return value instanceof Object && value.nodeIndex !== undefined && value.isJoint !== undefined;
19386
19624
  }
19625
+ static checkImageSource(value) {
19626
+ return isCanvas(value) || value instanceof HTMLImageElement;
19627
+ }
19387
19628
  static deserializeProperty(property, engine, level, type) {
19388
19629
  if (level > 14) {
19389
19630
  console.error('序列化数据的内嵌对象层数大于上限');
@@ -19400,7 +19641,7 @@ class SerializationHelper {
19400
19641
  // TODO json 数据避免传 typedArray
19401
19642
  } else if (SerializationHelper.checkDataPath(property)) {
19402
19643
  return engine.assetLoader.loadGUID(property.id);
19403
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19644
+ } else if (property instanceof EffectsObject || SerializationHelper.checkImageSource(property) || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19404
19645
  return property;
19405
19646
  } else if (property instanceof Object) {
19406
19647
  let res;
@@ -19435,7 +19676,7 @@ class SerializationHelper {
19435
19676
  } else if (SerializationHelper.checkDataPath(property)) {
19436
19677
  const res = yield engine.assetLoader.loadGUIDAsync(property.id);
19437
19678
  return res;
19438
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19679
+ } else if (property instanceof EffectsObject || SerializationHelper.checkImageSource(property) || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19439
19680
  return property;
19440
19681
  } else if (property instanceof Object) {
19441
19682
  let res;
@@ -19539,9 +19780,8 @@ class SerializationHelper {
19539
19780
  effectsObject = Geometry.create(this.engine);
19540
19781
  break;
19541
19782
  case DataType.Texture:
19542
- // @ts-expect-error
19543
- effectsObject = Texture.create(this.engine, effectsObjectData);
19544
- return effectsObject;
19783
+ effectsObject = Texture.create(this.engine);
19784
+ break;
19545
19785
  default:
19546
19786
  {
19547
19787
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -19589,9 +19829,8 @@ class SerializationHelper {
19589
19829
  effectsObject = Geometry.create(_this.engine);
19590
19830
  break;
19591
19831
  case DataType.Texture:
19592
- // @ts-expect-error
19593
- effectsObject = Texture.create(_this.engine, effectsObjectData);
19594
- return effectsObject;
19832
+ effectsObject = Texture.create(_this.engine);
19833
+ break;
19595
19834
  default:
19596
19835
  {
19597
19836
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -20446,6 +20685,7 @@ function getStandardCameraContent(model) {
20446
20685
  _result;
20447
20686
  const result = _extends({}, json, {
20448
20687
  items: [],
20688
+ compositions: [],
20449
20689
  components: [],
20450
20690
  materials: [],
20451
20691
  shaders: [],
@@ -20536,8 +20776,15 @@ function getStandardCameraContent(model) {
20536
20776
  id: item.id
20537
20777
  };
20538
20778
  });
20779
+ const compositionData = _extends({}, composition, {
20780
+ timelineAsset: {
20781
+ id: ''
20782
+ },
20783
+ sceneBindings: []
20784
+ });
20785
+ result.compositions.push(compositionData);
20539
20786
  // 生成时间轴数据
20540
- convertTimelineAsset(composition, guidToItemMap, result);
20787
+ convertTimelineAsset(compositionData, guidToItemMap, result);
20541
20788
  }
20542
20789
  for (const item of result.items){
20543
20790
  // 原 texture 索引转为统一 guid 索引
@@ -20651,7 +20898,7 @@ function getStandardCameraContent(model) {
20651
20898
  content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
20652
20899
  }
20653
20900
  // 修复相机K帧缺失 asMovement 参数
20654
- if (item.type === ItemType.camera) {
20901
+ if (item.type === ItemType.camera && item.content.positionOverLifetime && Object.keys(item.content.positionOverLifetime).length !== 0) {
20655
20902
  item.content.positionOverLifetime.asMovement = true;
20656
20903
  }
20657
20904
  // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
@@ -20704,10 +20951,7 @@ function getStandardCameraContent(model) {
20704
20951
  item.type = 'orientation-transformer';
20705
20952
  }
20706
20953
  // item 的 content 转为 component data 加入 JSONScene.components
20707
- if (item.type === ItemType.sprite || item.type === ItemType.particle || item.type === ItemType.mesh || item.type === ItemType.skybox || item.type === ItemType.light || // @ts-expect-error
20708
- 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
20709
- item.type === 'editor-gizmo' || // @ts-expect-error
20710
- item.type === 'orientation-transformer') {
20954
+ 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') {
20711
20955
  item.components = [];
20712
20956
  result.components.push(item.content);
20713
20957
  item.content.id = generateGUID();
@@ -20739,15 +20983,12 @@ function getStandardCameraContent(model) {
20739
20983
  case ItemType.light:
20740
20984
  item.content.dataType = DataType.LightComponent;
20741
20985
  break;
20742
- // @ts-expect-error
20743
20986
  case 'camera':
20744
20987
  item.content.dataType = DataType.CameraComponent;
20745
20988
  break;
20746
- // @ts-expect-error
20747
20989
  case 'editor-gizmo':
20748
20990
  item.content.dataType = 'GizmoComponent';
20749
20991
  break;
20750
- // @ts-expect-error
20751
20992
  case 'orientation-transformer':
20752
20993
  item.content.dataType = 'OrientationComponent';
20753
20994
  break;
@@ -20813,8 +21054,32 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20813
21054
  for (const itemDataPath of composition.items){
20814
21055
  const item = guidToItemMap[itemDataPath.id];
20815
21056
  const subTrackDatas = [];
21057
+ const newActivationPlayableAsset = {
21058
+ id: generateGUID(),
21059
+ dataType: 'ActivationPlayableAsset'
21060
+ };
21061
+ playableAssetDatas.push(newActivationPlayableAsset);
21062
+ const newActivationTrackData = {
21063
+ id: generateGUID(),
21064
+ dataType: 'ActivationTrack',
21065
+ children: [],
21066
+ clips: [
21067
+ {
21068
+ start: item.delay,
21069
+ duration: item.duration,
21070
+ endBehaviour: item.endBehavior,
21071
+ asset: {
21072
+ id: newActivationPlayableAsset.id
21073
+ }
21074
+ }
21075
+ ]
21076
+ };
21077
+ subTrackDatas.push({
21078
+ id: newActivationTrackData.id
21079
+ });
21080
+ trackDatas.push(newActivationTrackData);
20816
21081
  if (item.type !== ItemType.particle) {
20817
- const newPlayableAssetData = {
21082
+ const newTransformPlayableAssetData = {
20818
21083
  id: generateGUID(),
20819
21084
  dataType: 'TransformPlayableAsset',
20820
21085
  //@ts-expect-error
@@ -20824,15 +21089,18 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20824
21089
  //@ts-expect-error
20825
21090
  positionOverLifetime: item.content.positionOverLifetime
20826
21091
  };
20827
- playableAssetDatas.push(newPlayableAssetData);
21092
+ playableAssetDatas.push(newTransformPlayableAssetData);
20828
21093
  const newTrackData = {
20829
21094
  id: generateGUID(),
20830
21095
  dataType: 'TransformTrack',
20831
21096
  children: [],
20832
21097
  clips: [
20833
21098
  {
21099
+ start: item.delay,
21100
+ duration: item.duration,
21101
+ endBehaviour: item.endBehavior,
20834
21102
  asset: {
20835
- id: newPlayableAssetData.id
21103
+ id: newTransformPlayableAssetData.id
20836
21104
  }
20837
21105
  }
20838
21106
  ]
@@ -20843,21 +21111,50 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20843
21111
  trackDatas.push(newTrackData);
20844
21112
  }
20845
21113
  if (item.type === ItemType.sprite) {
20846
- const newPlayableAssetData = {
21114
+ const newSpriteColorPlayableAssetData = {
20847
21115
  id: generateGUID(),
20848
21116
  dataType: 'SpriteColorPlayableAsset',
20849
21117
  colorOverLifetime: item.content.colorOverLifetime,
20850
21118
  startColor: item.content.options.startColor
20851
21119
  };
20852
- playableAssetDatas.push(newPlayableAssetData);
21120
+ playableAssetDatas.push(newSpriteColorPlayableAssetData);
20853
21121
  const newTrackData = {
20854
21122
  id: generateGUID(),
20855
21123
  dataType: 'SpriteColorTrack',
20856
21124
  children: [],
20857
21125
  clips: [
20858
21126
  {
21127
+ start: item.delay,
21128
+ duration: item.duration,
21129
+ endBehaviour: item.endBehavior,
21130
+ asset: {
21131
+ id: newSpriteColorPlayableAssetData.id
21132
+ }
21133
+ }
21134
+ ]
21135
+ };
21136
+ subTrackDatas.push({
21137
+ id: newTrackData.id
21138
+ });
21139
+ trackDatas.push(newTrackData);
21140
+ }
21141
+ if (item.type === ItemType.composition) {
21142
+ const newSubCompositionPlayableAssetData = {
21143
+ id: generateGUID(),
21144
+ dataType: 'SubCompositionPlayableAsset'
21145
+ };
21146
+ playableAssetDatas.push(newSubCompositionPlayableAssetData);
21147
+ const newTrackData = {
21148
+ id: generateGUID(),
21149
+ dataType: 'SubCompositionTrack',
21150
+ children: [],
21151
+ clips: [
21152
+ {
21153
+ start: item.delay,
21154
+ duration: item.duration,
21155
+ endBehaviour: item.endBehavior,
20859
21156
  asset: {
20860
- id: newPlayableAssetData.id
21157
+ id: newSubCompositionPlayableAssetData.id
20861
21158
  }
20862
21159
  }
20863
21160
  ]
@@ -20892,11 +21189,9 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20892
21189
  id: trackData.id
20893
21190
  });
20894
21191
  }
20895
- //@ts-expect-error
20896
21192
  composition.timelineAsset = {
20897
21193
  id: timelineAssetData.id
20898
21194
  };
20899
- //@ts-expect-error
20900
21195
  composition.sceneBindings = sceneBindings;
20901
21196
  if (!jsonScene.animations) {
20902
21197
  jsonScene.animations = [];
@@ -21763,40 +22058,6 @@ function createTextureOptionsBySource(image, sourceFrom) {
21763
22058
  }
21764
22059
  throw new Error('Invalid texture options');
21765
22060
  }
21766
- function base64ToFile(base64, filename = 'base64File', contentType = '') {
21767
- // 去掉 Base64 字符串的 Data URL 部分(如果存在)
21768
- const base64WithoutPrefix = base64.split(',')[1] || base64;
21769
- // 将 base64 编码的字符串转换为二进制字符串
21770
- const byteCharacters = atob(base64WithoutPrefix);
21771
- // 创建一个 8 位无符号整数值的数组,即“字节数组”
21772
- const byteArrays = [];
21773
- // 切割二进制字符串为多个片段,并将每个片段转换成一个字节数组
21774
- for(let offset = 0; offset < byteCharacters.length; offset += 512){
21775
- const slice = byteCharacters.slice(offset, offset + 512);
21776
- const byteNumbers = new Array(slice.length);
21777
- for(let i = 0; i < slice.length; i++){
21778
- byteNumbers[i] = slice.charCodeAt(i);
21779
- }
21780
- const byteArray = new Uint8Array(byteNumbers);
21781
- byteArrays.push(byteArray);
21782
- }
21783
- // 使用字节数组创建 Blob 对象
21784
- const blob = new Blob(byteArrays, {
21785
- type: contentType
21786
- });
21787
- // 创建 File 对象
21788
- const file = new File([
21789
- blob
21790
- ], filename, {
21791
- type: contentType
21792
- });
21793
- return file;
21794
- }
21795
- function isCanvas(canvas) {
21796
- var _canvas_tagName;
21797
- // 小程序 Canvas 无法使用 instanceof HTMLCanvasElement 判断
21798
- return typeof canvas === 'object' && canvas !== null && ((_canvas_tagName = canvas.tagName) == null ? void 0 : _canvas_tagName.toUpperCase()) === 'CANVAS';
21799
- }
21800
22061
 
21801
22062
  const tmpScale = new Vector3(1, 1, 1);
21802
22063
  /**
@@ -22050,214 +22311,173 @@ const tmpScale = new Vector3(1, 1, 1);
22050
22311
  this.dirty = true;
22051
22312
  this.updateMatrix();
22052
22313
  }
22053
- }
22054
-
22055
- /**
22056
- * @since 2.0.0
22057
- * @internal
22058
- */ class CompositionComponent extends ItemBehaviour {
22059
- start() {
22060
- const { startTime = 0 } = this.item.props;
22061
- this.startTime = startTime;
22062
- this.masterTracks = [];
22063
- for (const sceneBinding of this.sceneBindings){
22064
- sceneBinding.key.binding = sceneBinding.value;
22314
+ }
22315
+
22316
+ let listOrder = 0;
22317
+ /**
22318
+ * 合成资源管理
22319
+ */ class CompositionSourceManager {
22320
+ getContent(composition) {
22321
+ // TODO: specification 中补充 globalVolume 类型
22322
+ // @ts-expect-error
22323
+ const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0 } = composition;
22324
+ const items = this.assembleItems(composition);
22325
+ return _extends({}, composition, {
22326
+ id,
22327
+ duration,
22328
+ name,
22329
+ endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
22330
+ // looping,
22331
+ items,
22332
+ camera,
22333
+ startTime,
22334
+ globalVolume
22335
+ });
22336
+ }
22337
+ assembleItems(composition) {
22338
+ const items = [];
22339
+ this.mask++;
22340
+ const componentMap = {};
22341
+ //@ts-expect-error
22342
+ for (const component of this.jsonScene.components){
22343
+ componentMap[component.id] = component;
22065
22344
  }
22066
- this.initializeTrackBindings(this.timelineAsset.tracks);
22067
- this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
22068
- this.timelinePlayable.play();
22069
- for (const track of this.timelineAsset.tracks){
22070
- // 重播不销毁元素
22071
- if (this.item.endBehavior !== ItemEndBehavior.destroy || this.reusable) {
22072
- if (track instanceof ObjectBindingTrack) {
22073
- track.binding.reusable = true;
22345
+ for (const itemDataPath of composition.items){
22346
+ //@ts-expect-error
22347
+ const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
22348
+ const itemProps = sourceItemData;
22349
+ if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
22350
+ if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
22351
+ for (const componentPath of itemProps.components){
22352
+ const componentData = componentMap[componentPath.id];
22353
+ this.preProcessItemContent(componentData);
22354
+ }
22355
+ } else {
22356
+ const renderContent = itemProps.content;
22357
+ if (renderContent) {
22358
+ this.preProcessItemContent(renderContent);
22359
+ }
22074
22360
  }
22075
- const subCompositionComponent = track.binding.getComponent(CompositionComponent);
22076
- if (subCompositionComponent) {
22077
- subCompositionComponent.reusable = true;
22361
+ itemProps.listIndex = listOrder++;
22362
+ // 处理预合成的渲染顺序
22363
+ if (itemProps.type === ItemType.composition) {
22364
+ const refId = sourceItemData.content.options.refId;
22365
+ if (!this.refCompositions.get(refId)) {
22366
+ throw new Error('Invalid Ref Composition id: ' + refId);
22367
+ }
22368
+ const ref = this.getContent(this.refCompositions.get(refId));
22369
+ if (!this.refCompositionProps.has(refId)) {
22370
+ this.refCompositionProps.set(refId, ref);
22371
+ }
22372
+ ref.items.forEach((item)=>{
22373
+ this.processMask(item.content);
22374
+ });
22375
+ itemProps.items = ref.items;
22078
22376
  }
22377
+ items.push(itemProps);
22079
22378
  }
22080
- this.masterTracks.push(track);
22081
22379
  }
22380
+ return items;
22082
22381
  }
22083
- initializeTrackBindings(masterTracks) {
22084
- for (const track of masterTracks){
22085
- track.initializeBindingRecursive(track.binding);
22382
+ preProcessItemContent(renderContent) {
22383
+ if (renderContent.renderer) {
22384
+ renderContent.renderer = this.changeTex(renderContent.renderer);
22385
+ if (!renderContent.renderer.mask) {
22386
+ this.processMask(renderContent.renderer);
22387
+ }
22388
+ const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
22389
+ if (Number.isInteger(renderContent.renderer.shape)) {
22390
+ var _this_jsonScene;
22391
+ // TODO: scene.shapes 类型问题?
22392
+ renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
22393
+ } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
22394
+ renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
22395
+ }
22396
+ }
22397
+ if (renderContent.trails) {
22398
+ renderContent.trails = this.changeTex(renderContent.trails);
22086
22399
  }
22087
22400
  }
22088
- update(dt) {
22089
- const time = this.time;
22090
- // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
22091
- if (this.item.isEnded(this.time) && !this.item.parent) {
22092
- this.item.ended = true;
22401
+ changeTex(renderer) {
22402
+ if (!renderer.texture) {
22403
+ return renderer;
22093
22404
  }
22094
- this.timelinePlayable.setTime(time);
22095
- this.graph.evaluate(dt);
22096
- for(let i = 0; i < this.items.length; i++){
22097
- const item = this.items[i];
22098
- const subCompostionComponent = item.getComponent(CompositionComponent);
22099
- if (subCompostionComponent) {
22100
- const subCompositionTrack = this.masterTracks[i];
22101
- subCompostionComponent.time = subCompositionTrack.toLocalTime(time);
22102
- }
22405
+ //@ts-expect-error
22406
+ const texIdx = renderer.texture.id;
22407
+ if (texIdx !== undefined) {
22408
+ //@ts-expect-error
22409
+ this.addTextureUsage(texIdx) || texIdx;
22103
22410
  }
22411
+ return renderer;
22104
22412
  }
22105
- /**
22106
- * 重置元素状态属性
22107
- */ resetStatus() {
22108
- this.item.ended = false;
22109
- }
22110
- createContent() {
22111
- const sceneBindings = [];
22112
- for (const sceneBindingData of this.data.sceneBindings){
22113
- sceneBindings.push({
22114
- key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
22115
- value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
22116
- });
22117
- }
22118
- this.sceneBindings = sceneBindings;
22119
- const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
22120
- this.timelineAsset = timelineAsset;
22121
- const items = this.items;
22122
- this.items.length = 0;
22123
- if (this.item.composition) {
22124
- const assetLoader = this.item.engine.assetLoader;
22125
- const itemProps = this.item.props.items ? this.item.props.items : [];
22126
- for(let i = 0; i < itemProps.length; i++){
22127
- let item;
22128
- const itemData = itemProps[i];
22129
- // 设置预合成作为元素时的时长、结束行为和渲染延时
22130
- if (Item.isComposition(itemData)) {
22131
- const refId = itemData.content.options.refId;
22132
- const props = this.item.composition.refCompositionProps.get(refId);
22133
- if (!props) {
22134
- throw new Error(`引用的Id: ${refId} 的预合成不存在`);
22135
- }
22136
- // endBehaviour 类型需优化
22137
- props.content = itemData.content;
22138
- item = assetLoader.loadGUID(itemData.id);
22139
- item.composition = this.item.composition;
22140
- const compositionComponent = item.addComponent(CompositionComponent);
22141
- compositionComponent.data = props;
22142
- compositionComponent.refId = refId;
22143
- item.transform.parentTransform = this.transform;
22144
- this.item.composition.refContent.push(item);
22145
- if (item.endBehavior === ItemEndBehavior.loop) {
22146
- this.item.composition.autoRefTex = false;
22147
- }
22148
- compositionComponent.createContent();
22149
- for (const vfxItem of compositionComponent.items){
22150
- vfxItem.setInstanceId(generateGUID());
22151
- for (const component of vfxItem.components){
22152
- component.setInstanceId(generateGUID());
22153
- }
22154
- }
22155
- } else {
22156
- item = assetLoader.loadGUID(itemData.id);
22157
- item.composition = this.item.composition;
22158
- }
22159
- item.parent = this.item;
22160
- // 相机不跟随合成移动
22161
- item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
22162
- if (VFXItem.isExtraCamera(item)) {
22163
- this.item.composition.extraCamera = item;
22164
- }
22165
- items.push(item);
22413
+ addTextureUsage(texIdx) {
22414
+ const texId = texIdx;
22415
+ var _this_imgUsage;
22416
+ // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
22417
+ const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
22418
+ if (texId && imageUsage) {
22419
+ // eslint-disable-next-line no-prototype-builtins
22420
+ if (!imageUsage.hasOwnProperty(texId)) {
22421
+ imageUsage[texId] = 0;
22166
22422
  }
22423
+ imageUsage[texId]++;
22167
22424
  }
22168
22425
  }
22169
- onDestroy() {
22170
- if (this.item.composition) {
22171
- if (this.items) {
22172
- this.items.forEach((item)=>item.dispose());
22173
- this.items.length = 0;
22426
+ /**
22427
+ * 处理蒙版和遮挡关系写入 stencil 的 ref 值
22428
+ */ processMask(renderer) {
22429
+ const maskMode = renderer.maskMode;
22430
+ if (maskMode === MaskMode.NONE) {
22431
+ return;
22432
+ }
22433
+ if (!renderer.mask) {
22434
+ if (maskMode === MaskMode.MASK) {
22435
+ renderer.mask = ++this.mask;
22436
+ } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
22437
+ renderer.mask = this.mask;
22174
22438
  }
22175
22439
  }
22176
22440
  }
22177
- hitTest(ray, x, y, regions, force, options) {
22178
- const hitPositions = [];
22179
- const stop = (options == null ? void 0 : options.stop) || noop;
22180
- const skip = (options == null ? void 0 : options.skip) || noop;
22181
- const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
22182
- for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
22183
- const item = this.items[i];
22184
- if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
22185
- const hitParams = item.getHitTestParams(force);
22186
- if (hitParams) {
22187
- let success = false;
22188
- const intersectPoint = new Vector3();
22189
- if (hitParams.type === HitTestType.triangle) {
22190
- const { triangles, backfaceCulling } = hitParams;
22191
- for(let j = 0; j < triangles.length; j++){
22192
- const triangle = triangles[j];
22193
- if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
22194
- success = true;
22195
- hitPositions.push(intersectPoint);
22196
- break;
22197
- }
22198
- }
22199
- } else if (hitParams.type === HitTestType.box) {
22200
- const { center, size } = hitParams;
22201
- const boxMin = center.clone().addScaledVector(size, 0.5);
22202
- const boxMax = center.clone().addScaledVector(size, -0.5);
22203
- if (ray.intersectBox({
22204
- min: boxMin,
22205
- max: boxMax
22206
- }, intersectPoint)) {
22207
- success = true;
22208
- hitPositions.push(intersectPoint);
22209
- }
22210
- } else if (hitParams.type === HitTestType.sphere) {
22211
- const { center, radius } = hitParams;
22212
- if (ray.intersectSphere({
22213
- center,
22214
- radius
22215
- }, intersectPoint)) {
22216
- success = true;
22217
- hitPositions.push(intersectPoint);
22218
- }
22219
- } else if (hitParams.type === HitTestType.custom) {
22220
- const tempPosition = hitParams.collect(ray, new Vector2(x, y));
22221
- if (tempPosition && tempPosition.length > 0) {
22222
- tempPosition.forEach((pos)=>{
22223
- hitPositions.push(pos);
22224
- });
22225
- success = true;
22226
- }
22227
- }
22228
- if (success) {
22229
- const region = {
22230
- compContent: this.item,
22231
- id: item.id,
22232
- name: item.name,
22233
- position: hitPositions[hitPositions.length - 1],
22234
- parentId: item.parentId,
22235
- hitPositions,
22236
- behavior: hitParams.behavior
22237
- };
22238
- regions.push(region);
22239
- if (stop(region)) {
22240
- return regions;
22241
- }
22242
- }
22243
- }
22441
+ dispose() {
22442
+ this.textures = [];
22443
+ this.composition = undefined;
22444
+ this.jsonScene = undefined;
22445
+ this.totalTime = 0;
22446
+ this.pluginSystem = undefined;
22447
+ this.sourceContent = undefined;
22448
+ this.refCompositions.clear();
22449
+ this.refCompositionProps.clear();
22450
+ }
22451
+ constructor(scene, engine){
22452
+ this.refCompositions = new Map();
22453
+ this.refCompositionProps = new Map();
22454
+ this.mask = 0;
22455
+ this.engine = engine;
22456
+ // 资源
22457
+ const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
22458
+ const { compositions, imgUsage, compositionId } = jsonScene;
22459
+ if (!textureOptions) {
22460
+ throw new Error('scene.textures expected');
22461
+ }
22462
+ const cachedTextures = textureOptions;
22463
+ for (const comp of compositions){
22464
+ if (comp.id === compositionId) {
22465
+ this.composition = comp;
22466
+ } else {
22467
+ this.refCompositions.set(comp.id, comp);
22244
22468
  }
22245
22469
  }
22246
- return regions;
22247
- }
22248
- fromData(data) {
22249
- // this.timelineAsset = data.timelineAsset;
22250
- }
22251
- constructor(...args){
22252
- super(...args);
22253
- this.time = 0;
22254
- this.startTime = 0;
22255
- this.items = [] // 场景的所有元素
22256
- ;
22257
- this.reusable = false;
22258
- this.sceneBindings = [];
22259
- this.masterTracks = [];
22260
- this.graph = new PlayableGraph();
22470
+ if (!this.composition) {
22471
+ throw new Error('Invalid composition id: ' + compositionId);
22472
+ }
22473
+ this.jsonScene = jsonScene;
22474
+ this.renderLevel = renderLevel;
22475
+ this.pluginSystem = pluginSystem;
22476
+ this.totalTime = totalTime != null ? totalTime : 0;
22477
+ this.imgUsage = imgUsage != null ? imgUsage : {};
22478
+ this.textures = cachedTextures;
22479
+ listOrder = 0;
22480
+ this.sourceContent = this.getContent(this.composition);
22261
22481
  }
22262
22482
  }
22263
22483
 
@@ -22267,6 +22487,11 @@ const tmpScale = new Vector3(1, 1, 1);
22267
22487
  * 也负责 Item 相关的动画播放控制,和持有渲染帧数据。
22268
22488
  */ class Composition {
22269
22489
  /**
22490
+ * 所有合成 Item 的根变换
22491
+ */ get transform() {
22492
+ return this.rootItem.transform;
22493
+ }
22494
+ /**
22270
22495
  * 获取场景中的纹理数组
22271
22496
  */ get textures() {
22272
22497
  return this.compositionSourceManager.textures;
@@ -22300,16 +22525,8 @@ const tmpScale = new Vector3(1, 1, 1);
22300
22525
  /**
22301
22526
  * 重新开始合成
22302
22527
  */ restart() {
22303
- // const contentItems = this.rootComposition.items;
22304
- // contentItems.forEach(item => item.dispose());
22305
- // contentItems.length = 0;
22306
- this.prepareRender();
22307
22528
  this.reset();
22308
- this.transform.setValid(true);
22309
- this.rootComposition.resetStatus();
22310
22529
  this.forwardTime(this.startTime);
22311
- // this.content.onUpdate(0);
22312
- // this.loaderData.spriteGroup.onUpdate(0);
22313
22530
  }
22314
22531
  /**
22315
22532
  * 设置当前合成的渲染顺序
@@ -22436,27 +22653,9 @@ const tmpScale = new Vector3(1, 1, 1);
22436
22653
  /**
22437
22654
  * 重置状态函数
22438
22655
  */ reset() {
22439
- const vfxItem = new VFXItem(this.getEngine(), this.compositionSourceManager.sourceContent);
22440
- // TODO 编辑器数据传入 composition type 后移除
22441
- vfxItem.type = ItemType.composition;
22442
- vfxItem.composition = this;
22443
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
22444
- this.rootComposition.data = this.compositionSourceManager.sourceContent;
22445
- this.transform = new Transform({
22446
- name: this.name
22447
- });
22448
- this.transform.engine = this.getEngine();
22449
- vfxItem.transform = this.transform;
22450
- this.rootItem = vfxItem;
22451
22656
  this.rendererOptions = null;
22452
22657
  this.globalTime = 0;
22453
- this.rootComposition.createContent();
22454
- this.buildItemTree(this.rootItem);
22455
- this.rootItem.onEnd = ()=>{
22456
- window.setTimeout(()=>{
22457
- this.onEnd == null ? void 0 : this.onEnd.call(this, this);
22458
- }, 0);
22459
- };
22658
+ this.rootItem.ended = false;
22460
22659
  this.pluginSystem.resetComposition(this, this.renderFrame);
22461
22660
  }
22462
22661
  prepareRender() {
@@ -22497,7 +22696,6 @@ const tmpScale = new Vector3(1, 1, 1);
22497
22696
  }
22498
22697
  const { ended, endBehavior } = this.rootItem;
22499
22698
  // TODO: 合成结束行为
22500
- // @ts-expect-error
22501
22699
  return ended && (!endBehavior || endBehavior === END_BEHAVIOR_PAUSE_AND_DESTROY);
22502
22700
  }
22503
22701
  /**
@@ -22586,7 +22784,7 @@ const tmpScale = new Vector3(1, 1, 1);
22586
22784
  for (const child of item.children){
22587
22785
  if (VFXItem.isComposition(child)) {
22588
22786
  if (child.ended && child.endBehavior === ItemEndBehavior.loop) {
22589
- child.getComponent(CompositionComponent).resetStatus();
22787
+ child.ended = false;
22590
22788
  // TODO K帧动画在元素重建后需要 tick ,否则会导致元素位置和 k 帧第一帧位置不一致
22591
22789
  this.callUpdate(child, 0);
22592
22790
  } else {
@@ -22953,23 +23151,32 @@ const tmpScale = new Vector3(1, 1, 1);
22953
23151
  * @param props - composition 的创建参数
22954
23152
  * @param scene
22955
23153
  * @param compositionSourceManager
22956
- */ constructor(props, scene, compositionSourceManager){
22957
- this.compositionSourceManager = compositionSourceManager;
22958
- this./**
23154
+ */ constructor(props, scene){
23155
+ /**
22959
23156
  * 动画播放速度
22960
- */ speed = 1;
22961
- this.loaderData = {};
22962
- this.refContent = [];
22963
- this./**
23157
+ */ this.speed = 1;
23158
+ /**
23159
+ * 用于保存与当前合成相关的插件数据
23160
+ */ this.loaderData = {};
23161
+ /**
23162
+ * 预合成数组
23163
+ */ this.refContent = [];
23164
+ /**
22964
23165
  * 预合成的合成属性,在 content 中会被其元素属性覆盖
22965
- */ refCompositionProps = new Map();
23166
+ */ this.refCompositionProps = new Map();
22966
23167
  this.editorScaleRatio = 1.0;
23168
+ // TODO: 待优化
22967
23169
  this.assigned = false;
22968
- this.destroyed = false;
22969
- this.paused = false;
23170
+ /**
23171
+ * 销毁状态位
23172
+ */ this.destroyed = false;
23173
+ /**
23174
+ * 合成暂停/播放 标识
23175
+ */ this.paused = false;
22970
23176
  this.lastVideoUpdateTime = 0;
22971
23177
  this.postLoaders = [];
22972
23178
  const { reusable = false, speed = 1, baseRenderOrder = 0, renderer, onPlayerPause, onMessageItem, onEnd, event, width, height } = props;
23179
+ this.compositionSourceManager = new CompositionSourceManager(scene, renderer.engine);
22973
23180
  scene.jsonScene.imgUsage = undefined;
22974
23181
  if (reusable) {
22975
23182
  this.keepResource = true;
@@ -22980,19 +23187,12 @@ const tmpScale = new Vector3(1, 1, 1);
22980
23187
  assertExist(sourceContent);
22981
23188
  this.renderer = renderer;
22982
23189
  this.refCompositionProps = refCompositionProps;
22983
- const vfxItem = new VFXItem(this.getEngine(), sourceContent);
22984
- vfxItem.name = 'rootItem';
22985
- // TODO 编辑器数据传入 composition type 后移除
22986
- vfxItem.type = ItemType.composition;
22987
- vfxItem.composition = this;
22988
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
23190
+ this.rootItem = new VFXItem(this.getEngine(), sourceContent);
23191
+ this.rootItem.name = 'rootItem';
23192
+ this.rootItem.composition = this;
23193
+ this.rootComposition = this.rootItem.addComponent(CompositionComponent);
22989
23194
  this.rootComposition.data = sourceContent;
22990
23195
  const imageUsage = !reusable && imgUsage;
22991
- this.transform = new Transform({
22992
- name: this.name
22993
- });
22994
- this.transform.engine = this.getEngine();
22995
- vfxItem.transform = this.transform;
22996
23196
  this.globalVolume = sourceContent.globalVolume;
22997
23197
  this.width = width;
22998
23198
  this.height = height;
@@ -23010,8 +23210,7 @@ const tmpScale = new Vector3(1, 1, 1);
23010
23210
  this.reusable = reusable;
23011
23211
  this.speed = speed;
23012
23212
  this.renderLevel = renderLevel;
23013
- this.autoRefTex = !this.keepResource && imageUsage && vfxItem.endBehavior !== ItemEndBehavior.loop;
23014
- this.rootItem = vfxItem;
23213
+ this.autoRefTex = !this.keepResource && imageUsage && this.rootItem.endBehavior !== ItemEndBehavior.loop;
23015
23214
  this.name = sourceContent.name;
23016
23215
  this.pluginSystem = pluginSystem;
23017
23216
  this.pluginSystem.initializeComposition(this, scene);
@@ -23037,182 +23236,6 @@ const tmpScale = new Vector3(1, 1, 1);
23037
23236
  }
23038
23237
  }
23039
23238
 
23040
- let listOrder = 0;
23041
- /**
23042
- * 合成资源管理
23043
- */ class CompositionSourceManager {
23044
- getContent(composition) {
23045
- // TODO: specification 中补充 globalVolume 类型
23046
- // @ts-expect-error
23047
- const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0, timelineAsset } = composition;
23048
- const items = this.assembleItems(composition);
23049
- //@ts-expect-error
23050
- if (!composition.sceneBindings) {
23051
- //@ts-expect-error
23052
- composition.sceneBindings = [];
23053
- }
23054
- return {
23055
- id,
23056
- duration,
23057
- name,
23058
- endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
23059
- // looping,
23060
- items,
23061
- camera,
23062
- startTime,
23063
- globalVolume,
23064
- timelineAsset: timelineAsset,
23065
- //@ts-expect-error
23066
- sceneBindings: composition.sceneBindings
23067
- };
23068
- }
23069
- assembleItems(composition) {
23070
- const items = [];
23071
- this.mask++;
23072
- const componentMap = {};
23073
- //@ts-expect-error
23074
- for (const component of this.jsonScene.components){
23075
- componentMap[component.id] = component;
23076
- }
23077
- for (const itemDataPath of composition.items){
23078
- //@ts-expect-error
23079
- const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
23080
- const itemProps = sourceItemData;
23081
- if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
23082
- if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
23083
- for (const componentPath of itemProps.components){
23084
- const componentData = componentMap[componentPath.id];
23085
- this.preProcessItemContent(componentData);
23086
- }
23087
- } else {
23088
- const renderContent = itemProps.content;
23089
- if (renderContent) {
23090
- this.preProcessItemContent(renderContent);
23091
- }
23092
- }
23093
- itemProps.listIndex = listOrder++;
23094
- // 处理预合成的渲染顺序
23095
- if (itemProps.type === ItemType.composition) {
23096
- const refId = sourceItemData.content.options.refId;
23097
- if (!this.refCompositions.get(refId)) {
23098
- throw new Error('Invalid Ref Composition id: ' + refId);
23099
- }
23100
- const ref = this.getContent(this.refCompositions.get(refId));
23101
- if (!this.refCompositionProps.has(refId)) {
23102
- this.refCompositionProps.set(refId, ref);
23103
- }
23104
- ref.items.forEach((item)=>{
23105
- this.processMask(item.content);
23106
- });
23107
- itemProps.items = ref.items;
23108
- }
23109
- items.push(itemProps);
23110
- }
23111
- }
23112
- return items;
23113
- }
23114
- preProcessItemContent(renderContent) {
23115
- if (renderContent.renderer) {
23116
- renderContent.renderer = this.changeTex(renderContent.renderer);
23117
- if (!renderContent.renderer.mask) {
23118
- this.processMask(renderContent.renderer);
23119
- }
23120
- const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
23121
- if (Number.isInteger(renderContent.renderer.shape)) {
23122
- var _this_jsonScene;
23123
- // TODO: scene.shapes 类型问题?
23124
- renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
23125
- } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
23126
- renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
23127
- }
23128
- }
23129
- if (renderContent.trails) {
23130
- renderContent.trails = this.changeTex(renderContent.trails);
23131
- }
23132
- }
23133
- changeTex(renderer) {
23134
- if (!renderer.texture) {
23135
- return renderer;
23136
- }
23137
- //@ts-expect-error
23138
- const texIdx = renderer.texture.id;
23139
- if (texIdx !== undefined) {
23140
- //@ts-expect-error
23141
- this.addTextureUsage(texIdx) || texIdx;
23142
- }
23143
- return renderer;
23144
- }
23145
- addTextureUsage(texIdx) {
23146
- const texId = texIdx;
23147
- var _this_imgUsage;
23148
- // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
23149
- const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
23150
- if (texId && imageUsage) {
23151
- // eslint-disable-next-line no-prototype-builtins
23152
- if (!imageUsage.hasOwnProperty(texId)) {
23153
- imageUsage[texId] = 0;
23154
- }
23155
- imageUsage[texId]++;
23156
- }
23157
- }
23158
- /**
23159
- * 处理蒙版和遮挡关系写入 stencil 的 ref 值
23160
- */ processMask(renderer) {
23161
- const maskMode = renderer.maskMode;
23162
- if (maskMode === MaskMode.NONE) {
23163
- return;
23164
- }
23165
- if (!renderer.mask) {
23166
- if (maskMode === MaskMode.MASK) {
23167
- renderer.mask = ++this.mask;
23168
- } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
23169
- renderer.mask = this.mask;
23170
- }
23171
- }
23172
- }
23173
- dispose() {
23174
- this.textures = [];
23175
- this.composition = undefined;
23176
- this.jsonScene = undefined;
23177
- this.totalTime = 0;
23178
- this.pluginSystem = undefined;
23179
- this.sourceContent = undefined;
23180
- this.refCompositions.clear();
23181
- this.refCompositionProps.clear();
23182
- }
23183
- constructor(scene, engine){
23184
- this.refCompositions = new Map();
23185
- this.refCompositionProps = new Map();
23186
- this.mask = 0;
23187
- this.engine = engine;
23188
- // 资源
23189
- const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
23190
- const { compositions, imgUsage, compositionId } = jsonScene;
23191
- if (!textureOptions) {
23192
- throw new Error('scene.textures expected');
23193
- }
23194
- const cachedTextures = textureOptions;
23195
- for (const comp of compositions){
23196
- if (comp.id === compositionId) {
23197
- this.composition = comp;
23198
- } else {
23199
- this.refCompositions.set(comp.id, comp);
23200
- }
23201
- }
23202
- if (!this.composition) {
23203
- throw new Error('Invalid composition id: ' + compositionId);
23204
- }
23205
- this.jsonScene = jsonScene;
23206
- this.renderLevel = renderLevel;
23207
- this.pluginSystem = pluginSystem;
23208
- this.totalTime = totalTime != null ? totalTime : 0;
23209
- this.imgUsage = imgUsage != null ? imgUsage : {};
23210
- this.textures = cachedTextures;
23211
- listOrder = 0;
23212
- this.sourceContent = this.getContent(this.composition);
23213
- }
23214
- }
23215
-
23216
23239
  /**
23217
23240
  * Engine 基类,负责维护所有 GPU 资源的管理及销毁
23218
23241
  */ class Engine {
@@ -23236,65 +23259,48 @@ let listOrder = 0;
23236
23259
  delete this.objectInstance[id];
23237
23260
  }
23238
23261
  addPackageDatas(scene) {
23239
- const jsonScene = scene.jsonScene;
23240
- if (jsonScene.items) {
23241
- for (const vfxItemData of jsonScene.items){
23242
- this.addEffectsObjectData(vfxItemData);
23243
- }
23262
+ const { jsonScene, textureOptions = [] } = scene;
23263
+ const { items = [], materials = [], shaders = [], geometries = [], components = [], animations = [], bins = [] } = jsonScene;
23264
+ for (const vfxItemData of items){
23265
+ this.addEffectsObjectData(vfxItemData);
23244
23266
  }
23245
- if (jsonScene.materials) {
23246
- for (const materialData of jsonScene.materials){
23247
- this.addEffectsObjectData(materialData);
23248
- }
23267
+ for (const materialData of materials){
23268
+ this.addEffectsObjectData(materialData);
23249
23269
  }
23250
- if (jsonScene.shaders) {
23251
- for (const shaderData of jsonScene.shaders){
23252
- this.addEffectsObjectData(shaderData);
23253
- }
23270
+ for (const shaderData of shaders){
23271
+ this.addEffectsObjectData(shaderData);
23254
23272
  }
23255
- if (jsonScene.geometries) {
23256
- for (const geometryData of jsonScene.geometries){
23257
- this.addEffectsObjectData(geometryData);
23258
- }
23273
+ for (const geometryData of geometries){
23274
+ this.addEffectsObjectData(geometryData);
23259
23275
  }
23260
- if (jsonScene.components) {
23261
- for (const componentData of jsonScene.components){
23262
- this.addEffectsObjectData(componentData);
23263
- }
23276
+ for (const componentData of components){
23277
+ this.addEffectsObjectData(componentData);
23264
23278
  }
23265
- if (jsonScene.animations) {
23266
- for (const animationData of jsonScene.animations){
23267
- this.addEffectsObjectData(animationData);
23268
- }
23279
+ for (const animationData of animations){
23280
+ this.addEffectsObjectData(animationData);
23269
23281
  }
23270
- if (jsonScene.bins) {
23271
- for(let i = 0; i < jsonScene.bins.length; i++){
23272
- const binaryData = jsonScene.bins[i];
23273
- const binaryBuffer = scene.bins[i];
23274
- //@ts-expect-error
23275
- binaryData.buffer = binaryBuffer;
23282
+ for(let i = 0; i < bins.length; i++){
23283
+ const binaryData = bins[i];
23284
+ const binaryBuffer = scene.bins[i];
23285
+ //@ts-expect-error
23286
+ binaryData.buffer = binaryBuffer;
23287
+ //@ts-expect-error
23288
+ if (binaryData.id) {
23276
23289
  //@ts-expect-error
23277
- if (binaryData.id) {
23278
- //@ts-expect-error
23279
- this.addEffectsObjectData(binaryData);
23280
- }
23290
+ this.addEffectsObjectData(binaryData);
23281
23291
  }
23282
23292
  }
23283
- if (scene.textureOptions) {
23284
- for (const textureData of scene.textureOptions){
23285
- this.addEffectsObjectData(textureData);
23286
- }
23293
+ for (const textureData of textureOptions){
23294
+ this.addEffectsObjectData(textureData);
23287
23295
  }
23288
23296
  }
23289
23297
  createVFXItems(scene) {
23290
23298
  var _this = this;
23291
23299
  return _async_to_generator(function*() {
23292
- const jsonScene = scene.jsonScene;
23300
+ const { jsonScene } = scene;
23293
23301
  for (const itemData of jsonScene.items){
23294
23302
  const itemType = itemData.type;
23295
- if (!// @ts-expect-error
23296
- (itemType === 'ECS' || // @ts-expect-error
23297
- 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)) {
23303
+ 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)) {
23298
23304
  continue;
23299
23305
  }
23300
23306
  if (_this.database) {
@@ -23392,21 +23398,11 @@ let listOrder = 0;
23392
23398
  if (info.length > 0) {
23393
23399
  logger.warn(`Release GPU memory: ${info.join(', ')}`);
23394
23400
  }
23395
- this.renderPasses.forEach((pass)=>{
23396
- pass.dispose();
23397
- });
23398
- this.meshes.forEach((mesh)=>{
23399
- mesh.dispose();
23400
- });
23401
- this.geometries.forEach((geo)=>{
23402
- geo.dispose();
23403
- });
23404
- this.materials.forEach((mat)=>{
23405
- mat.dispose();
23406
- });
23407
- this.textures.forEach((tex)=>{
23408
- tex.dispose();
23409
- });
23401
+ this.renderPasses.forEach((pass)=>pass.dispose());
23402
+ this.meshes.forEach((mesh)=>mesh.dispose());
23403
+ this.geometries.forEach((geo)=>geo.dispose());
23404
+ this.materials.forEach((mat)=>mat.dispose());
23405
+ this.textures.forEach((tex)=>tex.dispose());
23410
23406
  this.textures = [];
23411
23407
  this.materials = [];
23412
23408
  this.geometries = [];
@@ -23556,5 +23552,5 @@ registerPlugin('particle', ParticleLoader, VFXItem, true);
23556
23552
  registerPlugin('cal', CalculateLoader, VFXItem, true);
23557
23553
  registerPlugin('interact', InteractLoader, VFXItem, true);
23558
23554
 
23559
- export { AbstractPlugin, ActivationPlayable, ActivationPlayableAsset, ActivationTrack, AnimationClip, AnimationClipPlayable, AssetLoader, AssetManager, BYTES_TYPE_MAP, Behaviour, BezierCurve, BezierCurvePath, BezierCurveQuat, BinaryAsset, COMPRESSED_TEXTURE, COPY_FRAGMENT_SHADER, COPY_MESH_SHADER_ID, COPY_VERTEX_SHADER, CalculateLoader, Camera, CameraController, CameraVFXItemLoader, Component, Composition, CompositionComponent, CompositionSourceManager, DEFAULT_FONTS, Database, DestroyOptions, Downloader, EFFECTS_COPY_MESH_NAME, EVENT_TYPE_CLICK, EVENT_TYPE_TOUCH_END, EVENT_TYPE_TOUCH_MOVE, EVENT_TYPE_TOUCH_START, EffectComponent, EffectsObject, Engine, EventSystem, FilterMode, Float16ArrayWrapper, Framebuffer, GLSLVersion, GPUCapability, Geometry, GlobalUniforms, GradientValue, HELP_LINK, HitTestType, InteractComponent, InteractLoader, InteractMesh, Item, ItemBehaviour, KTXTexture, LineSegments, LinearValue, Material, MaterialDataBlock, MaterialRenderType, Mesh, ObjectBindingTrack, OrderType, PLAYER_OPTIONS_ENV_EDITOR, POST_PROCESS_SETTINGS, ParticleBehaviourPlayable, ParticleBehaviourPlayableAsset, ParticleLoader, ParticleMesh, ParticleSystem, ParticleSystemRenderer, PassTextureCache, PathSegments, PluginSystem, RENDER_PASS_NAME_PREFIX, RENDER_PREFER_LOOKUP_TEXTURE, RUNTIME_ENV, RandomSetValue, RandomValue, RandomVectorValue, RenderFrame, RenderPass, RenderPassAttachmentStorageType, RenderPassDestroyAttachmentType, RenderPassPriorityNormal, RenderPassPriorityPostprocess, RenderPassPriorityPrepare, RenderTargetHandle, RenderTextureFormat, Renderbuffer, Renderer, RendererComponent, RuntimeClip, SEMANTIC_MAIN_PRE_COLOR_ATTACHMENT_0, SEMANTIC_MAIN_PRE_COLOR_ATTACHMENT_SIZE_0, SEMANTIC_PRE_COLOR_ATTACHMENT_0, SEMANTIC_PRE_COLOR_ATTACHMENT_SIZE_0, SPRITE_VERTEX_STRIDE, SemanticMap, SerializationHelper, Shader, ShaderCompileResultStatus, ShaderType, ShaderVariant, SpriteColorPlayable, SpriteColorPlayableAsset, SpriteColorTrack, SpriteComponent, SpriteLoader, StaticValue, TEMPLATE_USE_OFFSCREEN_CANVAS, TextComponent, TextLoader, Texture, TextureFactory, TextureLoadAction, TextureSourceType, TextureStoreAction, Ticker, TimelineAsset, TimelineClip, TimelinePlayable, TrackAsset, TrackSortWrapper, TrackType, Transform, TransformAnimationPlayable, TransformPlayableAsset, TransformTrack, VFXItem, ValueGetter, addByOrder, addItem, addItemWithOrder, assertExist, asserts, blend, calculateTranslation, canvasPool, colorGradingFrag, colorStopsFromGradient, colorToArr$1 as colorToArr, combineImageTemplate, compatible_frag as compatibleFrag, compatible_vert as compatibleVert, createCopyShader, createGLContext, createKeyFrameMeta, createShaderWithMarcos, createShape, createVFXItem, createValueGetter, decimalEqual, deepClone, defaultGlobalVolume, defaultPlugins, deserializeMipmapTexture, earcut, effectsClass, effectsClassStore, enlargeBuffer, ensureFixedNumber, ensureVec3, findPreviousRenderPass, gaussianDown_frag as gaussianDownFrag, gaussianDownHFrag, gaussianDownVFrag, gaussianUpFrag, generateEmptyTypedArray, generateGUID, generateHalfFloatTexture, generateTransparentTexture, generateWhiteTexture, getBackgroundImage, getColorFromGradientStops, getConfig, getDefaultTemplateCanvasPool, getDefaultTextureFactory, getGeometryByShape, getGeometryTriangles, getImageItemRenderInfo, getKTXTextureOptions, getKeyFrameMetaByRawValue, getMergedStore, getParticleMeshShader, getPixelRatio, getPreMultiAlpha, getStandardComposition, getStandardImage, getStandardItem, getStandardJSON, getTextureSize, glContext, glType2VertexFormatType, gpuTimer, imageDataFromColor, imageDataFromGradient, initErrors, initGLContext, integrate, interpolateColor, isAlipayMiniApp, isAndroid, isArray, isFunction, isIOS, isObject, isSceneJSON, isSceneURL, isSceneWithOptions, isSimulatorCellPhone, isString, isUniformStruct, isUniformStructArray, isValidFontFamily, isWebGL2, itemFrag, itemFrameFrag, itemVert, loadBinary, loadBlob, loadImage, loadMedia, loadVideo, loadWebPOptional, logger, index as math, maxSpriteMeshItemCount, maxSpriteTextureCount, modifyMaxKeyframeShader, nearestPowerOfTwo, noop, normalizeColor, numberToFix, parsePercent$1 as parsePercent, particleFrag, particleOriginTranslateMap$1 as particleOriginTranslateMap, particleUniformTypeMap, particleVert, pluginLoaderMap, pointOnLine, random, registerPlugin, removeItem, rotateVec2, screenMeshVert, serialize, setBlendMode, setConfig, setDefaultTextureFactory, setMaskMode, setMaxSpriteMeshItemCount, setRayFromCamera, setSideMode, setSpriteMeshMaxFragmentTextures, setSpriteMeshMaxItemCountByGPU, sortByOrder, index$1 as spec, spriteMeshShaderFromFilter, spriteMeshShaderFromRenderInfo, spriteMeshShaderIdFromRenderInfo, thresholdFrag, throwDestroyedError, trailVert, translatePoint, trianglesFromRect, unregisterPlugin, valIfUndefined, value, valueDefine, vecAssign, vecFill, vecMulCombine, vecNormalize, vertexFormatType2GLType };
23555
+ export { AbstractPlugin, ActivationPlayable, ActivationPlayableAsset, ActivationTrack, AnimationClip, AnimationClipPlayable, AssetLoader, AssetManager, BYTES_TYPE_MAP, Behaviour, BezierCurve, BezierCurvePath, BezierCurveQuat, BinaryAsset, COMPRESSED_TEXTURE, COPY_FRAGMENT_SHADER, COPY_MESH_SHADER_ID, COPY_VERTEX_SHADER, CalculateLoader, Camera, CameraController, CameraVFXItemLoader, Component, Composition, CompositionComponent, CompositionSourceManager, DEFAULT_FONTS, Database, DestroyOptions, Downloader, EFFECTS_COPY_MESH_NAME, EVENT_TYPE_CLICK, EVENT_TYPE_TOUCH_END, EVENT_TYPE_TOUCH_MOVE, EVENT_TYPE_TOUCH_START, EffectComponent, EffectsObject, Engine, EventSystem, FilterMode, Float16ArrayWrapper, Framebuffer, GLSLVersion, GPUCapability, Geometry, GlobalUniforms, GradientValue, HELP_LINK, HitTestType, InteractComponent, InteractLoader, InteractMesh, Item, ItemBehaviour, KTXTexture, LineSegments, LinearValue, Material, MaterialDataBlock, MaterialRenderType, Mesh, ObjectBindingTrack, OrderType, PLAYER_OPTIONS_ENV_EDITOR, POST_PROCESS_SETTINGS, ParticleBehaviourPlayable, ParticleBehaviourPlayableAsset, ParticleLoader, ParticleMesh, ParticleSystem, ParticleSystemRenderer, PassTextureCache, PathSegments, PluginSystem, RENDER_PASS_NAME_PREFIX, RENDER_PREFER_LOOKUP_TEXTURE, RUNTIME_ENV, RandomSetValue, RandomValue, RandomVectorValue, RenderFrame, RenderPass, RenderPassAttachmentStorageType, RenderPassDestroyAttachmentType, RenderPassPriorityNormal, RenderPassPriorityPostprocess, RenderPassPriorityPrepare, RenderTargetHandle, RenderTextureFormat, Renderbuffer, Renderer, RendererComponent, RuntimeClip, SEMANTIC_MAIN_PRE_COLOR_ATTACHMENT_0, SEMANTIC_MAIN_PRE_COLOR_ATTACHMENT_SIZE_0, SEMANTIC_PRE_COLOR_ATTACHMENT_0, SEMANTIC_PRE_COLOR_ATTACHMENT_SIZE_0, SPRITE_VERTEX_STRIDE, SemanticMap, SerializationHelper, Shader, ShaderCompileResultStatus, ShaderType, ShaderVariant, SpriteColorPlayable, SpriteColorPlayableAsset, SpriteColorTrack, SpriteComponent, SpriteLoader, StaticValue, SubCompositionPlayableAsset, SubCompositionTrack, TEMPLATE_USE_OFFSCREEN_CANVAS, TextComponent, TextLoader, Texture, TextureFactory, TextureLoadAction, TextureSourceType, TextureStoreAction, Ticker, TimelineAsset, TimelineClip, TimelinePlayable, TrackAsset, TrackSortWrapper, TrackType, Transform, TransformAnimationPlayable, TransformPlayableAsset, TransformTrack, VFXItem, ValueGetter, addByOrder, addItem, addItemWithOrder, assertExist, asserts, base64ToFile, blend, calculateTranslation, canvasPool, colorGradingFrag, colorStopsFromGradient, colorToArr$1 as colorToArr, combineImageTemplate, compatible_frag as compatibleFrag, compatible_vert as compatibleVert, createCopyShader, createGLContext, createKeyFrameMeta, createShaderWithMarcos, createShape, createVFXItem, createValueGetter, decimalEqual, deepClone, defaultGlobalVolume, defaultPlugins, deserializeMipmapTexture, earcut, effectsClass, effectsClassStore, enlargeBuffer, ensureFixedNumber, ensureVec3, findPreviousRenderPass, gaussianDown_frag as gaussianDownFrag, gaussianDownHFrag, gaussianDownVFrag, gaussianUpFrag, generateEmptyTypedArray, generateGUID, generateHalfFloatTexture, generateTransparentTexture, generateWhiteTexture, getBackgroundImage, getColorFromGradientStops, getConfig, getDefaultTemplateCanvasPool, getDefaultTextureFactory, getGeometryByShape, getGeometryTriangles, getImageItemRenderInfo, getKTXTextureOptions, getKeyFrameMetaByRawValue, getMergedStore, getParticleMeshShader, getPixelRatio, getPreMultiAlpha, getStandardComposition, getStandardImage, getStandardItem, getStandardJSON, getTextureSize, glContext, glType2VertexFormatType, gpuTimer, imageDataFromColor, imageDataFromGradient, initErrors, initGLContext, integrate, interpolateColor, isAlipayMiniApp, isAndroid, isArray, isCanvas, isFunction, isIOS, isObject, isSceneJSON, isSceneURL, isSceneWithOptions, isSimulatorCellPhone, isString, isUniformStruct, isUniformStructArray, isValidFontFamily, isWebGL2, itemFrag, itemFrameFrag, itemVert, loadBinary, loadBlob, loadImage, loadMedia, loadVideo, loadWebPOptional, logger, index as math, maxSpriteMeshItemCount, maxSpriteTextureCount, modifyMaxKeyframeShader, nearestPowerOfTwo, noop, normalizeColor, numberToFix, parsePercent$1 as parsePercent, particleFrag, particleOriginTranslateMap$1 as particleOriginTranslateMap, particleUniformTypeMap, particleVert, pluginLoaderMap, pointOnLine, random, registerPlugin, removeItem, rotateVec2, screenMeshVert, serialize, setBlendMode, setConfig, setDefaultTextureFactory, setMaskMode, setMaxSpriteMeshItemCount, setRayFromCamera, setSideMode, setSpriteMeshMaxFragmentTextures, setSpriteMeshMaxItemCountByGPU, sortByOrder, index$1 as spec, spriteMeshShaderFromFilter, spriteMeshShaderFromRenderInfo, spriteMeshShaderIdFromRenderInfo, thresholdFrag, throwDestroyedError, trailVert, translatePoint, trianglesFromRect, unregisterPlugin, valIfUndefined, value, valueDefine, vecAssign, vecFill, vecMulCombine, vecNormalize, vertexFormatType2GLType };
23560
23556
  //# sourceMappingURL=index.mjs.map