[ts][pixi-v8] Implemented canvas rendering (no support for slot objects). Pixi min version 8.16. See #3023.

This commit is contained in:
Davide Tantillo 2026-02-18 12:14:37 +01:00
parent e8231db647
commit afa4b71b45
5 changed files with 71 additions and 18 deletions

View File

@ -1022,7 +1022,9 @@
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/@xmldom/xmldom": { "node_modules/@xmldom/xmldom": {
"version": "0.8.10", "version": "0.8.11",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz",
"integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"engines": { "engines": {
@ -2410,22 +2412,22 @@
} }
}, },
"node_modules/pixi.js": { "node_modules/pixi.js": {
"version": "8.12.0", "version": "8.16.0",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.12.0.tgz", "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.16.0.tgz",
"integrity": "sha512-or7vrH7WajLevu/JnGMdD80JaSpTlXfjwCLtzhg2BL60LWPf1pF0w08Qleiqr1Saj012gevguM//+6HzzVlnfA==", "integrity": "sha512-gu2xw3sZGAn3cWBtk0HqTQT+v19YAfiaYXwUGgWoJl5NKz4cEZJUgWrwkmdfDszGyYBAGqOvJNbd2M9+vzLLMg==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@pixi/colord": "^2.9.6", "@pixi/colord": "^2.9.6",
"@types/css-font-loading-module": "^0.0.12",
"@types/earcut": "^3.0.0", "@types/earcut": "^3.0.0",
"@webgpu/types": "^0.1.40", "@webgpu/types": "^0.1.69",
"@xmldom/xmldom": "^0.8.10", "@xmldom/xmldom": "^0.8.11",
"earcut": "^3.0.2", "earcut": "^3.0.2",
"eventemitter3": "^5.0.1", "eventemitter3": "^5.0.1",
"gifuct-js": "^2.1.2", "gifuct-js": "^2.1.2",
"ismobilejs": "^1.1.1", "ismobilejs": "^1.1.1",
"parse-svg-path": "^0.1.2" "parse-svg-path": "^0.1.2",
"tiny-lru": "^11.4.7"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -2440,7 +2442,9 @@
"peer": true "peer": true
}, },
"node_modules/pixi.js/node_modules/@webgpu/types": { "node_modules/pixi.js/node_modules/@webgpu/types": {
"version": "0.1.60", "version": "0.1.69",
"resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz",
"integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"peer": true "peer": true
}, },
@ -2955,6 +2959,16 @@
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
} }
}, },
"node_modules/tiny-lru": {
"version": "11.4.7",
"resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.4.7.tgz",
"integrity": "sha512-w/Te7uMUVeH0CR8vZIjr+XiN41V+30lkDdK+NRIDCUYKKuL9VcmaUEmaPISuwGhLlrTGh5yu18lENtR9axSxYw==",
"license": "BSD-3-Clause",
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/toidentifier": { "node_modules/toidentifier": {
"version": "1.0.1", "version": "1.0.1",
"dev": true, "dev": true,
@ -3287,10 +3301,10 @@
"version": "4.2.82", "version": "4.2.82",
"license": "LicenseRef-LICENSE", "license": "LicenseRef-LICENSE",
"dependencies": { "dependencies": {
"@esotericsoftware/spine-core": "4.2.82" "@esotericsoftware/spine-canvas": "4.2.82"
}, },
"peerDependencies": { "peerDependencies": {
"pixi.js": "^8.12.0" "pixi.js": "^8.16.0"
} }
}, },
"spine-player": { "spine-player": {

View File

@ -31,9 +31,9 @@
}, },
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
"dependencies": { "dependencies": {
"@esotericsoftware/spine-core": "4.2.82" "@esotericsoftware/spine-canvas": "4.2.82"
}, },
"peerDependencies": { "peerDependencies": {
"pixi.js": "^8.12.0" "pixi.js": "^8.16.0"
} }
} }

View File

@ -785,7 +785,7 @@ export class Spine extends ViewContainer {
container.visible = this.skeleton.drawOrder.includes(slot) && followAttachmentValue; container.visible = this.skeleton.drawOrder.includes(slot) && followAttachmentValue;
if (container.visible) { if (container.visible) {
let applied = slot.bone.applied; const applied = slot.bone.applied;
const matrix = container.localTransform; const matrix = container.localTransform;
matrix.a = applied.a; matrix.a = applied.a;

View File

@ -27,13 +27,15 @@
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
import { MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-core'; import { SkeletonRenderer as CanvasSkeletonRenderer, MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-canvas';
import { import {
type BLEND_MODES, type BLEND_MODES,
type CanvasRenderer,
type Container, ExtensionType, type Container, ExtensionType,
extensions, extensions,
type InstructionSet, type InstructionSet,
type Renderer, type Renderer,
RendererType,
type RenderPipe, type RenderPipe,
} from 'pixi.js'; } from 'pixi.js';
import { BatchableSpineSlot } from './BatchableSpineSlot.js'; import { BatchableSpineSlot } from './BatchableSpineSlot.js';
@ -61,6 +63,7 @@ export class SpinePipe implements RenderPipe<Spine> {
} as const; } as const;
renderer: Renderer; renderer: Renderer;
private canvasSkeletonRenderer!: CanvasSkeletonRenderer;
private gpuSpineData: Record<string, GpuSpineDataElement> = {}; private gpuSpineData: Record<string, GpuSpineDataElement> = {};
private readonly _destroyRenderableBound = this.destroyRenderable.bind(this) as (renderable: Container) => void; private readonly _destroyRenderableBound = this.destroyRenderable.bind(this) as (renderable: Container) => void;
@ -70,6 +73,10 @@ export class SpinePipe implements RenderPipe<Spine> {
} }
validateRenderable (spine: Spine): boolean { validateRenderable (spine: Spine): boolean {
if (this.renderer.type === RendererType.CANVAS) {
return true;
}
spine._validateAndTransformAttachments(); spine._validateAndTransformAttachments();
// if spine attachments have changed or destroyed, we need to rebuild the batch! // if spine attachments have changed or destroyed, we need to rebuild the batch!
@ -105,7 +112,38 @@ export class SpinePipe implements RenderPipe<Spine> {
return false; return false;
} }
execute (spine: Spine) {
if (this.renderer.type === RendererType.CANVAS) {
const renderer = this.renderer as CanvasRenderer;
const groupAlpha = ((spine.groupColorAlpha >>> 24) & 0xFF) / 255;
const contextSystem = renderer.canvasContext;
const context = contextSystem.activeContext;
context.save();
if (!this.canvasSkeletonRenderer) {
this.canvasSkeletonRenderer = new CanvasSkeletonRenderer(context as unknown as CanvasRenderingContext2D);
this.canvasSkeletonRenderer.triangleRendering = true;
}
contextSystem.setContextTransform(spine.groupTransform, (renderer._roundPixels | spine._roundPixels) === 1);
const oldAlpha = spine.skeleton.color.a;
spine.skeleton.color.a *= groupAlpha;
this.canvasSkeletonRenderer.draw(spine.skeleton);
spine.skeleton.color.a = oldAlpha;
context.restore();
}
}
addRenderable (spine: Spine, instructionSet: InstructionSet) { addRenderable (spine: Spine, instructionSet: InstructionSet) {
if (this.renderer.type === RendererType.CANVAS) {
this.renderer.renderPipes.batch.break(instructionSet);
instructionSet.add(spine);
return;
}
const gpuSpine = this._getSpineData(spine); const gpuSpine = this._getSpineData(spine);
const batcher = this.renderer.renderPipes.batch; const batcher = this.renderer.renderPipes.batch;
@ -193,6 +231,7 @@ export class SpinePipe implements RenderPipe<Spine> {
destroy () { destroy () {
(this.gpuSpineData as unknown) = null; (this.gpuSpineData as unknown) = null;
(this.renderer as unknown) = null; (this.renderer as unknown) = null;
(this.canvasSkeletonRenderer as unknown) = null;
} }
private _getSpineData (spine: Spine): GpuSpineDataElement { private _getSpineData (spine: Spine): GpuSpineDataElement {

View File

@ -5,8 +5,8 @@
"rootDir": "./src", "rootDir": "./src",
"outDir": "./dist", "outDir": "./dist",
"paths": { "paths": {
"@esotericsoftware/spine-core": [ "@esotericsoftware/spine-canvas": [
"../spine-core/src" "../spine-canvas/src"
] ]
} }
}, },
@ -19,7 +19,7 @@
], ],
"references": [ "references": [
{ {
"path": "../spine-core" "path": "../spine-canvas"
} }
] ]
} }