From 8d8857283460367cca686ae3c07d3dc93275d13b Mon Sep 17 00:00:00 2001 From: Mahiru Date: Tue, 24 Dec 2024 21:49:33 +0800 Subject: [PATCH] remove spine package --- packages/webgal/package.json | 1 - .../src/Core/controller/stage/pixi/spine.ts | 186 ++++++++++++------ yarn.lock | 56 ------ 3 files changed, 125 insertions(+), 118 deletions(-) diff --git a/packages/webgal/package.json b/packages/webgal/package.json index 12db98225..532b815a2 100644 --- a/packages/webgal/package.json +++ b/packages/webgal/package.json @@ -22,7 +22,6 @@ "modern-css-reset": "^1.4.0", "pixi-filters": "^4.2.0", "pixi-live2d-display-webgal": "^0.5.8", - "pixi-spine": "^3.1.2", "pixi.js": "^6.3.0", "popmotion": "^11.0.5", "react": "^17.0.2", diff --git a/packages/webgal/src/Core/controller/stage/pixi/spine.ts b/packages/webgal/src/Core/controller/stage/pixi/spine.ts index 3ffe12f98..f93ab4790 100644 --- a/packages/webgal/src/Core/controller/stage/pixi/spine.ts +++ b/packages/webgal/src/Core/controller/stage/pixi/spine.ts @@ -1,21 +1,64 @@ +// spineHandlers.ts import { WebGALPixiContainer } from '@/Core/controller/stage/pixi/WebGALPixiContainer'; import { v4 as uuid } from 'uuid'; -import 'pixi-spine'; // Do this once at the very start of your code. This registers the loader! -import { Spine } from 'pixi-spine'; import * as PIXI from 'pixi.js'; import PixiStage from '@/Core/controller/stage/pixi/PixiController'; import { logger } from '@/Core/util/logger'; +// utils/loadPixiSpine.ts +// @ts-ignore +let pixiSpineModule: typeof import('pixi-spine') | null = null; +// @ts-ignore +let pixiSpineLoading: Promise | null = null; +let spineLoader: undefined | PIXI.Loader; + +/** + * 动态加载 'pixi-spine' 模块,并缓存结果 + * @returns {Promise} + */ +// @ts-ignore +export async function loadPixiSpine(): Promise { + if (pixiSpineModule) { + return pixiSpineModule; + } + + if (pixiSpineLoading) { + return pixiSpineLoading; + } + + // @ts-ignore + // pixiSpineLoading = import('pixi-spine') + // .then((module) => { + // spineLoader = new PIXI.Loader(); + // pixiSpineModule = module; + // return module; + // }) + // .catch((error) => { + // console.error('Failed to load pixi-spine. Spine features will be disabled.', error); + // return null; + // }) + // .finally(() => { + // pixiSpineLoading = null; + // }); + + return pixiSpineLoading; +} + +/** + * 添加 Spine 立绘的实现函数 + * @param key 立绘的标识 + * @param url Spine 数据的 URL + * @param presetPosition 预设位置 + */ // eslint-disable-next-line max-params -export function addSpineFigureImpl( +export async function addSpineFigureImpl( this: PixiStage, key: string, url: string, presetPosition: 'left' | 'center' | 'right' = 'center', ) { - console.log(key, url, presetPosition); const spineId = `spine-${url}`; - const loader = this.assetLoader; + const pixiSpine = await loadPixiSpine(); // 准备用于存放这个立绘的 Container const thisFigureContainer = new WebGALPixiContainer(); @@ -42,73 +85,84 @@ export function addSpineFigureImpl( key: key, pixiContainer: thisFigureContainer, sourceUrl: url, - sourceType: 'live2d', + sourceType: 'spine', // 修改为 'spine' sourceExt: this.getExtName(url), }); // 完成图片加载后执行的函数 - const setup = () => { - const spineResource: any = this.assetLoader.resources?.[spineId]; - // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常! - setTimeout(() => { - if (spineResource && this.getStageObjByUuid(figureUuid)) { - const figureSpine = new Spine(spineResource.spineData); - const spineBounds = figureSpine.getLocalBounds(); - const spineCenterX = spineBounds.x + spineBounds.width / 2; - const spineCenterY = spineBounds.y + spineBounds.height / 2; - figureSpine.pivot.set(spineCenterX, spineCenterY); - // TODO: set animation 还没做 - // figureSpine.state.setAnimation() - /** - * 重设大小 - */ - const originalWidth = figureSpine.width; - const originalHeight = figureSpine.height; - const scaleX = this.stageWidth / originalWidth; - const scaleY = this.stageHeight / originalHeight; - const targetScale = Math.min(scaleX, scaleY); - const figureSprite = new PIXI.Sprite(); - figureSprite.addChild(figureSpine); - figureSprite.scale.x = targetScale; - figureSprite.scale.y = targetScale; - figureSprite.anchor.set(0.5); - figureSprite.position.y = this.stageHeight / 2; - const targetWidth = originalWidth * targetScale; - const targetHeight = originalHeight * targetScale; - thisFigureContainer.setBaseY(this.stageHeight / 2); - if (targetHeight < this.stageHeight) { - thisFigureContainer.setBaseY(this.stageHeight / 2 + this.stageHeight - targetHeight / 2); - } - if (presetPosition === 'center') { - thisFigureContainer.setBaseX(this.stageWidth / 2); - } - if (presetPosition === 'left') { - thisFigureContainer.setBaseX(targetWidth / 2); - } - if (presetPosition === 'right') { - thisFigureContainer.setBaseX(this.stageWidth - targetWidth / 2); - } - thisFigureContainer.pivot.set(0, this.stageHeight / 2); - thisFigureContainer.addChild(figureSprite); + const setup = async () => { + if (!pixiSpine) { + // 无法加载 'pixi-spine',跳过 Spine 相关逻辑 + logger.warn(`Spine module not loaded. Skipping Spine figure: ${key}`); + return; + } + + const { Spine } = pixiSpine; + const spineResource: any = spineLoader!.resources?.[spineId]; + if (spineResource && this.getStageObjByUuid(figureUuid)) { + const figureSpine = new Spine(spineResource.spineData); + const spineBounds = figureSpine.getLocalBounds(); + const spineCenterX = spineBounds.x + spineBounds.width / 2; + const spineCenterY = spineBounds.y + spineBounds.height / 2; + figureSpine.pivot.set(spineCenterX, spineCenterY); + // TODO: set animation 还没做 + // figureSpine.state.setAnimation(0, figureSpine.spineData.animations[0].name, true) + + /** + * 重设大小 + */ + const originalWidth = figureSpine.width; + const originalHeight = figureSpine.height; + const scaleX = this.stageWidth / originalWidth; + const scaleY = this.stageHeight / originalHeight; + const targetScale = Math.min(scaleX, scaleY); + const figureSprite = new PIXI.Sprite(); + figureSprite.addChild(figureSpine); + figureSprite.scale.x = targetScale; + figureSprite.scale.y = targetScale; + figureSprite.anchor.set(0.5); + figureSprite.position.y = this.stageHeight / 2; + const targetWidth = originalWidth * targetScale; + const targetHeight = originalHeight * targetScale; + thisFigureContainer.setBaseY(this.stageHeight / 2); + if (targetHeight < this.stageHeight) { + thisFigureContainer.setBaseY(this.stageHeight / 2 + this.stageHeight - targetHeight / 2); } - }, 0); + if (presetPosition === 'center') { + thisFigureContainer.setBaseX(this.stageWidth / 2); + } + if (presetPosition === 'left') { + thisFigureContainer.setBaseX(targetWidth / 2); + } + if (presetPosition === 'right') { + thisFigureContainer.setBaseX(this.stageWidth - targetWidth / 2); + } + thisFigureContainer.pivot.set(0, this.stageHeight / 2); + thisFigureContainer.addChild(figureSprite); + } }; /** * 加载器部分 + * 这里不再使用 this.loadAsset,因为我们可能需要单独管理 Spine 资源 + * 但为了避免性能问题,我们继续使用现有的 loader,并确保资源只加载一次 */ this.cacheGC(); - if (!loader.resources?.[url]) { - this.loadAsset(url, setup, spineId); + if (!spineLoader!.resources?.[spineId]) { + spineLoader!.add(spineId, url).load(setup); } else { // 复用 - setup(); + await setup(); } } -export function addSpineBgImpl(this: PixiStage, key: string, url: string) { +/** + * 添加 Spine 背景的实现函数 + * @param key 背景的标识 + * @param url Spine 数据的 URL + */ +export async function addSpineBgImpl(this: PixiStage, key: string, url: string) { const spineId = `spine-${url}`; - const loader = this.assetLoader; // 准备用于存放这个背景的 Container const thisBgContainer = new WebGALPixiContainer(); @@ -130,13 +184,21 @@ export function addSpineBgImpl(this: PixiStage, key: string, url: string) { key: key, pixiContainer: thisBgContainer, sourceUrl: url, - sourceType: 'live2d', + sourceType: 'spine', // 修改为 'spine' sourceExt: this.getExtName(url), }); // 完成图片加载后执行的函数 - const setup = () => { - const spineResource: any = this.assetLoader.resources?.[spineId]; + const setup = async () => { + const pixiSpine = await loadPixiSpine(); + if (!pixiSpine) { + // 无法加载 'pixi-spine',跳过 Spine 相关逻辑 + logger.warn(`Spine module not loaded. Skipping Spine background: ${key}`); + return; + } + + const { Spine } = pixiSpine; + const spineResource: any = spineLoader!.resources?.[spineId]; // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常! setTimeout(() => { if (spineResource && this.getStageObjByUuid(bgUuid)) { @@ -174,12 +236,14 @@ export function addSpineBgImpl(this: PixiStage, key: string, url: string) { /** * 加载器部分 + * 这里不再使用 this.loadAsset,因为我们可能需要单独管理 Spine 资源 + * 但为了避免性能问题,我们继续使用现有的 loader,并确保资源只加载一次 */ this.cacheGC(); - if (!loader.resources?.[url]) { - this.loadAsset(url, setup, spineId); + if (!spineLoader!.resources?.[spineId]) { + spineLoader!.add(spineId, url).load(setup); } else { // 复用 - setup(); + await setup(); } } diff --git a/yarn.lock b/yarn.lock index 4370c5416..5d84e341e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -603,50 +603,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pixi-spine/base@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/base/-/base-3.1.2.tgz#0bf9ec7a1367d8d8474004f0784d990300328310" - integrity sha512-sMOZsCJQW4O11QR7afuHcuu8cSUgJv3paSNzZOh+imxvYB/cOcyG7K+f5sWqlGe+z3J2CLEYCX2WfXeeJi6pHg== - -"@pixi-spine/loader-base@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/loader-base/-/loader-base-3.1.2.tgz#b208f14f2cd4b29ff575fc5a32c4f5328e6008f1" - integrity sha512-llg0RuuWiqVkyoQA+ceORV0sfUtrWGJj4jQ6erDFn2hMnob+QGzh+qwHSTMAnTNZTINEMfiUxmcwbmUYwTd8Ag== - dependencies: - "@pixi-spine/base" "~3.1.2" - -"@pixi-spine/loader-uni@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/loader-uni/-/loader-uni-3.1.2.tgz#3671675dba01d655f5c207b10723823313e09d00" - integrity sha512-5th9gXqNQWMSuOu3euMw2kHETlncxU7LIFvOYqTMsKnwrOAIsPjHSF/4Sat1d3EAvvdMrYm4LmhHklgrAfk6UA== - dependencies: - "@pixi-spine/base" "~3.1.2" - "@pixi-spine/loader-base" "~3.1.2" - "@pixi-spine/runtime-3.7" "~3.1.2" - "@pixi-spine/runtime-3.8" "~3.1.2" - "@pixi-spine/runtime-4.1" "~3.1.2" - -"@pixi-spine/runtime-3.7@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/runtime-3.7/-/runtime-3.7-3.1.2.tgz#909ee4b906fe3e1faf8df996025d29c05f2c68b4" - integrity sha512-dMcw5x9jG+0itzzbPsJUn8hvhxzRXRzbm/kCUQ51iyFfLZQIK1LoPck4XPVuXckwFjU1qCT+tDZSEGBMYs5//A== - dependencies: - "@pixi-spine/base" "~3.1.2" - -"@pixi-spine/runtime-3.8@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/runtime-3.8/-/runtime-3.8-3.1.2.tgz#be0fe73ce75384d3815a729c826b09c43a9c3db4" - integrity sha512-AgS3mUC+5HQ/ehJO5Wo4oBoLg8F+tssF5WXi3FnnjqOaMcO+Ag232ForoL2iYHW40TKx0xMi5MpXsSafgS1i1A== - dependencies: - "@pixi-spine/base" "~3.1.2" - -"@pixi-spine/runtime-4.1@~3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@pixi-spine/runtime-4.1/-/runtime-4.1-3.1.2.tgz#43aa99b71dca01a962db7dee04a38e2fe167d33e" - integrity sha512-XtaKAuLTtJ3o3llcUTr0d94dnRTyYHlss+x4VsYm1H38r4DUmQTBS13nisW0pgS3fY60D8AbEJkYVW7mwokxag== - dependencies: - "@pixi-spine/base" "~3.1.2" - "@pixi/accessibility@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@pixi/accessibility/-/accessibility-6.5.10.tgz#53727df881251ad0db545de93f8b273c5b34ff67" @@ -4281,18 +4237,6 @@ pixi-live2d-display-webgal@^0.5.8: dependencies: gh-pages "^4.0.0" -pixi-spine@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pixi-spine/-/pixi-spine-3.1.2.tgz#f63c5c566c2e74eae3e0c99da172f67404227398" - integrity sha512-rTTwXhBl5gZFZ793zdM/to0bifU8K4aa1gD0ilOiCqC/pgw5OxCcKnoRW3i05ythjzI3GlN6G0MDblOe2myr3w== - dependencies: - "@pixi-spine/base" "~3.1.2" - "@pixi-spine/loader-base" "~3.1.2" - "@pixi-spine/loader-uni" "~3.1.2" - "@pixi-spine/runtime-3.7" "~3.1.2" - "@pixi-spine/runtime-3.8" "~3.1.2" - "@pixi-spine/runtime-4.1" "~3.1.2" - pixi.js@^6.3.0: version "6.5.10" resolved "https://registry.yarnpkg.com/pixi.js/-/pixi.js-6.5.10.tgz#a82638e0b7afc5bf7f3ab70d960521477276e866"