mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
Merge branch '4.1' into 4.2-beta
# Conflicts: # spine-ts/package-lock.json # spine-ts/package.json # spine-ts/publish.sh # spine-ts/spine-canvas/package.json # spine-ts/spine-core/package.json # spine-ts/spine-phaser/package.json # spine-ts/spine-player/package.json # spine-ts/spine-threejs/package.json # spine-ts/spine-webgl/package.json
This commit is contained in:
commit
db6f624bc6
@ -207,6 +207,9 @@
|
||||
* `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument.
|
||||
* Removed `PlayerEditor`.
|
||||
* `VertexEffect` has been removed.
|
||||
* Removed `RegionAttachment.rendererObject`.
|
||||
* Renamed `TextureRegion.renderObject` to `TextureRegion.texture`.
|
||||
|
||||
|
||||
### WebGL backend
|
||||
* `PolygonBatcher` can now disable culling automatically if the static variable `PolygonBatcher.disableCulling` is set to true.
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
<li><a href="/spine-webgl/example">Example</a></li>
|
||||
<li><a href="/spine-webgl/example/barebones.html">Barebones</a></li>
|
||||
<li><a href="/spine-webgl/example/mix-and-match.html">Mix & match</a></li>
|
||||
<li><a href="/spine-webgl/example/custom-attachment.html">Custom attachment</a></li>
|
||||
<li><a href="/spine-webgl/example/drag-and-drop.html">Drag & drop</a></li>
|
||||
<li><a href="/spine-webgl/example/dress-up.html">Dress-up</a></li>
|
||||
<li><a href="/spine-webgl/example/bone-dragging.html">Bone dragging</a></li>
|
||||
|
||||
@ -60,6 +60,9 @@
|
||||
"esbuild": "^0.16.4",
|
||||
"live-server": "^1.2.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^4.9.4"
|
||||
"typescript": "^4.9.4",
|
||||
"@types/three": "^0.146.0",
|
||||
"three": "^0.146.0",
|
||||
"phaser": "^3.60.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
canvas = document.getElementById("canvas");
|
||||
context = canvas.getContext("2d");
|
||||
skeletonRenderer = new spine.SkeletonRenderer(context);
|
||||
// skeletonRenderer.triangleRendering = true;
|
||||
|
||||
// Load the assets.
|
||||
assetManager = new spine.AssetManager("https://esotericsoftware.com/files/examples/4.0/spineboy/export/");
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import { Utils, Color, Skeleton, RegionAttachment, TextureAtlasRegion, BlendMode, MeshAttachment, Slot } from "@esotericsoftware/spine-core";
|
||||
import { Utils, Color, Skeleton, RegionAttachment, BlendMode, MeshAttachment, Slot, TextureRegion, TextureAtlasRegion } from "@esotericsoftware/spine-core";
|
||||
import { CanvasTexture } from "./CanvasTexture";
|
||||
|
||||
const worldVertices = Utils.newFloatArray(8);
|
||||
@ -68,8 +68,9 @@ export class SkeletonRenderer {
|
||||
let attachment = slot.getAttachment();
|
||||
if (!(attachment instanceof RegionAttachment)) continue;
|
||||
attachment.computeWorldVertices(slot, worldVertices, 0, 2);
|
||||
let region: TextureAtlasRegion = <TextureAtlasRegion>attachment.region;
|
||||
let image: HTMLImageElement = (<CanvasTexture>region.page.texture).getImage() as HTMLImageElement;
|
||||
let region: TextureRegion = <TextureRegion>attachment.region;
|
||||
|
||||
let image: HTMLImageElement = (<CanvasTexture>region.texture).getImage() as HTMLImageElement;
|
||||
|
||||
let slotColor = slot.color;
|
||||
let regionColor = attachment.color;
|
||||
@ -98,7 +99,7 @@ export class SkeletonRenderer {
|
||||
ctx.translate(-w / 2, -h / 2);
|
||||
|
||||
ctx.globalAlpha = color.a;
|
||||
ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h);
|
||||
ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);
|
||||
if (this.debugRendering) ctx.strokeRect(0, 0, w, h);
|
||||
ctx.restore();
|
||||
}
|
||||
@ -123,15 +124,13 @@ export class SkeletonRenderer {
|
||||
if (attachment instanceof RegionAttachment) {
|
||||
let regionAttachment = <RegionAttachment>attachment;
|
||||
vertices = this.computeRegionVertices(slot, regionAttachment, false);
|
||||
triangles = SkeletonRenderer.QUAD_TRIANGLES;
|
||||
region = <TextureAtlasRegion>regionAttachment.region;
|
||||
texture = (<CanvasTexture>region.page.texture).getImage() as HTMLImageElement;
|
||||
triangles = SkeletonRenderer.QUAD_TRIANGLES;
|
||||
texture = (<CanvasTexture>regionAttachment.region!.texture).getImage() as HTMLImageElement;
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
vertices = this.computeMeshVertices(slot, mesh, false);
|
||||
triangles = mesh.triangles;
|
||||
let region = (<TextureAtlasRegion>mesh.region!.renderObject);
|
||||
texture = region.page.texture!.getImage() as HTMLImageElement;
|
||||
triangles = mesh.triangles;
|
||||
texture = (<CanvasTexture>mesh.region!.texture).getImage() as HTMLImageElement;
|
||||
} else
|
||||
continue;
|
||||
|
||||
|
||||
@ -55,8 +55,7 @@ export class AtlasAttachmentLoader implements AttachmentLoader {
|
||||
let path = sequence.getPath(basePath, i);
|
||||
let region = this.atlas.findRegion(path);
|
||||
if (region == null) throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")");
|
||||
regions[i] = region;
|
||||
regions[i].renderObject = regions[i];
|
||||
regions[i] = region;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,8 +65,7 @@ export class AtlasAttachmentLoader implements AttachmentLoader {
|
||||
this.loadSequence(name, path, sequence);
|
||||
} else {
|
||||
let region = this.atlas.findRegion(path);
|
||||
if (!region) throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
||||
region.renderObject = region;
|
||||
if (!region) throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
||||
attachment.region = region;
|
||||
}
|
||||
return attachment;
|
||||
@ -79,8 +77,7 @@ export class AtlasAttachmentLoader implements AttachmentLoader {
|
||||
this.loadSequence(name, path, sequence);
|
||||
} else {
|
||||
let region = this.atlas.findRegion(path);
|
||||
if (!region) throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
||||
region.renderObject = region;
|
||||
if (!region) throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
||||
attachment.region = region;
|
||||
}
|
||||
return attachment;
|
||||
|
||||
@ -60,7 +60,7 @@ export enum TextureWrap {
|
||||
}
|
||||
|
||||
export class TextureRegion {
|
||||
renderObject: any;
|
||||
texture: any;
|
||||
u = 0; v = 0;
|
||||
u2 = 0; v2 = 0;
|
||||
width = 0; height = 0;
|
||||
|
||||
@ -236,6 +236,7 @@ export class TextureAtlasPage {
|
||||
width: number = 0;
|
||||
height: number = 0;
|
||||
pma: boolean = false;
|
||||
regions = new Array<TextureAtlasRegion>();
|
||||
|
||||
constructor (name: string) {
|
||||
this.name = name;
|
||||
@ -245,6 +246,8 @@ export class TextureAtlasPage {
|
||||
this.texture = texture;
|
||||
texture.setFilters(this.minFilter, this.magFilter);
|
||||
texture.setWraps(this.uWrap, this.vWrap);
|
||||
for (let region of this.regions)
|
||||
region.texture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,5 +269,6 @@ export class TextureAtlasRegion extends TextureRegion {
|
||||
super();
|
||||
this.page = page;
|
||||
this.name = name;
|
||||
page.regions.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,8 +65,7 @@ export class RegionAttachment extends Attachment implements HasTextureRegion {
|
||||
|
||||
/** The name of the texture region for this attachment. */
|
||||
path: string;
|
||||
|
||||
private rendererObject: any = null;
|
||||
|
||||
region: TextureRegion | null = null;
|
||||
sequence: Sequence | null = null;
|
||||
|
||||
@ -195,8 +194,7 @@ export class RegionAttachment extends Attachment implements HasTextureRegion {
|
||||
|
||||
copy (): Attachment {
|
||||
let copy = new RegionAttachment(this.name, this.path);
|
||||
copy.region = this.region;
|
||||
copy.rendererObject = this.rendererObject;
|
||||
copy.region = this.region;
|
||||
copy.x = this.x;
|
||||
copy.y = this.y;
|
||||
copy.scaleX = this.scaleX;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 563 B |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
@ -30,9 +30,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.2.11",
|
||||
"@esotericsoftware/spine-webgl": "^4.2.11",
|
||||
"@esotericsoftware/spine-canvas": "^4.2.11",
|
||||
"phaser": "^3.55.2"
|
||||
"@esotericsoftware/spine-core": "^4.1.27",
|
||||
"@esotericsoftware/spine-webgl": "^4.1.27",
|
||||
"@esotericsoftware/spine-canvas": "^4.1.27"
|
||||
}
|
||||
}
|
||||
@ -130,11 +130,11 @@ export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||
this.game.scale.on(Phaser.Scale.Events.RESIZE, this.onResize, this);
|
||||
} else {
|
||||
if (!this.canvasRenderer) {
|
||||
this.canvasRenderer = new SkeletonRenderer(this.scene.sys.context);
|
||||
this.canvasRenderer = new SkeletonRenderer(this.scene!.sys.context);
|
||||
}
|
||||
}
|
||||
|
||||
var eventEmitter = this.systems.events;
|
||||
var eventEmitter = this.systems!.events;
|
||||
eventEmitter.once('shutdown', this.shutdown, this);
|
||||
eventEmitter.once('destroy', this.destroy, this);
|
||||
this.game.events.once('destroy', this.gameDestroy, this);
|
||||
@ -156,7 +156,7 @@ export class SpinePlugin extends Phaser.Plugins.ScenePlugin {
|
||||
}
|
||||
|
||||
shutdown () {
|
||||
this.systems.events.off("shutdown", this.shutdown, this);
|
||||
this.systems!.events.off("shutdown", this.shutdown, this);
|
||||
if (this.isWebGL) {
|
||||
this.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this);
|
||||
}
|
||||
|
||||
@ -30,8 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@types/three": "^0.146.0",
|
||||
"three": "^0.146.0",
|
||||
"@esotericsoftware/spine-core": "^4.2.11"
|
||||
"@esotericsoftware/spine-core": "^4.1.27"
|
||||
}
|
||||
}
|
||||
@ -181,7 +181,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
region.computeWorldVertices(slot, vertices, 0, vertexSize);
|
||||
triangles = SkeletonMesh.QUAD_TRIANGLES;
|
||||
uvs = region.uvs;
|
||||
texture = <ThreeJsTexture>(<TextureAtlasRegion>region.region!.renderObject).page.texture;
|
||||
texture = <ThreeJsTexture>region.region!.texture;
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
attachmentColor = mesh.color;
|
||||
@ -193,7 +193,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, vertexSize);
|
||||
triangles = mesh.triangles;
|
||||
uvs = mesh.uvs;
|
||||
texture = <ThreeJsTexture>(<TextureAtlasRegion>mesh.region!.renderObject).page.texture;
|
||||
texture = <ThreeJsTexture>mesh.region!.texture;
|
||||
} else if (attachment instanceof ClippingAttachment) {
|
||||
let clip = <ClippingAttachment>(attachment);
|
||||
clipper.clipStart(slot, clip);
|
||||
|
||||
97
spine-ts/spine-webgl/example/custom-attachment.html
Normal file
97
spine-ts/spine-webgl/example/custom-attachment.html
Normal file
@ -0,0 +1,97 @@
|
||||
<html>
|
||||
<script src="../dist/iife/spine-webgl.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas" style="position: absolute; width: 100%; height: 100%;"></canvas>
|
||||
<script>
|
||||
class App {
|
||||
constructor() {
|
||||
this.skeleton = null;
|
||||
this.animationState = null;
|
||||
}
|
||||
|
||||
loadAssets(canvas) {
|
||||
canvas.assetManager.loadBinary("assets/spineboy-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/spineboy-pma.atlas");
|
||||
canvas.assetManager.loadTexture("head.png");
|
||||
}
|
||||
|
||||
initialize(canvas) {
|
||||
let assetManager = canvas.assetManager;
|
||||
|
||||
// Create the texture atlas.
|
||||
let atlas = assetManager.require("assets/spineboy-pma.atlas");
|
||||
|
||||
// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
|
||||
let atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
|
||||
// Create a SkeletonBinary instance for parsing the .skel file.
|
||||
let skeletonBinary = new spine.SkeletonBinary(atlasLoader);
|
||||
|
||||
// Set the scale to apply during parsing, parse the file, and create a new skeleton.
|
||||
skeletonBinary.scale = 1;
|
||||
let skeletonData = skeletonBinary.readSkeletonData(assetManager.require("assets/spineboy-pro.skel"));
|
||||
this.skeleton = new spine.Skeleton(skeletonData);
|
||||
|
||||
// Create an AnimationState, and set the "run" animation in looping mode.
|
||||
let animationStateData = new spine.AnimationStateData(skeletonData);
|
||||
this.animationState = new spine.AnimationState(animationStateData);
|
||||
this.animationState.setAnimation(0, "run", true);
|
||||
|
||||
// Get the custom head image from the asset manager and create an
|
||||
// attachment from it.
|
||||
let texture = assetManager.require("head.png");
|
||||
let textureRegion = {
|
||||
texture: texture,
|
||||
u: 0, v: 0, u2: 1, v2: 1,
|
||||
width: texture.getImage().width, height: texture.getImage().height,
|
||||
degrees: 0,
|
||||
offsetX: 0, offsetY: 0,
|
||||
originalWidth: texture.getImage().width, originalHeight: texture.getImage().height
|
||||
};
|
||||
let headSlot = this.skeleton.findSlot("head");
|
||||
let newHeadAttachment = headSlot.getAttachment().copy();
|
||||
newHeadAttachment.region = textureRegion;
|
||||
newHeadAttachment.updateRegion();
|
||||
headSlot.setAttachment(newHeadAttachment);
|
||||
}
|
||||
|
||||
update(canvas, delta) {
|
||||
// Update the animation state using the delta time.
|
||||
this.animationState.update(delta);
|
||||
// Apply the animation state to the skeleton.
|
||||
this.animationState.apply(this.skeleton);
|
||||
// Let the skeleton update the transforms of its bones.
|
||||
this.skeleton.updateWorldTransform();
|
||||
}
|
||||
|
||||
render(canvas) {
|
||||
let renderer = canvas.renderer;
|
||||
// Resize the viewport to the full canvas.
|
||||
renderer.resize(spine.ResizeMode.Expand);
|
||||
|
||||
// Clear the canvas with a light gray color.
|
||||
canvas.clear(0.2, 0.2, 0.2, 1);
|
||||
|
||||
// Begin rendering.
|
||||
renderer.begin();
|
||||
// Draw the skeleton
|
||||
renderer.drawSkeleton(this.skeleton, false);
|
||||
// Complete rendering.
|
||||
renderer.end();
|
||||
}
|
||||
}
|
||||
|
||||
new spine.SpineCanvas(document.getElementById("canvas"), {
|
||||
app: new App()
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
spine-ts/spine-webgl/example/head.png
Normal file
BIN
spine-ts/spine-webgl/example/head.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
@ -113,7 +113,7 @@ export class SkeletonRenderer {
|
||||
region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize);
|
||||
triangles = SkeletonRenderer.QUAD_TRIANGLES;
|
||||
uvs = region.uvs;
|
||||
texture = <GLTexture>(<TextureAtlasRegion>region.region!.renderObject).page.texture;
|
||||
texture = <GLTexture>region.region!.texture;
|
||||
attachmentColor = region.color;
|
||||
} else if (attachment instanceof MeshAttachment) {
|
||||
let mesh = <MeshAttachment>attachment;
|
||||
@ -125,7 +125,7 @@ export class SkeletonRenderer {
|
||||
}
|
||||
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
|
||||
triangles = mesh.triangles;
|
||||
texture = <GLTexture>(<TextureAtlasRegion>mesh.region!.renderObject).page.texture;
|
||||
texture = <GLTexture>mesh.region!.texture;
|
||||
uvs = mesh.uvs;
|
||||
attachmentColor = mesh.color;
|
||||
} else if (attachment instanceof ClippingAttachment) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user