@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.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.13
6
+ * Version: v2.0.0-alpha.15
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;
@@ -17452,6 +17486,9 @@ class ActivationPlayableAsset extends PlayableAsset {
17452
17486
  return new ActivationPlayable(graph);
17453
17487
  }
17454
17488
  }
17489
+ ActivationPlayableAsset = __decorate([
17490
+ effectsClass('ActivationPlayableAsset')
17491
+ ], ActivationPlayableAsset);
17455
17492
  class AnimationClip extends EffectsObject {
17456
17493
  sampleAnimation(vfxItem, time) {
17457
17494
  const duration = vfxItem.duration;
@@ -17550,16 +17587,15 @@ class AnimationClipPlayable extends Playable {
17550
17587
  }
17551
17588
 
17552
17589
  class TrackAsset extends PlayableAsset {
17553
- initializeBinding(parentBinding) {
17554
- this.binding = parentBinding;
17590
+ /**
17591
+ * 重写该方法以获取自定义对象绑定
17592
+ */ resolveBinding(parentBinding) {
17593
+ return parentBinding;
17555
17594
  }
17556
17595
  /**
17557
- * @internal
17558
- */ initializeBindingRecursive(parentBinding) {
17559
- this.initializeBinding(parentBinding);
17560
- for (const subTrack of this.children){
17561
- subTrack.initializeBindingRecursive(this.binding);
17562
- }
17596
+ * 重写该方法以创建自定义混合器
17597
+ */ createTrackMixer(graph) {
17598
+ return new Playable(graph);
17563
17599
  }
17564
17600
  createOutput() {
17565
17601
  const output = new PlayableOutput();
@@ -17588,17 +17624,15 @@ class TrackAsset extends PlayableAsset {
17588
17624
  }
17589
17625
  return mixer;
17590
17626
  }
17591
- /**
17592
- * 重写该方法以创建自定义混合器
17593
- */ createTrackMixer(graph) {
17594
- return new Playable(graph);
17595
- }
17596
17627
  createPlayable(graph) {
17597
17628
  return new Playable(graph);
17598
17629
  }
17599
17630
  getChildTracks() {
17600
17631
  return this.children;
17601
17632
  }
17633
+ addChild(child) {
17634
+ this.children.push(child);
17635
+ }
17602
17636
  createClip(classConstructor, name) {
17603
17637
  const newClip = new TimelineClip();
17604
17638
  newClip.asset = new classConstructor(this.engine);
@@ -17680,9 +17714,10 @@ class RuntimeClip {
17680
17714
  let weight = 1.0;
17681
17715
  let ended = false;
17682
17716
  let started = false;
17717
+ const boundItem = this.track.binding;
17683
17718
  if (localTime > clip.start + clip.duration + 0.001 && clip.endBehaviour === ItemEndBehavior.destroy) {
17684
- var _this_track_binding_getComponent;
17685
- if (VFXItem.isParticle(this.track.binding) && !((_this_track_binding_getComponent = this.track.binding.getComponent(ParticleSystem)) == null ? void 0 : _this_track_binding_getComponent.destroyed)) {
17719
+ var _boundItem_getComponent;
17720
+ if (VFXItem.isParticle(boundItem) && !((_boundItem_getComponent = boundItem.getComponent(ParticleSystem)) == null ? void 0 : _boundItem_getComponent.destroyed)) {
17686
17721
  weight = 1.0;
17687
17722
  } else {
17688
17723
  weight = 0.0;
@@ -17698,7 +17733,6 @@ class RuntimeClip {
17698
17733
  this.playable.play();
17699
17734
  }
17700
17735
  this.parentMixer.setInputWeight(this.playable, weight);
17701
- const boundItem = this.track.binding;
17702
17736
  // 判断动画是否结束
17703
17737
  if (ended && !boundItem.ended) {
17704
17738
  boundItem.ended = true;
@@ -17727,6 +17761,34 @@ class RuntimeClip {
17727
17761
  }
17728
17762
  }
17729
17763
 
17764
+ class ObjectBindingTrack extends TrackAsset {
17765
+ create(timelineAsset) {
17766
+ const boundItem = this.binding;
17767
+ // 添加粒子动画 clip
17768
+ if (boundItem.getComponent(ParticleSystem)) {
17769
+ const particleTrack = timelineAsset.createTrack(TrackAsset, this, 'ParticleTrack');
17770
+ particleTrack.binding = this.binding;
17771
+ const particleClip = particleTrack.createClip(ParticleBehaviourPlayableAsset);
17772
+ particleClip.start = boundItem.start;
17773
+ particleClip.duration = boundItem.duration;
17774
+ particleClip.endBehaviour = boundItem.endBehavior;
17775
+ }
17776
+ }
17777
+ fromData(data) {
17778
+ super.fromData(data);
17779
+ this.data = data;
17780
+ }
17781
+ }
17782
+ ObjectBindingTrack = __decorate([
17783
+ effectsClass('ObjectBindingTrack')
17784
+ ], ObjectBindingTrack);
17785
+
17786
+ class TransformTrack extends TrackAsset {
17787
+ }
17788
+ TransformTrack = __decorate([
17789
+ effectsClass('TransformTrack')
17790
+ ], TransformTrack);
17791
+
17730
17792
  class ActivationMixerPlayable extends Playable {
17731
17793
  processFrame(context) {
17732
17794
  if (!this.bindingItem) {
@@ -17776,73 +17838,6 @@ ActivationTrack = __decorate([
17776
17838
  effectsClass('ActivationTrack')
17777
17839
  ], ActivationTrack);
17778
17840
 
17779
- class ObjectBindingTrack extends TrackAsset {
17780
- create() {
17781
- this.options = {
17782
- start: this.binding.start,
17783
- duration: this.binding.duration,
17784
- looping: this.binding.endBehavior === ItemEndBehavior.loop,
17785
- endBehavior: this.binding.endBehavior || ItemEndBehavior.destroy
17786
- };
17787
- this.id = this.binding.id;
17788
- this.name = this.binding.name;
17789
- const activationTrack = this.createTrack(ActivationTrack, 'ActivationTrack');
17790
- activationTrack.binding = this.binding;
17791
- activationTrack.createClip(ActivationPlayableAsset, 'ActivationTimelineClip');
17792
- // 添加粒子动画 clip
17793
- if (this.binding.getComponent(ParticleSystem)) {
17794
- const particleTrack = this.createTrack(TrackAsset, 'ParticleTrack');
17795
- particleTrack.binding = this.binding;
17796
- particleTrack.createClip(ParticleBehaviourPlayableAsset);
17797
- }
17798
- // TODO TimelineClip 需要传入 start 和 duration 数据
17799
- for (const track of this.children){
17800
- for (const clip of track.getClips()){
17801
- clip.start = this.binding.start;
17802
- clip.duration = this.binding.duration;
17803
- clip.endBehaviour = this.binding.endBehavior;
17804
- }
17805
- }
17806
- }
17807
- toLocalTime(time) {
17808
- let localTime = time - this.options.start;
17809
- const duration = this.options.duration;
17810
- if (localTime - duration > 0.001) {
17811
- if (this.options.endBehavior === END_BEHAVIOR_RESTART) {
17812
- localTime = localTime % duration;
17813
- } else if (this.options.endBehavior === END_BEHAVIOR_FREEZE) {
17814
- localTime = Math.min(duration, localTime);
17815
- }
17816
- }
17817
- return localTime;
17818
- }
17819
- createTrack(classConstructor, name) {
17820
- const newTrack = new classConstructor(this.engine);
17821
- newTrack.binding = this.binding;
17822
- newTrack.id = (this.trackSeed++).toString();
17823
- newTrack.name = name ? name : 'Track' + newTrack.id;
17824
- this.children.push(newTrack);
17825
- return newTrack;
17826
- }
17827
- fromData(data) {
17828
- super.fromData(data);
17829
- this.data = data;
17830
- }
17831
- constructor(...args){
17832
- super(...args);
17833
- this.trackSeed = 0;
17834
- }
17835
- }
17836
- ObjectBindingTrack = __decorate([
17837
- effectsClass('ObjectBindingTrack')
17838
- ], ObjectBindingTrack);
17839
-
17840
- class TransformTrack extends TrackAsset {
17841
- }
17842
- TransformTrack = __decorate([
17843
- effectsClass('TransformTrack')
17844
- ], TransformTrack);
17845
-
17846
17841
  class SpriteColorTrack extends TrackAsset {
17847
17842
  }
17848
17843
  SpriteColorTrack = __decorate([
@@ -17851,20 +17846,31 @@ SpriteColorTrack = __decorate([
17851
17846
 
17852
17847
  class TimelineAsset extends PlayableAsset {
17853
17848
  createPlayable(graph) {
17854
- this.graph = graph;
17855
17849
  const timelinePlayable = new TimelinePlayable(graph);
17856
17850
  timelinePlayable.setTraversalMode(PlayableTraversalMode.Passthrough);
17851
+ for (const track of this.tracks){
17852
+ if (track instanceof ObjectBindingTrack) {
17853
+ track.create(this);
17854
+ }
17855
+ }
17857
17856
  timelinePlayable.compileTracks(graph, this.tracks);
17858
17857
  return timelinePlayable;
17859
17858
  }
17860
- fromData(data) {
17861
- this.tracks = data.tracks;
17859
+ createTrack(classConstructor, parent, name) {
17860
+ const newTrack = new classConstructor(this.engine);
17861
+ newTrack.name = name ? name : classConstructor.name;
17862
+ parent.addChild(newTrack);
17863
+ return newTrack;
17862
17864
  }
17865
+ fromData(data) {}
17863
17866
  constructor(...args){
17864
17867
  super(...args);
17865
17868
  this.tracks = [];
17866
17869
  }
17867
17870
  }
17871
+ __decorate([
17872
+ serialize()
17873
+ ], TimelineAsset.prototype, "tracks", void 0);
17868
17874
  TimelineAsset = __decorate([
17869
17875
  effectsClass('TimelineAsset')
17870
17876
  ], TimelineAsset);
@@ -17881,12 +17887,6 @@ class TimelinePlayable extends Playable {
17881
17887
  }
17882
17888
  compileTracks(graph, tracks) {
17883
17889
  this.sortTracks(tracks);
17884
- for (const track of tracks){
17885
- if (track instanceof ObjectBindingTrack) {
17886
- track.create();
17887
- }
17888
- this.masterTracks.push(track);
17889
- }
17890
17890
  const outputTrack = [];
17891
17891
  for (const masterTrack of tracks){
17892
17892
  outputTrack.push(masterTrack);
@@ -17923,7 +17923,6 @@ class TimelinePlayable extends Playable {
17923
17923
  constructor(...args){
17924
17924
  super(...args);
17925
17925
  this.clips = [];
17926
- this.masterTracks = [];
17927
17926
  }
17928
17927
  }
17929
17928
  class TrackSortWrapper {
@@ -17943,134 +17942,373 @@ function isAncestor(ancestorCandidate, descendantCandidate) {
17943
17942
  return false;
17944
17943
  }
17945
17944
  function compareTracks(a, b) {
17946
- if (isAncestor(a.track.binding, b.track.binding)) {
17945
+ const bindingA = a.track.binding;
17946
+ const bindingB = b.track.binding;
17947
+ if (!(bindingA instanceof VFXItem) || !(bindingB instanceof VFXItem)) {
17948
+ return a.originalIndex - b.originalIndex;
17949
+ }
17950
+ if (isAncestor(bindingA, bindingB)) {
17947
17951
  return -1;
17948
- } else if (isAncestor(b.track.binding, a.track.binding)) {
17952
+ } else if (isAncestor(bindingB, bindingA)) {
17949
17953
  return 1;
17950
17954
  } else {
17951
17955
  return a.originalIndex - b.originalIndex; // 非父子关系的元素保持原始顺序
17952
17956
  }
17953
17957
  }
17954
17958
 
17955
- class TextLayout {
17956
- getOffsetY(style) {
17957
- let offsetY = 0;
17958
- const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
17959
- switch(this.textBaseline){
17960
- case TextBaseline.top:
17961
- offsetY = offset;
17962
- break;
17963
- case TextBaseline.middle:
17964
- offsetY = (this.height + offset) / 2; // fonSize;
17965
- break;
17966
- case TextBaseline.bottom:
17967
- offsetY = this.height - offset / 2;
17968
- break;
17959
+ /**
17960
+ * @since 2.0.0
17961
+ * @internal
17962
+ */ class CompositionComponent extends ItemBehaviour {
17963
+ start() {
17964
+ const { startTime = 0 } = this.item.props;
17965
+ this.startTime = startTime;
17966
+ this.resolveBindings();
17967
+ this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
17968
+ this.timelinePlayable.play();
17969
+ // 重播不销毁元素
17970
+ if (this.item.endBehavior !== ItemEndBehavior.destroy) {
17971
+ this.setReusable(true);
17969
17972
  }
17970
- return offsetY;
17971
17973
  }
17972
- getOffsetX(style, maxWidth) {
17973
- let offsetX = 0;
17974
- switch(this.textAlign){
17975
- case TextAlignment.left:
17976
- offsetX = style.outlineWidth * style.fontScale;
17977
- break;
17978
- case TextAlignment.middle:
17979
- offsetX = (this.width * style.fontScale - maxWidth) / 2;
17980
- break;
17981
- case TextAlignment.right:
17982
- offsetX = this.width * style.fontScale - maxWidth;
17983
- break;
17974
+ setReusable(value) {
17975
+ for (const track of this.timelineAsset.tracks){
17976
+ const binding = track.binding;
17977
+ if (binding instanceof VFXItem) {
17978
+ if (track instanceof ObjectBindingTrack) {
17979
+ binding.reusable = value;
17980
+ }
17981
+ const subCompositionComponent = binding.getComponent(CompositionComponent);
17982
+ if (subCompositionComponent) {
17983
+ subCompositionComponent.setReusable(value);
17984
+ }
17985
+ }
17984
17986
  }
17985
- return offsetX;
17986
17987
  }
17987
- /**
17988
- * 设置文本框的宽度和高度
17989
- * @param width 文本框宽度
17990
- * @param height 文本框高度
17991
- */ setSize(width, height) {
17992
- this.width = width;
17993
- this.height = height;
17988
+ getReusable() {
17989
+ return this.reusable;
17994
17990
  }
17995
- constructor(options){
17996
- this.width = 0;
17997
- this.height = 0;
17998
- const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
17999
- const tempWidth = fontSize + letterSpace;
18000
- this.autoWidth = autoWidth;
18001
- this.maxTextWidth = text.length * tempWidth;
18002
- // if (autoWidth) {
18003
- // this.width = this.maxTextWidth + this.lineWidth;
18004
- // this.height = fontSize + this.lineHeight;
18005
- // } else {
18006
- // if (textWidth) {
18007
- // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18008
- // this.width = textWidth;
18009
- // } else {
18010
- // this.width = basicScale[0] * 100;
18011
- // }
18012
- // this.height = basicScale[1] * 100;
18013
- // }
18014
- this.width = textWidth;
18015
- this.height = textHeight;
18016
- this.letterSpace = letterSpace;
18017
- this.overFlow = textOverflow;
18018
- this.textBaseline = textBaseline;
18019
- this.textAlign = textAlign;
18020
- this.lineHeight = lineHeight;
17991
+ update(dt) {
17992
+ const time = this.time;
17993
+ // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
17994
+ if (this.item.isEnded(this.time) && !this.item.parent) {
17995
+ this.item.ended = true;
17996
+ }
17997
+ this.timelinePlayable.setTime(time);
17998
+ this.graph.evaluate(dt);
18021
17999
  }
18022
- }
18023
-
18024
- class TextStyle {
18025
- constructor(options){
18026
- /**
18027
- * 是否有下划线(暂时无效)
18028
- */ this.isUnderline = false // ttf
18029
- ;
18030
- /**
18031
- * 下划线高度(暂时无效)
18032
- */ this.underlineHeight = 1 // ttf
18033
- ;
18034
- /**
18035
- * 是否有外描边
18036
- */ this.isOutlined = false // both // ttf & char
18037
- ;
18038
- /**
18039
- * 外描边宽度
18040
- */ this.outlineWidth = 0 // both // ttf & char
18041
- ;
18042
- /**
18043
- * 是否有阴影
18044
- */ this.hasShadow = false // ttf
18045
- ;
18046
- this.fontDesc = '' // both
18047
- ;
18048
- /**
18049
- * 字体倍数
18050
- */ this.fontScale = 2;
18051
- this.fontOffset = 0;
18052
- const { textColor = [
18053
- 1,
18054
- 1,
18055
- 1,
18056
- 1
18057
- ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18058
- this.textColor = textColor;
18059
- //@ts-expect-error
18060
- this.textWeight = fontWeight;
18061
- //@ts-expect-error
18062
- this.fontStyle = fontStyle;
18063
- this.fontFamily = fontFamily;
18064
- this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18065
- if (outline) {
18066
- this.isOutlined = true;
18067
- var _outline_outlineColor;
18068
- this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18069
- 1,
18070
- 1,
18071
- 1,
18072
- 1
18073
- ];
18000
+ createContent() {
18001
+ const sceneBindings = [];
18002
+ for (const sceneBindingData of this.data.sceneBindings){
18003
+ sceneBindings.push({
18004
+ key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
18005
+ value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
18006
+ });
18007
+ }
18008
+ this.sceneBindings = sceneBindings;
18009
+ const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
18010
+ this.timelineAsset = timelineAsset;
18011
+ const items = this.items;
18012
+ this.items.length = 0;
18013
+ if (this.item.composition) {
18014
+ const assetLoader = this.item.engine.assetLoader;
18015
+ const itemProps = this.item.props.items ? this.item.props.items : [];
18016
+ for(let i = 0; i < itemProps.length; i++){
18017
+ let item;
18018
+ const itemData = itemProps[i];
18019
+ // 设置预合成作为元素时的时长、结束行为和渲染延时
18020
+ if (exports.Item.isComposition(itemData)) {
18021
+ const refId = itemData.content.options.refId;
18022
+ const props = this.item.composition.refCompositionProps.get(refId);
18023
+ if (!props) {
18024
+ throw new Error(`引用的Id: ${refId} 的预合成不存在`);
18025
+ }
18026
+ // endBehaviour 类型需优化
18027
+ props.content = itemData.content;
18028
+ item = assetLoader.loadGUID(itemData.id);
18029
+ item.composition = this.item.composition;
18030
+ const compositionComponent = item.addComponent(CompositionComponent);
18031
+ compositionComponent.data = props;
18032
+ compositionComponent.refId = refId;
18033
+ item.transform.parentTransform = this.transform;
18034
+ this.item.composition.refContent.push(item);
18035
+ if (item.endBehavior === ItemEndBehavior.loop) {
18036
+ this.item.composition.autoRefTex = false;
18037
+ }
18038
+ compositionComponent.createContent();
18039
+ for (const vfxItem of compositionComponent.items){
18040
+ vfxItem.setInstanceId(generateGUID());
18041
+ for (const component of vfxItem.components){
18042
+ component.setInstanceId(generateGUID());
18043
+ }
18044
+ }
18045
+ } else {
18046
+ item = assetLoader.loadGUID(itemData.id);
18047
+ item.composition = this.item.composition;
18048
+ }
18049
+ item.parent = this.item;
18050
+ // 相机不跟随合成移动
18051
+ item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
18052
+ if (VFXItem.isExtraCamera(item)) {
18053
+ this.item.composition.extraCamera = item;
18054
+ }
18055
+ items.push(item);
18056
+ }
18057
+ }
18058
+ }
18059
+ onDestroy() {
18060
+ if (this.item.composition) {
18061
+ if (this.items) {
18062
+ this.items.forEach((item)=>item.dispose());
18063
+ this.items.length = 0;
18064
+ }
18065
+ }
18066
+ }
18067
+ hitTest(ray, x, y, regions, force, options) {
18068
+ const hitPositions = [];
18069
+ const stop = (options == null ? void 0 : options.stop) || noop;
18070
+ const skip = (options == null ? void 0 : options.skip) || noop;
18071
+ const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
18072
+ for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
18073
+ const item = this.items[i];
18074
+ if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
18075
+ const hitParams = item.getHitTestParams(force);
18076
+ if (hitParams) {
18077
+ let success = false;
18078
+ const intersectPoint = new Vector3();
18079
+ if (hitParams.type === exports.HitTestType.triangle) {
18080
+ const { triangles, backfaceCulling } = hitParams;
18081
+ for(let j = 0; j < triangles.length; j++){
18082
+ const triangle = triangles[j];
18083
+ if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
18084
+ success = true;
18085
+ hitPositions.push(intersectPoint);
18086
+ break;
18087
+ }
18088
+ }
18089
+ } else if (hitParams.type === exports.HitTestType.box) {
18090
+ const { center, size } = hitParams;
18091
+ const boxMin = center.clone().addScaledVector(size, 0.5);
18092
+ const boxMax = center.clone().addScaledVector(size, -0.5);
18093
+ if (ray.intersectBox({
18094
+ min: boxMin,
18095
+ max: boxMax
18096
+ }, intersectPoint)) {
18097
+ success = true;
18098
+ hitPositions.push(intersectPoint);
18099
+ }
18100
+ } else if (hitParams.type === exports.HitTestType.sphere) {
18101
+ const { center, radius } = hitParams;
18102
+ if (ray.intersectSphere({
18103
+ center,
18104
+ radius
18105
+ }, intersectPoint)) {
18106
+ success = true;
18107
+ hitPositions.push(intersectPoint);
18108
+ }
18109
+ } else if (hitParams.type === exports.HitTestType.custom) {
18110
+ const tempPosition = hitParams.collect(ray, new Vector2(x, y));
18111
+ if (tempPosition && tempPosition.length > 0) {
18112
+ tempPosition.forEach((pos)=>{
18113
+ hitPositions.push(pos);
18114
+ });
18115
+ success = true;
18116
+ }
18117
+ }
18118
+ if (success) {
18119
+ const region = {
18120
+ compContent: this.item,
18121
+ id: item.id,
18122
+ name: item.name,
18123
+ position: hitPositions[hitPositions.length - 1],
18124
+ parentId: item.parentId,
18125
+ hitPositions,
18126
+ behavior: hitParams.behavior
18127
+ };
18128
+ regions.push(region);
18129
+ if (stop(region)) {
18130
+ return regions;
18131
+ }
18132
+ }
18133
+ }
18134
+ }
18135
+ }
18136
+ return regions;
18137
+ }
18138
+ fromData(data) {}
18139
+ resolveBindings() {
18140
+ for (const sceneBinding of this.sceneBindings){
18141
+ sceneBinding.key.binding = sceneBinding.value;
18142
+ }
18143
+ for (const masterTrack of this.timelineAsset.tracks){
18144
+ this.resolveTrackBindingsWithRoot(masterTrack);
18145
+ }
18146
+ }
18147
+ resolveTrackBindingsWithRoot(track) {
18148
+ for (const subTrack of track.getChildTracks()){
18149
+ subTrack.binding = subTrack.resolveBinding(track.binding);
18150
+ this.resolveTrackBindingsWithRoot(subTrack);
18151
+ }
18152
+ }
18153
+ constructor(...args){
18154
+ super(...args);
18155
+ this.time = 0;
18156
+ this.startTime = 0;
18157
+ this.items = [] // 场景的所有元素
18158
+ ;
18159
+ this.reusable = false;
18160
+ this.sceneBindings = [];
18161
+ this.graph = new PlayableGraph();
18162
+ }
18163
+ }
18164
+
18165
+ class SubCompositionTrack extends TrackAsset {
18166
+ resolveBinding(parentBinding) {
18167
+ if (!(parentBinding instanceof VFXItem)) {
18168
+ throw new Error('SubCompositionTrack needs to be set under the VFXItem track');
18169
+ }
18170
+ return parentBinding.getComponent(CompositionComponent);
18171
+ }
18172
+ }
18173
+ SubCompositionTrack = __decorate([
18174
+ effectsClass('SubCompositionTrack')
18175
+ ], SubCompositionTrack);
18176
+
18177
+ class SubCompositionClipPlayable extends Playable {
18178
+ processFrame(context) {
18179
+ const boundObject = context.output.getUserData();
18180
+ boundObject.time = this.getTime();
18181
+ }
18182
+ }
18183
+
18184
+ class SubCompositionPlayableAsset extends PlayableAsset {
18185
+ createPlayable(graph) {
18186
+ return new SubCompositionClipPlayable(graph);
18187
+ }
18188
+ }
18189
+ SubCompositionPlayableAsset = __decorate([
18190
+ effectsClass('SubCompositionPlayableAsset')
18191
+ ], SubCompositionPlayableAsset);
18192
+
18193
+ class TextLayout {
18194
+ getOffsetY(style) {
18195
+ let offsetY = 0;
18196
+ const offset = (style.fontSize + style.outlineWidth) * style.fontScale;
18197
+ switch(this.textBaseline){
18198
+ case TextBaseline.top:
18199
+ offsetY = offset;
18200
+ break;
18201
+ case TextBaseline.middle:
18202
+ offsetY = (this.height + offset) / 2; // fonSize;
18203
+ break;
18204
+ case TextBaseline.bottom:
18205
+ offsetY = this.height - offset / 2;
18206
+ break;
18207
+ }
18208
+ return offsetY;
18209
+ }
18210
+ getOffsetX(style, maxWidth) {
18211
+ let offsetX = 0;
18212
+ switch(this.textAlign){
18213
+ case TextAlignment.left:
18214
+ offsetX = style.outlineWidth * style.fontScale;
18215
+ break;
18216
+ case TextAlignment.middle:
18217
+ offsetX = (this.width * style.fontScale - maxWidth) / 2;
18218
+ break;
18219
+ case TextAlignment.right:
18220
+ offsetX = this.width * style.fontScale - maxWidth;
18221
+ break;
18222
+ }
18223
+ return offsetX;
18224
+ }
18225
+ /**
18226
+ * 设置文本框的宽度和高度
18227
+ * @param width 文本框宽度
18228
+ * @param height 文本框高度
18229
+ */ setSize(width, height) {
18230
+ this.width = width;
18231
+ this.height = height;
18232
+ }
18233
+ constructor(options){
18234
+ this.width = 0;
18235
+ this.height = 0;
18236
+ const { textHeight = 100, textWidth = 100, textOverflow = TextOverflow.display, textBaseline = TextBaseline.top, textAlign = TextAlignment.left, text, letterSpace = 0, autoWidth = false, fontSize, lineHeight = fontSize } = options;
18237
+ const tempWidth = fontSize + letterSpace;
18238
+ this.autoWidth = autoWidth;
18239
+ this.maxTextWidth = text.length * tempWidth;
18240
+ // if (autoWidth) {
18241
+ // this.width = this.maxTextWidth + this.lineWidth;
18242
+ // this.height = fontSize + this.lineHeight;
18243
+ // } else {
18244
+ // if (textWidth) {
18245
+ // this.maxCharCount = Math.floor((textWidth - this.lineWidth) / (tempWidth));
18246
+ // this.width = textWidth;
18247
+ // } else {
18248
+ // this.width = basicScale[0] * 100;
18249
+ // }
18250
+ // this.height = basicScale[1] * 100;
18251
+ // }
18252
+ this.width = textWidth;
18253
+ this.height = textHeight;
18254
+ this.letterSpace = letterSpace;
18255
+ this.overFlow = textOverflow;
18256
+ this.textBaseline = textBaseline;
18257
+ this.textAlign = textAlign;
18258
+ this.lineHeight = lineHeight;
18259
+ }
18260
+ }
18261
+
18262
+ class TextStyle {
18263
+ constructor(options){
18264
+ /**
18265
+ * 是否有下划线(暂时无效)
18266
+ */ this.isUnderline = false // ttf
18267
+ ;
18268
+ /**
18269
+ * 下划线高度(暂时无效)
18270
+ */ this.underlineHeight = 1 // ttf
18271
+ ;
18272
+ /**
18273
+ * 是否有外描边
18274
+ */ this.isOutlined = false // both // ttf & char
18275
+ ;
18276
+ /**
18277
+ * 外描边宽度
18278
+ */ this.outlineWidth = 0 // both // ttf & char
18279
+ ;
18280
+ /**
18281
+ * 是否有阴影
18282
+ */ this.hasShadow = false // ttf
18283
+ ;
18284
+ this.fontDesc = '' // both
18285
+ ;
18286
+ /**
18287
+ * 字体倍数
18288
+ */ this.fontScale = 2;
18289
+ this.fontOffset = 0;
18290
+ const { textColor = [
18291
+ 1,
18292
+ 1,
18293
+ 1,
18294
+ 1
18295
+ ], fontSize = 40, outline, shadow, fontWeight = 'normal', fontStyle = 'normal', fontFamily = 'sans-serif' } = options;
18296
+ this.textColor = textColor;
18297
+ //@ts-expect-error
18298
+ this.textWeight = fontWeight;
18299
+ //@ts-expect-error
18300
+ this.fontStyle = fontStyle;
18301
+ this.fontFamily = fontFamily;
18302
+ this.fontSize = fontSize; // 暂时取消字号限制 Math.min(fontSize, this.maxFontSize);
18303
+ if (outline) {
18304
+ this.isOutlined = true;
18305
+ var _outline_outlineColor;
18306
+ this.outlineColor = (_outline_outlineColor = outline.outlineColor) != null ? _outline_outlineColor : [
18307
+ 1,
18308
+ 1,
18309
+ 1,
18310
+ 1
18311
+ ];
18074
18312
  var _outline_outlineWidth;
18075
18313
  this.outlineWidth = (_outline_outlineWidth = outline.outlineWidth) != null ? _outline_outlineWidth : 1;
18076
18314
  this.fontOffset += this.outlineWidth;
@@ -19388,6 +19626,9 @@ class SerializationHelper {
19388
19626
  static checkGLTFNode(value) {
19389
19627
  return value instanceof Object && value.nodeIndex !== undefined && value.isJoint !== undefined;
19390
19628
  }
19629
+ static checkImageSource(value) {
19630
+ return isCanvas(value) || value instanceof HTMLImageElement;
19631
+ }
19391
19632
  static deserializeProperty(property, engine, level, type) {
19392
19633
  if (level > 14) {
19393
19634
  console.error('序列化数据的内嵌对象层数大于上限');
@@ -19404,7 +19645,7 @@ class SerializationHelper {
19404
19645
  // TODO json 数据避免传 typedArray
19405
19646
  } else if (SerializationHelper.checkDataPath(property)) {
19406
19647
  return engine.assetLoader.loadGUID(property.id);
19407
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19648
+ } else if (property instanceof EffectsObject || SerializationHelper.checkImageSource(property) || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19408
19649
  return property;
19409
19650
  } else if (property instanceof Object) {
19410
19651
  let res;
@@ -19439,7 +19680,7 @@ class SerializationHelper {
19439
19680
  } else if (SerializationHelper.checkDataPath(property)) {
19440
19681
  const res = yield engine.assetLoader.loadGUIDAsync(property.id);
19441
19682
  return res;
19442
- } else if (property instanceof EffectsObject || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19683
+ } else if (property instanceof EffectsObject || SerializationHelper.checkImageSource(property) || SerializationHelper.checkTypedArray(property) || SerializationHelper.checkGLTFNode(property)) {
19443
19684
  return property;
19444
19685
  } else if (property instanceof Object) {
19445
19686
  let res;
@@ -19543,9 +19784,8 @@ class SerializationHelper {
19543
19784
  effectsObject = Geometry.create(this.engine);
19544
19785
  break;
19545
19786
  case DataType.Texture:
19546
- // @ts-expect-error
19547
- effectsObject = Texture.create(this.engine, effectsObjectData);
19548
- return effectsObject;
19787
+ effectsObject = Texture.create(this.engine);
19788
+ break;
19549
19789
  default:
19550
19790
  {
19551
19791
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -19593,9 +19833,8 @@ class SerializationHelper {
19593
19833
  effectsObject = Geometry.create(_this.engine);
19594
19834
  break;
19595
19835
  case DataType.Texture:
19596
- // @ts-expect-error
19597
- effectsObject = Texture.create(_this.engine, effectsObjectData);
19598
- return effectsObject;
19836
+ effectsObject = Texture.create(_this.engine);
19837
+ break;
19599
19838
  default:
19600
19839
  {
19601
19840
  const classConstructor = AssetLoader.getClass(effectsObjectData.dataType);
@@ -20450,6 +20689,7 @@ function getStandardCameraContent(model) {
20450
20689
  _result;
20451
20690
  const result = _extends({}, json, {
20452
20691
  items: [],
20692
+ compositions: [],
20453
20693
  components: [],
20454
20694
  materials: [],
20455
20695
  shaders: [],
@@ -20540,8 +20780,15 @@ function getStandardCameraContent(model) {
20540
20780
  id: item.id
20541
20781
  };
20542
20782
  });
20783
+ const compositionData = _extends({}, composition, {
20784
+ timelineAsset: {
20785
+ id: ''
20786
+ },
20787
+ sceneBindings: []
20788
+ });
20789
+ result.compositions.push(compositionData);
20543
20790
  // 生成时间轴数据
20544
- convertTimelineAsset(composition, guidToItemMap, result);
20791
+ convertTimelineAsset(compositionData, guidToItemMap, result);
20545
20792
  }
20546
20793
  for (const item of result.items){
20547
20794
  // 原 texture 索引转为统一 guid 索引
@@ -20655,7 +20902,7 @@ function getStandardCameraContent(model) {
20655
20902
  content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
20656
20903
  }
20657
20904
  // 修复相机K帧缺失 asMovement 参数
20658
- if (item.type === ItemType.camera) {
20905
+ if (item.type === ItemType.camera && item.content.positionOverLifetime && Object.keys(item.content.positionOverLifetime).length !== 0) {
20659
20906
  item.content.positionOverLifetime.asMovement = true;
20660
20907
  }
20661
20908
  // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
@@ -20708,10 +20955,7 @@ function getStandardCameraContent(model) {
20708
20955
  item.type = 'orientation-transformer';
20709
20956
  }
20710
20957
  // item 的 content 转为 component data 加入 JSONScene.components
20711
- if (item.type === ItemType.sprite || item.type === ItemType.particle || item.type === ItemType.mesh || item.type === ItemType.skybox || item.type === ItemType.light || // @ts-expect-error
20712
- 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
20713
- item.type === 'editor-gizmo' || // @ts-expect-error
20714
- item.type === 'orientation-transformer') {
20958
+ 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') {
20715
20959
  item.components = [];
20716
20960
  result.components.push(item.content);
20717
20961
  item.content.id = generateGUID();
@@ -20743,15 +20987,12 @@ function getStandardCameraContent(model) {
20743
20987
  case ItemType.light:
20744
20988
  item.content.dataType = DataType.LightComponent;
20745
20989
  break;
20746
- // @ts-expect-error
20747
20990
  case 'camera':
20748
20991
  item.content.dataType = DataType.CameraComponent;
20749
20992
  break;
20750
- // @ts-expect-error
20751
20993
  case 'editor-gizmo':
20752
20994
  item.content.dataType = 'GizmoComponent';
20753
20995
  break;
20754
- // @ts-expect-error
20755
20996
  case 'orientation-transformer':
20756
20997
  item.content.dataType = 'OrientationComponent';
20757
20998
  break;
@@ -20817,8 +21058,32 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20817
21058
  for (const itemDataPath of composition.items){
20818
21059
  const item = guidToItemMap[itemDataPath.id];
20819
21060
  const subTrackDatas = [];
21061
+ const newActivationPlayableAsset = {
21062
+ id: generateGUID(),
21063
+ dataType: 'ActivationPlayableAsset'
21064
+ };
21065
+ playableAssetDatas.push(newActivationPlayableAsset);
21066
+ const newActivationTrackData = {
21067
+ id: generateGUID(),
21068
+ dataType: 'ActivationTrack',
21069
+ children: [],
21070
+ clips: [
21071
+ {
21072
+ start: item.delay,
21073
+ duration: item.duration,
21074
+ endBehaviour: item.endBehavior,
21075
+ asset: {
21076
+ id: newActivationPlayableAsset.id
21077
+ }
21078
+ }
21079
+ ]
21080
+ };
21081
+ subTrackDatas.push({
21082
+ id: newActivationTrackData.id
21083
+ });
21084
+ trackDatas.push(newActivationTrackData);
20820
21085
  if (item.type !== ItemType.particle) {
20821
- const newPlayableAssetData = {
21086
+ const newTransformPlayableAssetData = {
20822
21087
  id: generateGUID(),
20823
21088
  dataType: 'TransformPlayableAsset',
20824
21089
  //@ts-expect-error
@@ -20828,15 +21093,18 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20828
21093
  //@ts-expect-error
20829
21094
  positionOverLifetime: item.content.positionOverLifetime
20830
21095
  };
20831
- playableAssetDatas.push(newPlayableAssetData);
21096
+ playableAssetDatas.push(newTransformPlayableAssetData);
20832
21097
  const newTrackData = {
20833
21098
  id: generateGUID(),
20834
21099
  dataType: 'TransformTrack',
20835
21100
  children: [],
20836
21101
  clips: [
20837
21102
  {
21103
+ start: item.delay,
21104
+ duration: item.duration,
21105
+ endBehaviour: item.endBehavior,
20838
21106
  asset: {
20839
- id: newPlayableAssetData.id
21107
+ id: newTransformPlayableAssetData.id
20840
21108
  }
20841
21109
  }
20842
21110
  ]
@@ -20847,21 +21115,50 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20847
21115
  trackDatas.push(newTrackData);
20848
21116
  }
20849
21117
  if (item.type === ItemType.sprite) {
20850
- const newPlayableAssetData = {
21118
+ const newSpriteColorPlayableAssetData = {
20851
21119
  id: generateGUID(),
20852
21120
  dataType: 'SpriteColorPlayableAsset',
20853
21121
  colorOverLifetime: item.content.colorOverLifetime,
20854
21122
  startColor: item.content.options.startColor
20855
21123
  };
20856
- playableAssetDatas.push(newPlayableAssetData);
21124
+ playableAssetDatas.push(newSpriteColorPlayableAssetData);
20857
21125
  const newTrackData = {
20858
21126
  id: generateGUID(),
20859
21127
  dataType: 'SpriteColorTrack',
20860
21128
  children: [],
20861
21129
  clips: [
20862
21130
  {
21131
+ start: item.delay,
21132
+ duration: item.duration,
21133
+ endBehaviour: item.endBehavior,
21134
+ asset: {
21135
+ id: newSpriteColorPlayableAssetData.id
21136
+ }
21137
+ }
21138
+ ]
21139
+ };
21140
+ subTrackDatas.push({
21141
+ id: newTrackData.id
21142
+ });
21143
+ trackDatas.push(newTrackData);
21144
+ }
21145
+ if (item.type === ItemType.composition) {
21146
+ const newSubCompositionPlayableAssetData = {
21147
+ id: generateGUID(),
21148
+ dataType: 'SubCompositionPlayableAsset'
21149
+ };
21150
+ playableAssetDatas.push(newSubCompositionPlayableAssetData);
21151
+ const newTrackData = {
21152
+ id: generateGUID(),
21153
+ dataType: 'SubCompositionTrack',
21154
+ children: [],
21155
+ clips: [
21156
+ {
21157
+ start: item.delay,
21158
+ duration: item.duration,
21159
+ endBehaviour: item.endBehavior,
20863
21160
  asset: {
20864
- id: newPlayableAssetData.id
21161
+ id: newSubCompositionPlayableAssetData.id
20865
21162
  }
20866
21163
  }
20867
21164
  ]
@@ -20896,11 +21193,9 @@ function convertTimelineAsset(composition, guidToItemMap, jsonScene) {
20896
21193
  id: trackData.id
20897
21194
  });
20898
21195
  }
20899
- //@ts-expect-error
20900
21196
  composition.timelineAsset = {
20901
21197
  id: timelineAssetData.id
20902
21198
  };
20903
- //@ts-expect-error
20904
21199
  composition.sceneBindings = sceneBindings;
20905
21200
  if (!jsonScene.animations) {
20906
21201
  jsonScene.animations = [];
@@ -21767,40 +22062,6 @@ function createTextureOptionsBySource(image, sourceFrom) {
21767
22062
  }
21768
22063
  throw new Error('Invalid texture options');
21769
22064
  }
21770
- function base64ToFile(base64, filename = 'base64File', contentType = '') {
21771
- // 去掉 Base64 字符串的 Data URL 部分(如果存在)
21772
- const base64WithoutPrefix = base64.split(',')[1] || base64;
21773
- // 将 base64 编码的字符串转换为二进制字符串
21774
- const byteCharacters = atob(base64WithoutPrefix);
21775
- // 创建一个 8 位无符号整数值的数组,即“字节数组”
21776
- const byteArrays = [];
21777
- // 切割二进制字符串为多个片段,并将每个片段转换成一个字节数组
21778
- for(let offset = 0; offset < byteCharacters.length; offset += 512){
21779
- const slice = byteCharacters.slice(offset, offset + 512);
21780
- const byteNumbers = new Array(slice.length);
21781
- for(let i = 0; i < slice.length; i++){
21782
- byteNumbers[i] = slice.charCodeAt(i);
21783
- }
21784
- const byteArray = new Uint8Array(byteNumbers);
21785
- byteArrays.push(byteArray);
21786
- }
21787
- // 使用字节数组创建 Blob 对象
21788
- const blob = new Blob(byteArrays, {
21789
- type: contentType
21790
- });
21791
- // 创建 File 对象
21792
- const file = new File([
21793
- blob
21794
- ], filename, {
21795
- type: contentType
21796
- });
21797
- return file;
21798
- }
21799
- function isCanvas(canvas) {
21800
- var _canvas_tagName;
21801
- // 小程序 Canvas 无法使用 instanceof HTMLCanvasElement 判断
21802
- return typeof canvas === 'object' && canvas !== null && ((_canvas_tagName = canvas.tagName) == null ? void 0 : _canvas_tagName.toUpperCase()) === 'CANVAS';
21803
- }
21804
22065
 
21805
22066
  const tmpScale = new Vector3(1, 1, 1);
21806
22067
  /**
@@ -22054,214 +22315,173 @@ const tmpScale = new Vector3(1, 1, 1);
22054
22315
  this.dirty = true;
22055
22316
  this.updateMatrix();
22056
22317
  }
22057
- }
22058
-
22059
- /**
22060
- * @since 2.0.0
22061
- * @internal
22062
- */ class CompositionComponent extends ItemBehaviour {
22063
- start() {
22064
- const { startTime = 0 } = this.item.props;
22065
- this.startTime = startTime;
22066
- this.masterTracks = [];
22067
- for (const sceneBinding of this.sceneBindings){
22068
- sceneBinding.key.binding = sceneBinding.value;
22318
+ }
22319
+
22320
+ let listOrder = 0;
22321
+ /**
22322
+ * 合成资源管理
22323
+ */ class CompositionSourceManager {
22324
+ getContent(composition) {
22325
+ // TODO: specification 中补充 globalVolume 类型
22326
+ // @ts-expect-error
22327
+ const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0 } = composition;
22328
+ const items = this.assembleItems(composition);
22329
+ return _extends({}, composition, {
22330
+ id,
22331
+ duration,
22332
+ name,
22333
+ endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
22334
+ // looping,
22335
+ items,
22336
+ camera,
22337
+ startTime,
22338
+ globalVolume
22339
+ });
22340
+ }
22341
+ assembleItems(composition) {
22342
+ const items = [];
22343
+ this.mask++;
22344
+ const componentMap = {};
22345
+ //@ts-expect-error
22346
+ for (const component of this.jsonScene.components){
22347
+ componentMap[component.id] = component;
22069
22348
  }
22070
- this.initializeTrackBindings(this.timelineAsset.tracks);
22071
- this.timelinePlayable = this.timelineAsset.createPlayable(this.graph);
22072
- this.timelinePlayable.play();
22073
- for (const track of this.timelineAsset.tracks){
22074
- // 重播不销毁元素
22075
- if (this.item.endBehavior !== ItemEndBehavior.destroy || this.reusable) {
22076
- if (track instanceof ObjectBindingTrack) {
22077
- track.binding.reusable = true;
22349
+ for (const itemDataPath of composition.items){
22350
+ //@ts-expect-error
22351
+ const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
22352
+ const itemProps = sourceItemData;
22353
+ if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
22354
+ if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
22355
+ for (const componentPath of itemProps.components){
22356
+ const componentData = componentMap[componentPath.id];
22357
+ this.preProcessItemContent(componentData);
22358
+ }
22359
+ } else {
22360
+ const renderContent = itemProps.content;
22361
+ if (renderContent) {
22362
+ this.preProcessItemContent(renderContent);
22363
+ }
22078
22364
  }
22079
- const subCompositionComponent = track.binding.getComponent(CompositionComponent);
22080
- if (subCompositionComponent) {
22081
- subCompositionComponent.reusable = true;
22365
+ itemProps.listIndex = listOrder++;
22366
+ // 处理预合成的渲染顺序
22367
+ if (itemProps.type === ItemType.composition) {
22368
+ const refId = sourceItemData.content.options.refId;
22369
+ if (!this.refCompositions.get(refId)) {
22370
+ throw new Error('Invalid Ref Composition id: ' + refId);
22371
+ }
22372
+ const ref = this.getContent(this.refCompositions.get(refId));
22373
+ if (!this.refCompositionProps.has(refId)) {
22374
+ this.refCompositionProps.set(refId, ref);
22375
+ }
22376
+ ref.items.forEach((item)=>{
22377
+ this.processMask(item.content);
22378
+ });
22379
+ itemProps.items = ref.items;
22082
22380
  }
22381
+ items.push(itemProps);
22083
22382
  }
22084
- this.masterTracks.push(track);
22085
22383
  }
22384
+ return items;
22086
22385
  }
22087
- initializeTrackBindings(masterTracks) {
22088
- for (const track of masterTracks){
22089
- track.initializeBindingRecursive(track.binding);
22386
+ preProcessItemContent(renderContent) {
22387
+ if (renderContent.renderer) {
22388
+ renderContent.renderer = this.changeTex(renderContent.renderer);
22389
+ if (!renderContent.renderer.mask) {
22390
+ this.processMask(renderContent.renderer);
22391
+ }
22392
+ const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
22393
+ if (Number.isInteger(renderContent.renderer.shape)) {
22394
+ var _this_jsonScene;
22395
+ // TODO: scene.shapes 类型问题?
22396
+ renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
22397
+ } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
22398
+ renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
22399
+ }
22400
+ }
22401
+ if (renderContent.trails) {
22402
+ renderContent.trails = this.changeTex(renderContent.trails);
22090
22403
  }
22091
22404
  }
22092
- update(dt) {
22093
- const time = this.time;
22094
- // 主合成 rootItem 没有绑定轨道,增加结束行为判断。
22095
- if (this.item.isEnded(this.time) && !this.item.parent) {
22096
- this.item.ended = true;
22405
+ changeTex(renderer) {
22406
+ if (!renderer.texture) {
22407
+ return renderer;
22097
22408
  }
22098
- this.timelinePlayable.setTime(time);
22099
- this.graph.evaluate(dt);
22100
- for(let i = 0; i < this.items.length; i++){
22101
- const item = this.items[i];
22102
- const subCompostionComponent = item.getComponent(CompositionComponent);
22103
- if (subCompostionComponent) {
22104
- const subCompositionTrack = this.masterTracks[i];
22105
- subCompostionComponent.time = subCompositionTrack.toLocalTime(time);
22106
- }
22409
+ //@ts-expect-error
22410
+ const texIdx = renderer.texture.id;
22411
+ if (texIdx !== undefined) {
22412
+ //@ts-expect-error
22413
+ this.addTextureUsage(texIdx) || texIdx;
22107
22414
  }
22415
+ return renderer;
22108
22416
  }
22109
- /**
22110
- * 重置元素状态属性
22111
- */ resetStatus() {
22112
- this.item.ended = false;
22113
- }
22114
- createContent() {
22115
- const sceneBindings = [];
22116
- for (const sceneBindingData of this.data.sceneBindings){
22117
- sceneBindings.push({
22118
- key: this.engine.assetLoader.loadGUID(sceneBindingData.key.id),
22119
- value: this.engine.assetLoader.loadGUID(sceneBindingData.value.id)
22120
- });
22121
- }
22122
- this.sceneBindings = sceneBindings;
22123
- const timelineAsset = this.data.timelineAsset ? this.engine.assetLoader.loadGUID(this.data.timelineAsset.id) : new TimelineAsset(this.engine);
22124
- this.timelineAsset = timelineAsset;
22125
- const items = this.items;
22126
- this.items.length = 0;
22127
- if (this.item.composition) {
22128
- const assetLoader = this.item.engine.assetLoader;
22129
- const itemProps = this.item.props.items ? this.item.props.items : [];
22130
- for(let i = 0; i < itemProps.length; i++){
22131
- let item;
22132
- const itemData = itemProps[i];
22133
- // 设置预合成作为元素时的时长、结束行为和渲染延时
22134
- if (exports.Item.isComposition(itemData)) {
22135
- const refId = itemData.content.options.refId;
22136
- const props = this.item.composition.refCompositionProps.get(refId);
22137
- if (!props) {
22138
- throw new Error(`引用的Id: ${refId} 的预合成不存在`);
22139
- }
22140
- // endBehaviour 类型需优化
22141
- props.content = itemData.content;
22142
- item = assetLoader.loadGUID(itemData.id);
22143
- item.composition = this.item.composition;
22144
- const compositionComponent = item.addComponent(CompositionComponent);
22145
- compositionComponent.data = props;
22146
- compositionComponent.refId = refId;
22147
- item.transform.parentTransform = this.transform;
22148
- this.item.composition.refContent.push(item);
22149
- if (item.endBehavior === ItemEndBehavior.loop) {
22150
- this.item.composition.autoRefTex = false;
22151
- }
22152
- compositionComponent.createContent();
22153
- for (const vfxItem of compositionComponent.items){
22154
- vfxItem.setInstanceId(generateGUID());
22155
- for (const component of vfxItem.components){
22156
- component.setInstanceId(generateGUID());
22157
- }
22158
- }
22159
- } else {
22160
- item = assetLoader.loadGUID(itemData.id);
22161
- item.composition = this.item.composition;
22162
- }
22163
- item.parent = this.item;
22164
- // 相机不跟随合成移动
22165
- item.transform.parentTransform = itemData.type === ItemType.camera ? new Transform() : this.transform;
22166
- if (VFXItem.isExtraCamera(item)) {
22167
- this.item.composition.extraCamera = item;
22168
- }
22169
- items.push(item);
22417
+ addTextureUsage(texIdx) {
22418
+ const texId = texIdx;
22419
+ var _this_imgUsage;
22420
+ // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
22421
+ const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
22422
+ if (texId && imageUsage) {
22423
+ // eslint-disable-next-line no-prototype-builtins
22424
+ if (!imageUsage.hasOwnProperty(texId)) {
22425
+ imageUsage[texId] = 0;
22170
22426
  }
22427
+ imageUsage[texId]++;
22171
22428
  }
22172
22429
  }
22173
- onDestroy() {
22174
- if (this.item.composition) {
22175
- if (this.items) {
22176
- this.items.forEach((item)=>item.dispose());
22177
- this.items.length = 0;
22430
+ /**
22431
+ * 处理蒙版和遮挡关系写入 stencil 的 ref 值
22432
+ */ processMask(renderer) {
22433
+ const maskMode = renderer.maskMode;
22434
+ if (maskMode === MaskMode.NONE) {
22435
+ return;
22436
+ }
22437
+ if (!renderer.mask) {
22438
+ if (maskMode === MaskMode.MASK) {
22439
+ renderer.mask = ++this.mask;
22440
+ } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
22441
+ renderer.mask = this.mask;
22178
22442
  }
22179
22443
  }
22180
22444
  }
22181
- hitTest(ray, x, y, regions, force, options) {
22182
- const hitPositions = [];
22183
- const stop = (options == null ? void 0 : options.stop) || noop;
22184
- const skip = (options == null ? void 0 : options.skip) || noop;
22185
- const maxCount = (options == null ? void 0 : options.maxCount) || this.items.length;
22186
- for(let i = 0; i < this.items.length && regions.length < maxCount; i++){
22187
- const item = this.items[i];
22188
- if (item.getVisible() && !item.ended && !VFXItem.isComposition(item) && !skip(item)) {
22189
- const hitParams = item.getHitTestParams(force);
22190
- if (hitParams) {
22191
- let success = false;
22192
- const intersectPoint = new Vector3();
22193
- if (hitParams.type === exports.HitTestType.triangle) {
22194
- const { triangles, backfaceCulling } = hitParams;
22195
- for(let j = 0; j < triangles.length; j++){
22196
- const triangle = triangles[j];
22197
- if (ray.intersectTriangle(triangle, intersectPoint, backfaceCulling)) {
22198
- success = true;
22199
- hitPositions.push(intersectPoint);
22200
- break;
22201
- }
22202
- }
22203
- } else if (hitParams.type === exports.HitTestType.box) {
22204
- const { center, size } = hitParams;
22205
- const boxMin = center.clone().addScaledVector(size, 0.5);
22206
- const boxMax = center.clone().addScaledVector(size, -0.5);
22207
- if (ray.intersectBox({
22208
- min: boxMin,
22209
- max: boxMax
22210
- }, intersectPoint)) {
22211
- success = true;
22212
- hitPositions.push(intersectPoint);
22213
- }
22214
- } else if (hitParams.type === exports.HitTestType.sphere) {
22215
- const { center, radius } = hitParams;
22216
- if (ray.intersectSphere({
22217
- center,
22218
- radius
22219
- }, intersectPoint)) {
22220
- success = true;
22221
- hitPositions.push(intersectPoint);
22222
- }
22223
- } else if (hitParams.type === exports.HitTestType.custom) {
22224
- const tempPosition = hitParams.collect(ray, new Vector2(x, y));
22225
- if (tempPosition && tempPosition.length > 0) {
22226
- tempPosition.forEach((pos)=>{
22227
- hitPositions.push(pos);
22228
- });
22229
- success = true;
22230
- }
22231
- }
22232
- if (success) {
22233
- const region = {
22234
- compContent: this.item,
22235
- id: item.id,
22236
- name: item.name,
22237
- position: hitPositions[hitPositions.length - 1],
22238
- parentId: item.parentId,
22239
- hitPositions,
22240
- behavior: hitParams.behavior
22241
- };
22242
- regions.push(region);
22243
- if (stop(region)) {
22244
- return regions;
22245
- }
22246
- }
22247
- }
22445
+ dispose() {
22446
+ this.textures = [];
22447
+ this.composition = undefined;
22448
+ this.jsonScene = undefined;
22449
+ this.totalTime = 0;
22450
+ this.pluginSystem = undefined;
22451
+ this.sourceContent = undefined;
22452
+ this.refCompositions.clear();
22453
+ this.refCompositionProps.clear();
22454
+ }
22455
+ constructor(scene, engine){
22456
+ this.refCompositions = new Map();
22457
+ this.refCompositionProps = new Map();
22458
+ this.mask = 0;
22459
+ this.engine = engine;
22460
+ // 资源
22461
+ const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
22462
+ const { compositions, imgUsage, compositionId } = jsonScene;
22463
+ if (!textureOptions) {
22464
+ throw new Error('scene.textures expected');
22465
+ }
22466
+ const cachedTextures = textureOptions;
22467
+ for (const comp of compositions){
22468
+ if (comp.id === compositionId) {
22469
+ this.composition = comp;
22470
+ } else {
22471
+ this.refCompositions.set(comp.id, comp);
22248
22472
  }
22249
22473
  }
22250
- return regions;
22251
- }
22252
- fromData(data) {
22253
- // this.timelineAsset = data.timelineAsset;
22254
- }
22255
- constructor(...args){
22256
- super(...args);
22257
- this.time = 0;
22258
- this.startTime = 0;
22259
- this.items = [] // 场景的所有元素
22260
- ;
22261
- this.reusable = false;
22262
- this.sceneBindings = [];
22263
- this.masterTracks = [];
22264
- this.graph = new PlayableGraph();
22474
+ if (!this.composition) {
22475
+ throw new Error('Invalid composition id: ' + compositionId);
22476
+ }
22477
+ this.jsonScene = jsonScene;
22478
+ this.renderLevel = renderLevel;
22479
+ this.pluginSystem = pluginSystem;
22480
+ this.totalTime = totalTime != null ? totalTime : 0;
22481
+ this.imgUsage = imgUsage != null ? imgUsage : {};
22482
+ this.textures = cachedTextures;
22483
+ listOrder = 0;
22484
+ this.sourceContent = this.getContent(this.composition);
22265
22485
  }
22266
22486
  }
22267
22487
 
@@ -22271,6 +22491,11 @@ const tmpScale = new Vector3(1, 1, 1);
22271
22491
  * 也负责 Item 相关的动画播放控制,和持有渲染帧数据。
22272
22492
  */ class Composition {
22273
22493
  /**
22494
+ * 所有合成 Item 的根变换
22495
+ */ get transform() {
22496
+ return this.rootItem.transform;
22497
+ }
22498
+ /**
22274
22499
  * 获取场景中的纹理数组
22275
22500
  */ get textures() {
22276
22501
  return this.compositionSourceManager.textures;
@@ -22304,16 +22529,8 @@ const tmpScale = new Vector3(1, 1, 1);
22304
22529
  /**
22305
22530
  * 重新开始合成
22306
22531
  */ restart() {
22307
- // const contentItems = this.rootComposition.items;
22308
- // contentItems.forEach(item => item.dispose());
22309
- // contentItems.length = 0;
22310
- this.prepareRender();
22311
22532
  this.reset();
22312
- this.transform.setValid(true);
22313
- this.rootComposition.resetStatus();
22314
22533
  this.forwardTime(this.startTime);
22315
- // this.content.onUpdate(0);
22316
- // this.loaderData.spriteGroup.onUpdate(0);
22317
22534
  }
22318
22535
  /**
22319
22536
  * 设置当前合成的渲染顺序
@@ -22440,27 +22657,9 @@ const tmpScale = new Vector3(1, 1, 1);
22440
22657
  /**
22441
22658
  * 重置状态函数
22442
22659
  */ reset() {
22443
- const vfxItem = new VFXItem(this.getEngine(), this.compositionSourceManager.sourceContent);
22444
- // TODO 编辑器数据传入 composition type 后移除
22445
- vfxItem.type = ItemType.composition;
22446
- vfxItem.composition = this;
22447
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
22448
- this.rootComposition.data = this.compositionSourceManager.sourceContent;
22449
- this.transform = new Transform({
22450
- name: this.name
22451
- });
22452
- this.transform.engine = this.getEngine();
22453
- vfxItem.transform = this.transform;
22454
- this.rootItem = vfxItem;
22455
22660
  this.rendererOptions = null;
22456
22661
  this.globalTime = 0;
22457
- this.rootComposition.createContent();
22458
- this.buildItemTree(this.rootItem);
22459
- this.rootItem.onEnd = ()=>{
22460
- window.setTimeout(()=>{
22461
- this.onEnd == null ? void 0 : this.onEnd.call(this, this);
22462
- }, 0);
22463
- };
22662
+ this.rootItem.ended = false;
22464
22663
  this.pluginSystem.resetComposition(this, this.renderFrame);
22465
22664
  }
22466
22665
  prepareRender() {
@@ -22501,7 +22700,6 @@ const tmpScale = new Vector3(1, 1, 1);
22501
22700
  }
22502
22701
  const { ended, endBehavior } = this.rootItem;
22503
22702
  // TODO: 合成结束行为
22504
- // @ts-expect-error
22505
22703
  return ended && (!endBehavior || endBehavior === END_BEHAVIOR_PAUSE_AND_DESTROY);
22506
22704
  }
22507
22705
  /**
@@ -22590,7 +22788,7 @@ const tmpScale = new Vector3(1, 1, 1);
22590
22788
  for (const child of item.children){
22591
22789
  if (VFXItem.isComposition(child)) {
22592
22790
  if (child.ended && child.endBehavior === ItemEndBehavior.loop) {
22593
- child.getComponent(CompositionComponent).resetStatus();
22791
+ child.ended = false;
22594
22792
  // TODO K帧动画在元素重建后需要 tick ,否则会导致元素位置和 k 帧第一帧位置不一致
22595
22793
  this.callUpdate(child, 0);
22596
22794
  } else {
@@ -22957,23 +23155,32 @@ const tmpScale = new Vector3(1, 1, 1);
22957
23155
  * @param props - composition 的创建参数
22958
23156
  * @param scene
22959
23157
  * @param compositionSourceManager
22960
- */ constructor(props, scene, compositionSourceManager){
22961
- this.compositionSourceManager = compositionSourceManager;
22962
- this./**
23158
+ */ constructor(props, scene){
23159
+ /**
22963
23160
  * 动画播放速度
22964
- */ speed = 1;
22965
- this.loaderData = {};
22966
- this.refContent = [];
22967
- this./**
23161
+ */ this.speed = 1;
23162
+ /**
23163
+ * 用于保存与当前合成相关的插件数据
23164
+ */ this.loaderData = {};
23165
+ /**
23166
+ * 预合成数组
23167
+ */ this.refContent = [];
23168
+ /**
22968
23169
  * 预合成的合成属性,在 content 中会被其元素属性覆盖
22969
- */ refCompositionProps = new Map();
23170
+ */ this.refCompositionProps = new Map();
22970
23171
  this.editorScaleRatio = 1.0;
23172
+ // TODO: 待优化
22971
23173
  this.assigned = false;
22972
- this.destroyed = false;
22973
- this.paused = false;
23174
+ /**
23175
+ * 销毁状态位
23176
+ */ this.destroyed = false;
23177
+ /**
23178
+ * 合成暂停/播放 标识
23179
+ */ this.paused = false;
22974
23180
  this.lastVideoUpdateTime = 0;
22975
23181
  this.postLoaders = [];
22976
23182
  const { reusable = false, speed = 1, baseRenderOrder = 0, renderer, onPlayerPause, onMessageItem, onEnd, event, width, height } = props;
23183
+ this.compositionSourceManager = new CompositionSourceManager(scene, renderer.engine);
22977
23184
  scene.jsonScene.imgUsage = undefined;
22978
23185
  if (reusable) {
22979
23186
  this.keepResource = true;
@@ -22984,19 +23191,12 @@ const tmpScale = new Vector3(1, 1, 1);
22984
23191
  assertExist(sourceContent);
22985
23192
  this.renderer = renderer;
22986
23193
  this.refCompositionProps = refCompositionProps;
22987
- const vfxItem = new VFXItem(this.getEngine(), sourceContent);
22988
- vfxItem.name = 'rootItem';
22989
- // TODO 编辑器数据传入 composition type 后移除
22990
- vfxItem.type = ItemType.composition;
22991
- vfxItem.composition = this;
22992
- this.rootComposition = vfxItem.addComponent(CompositionComponent);
23194
+ this.rootItem = new VFXItem(this.getEngine(), sourceContent);
23195
+ this.rootItem.name = 'rootItem';
23196
+ this.rootItem.composition = this;
23197
+ this.rootComposition = this.rootItem.addComponent(CompositionComponent);
22993
23198
  this.rootComposition.data = sourceContent;
22994
23199
  const imageUsage = !reusable && imgUsage;
22995
- this.transform = new Transform({
22996
- name: this.name
22997
- });
22998
- this.transform.engine = this.getEngine();
22999
- vfxItem.transform = this.transform;
23000
23200
  this.globalVolume = sourceContent.globalVolume;
23001
23201
  this.width = width;
23002
23202
  this.height = height;
@@ -23014,8 +23214,7 @@ const tmpScale = new Vector3(1, 1, 1);
23014
23214
  this.reusable = reusable;
23015
23215
  this.speed = speed;
23016
23216
  this.renderLevel = renderLevel;
23017
- this.autoRefTex = !this.keepResource && imageUsage && vfxItem.endBehavior !== ItemEndBehavior.loop;
23018
- this.rootItem = vfxItem;
23217
+ this.autoRefTex = !this.keepResource && imageUsage && this.rootItem.endBehavior !== ItemEndBehavior.loop;
23019
23218
  this.name = sourceContent.name;
23020
23219
  this.pluginSystem = pluginSystem;
23021
23220
  this.pluginSystem.initializeComposition(this, scene);
@@ -23041,182 +23240,6 @@ const tmpScale = new Vector3(1, 1, 1);
23041
23240
  }
23042
23241
  }
23043
23242
 
23044
- let listOrder = 0;
23045
- /**
23046
- * 合成资源管理
23047
- */ class CompositionSourceManager {
23048
- getContent(composition) {
23049
- // TODO: specification 中补充 globalVolume 类型
23050
- // @ts-expect-error
23051
- const { id, duration, name, endBehavior, camera, globalVolume, startTime = 0, timelineAsset } = composition;
23052
- const items = this.assembleItems(composition);
23053
- //@ts-expect-error
23054
- if (!composition.sceneBindings) {
23055
- //@ts-expect-error
23056
- composition.sceneBindings = [];
23057
- }
23058
- return {
23059
- id,
23060
- duration,
23061
- name,
23062
- endBehavior: isNaN(endBehavior) ? END_BEHAVIOR_PAUSE : endBehavior,
23063
- // looping,
23064
- items,
23065
- camera,
23066
- startTime,
23067
- globalVolume,
23068
- timelineAsset: timelineAsset,
23069
- //@ts-expect-error
23070
- sceneBindings: composition.sceneBindings
23071
- };
23072
- }
23073
- assembleItems(composition) {
23074
- const items = [];
23075
- this.mask++;
23076
- const componentMap = {};
23077
- //@ts-expect-error
23078
- for (const component of this.jsonScene.components){
23079
- componentMap[component.id] = component;
23080
- }
23081
- for (const itemDataPath of composition.items){
23082
- //@ts-expect-error
23083
- const sourceItemData = this.engine.jsonSceneData[itemDataPath.id];
23084
- const itemProps = sourceItemData;
23085
- if (passRenderLevel(sourceItemData.renderLevel, this.renderLevel)) {
23086
- if (itemProps.type === ItemType.sprite || itemProps.type === ItemType.particle) {
23087
- for (const componentPath of itemProps.components){
23088
- const componentData = componentMap[componentPath.id];
23089
- this.preProcessItemContent(componentData);
23090
- }
23091
- } else {
23092
- const renderContent = itemProps.content;
23093
- if (renderContent) {
23094
- this.preProcessItemContent(renderContent);
23095
- }
23096
- }
23097
- itemProps.listIndex = listOrder++;
23098
- // 处理预合成的渲染顺序
23099
- if (itemProps.type === ItemType.composition) {
23100
- const refId = sourceItemData.content.options.refId;
23101
- if (!this.refCompositions.get(refId)) {
23102
- throw new Error('Invalid Ref Composition id: ' + refId);
23103
- }
23104
- const ref = this.getContent(this.refCompositions.get(refId));
23105
- if (!this.refCompositionProps.has(refId)) {
23106
- this.refCompositionProps.set(refId, ref);
23107
- }
23108
- ref.items.forEach((item)=>{
23109
- this.processMask(item.content);
23110
- });
23111
- itemProps.items = ref.items;
23112
- }
23113
- items.push(itemProps);
23114
- }
23115
- }
23116
- return items;
23117
- }
23118
- preProcessItemContent(renderContent) {
23119
- if (renderContent.renderer) {
23120
- renderContent.renderer = this.changeTex(renderContent.renderer);
23121
- if (!renderContent.renderer.mask) {
23122
- this.processMask(renderContent.renderer);
23123
- }
23124
- const split = renderContent.splits && !renderContent.textureSheetAnimation && renderContent.splits[0];
23125
- if (Number.isInteger(renderContent.renderer.shape)) {
23126
- var _this_jsonScene;
23127
- // TODO: scene.shapes 类型问题?
23128
- renderContent.renderer.shape = getGeometryByShape((_this_jsonScene = this.jsonScene) == null ? void 0 : _this_jsonScene.shapes[renderContent.renderer.shape], split);
23129
- } else if (renderContent.renderer.shape && isObject(renderContent.renderer.shape)) {
23130
- renderContent.renderer.shape = getGeometryByShape(renderContent.renderer.shape, split);
23131
- }
23132
- }
23133
- if (renderContent.trails) {
23134
- renderContent.trails = this.changeTex(renderContent.trails);
23135
- }
23136
- }
23137
- changeTex(renderer) {
23138
- if (!renderer.texture) {
23139
- return renderer;
23140
- }
23141
- //@ts-expect-error
23142
- const texIdx = renderer.texture.id;
23143
- if (texIdx !== undefined) {
23144
- //@ts-expect-error
23145
- this.addTextureUsage(texIdx) || texIdx;
23146
- }
23147
- return renderer;
23148
- }
23149
- addTextureUsage(texIdx) {
23150
- const texId = texIdx;
23151
- var _this_imgUsage;
23152
- // FIXME: imageUsage 取自 scene.imgUsage,类型为 Record<string, number[]>,这里给的 number,类型对不上
23153
- const imageUsage = (_this_imgUsage = this.imgUsage) != null ? _this_imgUsage : {};
23154
- if (texId && imageUsage) {
23155
- // eslint-disable-next-line no-prototype-builtins
23156
- if (!imageUsage.hasOwnProperty(texId)) {
23157
- imageUsage[texId] = 0;
23158
- }
23159
- imageUsage[texId]++;
23160
- }
23161
- }
23162
- /**
23163
- * 处理蒙版和遮挡关系写入 stencil 的 ref 值
23164
- */ processMask(renderer) {
23165
- const maskMode = renderer.maskMode;
23166
- if (maskMode === MaskMode.NONE) {
23167
- return;
23168
- }
23169
- if (!renderer.mask) {
23170
- if (maskMode === MaskMode.MASK) {
23171
- renderer.mask = ++this.mask;
23172
- } else if (maskMode === MaskMode.OBSCURED || maskMode === MaskMode.REVERSE_OBSCURED) {
23173
- renderer.mask = this.mask;
23174
- }
23175
- }
23176
- }
23177
- dispose() {
23178
- this.textures = [];
23179
- this.composition = undefined;
23180
- this.jsonScene = undefined;
23181
- this.totalTime = 0;
23182
- this.pluginSystem = undefined;
23183
- this.sourceContent = undefined;
23184
- this.refCompositions.clear();
23185
- this.refCompositionProps.clear();
23186
- }
23187
- constructor(scene, engine){
23188
- this.refCompositions = new Map();
23189
- this.refCompositionProps = new Map();
23190
- this.mask = 0;
23191
- this.engine = engine;
23192
- // 资源
23193
- const { jsonScene, renderLevel, textureOptions, pluginSystem, totalTime } = scene;
23194
- const { compositions, imgUsage, compositionId } = jsonScene;
23195
- if (!textureOptions) {
23196
- throw new Error('scene.textures expected');
23197
- }
23198
- const cachedTextures = textureOptions;
23199
- for (const comp of compositions){
23200
- if (comp.id === compositionId) {
23201
- this.composition = comp;
23202
- } else {
23203
- this.refCompositions.set(comp.id, comp);
23204
- }
23205
- }
23206
- if (!this.composition) {
23207
- throw new Error('Invalid composition id: ' + compositionId);
23208
- }
23209
- this.jsonScene = jsonScene;
23210
- this.renderLevel = renderLevel;
23211
- this.pluginSystem = pluginSystem;
23212
- this.totalTime = totalTime != null ? totalTime : 0;
23213
- this.imgUsage = imgUsage != null ? imgUsage : {};
23214
- this.textures = cachedTextures;
23215
- listOrder = 0;
23216
- this.sourceContent = this.getContent(this.composition);
23217
- }
23218
- }
23219
-
23220
23243
  /**
23221
23244
  * Engine 基类,负责维护所有 GPU 资源的管理及销毁
23222
23245
  */ class Engine {
@@ -23240,65 +23263,48 @@ let listOrder = 0;
23240
23263
  delete this.objectInstance[id];
23241
23264
  }
23242
23265
  addPackageDatas(scene) {
23243
- const jsonScene = scene.jsonScene;
23244
- if (jsonScene.items) {
23245
- for (const vfxItemData of jsonScene.items){
23246
- this.addEffectsObjectData(vfxItemData);
23247
- }
23266
+ const { jsonScene, textureOptions = [] } = scene;
23267
+ const { items = [], materials = [], shaders = [], geometries = [], components = [], animations = [], bins = [] } = jsonScene;
23268
+ for (const vfxItemData of items){
23269
+ this.addEffectsObjectData(vfxItemData);
23248
23270
  }
23249
- if (jsonScene.materials) {
23250
- for (const materialData of jsonScene.materials){
23251
- this.addEffectsObjectData(materialData);
23252
- }
23271
+ for (const materialData of materials){
23272
+ this.addEffectsObjectData(materialData);
23253
23273
  }
23254
- if (jsonScene.shaders) {
23255
- for (const shaderData of jsonScene.shaders){
23256
- this.addEffectsObjectData(shaderData);
23257
- }
23274
+ for (const shaderData of shaders){
23275
+ this.addEffectsObjectData(shaderData);
23258
23276
  }
23259
- if (jsonScene.geometries) {
23260
- for (const geometryData of jsonScene.geometries){
23261
- this.addEffectsObjectData(geometryData);
23262
- }
23277
+ for (const geometryData of geometries){
23278
+ this.addEffectsObjectData(geometryData);
23263
23279
  }
23264
- if (jsonScene.components) {
23265
- for (const componentData of jsonScene.components){
23266
- this.addEffectsObjectData(componentData);
23267
- }
23280
+ for (const componentData of components){
23281
+ this.addEffectsObjectData(componentData);
23268
23282
  }
23269
- if (jsonScene.animations) {
23270
- for (const animationData of jsonScene.animations){
23271
- this.addEffectsObjectData(animationData);
23272
- }
23283
+ for (const animationData of animations){
23284
+ this.addEffectsObjectData(animationData);
23273
23285
  }
23274
- if (jsonScene.bins) {
23275
- for(let i = 0; i < jsonScene.bins.length; i++){
23276
- const binaryData = jsonScene.bins[i];
23277
- const binaryBuffer = scene.bins[i];
23278
- //@ts-expect-error
23279
- binaryData.buffer = binaryBuffer;
23286
+ for(let i = 0; i < bins.length; i++){
23287
+ const binaryData = bins[i];
23288
+ const binaryBuffer = scene.bins[i];
23289
+ //@ts-expect-error
23290
+ binaryData.buffer = binaryBuffer;
23291
+ //@ts-expect-error
23292
+ if (binaryData.id) {
23280
23293
  //@ts-expect-error
23281
- if (binaryData.id) {
23282
- //@ts-expect-error
23283
- this.addEffectsObjectData(binaryData);
23284
- }
23294
+ this.addEffectsObjectData(binaryData);
23285
23295
  }
23286
23296
  }
23287
- if (scene.textureOptions) {
23288
- for (const textureData of scene.textureOptions){
23289
- this.addEffectsObjectData(textureData);
23290
- }
23297
+ for (const textureData of textureOptions){
23298
+ this.addEffectsObjectData(textureData);
23291
23299
  }
23292
23300
  }
23293
23301
  createVFXItems(scene) {
23294
23302
  var _this = this;
23295
23303
  return _async_to_generator(function*() {
23296
- const jsonScene = scene.jsonScene;
23304
+ const { jsonScene } = scene;
23297
23305
  for (const itemData of jsonScene.items){
23298
23306
  const itemType = itemData.type;
23299
- if (!// @ts-expect-error
23300
- (itemType === 'ECS' || // @ts-expect-error
23301
- 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)) {
23307
+ 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)) {
23302
23308
  continue;
23303
23309
  }
23304
23310
  if (_this.database) {
@@ -23396,21 +23402,11 @@ let listOrder = 0;
23396
23402
  if (info.length > 0) {
23397
23403
  logger.warn(`Release GPU memory: ${info.join(', ')}`);
23398
23404
  }
23399
- this.renderPasses.forEach((pass)=>{
23400
- pass.dispose();
23401
- });
23402
- this.meshes.forEach((mesh)=>{
23403
- mesh.dispose();
23404
- });
23405
- this.geometries.forEach((geo)=>{
23406
- geo.dispose();
23407
- });
23408
- this.materials.forEach((mat)=>{
23409
- mat.dispose();
23410
- });
23411
- this.textures.forEach((tex)=>{
23412
- tex.dispose();
23413
- });
23405
+ this.renderPasses.forEach((pass)=>pass.dispose());
23406
+ this.meshes.forEach((mesh)=>mesh.dispose());
23407
+ this.geometries.forEach((geo)=>geo.dispose());
23408
+ this.materials.forEach((mat)=>mat.dispose());
23409
+ this.textures.forEach((tex)=>tex.dispose());
23414
23410
  this.textures = [];
23415
23411
  this.materials = [];
23416
23412
  this.geometries = [];
@@ -23657,6 +23653,8 @@ exports.SpriteColorTrack = SpriteColorTrack;
23657
23653
  exports.SpriteComponent = SpriteComponent;
23658
23654
  exports.SpriteLoader = SpriteLoader;
23659
23655
  exports.StaticValue = StaticValue;
23656
+ exports.SubCompositionPlayableAsset = SubCompositionPlayableAsset;
23657
+ exports.SubCompositionTrack = SubCompositionTrack;
23660
23658
  exports.TEMPLATE_USE_OFFSCREEN_CANVAS = TEMPLATE_USE_OFFSCREEN_CANVAS;
23661
23659
  exports.TextComponent = TextComponent;
23662
23660
  exports.TextLoader = TextLoader;
@@ -23679,6 +23677,7 @@ exports.addItem = addItem;
23679
23677
  exports.addItemWithOrder = addItemWithOrder;
23680
23678
  exports.assertExist = assertExist;
23681
23679
  exports.asserts = asserts;
23680
+ exports.base64ToFile = base64ToFile;
23682
23681
  exports.blend = blend;
23683
23682
  exports.calculateTranslation = calculateTranslation;
23684
23683
  exports.canvasPool = canvasPool;
@@ -23747,6 +23746,7 @@ exports.interpolateColor = interpolateColor;
23747
23746
  exports.isAlipayMiniApp = isAlipayMiniApp;
23748
23747
  exports.isAndroid = isAndroid;
23749
23748
  exports.isArray = isArray;
23749
+ exports.isCanvas = isCanvas;
23750
23750
  exports.isFunction = isFunction;
23751
23751
  exports.isIOS = isIOS;
23752
23752
  exports.isObject = isObject;