mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[ts][as3] Added mix-and-match example. See #1375.
This commit is contained in:
parent
c9ccd43121
commit
2946cec9d1
Binary file not shown.
@ -256,7 +256,7 @@ package spine {
|
|||||||
|
|
||||||
if (skinMap["transform"]) {
|
if (skinMap["transform"]) {
|
||||||
for (ii = 0; ii < skinMap["transform"].length; ii++) {
|
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]);
|
if (constraint == null) throw new Error("Skin transform constraint not found: " + skinMap["transform"][ii]);
|
||||||
skin.constraints.push(constraint);
|
skin.constraints.push(constraint);
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ package spine {
|
|||||||
|
|
||||||
if (skinMap["path"]) {
|
if (skinMap["path"]) {
|
||||||
for (ii = 0; ii < skinMap["path"].length; ii++) {
|
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]);
|
if (constraint == null) throw new Error("Skin path constraint not found: " + skinMap["path"][ii]);
|
||||||
skin.constraints.push(constraint);
|
skin.constraints.push(constraint);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -89,7 +89,7 @@ package spine.examples {
|
|||||||
if (touch && touch.phase == TouchPhase.BEGAN) {
|
if (touch && touch.phase == TouchPhase.BEGAN) {
|
||||||
var parent : DisplayObjectContainer = this.parent;
|
var parent : DisplayObjectContainer = this.parent;
|
||||||
this.removeFromParent(true);
|
this.removeFromParent(true);
|
||||||
parent.addChild(new SpineboyExample());
|
parent.addChild(new MixAndMatchExample());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ package spine.examples {
|
|||||||
private var _starling : Starling;
|
private var _starling : Starling;
|
||||||
|
|
||||||
public function Main() {
|
public function Main() {
|
||||||
_starling = new Starling(GoblinsExample, stage);
|
_starling = new Starling(MixAndMatchExample, stage);
|
||||||
_starling.enableErrorChecking = true;
|
_starling.enableErrorChecking = true;
|
||||||
_starling.showStats = true;
|
_starling.showStats = true;
|
||||||
_starling.skipUnchangedFrames = false;
|
_starling.skipUnchangedFrames = false;
|
||||||
|
|||||||
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
118
spine-ts/webgl/tests/test-mix-and-match.html
Normal file
118
spine-ts/webgl/tests/test-mix-and-match.html
Normal file
@ -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>
|
||||||
Loading…
x
Reference in New Issue
Block a user