Component({
  behaviors: [require('../common/share-behavior').default],
  properties: {
    markerImg: {
      type: String
    },
  },
  data: {
    loaded: false,
    arReady: false,
    isStartPlay1: false,
    adlScale: '0 0 0',
    adlPos: '-0.1 -0.5 -0.05',
    sunReady: false,
    tigerReady: false
  },
  lifetimes: {
    attached() {
    },
    detached() {
      this.stopSunRotation();
      this.stopTiger();
    }
  },
  methods: {
    handleReady({
      detail
    }) {
      const xrScene = this.scene = detail.value;
      // console.log('xr-scene', xrScene);
    },
    handleAssetsProgress: function ({
      detail
    }) {
      // console.log('assets progress', detail.value);
    },
    handleAssetsLoaded: function ({
      detail
    }) {
      console.log('assets loaded', detail.value);
      this.setData({
        loaded: true
      });
    },
    handleARReady: function ({
      detail
    }) {
      console.log('arReady');
      this.setData({
        arReady: true
      })
    },
    handleItem1Loaded({ detail }) {
      const el = detail.value.target;
      const animator = el.getComponent("animator");
      this.animator1 = animator
      console.log('animator1', animator)

      const gltf = el.getComponent("gltf");
      this.bgGltf = gltf;
      this.sunMeshes = this.resolveSunMeshesFromBG(gltf);
      this.setData({ sunReady: !!(this.sunMeshes && this.sunMeshes.length) });
      if (this.sunShouldRun) this.startSunRotation();

      this.tigerMeshes = this.resolveTigerMeshesFromBG(gltf);
      this.setData({ tigerReady: !!(this.tigerMeshes && this.tigerMeshes.length) });
      if (this.tigerShouldRun && this.tigerStartRequested) this.scheduleTigerStart();
    },
    handleItem2Loaded({ detail }) {
      const el = detail.value.target;
      const animator = el.getComponent("animator");
      this.animator2 = animator;
    },
    handleARTrackerState1({
      detail
    }) {
      // 事件的值即为`ARTracker`实例
      const tracker = detail.value;
      // 获取当前状态和错误信息
      console.log('tracker', tracker)

      const {
        state,
      } = tracker;
      if (state == 2) {
        this.play()
      } else {
        this.pause()
      }
    },
    play() {
      if (!this.data.loaded) return
      this.sunShouldRun = true;
      this.startSunRotation();
      this.tigerShouldRun = true;
      this.tigerStartRequested = false;
      this.prepareTigerAudio();
      this.prepareTigerFrames();

      if (!this.data.isStartPlay1) {
        this.setData({
          isStartPlay1: true
        }, () => {
          this.playitem1Action()
        })
      }
    },
    pause() {
      this.sunShouldRun = false;
      this.stopSunRotation();
      this.tigerShouldRun = false;
      this.tigerStartRequested = false;
      this.stopTiger();
    },
    resolveSunMeshesFromBG(gltf) {
      if (!gltf || !this.scene) return [];

      const candidates = this.getSunNameCandidates();
      const uniqueCandidates = [];
      for (const name of candidates) {
        if (name && !uniqueCandidates.includes(name)) uniqueCandidates.push(name);
      }

      for (const name of uniqueCandidates) {
        if (typeof gltf.getPrimitivesByNodeName === 'function') {
          const meshes = gltf.getPrimitivesByNodeName(name);
          if (meshes && meshes.length) return meshes;
        }
        if (typeof gltf.getPrimitivesByMeshName === 'function') {
          const meshes = gltf.getPrimitivesByMeshName(name);
          if (meshes && meshes.length) return meshes;
        }
      }

      if (typeof gltf.getMeshes === 'function') {
        const meshes = gltf.getMeshes() || [];
        const meshNames = meshes.map(m => m && (m.name || m.el && m.el.name)).filter(Boolean);
        console.warn('sun mesh not found, available mesh names:', meshNames);
      } else {
        console.warn('sun mesh not found');
      }
      return [];
    },
    getSunNameCandidates() {
      const defaultCandidates = ['Sun', 'sun', 'SUN', '太阳', 'Taiyang', 'taiyang'];
      if (!this.scene) return defaultCandidates;

      const gltfAsset = this.scene.assets && this.scene.assets.getAsset && this.scene.assets.getAsset('gltf', 'bg');
      const jsonRaw = gltfAsset && gltfAsset.jsonRaw;
      if (!jsonRaw) return defaultCandidates;

      const names = [];
      const addIfMatch = (n) => {
        if (!n || typeof n !== 'string') return;
        if (/Sun/i.test(n) || n.includes('太阳')) names.push(n);
      };

      if (Array.isArray(jsonRaw.nodes)) {
        for (const node of jsonRaw.nodes) addIfMatch(node && node.name);
      }
      if (Array.isArray(jsonRaw.meshes)) {
        for (const mesh of jsonRaw.meshes) addIfMatch(mesh && mesh.name);
      }

      return names.length ? names.concat(defaultCandidates) : defaultCandidates;
    },
    startSunRotation() {
      if (!this.scene) return;
      if (!this.sunShouldRun) return;
      if (!this.sunMeshes || !this.sunMeshes.length) return;
      if (this.sunRotationTimer) return;

      this.sunFrameCount = 159;
      this.sunFrameIndex = this.sunFrameIndex || 1;
      this.sunTextureCacheLimit = 12;
      if (!this.sunTextureCache) this.sunTextureCache = new Map();
      if (!this.sunTextureQueue) this.sunTextureQueue = [];

      this.updateSunFrame();
      this.sunRotationTimer = setInterval(() => this.updateSunFrame(), 80);
    },
    stopSunRotation() {
      if (this.sunRotationTimer) {
        clearInterval(this.sunRotationTimer);
        this.sunRotationTimer = null;
      }
      this.sunFrameLoading = false;
      if (this.scene && this.scene.assets && this.scene.assets.releaseAsset && this.sunTextureQueue) {
        for (const assetId of this.sunTextureQueue) {
          this.scene.assets.releaseAsset('texture', assetId);
        }
      }
      this.sunTextureCache = null;
      this.sunTextureQueue = null;
    },
    async updateSunFrame() {
      if (this.sunFrameLoading) return;
      if (!this.scene || !this.sunMeshes || !this.sunMeshes.length) return;
      if (!this.sunShouldRun) return;

      this.sunFrameLoading = true;
      try {
        const frame = this.sunFrameIndex;
        this.sunFrameIndex = frame >= this.sunFrameCount ? 1 : frame + 1;

        const frameStr = String(frame).padStart(3, '0');
        const assetId = `sun-${frameStr}`;
        const src = `https://ossxiaoan.4dage.com/hq-eduction-vr/sun/Sun_${frameStr}.png`;

        let texture = this.sunTextureCache && this.sunTextureCache.get(assetId);
        if (!texture) {
          const result = await this.scene.assets.loadAsset({ type: 'texture', assetId, src });
          texture = result && result.value;
          if (texture) {
            if (this.sunTextureCache) this.sunTextureCache.set(assetId, texture);
            if (this.sunTextureQueue) this.sunTextureQueue.push(assetId);
            while (this.sunTextureQueue && this.sunTextureQueue.length > this.sunTextureCacheLimit) {
              const oldAssetId = this.sunTextureQueue.shift();
              if (oldAssetId) {
                this.scene.assets.releaseAsset('texture', oldAssetId);
                if (this.sunTextureCache) this.sunTextureCache.delete(oldAssetId);
              }
            }
          }
        }

        if (texture) {
          for (const mesh of this.sunMeshes) {
            if (mesh && mesh.material && typeof mesh.material.setTexture === 'function') {
              mesh.material.setTexture('u_baseColorMap', texture);
            }
          }
        }
      } catch (e) {
        console.warn('updateSunFrame failed', e);
      } finally {
        this.sunFrameLoading = false;
      }
    },
    resolveTigerMeshesFromBG(gltf) {
      if (!gltf || !this.scene) return [];

      const candidates = this.getTigerNameCandidates();
      const uniqueCandidates = [];
      for (const name of candidates) {
        if (name && !uniqueCandidates.includes(name)) uniqueCandidates.push(name);
      }

      for (const name of uniqueCandidates) {
        if (typeof gltf.getPrimitivesByNodeName === 'function') {
          const meshes = gltf.getPrimitivesByNodeName(name);
          if (meshes && meshes.length) return meshes;
        }
        if (typeof gltf.getPrimitivesByMeshName === 'function') {
          const meshes = gltf.getPrimitivesByMeshName(name);
          if (meshes && meshes.length) return meshes;
        }
      }

      if (typeof gltf.getMeshes === 'function') {
        const meshes = gltf.getMeshes() || [];
        const meshNames = meshes.map(m => m && (m.name || m.el && m.el.name)).filter(Boolean);
        console.warn('tiger mesh not found, available mesh names:', meshNames);
      } else {
        console.warn('tiger mesh not found');
      }
      return [];
    },
    getTigerNameCandidates() {
      const defaultCandidates = ['Tiger', 'tiger', 'TIGER', '老虎', '虎', 'Laohu', 'laohu', 'hu'];
      if (!this.scene) return defaultCandidates;

      const gltfAsset = this.scene.assets && this.scene.assets.getAsset && this.scene.assets.getAsset('gltf', 'bg');
      const jsonRaw = gltfAsset && gltfAsset.jsonRaw;
      if (!jsonRaw) return defaultCandidates;

      const names = [];
      const addIfMatch = (n) => {
        if (!n || typeof n !== 'string') return;
        if (/tiger/i.test(n) || /laohu/i.test(n) || n.includes('虎')) names.push(n);
      };

      if (Array.isArray(jsonRaw.nodes)) {
        for (const node of jsonRaw.nodes) addIfMatch(node && node.name);
      }
      if (Array.isArray(jsonRaw.meshes)) {
        for (const mesh of jsonRaw.meshes) addIfMatch(mesh && mesh.name);
      }

      return names.length ? names.concat(defaultCandidates) : defaultCandidates;
    },
    scheduleTigerStart() {
      if (!this.scene) return;
      if (!this.tigerShouldRun) return;
      if (!this.tigerStartRequested) return;
      if (this.tigerCompleted) return;
      if (this.tigerRotationTimer) return;
      if (!this.tigerMeshes || !this.tigerMeshes.length) return;
      if (this.tigerAppearTimer) return;

      this.tigerAppearTimer = setInterval(() => {
        if (!this.tigerShouldRun || this.tigerCompleted) {
          this.stopTigerAppearWatch();
          return;
        }

        const visibleMeshes = this.getVisibleTigerMeshes();
        if (!visibleMeshes.length) return;

        this.stopTigerAppearWatch();
        this.tigerTargetMeshes = visibleMeshes;
        this.startTigerAudio();
        this.startTigerAnimation();
      }, 100);
    },
    stopTigerAppearWatch() {
      if (!this.tigerAppearTimer) return;
      clearInterval(this.tigerAppearTimer);
      this.tigerAppearTimer = null;
    },
    isTigerVisible() {
      return this.getVisibleTigerMeshes().length > 0;
    },
    getVisibleTigerMeshes() {
      if (!this.tigerMeshes || !this.tigerMeshes.length) return [];
      const visible = [];

      for (const mesh of this.tigerMeshes) {
        const el = mesh && mesh.el;
        if (!el || typeof el.getComponent !== 'function') continue;
        try {
          const transform = el.getComponent('transform');
          const scale = transform && transform.scale;
          if (!scale) continue;

          if (typeof scale === 'string') {
            const parts = scale.split(/\s+/).map(Number);
            const maxV = Math.max(...parts.filter(n => Number.isFinite(n)));
            if (Number.isFinite(maxV) && maxV > 0.001) visible.push(mesh);
            continue;
          }

          if (typeof scale === 'object') {
            const sx = typeof scale.x === 'number' ? scale.x : undefined;
            const sy = typeof scale.y === 'number' ? scale.y : undefined;
            const sz = typeof scale.z === 'number' ? scale.z : undefined;
            const maxV = Math.max(sx || 0, sy || 0, sz || 0);
            if (maxV > 0.001) visible.push(mesh);
          }
        } catch (e) {
        }
      }

      return visible;
    },
    startTigerAnimation() {
      if (!this.scene) return;
      if (!this.tigerShouldRun) return;
      if (!this.tigerMeshes || !this.tigerMeshes.length) return;
      if (this.tigerCompleted) return;
      if (this.tigerRotationTimer) return;

      this.tigerFrameStart = 1;
      this.tigerFrameEnd = 460;
      this.tigerFrameCount = 460;
      const skipFrames = 29;
      this.tigerPlayedFrames = Math.min(skipFrames, this.tigerFrameCount);
      this.tigerTextureCacheLimit = 48;
      if (!this.tigerTextureCache) this.tigerTextureCache = new Map();
      if (!this.tigerTextureQueue) this.tigerTextureQueue = [];
      this.prepareTigerFrames();

      this.updateTigerFrame();
      const intervalMs = this.getTigerFrameIntervalMs();
      this.tigerRotationTimer = setInterval(() => this.updateTigerFrame(), intervalMs);
    },
    getTigerFrameIntervalMs() {
      const durationMs = Number.isFinite(this.tigerAudioDurationMs) && this.tigerAudioDurationMs > 0
        ? this.tigerAudioDurationMs
        : 46000;
      const frameCount = typeof this.tigerFrameCount === 'number' && this.tigerFrameCount > 0 ? this.tigerFrameCount : 460;
      const raw = Math.round(durationMs / frameCount);
      return Math.min(500, Math.max(16, raw));
    },
    stopTiger() {
      this.stopTigerAppearWatch();
      if (this.tigerRotationTimer) {
        clearInterval(this.tigerRotationTimer);
        this.tigerRotationTimer = null;
      }
      this.tigerFrameLoading = false;
      this.tigerTargetMeshes = null;
      if (this.scene && this.scene.assets && this.scene.assets.releaseAsset && this.tigerTextureQueue) {
        for (const assetId of this.tigerTextureQueue) {
          if (assetId === this.tigerLastAssetId) continue;
          this.scene.assets.releaseAsset('texture', assetId);
        }
      }
      this.tigerTextureCache = null;
      this.tigerTextureQueue = null;
      this.stopTigerAudio();
      this.stopTigerFramesPreload();
    },
    prepareTigerFrames() {
      if (this.tigerFramesPrepared || this.tigerFramesPreparing) return;
      this.tigerFramesPreparing = true;
      this.tigerFramesAbort = false;

      if (!this.tigerFrameTempPaths) this.tigerFrameTempPaths = Object.create(null);
      if (!this.tigerFrameDownloadTasks) this.tigerFrameDownloadTasks = Object.create(null);

      const startNo = 39;
      const endNo = 460;
      const maxConcurrent = 6;
      let nextNo = startNo;
      let inFlight = 0;

      const pump = () => {
        if (this.tigerFramesAbort) return;

        while (inFlight < maxConcurrent && nextNo <= endNo && !this.tigerFramesAbort) {
          const frameNo = nextNo++;
          const frameStr = String(frameNo).padStart(3, '0');
          const assetId = `tigerx-${frameStr}`;
          if (this.tigerFrameTempPaths[assetId]) continue;

          inFlight += 1;
          const task = wx.downloadFile({
            url: `https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/Tigerx_${frameStr}.png`,
            success: (res) => {
              if (this.tigerFramesAbort) return;
              const tempPath = res && res.statusCode === 200 ? res.tempFilePath : '';
              if (tempPath) this.tigerFrameTempPaths[assetId] = tempPath;
            },
            complete: () => {
              inFlight -= 1;
              if (this.tigerFrameDownloadTasks) delete this.tigerFrameDownloadTasks[assetId];
              if (nextNo > endNo && inFlight <= 0) {
                this.tigerFramesPrepared = true;
                this.tigerFramesPreparing = false;
                return;
              }
              pump();
            }
          });
          if (task && typeof task.abort === 'function') this.tigerFrameDownloadTasks[assetId] = task;
        }
      };

      pump();
    },
    stopTigerFramesPreload() {
      this.tigerFramesAbort = true;
      this.tigerFramesPrepared = false;
      this.tigerFramesPreparing = false;
      if (this.tigerFrameDownloadTasks) {
        for (const k of Object.keys(this.tigerFrameDownloadTasks)) {
          const task = this.tigerFrameDownloadTasks[k];
          if (task && typeof task.abort === 'function') {
            try {
              task.abort();
            } catch (e) {
            }
          }
        }
      }
      this.tigerFrameDownloadTasks = null;
      this.tigerFrameTempPaths = null;
    },
    async updateTigerFrame() {
      if (this.tigerFrameLoading) return;
      if (!this.scene || !this.tigerMeshes || !this.tigerMeshes.length) return;
      if (!this.tigerShouldRun) return;
      if (this.tigerCompleted) return;

      this.tigerFrameLoading = true;
      try {
        const frameCount = typeof this.tigerFrameCount === 'number' && this.tigerFrameCount > 0 ? this.tigerFrameCount : 460;
        const durationMs = Number.isFinite(this.tigerAudioDurationMs) && this.tigerAudioDurationMs > 0
          ? this.tigerAudioDurationMs
          : 46000;

        const played = this.tigerPlayedFrames || 0;
        let desiredPlayed = played + 1;

        const audioCtx = this.tigerAudioCtx;
        if (audioCtx && this.tigerAudioStarted) {
          const currentTime = Number(audioCtx.currentTime);
          if (Number.isFinite(currentTime) && currentTime >= 0) {
            const p = Math.floor((currentTime * 1000 / durationMs) * frameCount) + 1;
            desiredPlayed = Math.max(desiredPlayed, p);
          }
        }

        if (desiredPlayed <= played) return;
        if (desiredPlayed >= frameCount) desiredPlayed = frameCount;

        if (played >= frameCount) {
          this.completeTigerAnimation();
          return;
        }

        const start = typeof this.tigerFrameStart === 'number' ? this.tigerFrameStart : 1;
        const end = typeof this.tigerFrameEnd === 'number' ? this.tigerFrameEnd : frameCount;
        const rangeLen = Math.max(1, end - start + 1);
        const frameNo = start + ((desiredPlayed - 1) % rangeLen);
        this.tigerPlayedFrames = desiredPlayed;

        const frameStr = String(frameNo).padStart(3, '0');
        const assetId = `tigerx-${frameStr}`;
        const localSrc = this.tigerFrameTempPaths && this.tigerFrameTempPaths[assetId];
        const src = localSrc || `https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/Tigerx_${frameStr}.png`;

        let texture = this.tigerTextureCache && this.tigerTextureCache.get(assetId);
        if (!texture) {
          const result = await this.scene.assets.loadAsset({ type: 'texture', assetId, src });
          texture = result && result.value;
          if (texture) {
            if (this.tigerTextureCache) this.tigerTextureCache.set(assetId, texture);
            if (this.tigerTextureQueue) this.tigerTextureQueue.push(assetId);
            while (this.tigerTextureQueue && this.tigerTextureQueue.length > this.tigerTextureCacheLimit) {
              const oldAssetId = this.tigerTextureQueue.shift();
              if (oldAssetId) {
                this.scene.assets.releaseAsset('texture', oldAssetId);
                if (this.tigerTextureCache) this.tigerTextureCache.delete(oldAssetId);
              }
            }
          }
        }

        if (texture) {
          this.tigerLastAssetId = assetId;
          const targets = (this.tigerTargetMeshes && this.tigerTargetMeshes.length) ? this.tigerTargetMeshes : this.tigerMeshes;
          for (const mesh of targets) {
            if (mesh && mesh.material && typeof mesh.material.setTexture === 'function') {
              mesh.material.setTexture('u_baseColorMap', texture);
            }
          }
        }

        if (this.tigerPlayedFrames >= this.tigerFrameCount) {
          this.completeTigerAnimation();
        }
      } catch (e) {
        console.warn('updateTigerFrame failed', e);
      } finally {
        this.tigerFrameLoading = false;
      }
    },
    completeTigerAnimation() {
      if (this.tigerRotationTimer) {
        clearInterval(this.tigerRotationTimer);
        this.tigerRotationTimer = null;
      }
      this.tigerCompleted = true;
    },
    prepareTigerAudio() {
      if (this.tigerAudioCtx || this.tigerAudioPreparing) return;
      const url = 'https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/tiger.mp3';

      this.tigerAudioPrepared = false;
      this.tigerAudioStartPending = !!this.tigerAudioStartPending;
      this.tigerAudioStarted = false;
      this.tigerAudioPreparing = true;

      const createAudioCtx = (src) => {
        const audioCtx = wx.createInnerAudioContext();
        audioCtx.src = src;
        audioCtx.loop = false;
        audioCtx.volume = 0;

        audioCtx.onCanplay(() => {
          if (this.tigerAudioPrepared) return;
          this.tigerAudioPrepared = true;
          if (this.tigerAudioStarted) return;

          const updateDuration = () => {
            if (!this.tigerAudioCtx) return;
            const d = Number(audioCtx.duration);
            if (Number.isFinite(d) && d > 0) this.tigerAudioDurationMs = Math.round(d * 1000);
          };
          updateDuration();
          setTimeout(updateDuration, 300);

          try {
            audioCtx.volume = 0;
          } catch (e) {
          }
          try {
            audioCtx.play();
          } catch (e) {
          }
          setTimeout(() => {
            if (!this.tigerAudioCtx) return;
            if (this.tigerAudioStarted) return;
            try {
              audioCtx.pause();
            } catch (e) {
            }
            try {
              if (Number(audioCtx.currentTime) > 0.1) audioCtx.seek(0);
            } catch (e) {
            }
            if (this.tigerAudioStartPending) this.startTigerAudio();
          }, 200);
        });

        audioCtx.onEnded(() => {
          this.stopTigerAudio();
          this.completeTigerAnimation();
        });

        this.tigerAudioCtx = audioCtx;
        this.tigerAudioPreparing = false;

        try {
          audioCtx.play();
        } catch (e) {
        }
      };

      if (this.tigerAudioTempPath) {
        createAudioCtx(this.tigerAudioTempPath);
        return;
      }

      wx.downloadFile({
        url,
        success: (res) => {
          const tempPath = res && res.statusCode === 200 ? res.tempFilePath : '';
          if (tempPath) this.tigerAudioTempPath = tempPath;
          createAudioCtx(tempPath || url);
        },
        fail: () => {
          createAudioCtx(url);
        }
      });
    },
    startTigerAudio() {
      if (this.tigerAudioStarted) return;

      if (!this.tigerAudioCtx) {
        this.tigerAudioStartPending = true;
        this.prepareTigerAudio();
      }
      if (!this.tigerAudioCtx) return;
      if (this.tigerAudioStarted) return;

      const audioCtx = this.tigerAudioCtx;
      const requestedOffsetSec = typeof this.tigerAudioStartOffsetSec === 'number' ? this.tigerAudioStartOffsetSec : 2;
      const startOffsetSec = Math.max(0, Math.min(3, requestedOffsetSec));
      const startNow = () => {
        if (!this.tigerAudioCtx) return;
        if (this.tigerAudioStarted) return;
        try {
          audioCtx.volume = 1;
        } catch (e) {
        }
        try {
          const t = Number(audioCtx.currentTime);
          if (startOffsetSec > 0) {
            if (!Number.isFinite(t) || Math.abs(t - startOffsetSec) > 0.2) audioCtx.seek(startOffsetSec);
          } else {
            if (Number.isFinite(t) && t > 0.1) audioCtx.seek(0);
          }
        } catch (e) {
        }
        try {
          audioCtx.play();
          this.tigerAudioStarted = true;
        } catch (e) {
          this.tigerAudioStarted = false;
        }
      };

      if (this.tigerAudioPrepared) {
        this.tigerAudioStartPending = false;
        startNow();
        return;
      }

      this.tigerAudioStartPending = true;
      startNow();
    },
    stopTigerAudio() {
      if (!this.tigerAudioCtx) return;
      this.tigerAudioCtx.stop();
      this.tigerAudioCtx.destroy();
      this.tigerAudioCtx = null;
      this.tigerAudioPrepared = false;
      this.tigerAudioStartPending = false;
      this.tigerAudioStarted = false;
      this.tigerAudioPreparing = false;
      this.tigerAudioDurationMs = null;
    },
    playitem1Action() {
      if (!this.animator1 || !this.animator2) return;

      console.log('start animator1');
      this.animator1.play('All Animations', {
        loop: 0
      });

      setTimeout(() => {
        console.log('start animator2');
        this.animator2.pause();

          const duration = 1500;
          const startTime = Date.now();
          const startScale = 0;
          const endScale = 0.38;
          const startPX = -0.1
          const endPX = 0
          const startPY = -0.5
          const endPY = 0
          const startPZ = -0.05
          const endPZ = 0

          const step = () => {
            const now = Date.now();
            let t = (now - startTime) / duration;
            if (t > 1) t = 1;

            const s = startScale + (endScale - startScale) * t;
            const scaleStr = `${s} ${s} ${s}`;
            const p = `${startPX + (endPX - startPX) * t} ${startPY + (endPY - startPY) * t} ${startPZ + (endPZ - startPZ) * t}`;

            if (t >= 0.5 && !this.isStartPlay2) {
              this.isStartPlay2 = true;
              this.animator2.play('All Animations', {
                loop: 0
              });
            }

            this.setData({
              adlScale: scaleStr,
              adlPos: p
            });

            if (t < 1) {
              setTimeout(step, 16); // 60fps
            } else {
              const audioUrl = 'https://houseoss.4dkankan.com/project/hq-eduction-vr/public/%E5%AE%89%E5%BE%B7%E7%83%88.mp3';
              if (!this.audioCtx) {
                const audioCtx = wx.createInnerAudioContext();
                audioCtx.src = audioUrl;
                audioCtx.play();
                audioCtx.onEnded(() => {
                  const hideDuration = 1000;
                  const hideStartTime = Date.now();
                  const startScaleHide = 0.38;
                  const endScaleHide = 0;

                  const hideStep = () => {
                    const now = Date.now();
                    let t = (now - hideStartTime) / hideDuration;
                    if (t > 1) t = 1;

                    const s = startScaleHide + (endScaleHide - startScaleHide) * t;
                    const scaleStr = `${s} ${s} ${s}`;
                    this.setData({
                      adlScale: scaleStr
                    });

                    if (t < 1) {
                      setTimeout(hideStep, 16);
                    } else {
                      this.animator2 = null;
                      if (this.audioCtx) {
                        this.audioCtx.destroy();
                        this.audioCtx = null;
                      }
                      this.tigerStartRequested = true;
                      this.scheduleTigerStart();
                    }
                  };

                  hideStep();
                });
              }
            }
          };

          this.setData({
            adlScale: '0 0 0'
          });
          step();
      }, 1500);
    }
  }
})
