Browse Source

[ts][canvas] Canvas renderer now supports shearing and non-uniform scale. Closes #851

badlogic 8 years ago
parent
commit
e8df948d9d

+ 5 - 1
spine-ts/README.md

@@ -20,7 +20,11 @@ The Spine Runtimes are developed with the intent to be used with data exported f
 
 spine-ts works with data exported from Spine 3.5.xx.
 
-spine-ts WebGL & Widget backends supports all Spine features. The spine-ts Canvas backend does not support color tinting, mesh attachments or shearing. Mesh attachments are supported by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers. The spine-ts THREE.JS backend does not support color tinting and blend modes. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
+spine-ts WebGL & Widget backends supports all Spine features. 
+
+spine-ts Canvas does not support color tinting and mesh attachments. Experimental support for mesh attachments can be enabled by setting `spine.canvas.SkeletonRenderer.useTriangleRendering` to true. Note that this method is slow and may lead to artifacts on some browsers. 
+
+spine-ts THREE.JS does not support color tinting and blend modes. The THREE.JS backend provides `SkeletonMesh.zOffset` to avoid z-fighting. Adjust to your near/far plane settings.
 
 spine-ts does not yet support loading the binary format.
 

+ 14 - 22
spine-ts/build/spine-all.js

@@ -231,10 +231,8 @@ var spine;
 					var attachment = slot.getAttachment();
 					var region = null;
 					var image = null;
-					var vertices = null;
 					if (attachment instanceof spine.RegionAttachment) {
 						var regionAttachment = attachment;
-						vertices = regionAttachment.updateWorldVertices(slot, false);
 						region = regionAttachment.region;
 						image = (region).texture.getImage();
 					}
@@ -242,28 +240,22 @@ var spine;
 						continue;
 					var att = attachment;
 					var bone = slot.bone;
-					var x = vertices[0];
-					var y = vertices[1];
-					var rotation = (bone.getWorldRotationX() - att.rotation) * Math.PI / 180;
-					var xx = vertices[24] - vertices[0];
-					var xy = vertices[25] - vertices[1];
-					var yx = vertices[8] - vertices[0];
-					var yy = vertices[9] - vertices[1];
-					var w = Math.sqrt(xx * xx + xy * xy), h = -Math.sqrt(yx * yx + yy * yy);
-					ctx.translate(x, y);
-					ctx.rotate(rotation);
-					if (region.rotate) {
-						ctx.rotate(Math.PI / 2);
-						ctx.drawImage(image, region.x, region.y, region.height, region.width, 0, 0, h, -w);
-						ctx.rotate(-Math.PI / 2);
-					}
-					else {
-						ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
-					}
+					var w = region.width;
+					var h = region.height;
+					var offsetX = attachment.offset[0];
+					var offsetY = attachment.offset[1];
+					ctx.save();
+					ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
+					ctx.translate(offsetX, offsetY);
+					ctx.rotate(attachment.rotation * Math.PI / 180);
+					ctx.scale(attachment.scaleX, attachment.scaleY);
+					ctx.translate(region.width / 2, region.height / 2);
+					ctx.scale(1, -1);
+					ctx.translate(-region.width / 2, -region.height / 2);
+					ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
 					if (this.debugRendering)
 						ctx.strokeRect(0, 0, w, h);
-					ctx.rotate(-rotation);
-					ctx.translate(-x, -y);
+					ctx.restore();
 				}
 			};
 			SkeletonRenderer.prototype.drawTriangles = function (skeleton) {

File diff suppressed because it is too large
+ 0 - 0
spine-ts/build/spine-all.js.map


+ 14 - 22
spine-ts/build/spine-canvas.js

@@ -231,10 +231,8 @@ var spine;
 					var attachment = slot.getAttachment();
 					var region = null;
 					var image = null;
-					var vertices = null;
 					if (attachment instanceof spine.RegionAttachment) {
 						var regionAttachment = attachment;
-						vertices = regionAttachment.updateWorldVertices(slot, false);
 						region = regionAttachment.region;
 						image = (region).texture.getImage();
 					}
@@ -242,28 +240,22 @@ var spine;
 						continue;
 					var att = attachment;
 					var bone = slot.bone;
-					var x = vertices[0];
-					var y = vertices[1];
-					var rotation = (bone.getWorldRotationX() - att.rotation) * Math.PI / 180;
-					var xx = vertices[24] - vertices[0];
-					var xy = vertices[25] - vertices[1];
-					var yx = vertices[8] - vertices[0];
-					var yy = vertices[9] - vertices[1];
-					var w = Math.sqrt(xx * xx + xy * xy), h = -Math.sqrt(yx * yx + yy * yy);
-					ctx.translate(x, y);
-					ctx.rotate(rotation);
-					if (region.rotate) {
-						ctx.rotate(Math.PI / 2);
-						ctx.drawImage(image, region.x, region.y, region.height, region.width, 0, 0, h, -w);
-						ctx.rotate(-Math.PI / 2);
-					}
-					else {
-						ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
-					}
+					var w = region.width;
+					var h = region.height;
+					var offsetX = attachment.offset[0];
+					var offsetY = attachment.offset[1];
+					ctx.save();
+					ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
+					ctx.translate(offsetX, offsetY);
+					ctx.rotate(attachment.rotation * Math.PI / 180);
+					ctx.scale(attachment.scaleX, attachment.scaleY);
+					ctx.translate(region.width / 2, region.height / 2);
+					ctx.scale(1, -1);
+					ctx.translate(-region.width / 2, -region.height / 2);
+					ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
 					if (this.debugRendering)
 						ctx.strokeRect(0, 0, w, h);
-					ctx.rotate(-rotation);
-					ctx.translate(-x, -y);
+					ctx.restore();
 				}
 			};
 			SkeletonRenderer.prototype.drawTriangles = function (skeleton) {

File diff suppressed because it is too large
+ 0 - 0
spine-ts/build/spine-canvas.js.map


+ 37 - 58
spine-ts/canvas/example/assets/spineboy.atlas

@@ -5,141 +5,120 @@ format: RGBA8888
 filter: Linear,Linear
 repeat: none
 eye_indifferent
-  rotate: true
-  xy: 648, 629
+  rotate: false
+  xy: 275, 349
   size: 93, 89
   orig: 93, 89
   offset: 0, 0
   index: -1
 eye_surprised
-  rotate: true
-  xy: 233, 179
+  rotate: false
+  xy: 214, 125
   size: 93, 89
   orig: 93, 89
   offset: 0, 0
   index: -1
 front_bracer
   rotate: false
-  xy: 245, 2
+  xy: 678, 774
   size: 58, 80
   orig: 58, 80
   offset: 0, 0
   index: -1
 front_fist_closed
   rotate: false
-  xy: 168, 45
+  xy: 944, 940
   size: 75, 82
   orig: 75, 82
   offset: 0, 0
   index: -1
 front_fist_open
   rotate: false
-  xy: 844, 646
+  xy: 132, 28
   size: 86, 87
   orig: 86, 87
   offset: 0, 0
   index: -1
 front_foot
-  rotate: true
-  xy: 310, 326
+  rotate: false
+  xy: 550, 785
   size: 126, 69
   orig: 126, 69
   offset: 0, 0
   index: -1
 front_foot_bend1
-  rotate: true
-  xy: 951, 894
+  rotate: false
+  xy: 2, 45
   size: 128, 70
   orig: 128, 70
   offset: 0, 0
   index: -1
 front_foot_bend2
   rotate: false
-  xy: 2, 33
+  xy: 729, 929
   size: 108, 93
   orig: 108, 93
   offset: 0, 0
   index: -1
 front_shin
-  rotate: true
-  xy: 739, 735
+  rotate: false
+  xy: 466, 670
   size: 82, 184
   orig: 82, 184
   offset: 0, 0
   index: -1
 front_thigh
   rotate: false
-  xy: 381, 340
+  xy: 281, 235
   size: 48, 112
   orig: 48, 112
   offset: 0, 0
   index: -1
 front_upper_arm
   rotate: false
-  xy: 112, 29
+  xy: 220, 26
   size: 54, 97
   orig: 54, 97
   offset: 0, 0
   index: -1
 goggles
   rotate: false
-  xy: 156, 454
+  xy: 466, 856
   size: 261, 166
   orig: 261, 166
   offset: 0, 0
   index: -1
 gun
   rotate: false
-  xy: 739, 819
+  xy: 2, 117
   size: 210, 203
   orig: 210, 203
   offset: 0, 0
   index: -1
 head
   rotate: false
-  xy: 466, 724
+  xy: 2, 322
   size: 271, 298
   orig: 271, 298
   offset: 0, 0
   index: -1
-hoverboard_board
-  rotate: true
-  xy: 2, 128
-  size: 492, 152
-  orig: 492, 152
-  offset: 0, 0
-  index: -1
-hoverboard_thruster
-  rotate: false
-  xy: 602, 558
-  size: 60, 64
-  orig: 60, 64
-  offset: 0, 0
-  index: -1
-hoverglow_small
-  rotate: true
-  xy: 156, 178
-  size: 274, 75
-  orig: 274, 75
-  offset: 0, 0
-  index: -1
 mouth_grind
-  rotate: true
-  xy: 951, 799
+  rotate: false
+  xy: 844, 878
   size: 93, 59
   orig: 93, 59
   offset: 0, 0
   index: -1
 mouth_oooo
-  rotate: true
-  xy: 245, 84
+  rotate: false
+  xy: 550, 656
   size: 93, 59
   orig: 93, 59
   offset: 0, 0
   index: -1
 mouth_smile
   rotate: false
-  xy: 925, 738
+  xy: 738, 806
   size: 93, 59
   orig: 93, 59
   offset: 0, 0
@@ -153,63 +132,63 @@ muzzle
   index: -1
 neck
   rotate: false
-  xy: 168, 2
+  xy: 2, 2
   size: 36, 41
   orig: 36, 41
   offset: 0, 0
   index: -1
 rear_bracer
   rotate: false
-  xy: 932, 664
+  xy: 276, 51
   size: 56, 72
   orig: 56, 72
   offset: 0, 0
   index: -1
 rear_foot
   rotate: false
-  xy: 487, 562
+  xy: 729, 867
   size: 113, 60
   orig: 113, 60
   offset: 0, 0
   index: -1
 rear_foot_bend1
-  rotate: true
-  xy: 419, 503
+  rotate: false
+  xy: 550, 717
   size: 117, 66
   orig: 117, 66
   offset: 0, 0
   index: -1
 rear_foot_bend2
   rotate: false
-  xy: 739, 650
+  xy: 839, 939
   size: 103, 83
   orig: 103, 83
   offset: 0, 0
   index: -1
 rear_shin
   rotate: false
-  xy: 233, 274
+  xy: 375, 442
   size: 75, 178
   orig: 75, 178
   offset: 0, 0
   index: -1
 rear_thigh
-  rotate: true
-  xy: 487, 495
+  rotate: false
+  xy: 214, 216
   size: 65, 104
   orig: 65, 104
   offset: 0, 0
   index: -1
 rear_upper_arm
-  rotate: true
-  xy: 156, 129
+  rotate: false
+  xy: 331, 260
   size: 47, 87
   orig: 47, 87
   offset: 0, 0
   index: -1
 torso
-  rotate: true
-  xy: 466, 624
+  rotate: false
+  xy: 275, 440
   size: 98, 180
   orig: 98, 180
   offset: 0, 0

File diff suppressed because it is too large
+ 0 - 2419
spine-ts/canvas/example/assets/spineboy.json


BIN
spine-ts/canvas/example/assets/spineboy.png


+ 31 - 20
spine-ts/canvas/example/index.html

@@ -17,6 +17,9 @@ var assetManager;
 var skeleton, state, bounds;
 var skeletonRenderer;
 
+var skelName = "spineboy";
+var animName = "idle";
+
 function init () {
 	canvas = document.getElementById("canvas");
 	canvas.width = window.innerWidth;
@@ -29,21 +32,21 @@ function init () {
 	// enable the triangle renderer, supports meshes, but may produce artifacts in some browsers
 	skeletonRenderer.triangleRendering = false;
 
-	assetManager = new spine.canvas.AssetManager();	
+	assetManager = new spine.canvas.AssetManager();
 
-	assetManager.loadText("assets/spineboy.json");
-	assetManager.loadText("assets/spineboy.atlas");
-	assetManager.loadTexture("assets/spineboy.png");
+	assetManager.loadText("assets/" + skelName + ".json");
+	assetManager.loadText("assets/" + skelName + ".atlas");
+	assetManager.loadTexture("assets/" + skelName + ".png");
 
 	requestAnimationFrame(load);
 }
 
 function load () {
 	if (assetManager.isLoadingComplete()) {
-		var data = loadSkeleton("spineboy", "walk", "default");
+		var data = loadSkeleton(skelName, animName, "default");
 		skeleton = data.skeleton;
 		state = data.state;
-		bounds = data.bounds;	
+		bounds = data.bounds;
 		requestAnimationFrame(render);
 	} else {
 		requestAnimationFrame(load);
@@ -56,7 +59,7 @@ function loadSkeleton (name, initialAnimation, skin) {
 	// Load the texture atlas using name.atlas and name.png from the AssetManager.
 	// The function passed to TextureAtlas is used to resolve relative paths.
 	atlas = new spine.TextureAtlas(assetManager.get("assets/" + name + ".atlas"), function(path) {
-		return assetManager.get("assets/" + path);				
+		return assetManager.get("assets/" + path);
 	});
 
 	// Create a AtlasAttachmentLoader, which is specific to the WebGL backend.
@@ -64,12 +67,12 @@ function loadSkeleton (name, initialAnimation, skin) {
 
 	// Create a SkeletonJson instance for parsing the .json file.
 	var skeletonJson = new spine.SkeletonJson(atlasLoader);
-	
-	// Set the scale to apply during parsing, parse the file, and create a new skeleton.	
+
+	// Set the scale to apply during parsing, parse the file, and create a new skeleton.
 	var skeletonData = skeletonJson.readSkeletonData(assetManager.get("assets/" + name + ".json"));
 	var skeleton = new spine.Skeleton(skeletonData);
-	skeleton.flipY = true;		
-	var bounds = calculateBounds(skeleton);	
+	skeleton.flipY = true;
+	var bounds = calculateBounds(skeleton);
 	skeleton.setSkinByName(skin);
 
 	// Create an AnimationState, and set the initial animation in looping mode.
@@ -100,7 +103,7 @@ function calculateBounds(skeleton) {
 	skeleton.updateWorldTransform();
 	var offset = new spine.Vector2();
 	var size = new spine.Vector2();
-	skeleton.getBounds(offset, size);	
+	skeleton.getBounds(offset, size);
 	return { offset: offset, size: size };
 }
 
@@ -108,7 +111,7 @@ function render () {
 	var now = Date.now() / 1000;
 	var delta = now - lastFrameTime;
 	lastFrameTime = now;
-	
+
 	resize();
 
 	context.save();
@@ -119,15 +122,23 @@ function render () {
 
 	state.update(delta);
 	state.apply(skeleton);
-	skeleton.updateWorldTransform();		 			
-	skeletonRenderer.draw(skeleton);	
+	skeleton.updateWorldTransform();
+	skeletonRenderer.draw(skeleton);
+
+	context.strokeStyle = "green";
+	context.beginPath();
+	context.moveTo(-1000, 0);
+	context.lineTo(1000, 0);
+	context.moveTo(0, -1000);
+	context.lineTo(0, 1000);
+	context.stroke();
 
 	requestAnimationFrame(render);
 }
 
 function resize () {
 	var w = canvas.clientWidth;
-	var h = canvas.clientHeight;	
+	var h = canvas.clientHeight;
 	if (canvas.width != w || canvas.height != h) {
 		canvas.width = w;
 		canvas.height = h;
@@ -140,12 +151,12 @@ function resize () {
 	var scaleY = bounds.size.y / canvas.height;
 	var scale = Math.max(scaleX, scaleY) * 1.2;
 	if (scale < 1) scale = 1;
-	var width = canvas.width * scale;
-	var height = canvas.height * scale;
-	
+	var width = canvas.width;
+	var height = canvas.height;
+
 	context.resetTransform();
 	context.scale(1 / scale, 1 / scale);
-	context.translate(-centerX, -centerY);	
+	context.translate(-centerX, -centerY);
 	context.translate(width / 2, height / 2);
 }
 

+ 14 - 22
spine-ts/canvas/src/SkeletonRenderer.ts

@@ -57,37 +57,29 @@ module spine.canvas {
 				let attachment = slot.getAttachment();
 				let region: TextureAtlasRegion = null;
 				let image: HTMLImageElement = null;
-				let vertices: ArrayLike<number> = null;
 				if (attachment instanceof RegionAttachment) {
 					let regionAttachment = <RegionAttachment>attachment;
-					vertices = regionAttachment.updateWorldVertices(slot, false);
 					region = <TextureAtlasRegion>regionAttachment.region;
 					image = (<CanvasTexture>(region).texture).getImage();
-
 				} else continue;
 
 				let att = <RegionAttachment>attachment;
 				let bone = slot.bone;
-				let x = vertices[0];
-				let y = vertices[1];
-				let rotation = (bone.getWorldRotationX() - att.rotation) * Math.PI / 180;
-				let xx = vertices[24] - vertices[0];
-				let xy = vertices[25] - vertices[1];
-				let yx = vertices[8] - vertices[0];
-				let yy = vertices[9] - vertices[1];
-				let w = Math.sqrt(xx * xx + xy * xy), h = -Math.sqrt(yx * yx + yy * yy);
-				ctx.translate(x, y);
-				ctx.rotate(rotation);
-				if (region.rotate) {
-					ctx.rotate(Math.PI / 2);
-					ctx.drawImage(image, region.x, region.y, region.height, region.width, 0, 0, h, -w);
-					ctx.rotate(-Math.PI / 2);
-				} else {
-					ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
-				}
+				let w = region.width;
+				let h = region.height;
+				let offsetX = attachment.offset[0];
+				let offsetY = attachment.offset[1];
+				ctx.save();
+				ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
+				ctx.translate(offsetX, offsetY);
+				ctx.rotate(attachment.rotation * Math.PI / 180);
+				ctx.scale(attachment.scaleX, attachment.scaleY);
+				ctx.translate(region.width / 2, region.height / 2);
+				ctx.scale(1, -1);
+				ctx.translate(-region.width / 2, -region.height / 2);
+				ctx.drawImage(image, region.x, region.y, region.width, region.height, 0, 0, w, h);
 				if (this.debugRendering) ctx.strokeRect(0, 0, w, h);
-				ctx.rotate(-rotation);
-				ctx.translate(-x, -y);
+				ctx.restore();
 			}
 		}
 

Some files were not shown because too many files changed in this diff