Browse Source

[ts][as3] Added mix-and-match example. See #1375.

badlogic 6 years ago
parent
commit
2946cec9d1

BIN
spine-as3/spine-as3-example/lib/spine-as3.swc


+ 3 - 3
spine-as3/spine-as3/src/spine/SkeletonJson.as

@@ -254,9 +254,9 @@ package spine {
 					}
 				}
 				
-				if (skinMap["transform"]) {
+				if (skinMap["transform"]) {									
 					for (ii = 0; ii < skinMap["transform"].length; ii++) {
-						var constraint : ConstraintData = skeletonData.findIkConstraint(skinMap["transform"][ii]);
+						var constraint : ConstraintData = skeletonData.findTransformConstraint(skinMap["transform"][ii]);
 						if (constraint == null) throw new Error("Skin transform constraint not found: " + skinMap["transform"][ii]);
 						skin.constraints.push(constraint);
 					}
@@ -264,7 +264,7 @@ package spine {
 				
 				if (skinMap["path"]) {
 					for (ii = 0; ii < skinMap["path"].length; ii++) {
-						var constraint : ConstraintData = skeletonData.findIkConstraint(skinMap["path"][ii]);
+						var constraint : ConstraintData = skeletonData.findPathConstraint(skinMap["path"][ii]);
 						if (constraint == null) throw new Error("Skin path constraint not found: " + skinMap["path"][ii]);
 						skin.constraints.push(constraint);
 					}

BIN
spine-starling/spine-starling-example/lib/spine-as3.swc


+ 1 - 1
spine-starling/spine-starling-example/src/spine/examples/CoinExample.as

@@ -89,7 +89,7 @@ package spine.examples {
 			if (touch && touch.phase == TouchPhase.BEGAN) {
 				var parent : DisplayObjectContainer = this.parent;
 				this.removeFromParent(true);
-				parent.addChild(new SpineboyExample());
+				parent.addChild(new MixAndMatchExample());
 			}
 		}
 	}

+ 1 - 1
spine-starling/spine-starling-example/src/spine/examples/Main.as

@@ -37,7 +37,7 @@ package spine.examples {
 		private var _starling : Starling;
 
 		public function Main() {
-			_starling = new Starling(GoblinsExample, stage);			
+			_starling = new Starling(MixAndMatchExample, stage);			
 			_starling.enableErrorChecking = true;
 			_starling.showStats = true;
 			_starling.skipUnchangedFrames = false;

+ 110 - 0
spine-starling/spine-starling-example/src/spine/examples/MixAndMatchExample.as

@@ -0,0 +1,110 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated May 1, 2019. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2019, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS
+ * INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+package spine.examples {
+	import spine.Skin;	
+	import starling.display.DisplayObjectContainer;
+	import starling.events.Touch;
+	import starling.events.TouchPhase;
+	import starling.core.Starling;
+	import starling.events.TouchEvent;
+	import starling.display.Sprite;
+
+	import spine.SkeletonData;
+	import spine.SkeletonJson;
+	import spine.attachments.AtlasAttachmentLoader;
+	import spine.starling.StarlingTextureLoader;
+	import spine.atlas.Atlas;
+	import spine.attachments.AttachmentLoader;
+	import spine.starling.SkeletonAnimation;
+
+	public class MixAndMatchExample extends Sprite {
+		[Embed(source = "/mix-and-match-pro.json", mimeType = "application/octet-stream")]
+		static public const MixAndMatchJson : Class;
+
+		[Embed(source = "/mix-and-match.atlas", mimeType = "application/octet-stream")]
+		static public const MixAndMatchAtlas : Class;
+
+		[Embed(source = "/mix-and-match.png")]
+		static public const MixAndMatchAtlasTexture : Class;
+		private var skeleton : SkeletonAnimation;
+
+		public function MixAndMatchExample() {
+			var attachmentLoader : AttachmentLoader;
+			var spineAtlas : Atlas = new Atlas(new MixAndMatchAtlas(), new StarlingTextureLoader(new MixAndMatchAtlasTexture()));
+			attachmentLoader = new AtlasAttachmentLoader(spineAtlas);
+
+			var json : SkeletonJson = new SkeletonJson(attachmentLoader);
+			json.scale = 0.5;
+			var skeletonData : SkeletonData = json.readSkeletonData(new MixAndMatchJson());
+
+			this.x = 400;
+			this.y = 500;
+
+			skeleton = new SkeletonAnimation(skeletonData);
+			skeleton.state.setAnimationByName(0, "dance", true);								
+			
+			// enable two color tinting, which breaks batching between this skeleton
+			// and other Starling objects.
+			skeleton.twoColorTint = true;
+			
+			// Create a new skin, by mixing and matching other skins
+			// that fit together. Items making up the girl are individual
+			// skins. Using the skin API, a new skin is created which is
+			// a combination of all these individual item skins.
+			var mixAndMatchSkin : Skin = new Skin("custom-girl");
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("skin-base"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("nose/short"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("eyes/eyelids-girly"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("eyes/violet"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("hair/brown"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("clothes/hoodie-orange"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("legs/pants-jeans"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("accessories/bag"));
+			mixAndMatchSkin.addSkin(skeletonData.findSkin("accessories/hat-red-yellow"));
+			skeleton.skeleton.skin = mixAndMatchSkin;
+			
+			skeleton.skeleton.updateWorldTransform();
+
+			addChild(skeleton);
+			Starling.juggler.add(skeleton);
+
+			addEventListener(TouchEvent.TOUCH, onClick);
+		}
+
+		private function onClick(event : TouchEvent) : void {
+			var touch : Touch = event.getTouch(this);
+			if (touch && touch.phase == TouchPhase.BEGAN) {
+				var parent : DisplayObjectContainer = this.parent;
+				this.removeFromParent(true);
+				parent.addChild(new SpineboyExample());
+			}
+		}
+	}
+}

BIN
spine-starling/spine-starling/lib/spine-as3.swc


+ 118 - 0
spine-ts/webgl/tests/test-mix-and-match.html

@@ -0,0 +1,118 @@
+<html>
+<script src="../../build/spine-webgl.js"></script>
+<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
+<style>
+	* { margin: 0; padding: 0; }
+	body, html { height: 100% }
+	canvas { position: absolute; width: 100% ;height: 100%; }
+</style>
+<body>
+<div id="label" style="position: absolute; top: 0; left: 0; color: #fff; z-index: 10"></div>
+<canvas id="canvas" style="background: red;"></canvas>
+</body>
+<script>
+
+var FILE = "mix-and-match-pro";
+var ANIMATION = "dance";
+var SCALE = 0.5;
+
+var canvas, context, gl, renderer, input, assetManager;
+var skeletons = [];
+var timeKeeper;
+var label = document.getElementById("label");
+var updateMean = new spine.WindowedMean();
+var renderMean = new spine.WindowedMean();
+
+function init() {
+	canvas = document.getElementById("canvas");
+	canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight;
+	context = new spine.webgl.ManagedWebGLRenderingContext(canvas, { alpha: false });
+	gl = context.gl;
+
+	renderer = new spine.webgl.SceneRenderer(canvas, context);
+	assetManager = new spine.webgl.AssetManager(context, "../example/assets/");
+	input = new spine.webgl.Input(canvas);
+
+	assetManager.loadTextureAtlas(FILE.replace("-pro", "").replace("-ess", "") + "-pma.atlas");
+	assetManager.loadBinary(FILE + ".skel");
+
+	timeKeeper = new spine.TimeKeeper();
+	requestAnimationFrame(load);
+}
+
+var run = true;
+
+function load() {
+	timeKeeper.update();
+	if (assetManager.isLoadingComplete()) {
+		var atlas = assetManager.get(FILE.replace("-pro", "").replace("-ess", "") + "-pma.atlas");
+		var atlasLoader = new spine.AtlasAttachmentLoader(atlas);
+		var skeletonBinary = new spine.SkeletonBinary(atlasLoader);
+		skeletonBinary.scale = SCALE;
+		var skeletonData = skeletonBinary.readSkeletonData(assetManager.get(FILE + ".skel"));
+
+		skeleton = new spine.Skeleton(skeletonData);
+		var stateData = new spine.AnimationStateData(skeleton.data);
+		state = new spine.AnimationState(stateData);
+		stateData.defaultMix = 0;
+
+		// Create a new skin, by mixing and matching other skins
+		// that fit together. Items making up the girl are individual
+		// skins. Using the skin API, a new skin is created which is
+		// a combination of all these individual item skins.
+		var mixAndMatchSkin = new spine.Skin("custom-girl");
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("skin-base"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("nose/short"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("eyes/eyelids-girly"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("eyes/violet"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("hair/brown"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("clothes/hoodie-orange"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("legs/pants-jeans"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("accessories/bag"));
+		mixAndMatchSkin.addSkin(skeletonData.findSkin("accessories/hat-red-yellow"));
+		skeleton.setSkin(mixAndMatchSkin);
+
+		state.setAnimation(0, ANIMATION, true);
+		skeletons.push({ skeleton: skeleton, state: state });
+
+		requestAnimationFrame(render);
+	} else {
+		requestAnimationFrame(load);
+	}
+}
+
+function render() {
+	var start = Date.now()
+	timeKeeper.update();
+	var delta = timeKeeper.delta;
+
+	for (var i = 0; i < skeletons.length; i++) {
+		var state = skeletons[i].state;
+		var skeleton = skeletons[i].skeleton;
+		state.update(delta);
+		state.apply(skeleton);
+		skeleton.updateWorldTransform();
+	}
+	updateMean.addValue(Date.now() - start);
+	start = Date.now();
+
+	gl.clearColor(0.2, 0.2, 0.2, 1);
+	gl.clear(gl.COLOR_BUFFER_BIT);
+
+	renderer.resize(spine.webgl.ResizeMode.Fit);
+	renderer.begin();
+	for (var i = 0; i < skeletons.length; i++) {
+		var skeleton = skeletons[i].skeleton;
+		renderer.drawSkeleton(skeleton, true);
+	}
+	renderer.end();
+
+	requestAnimationFrame(render)
+	renderMean.addValue(Date.now() - start);
+	label.innerHTML = ("Update time: " + Number(updateMean.getMean()).toFixed(2) + " ms\n" +
+					   "Render time: " + Number(renderMean.getMean()).toFixed(2) + " ms\n");
+}
+
+init();
+</script>
+</html>