mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 17:26:01 +08:00
Merge branch '4.1-beta' of https://github.com/esotericsoftware/spine-runtimes into 4.1-beta
This commit is contained in:
commit
ef5e059ed9
@ -79,6 +79,8 @@
|
||||
* Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect.
|
||||
* Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect.
|
||||
* Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0.
|
||||
* `GetRemappedClone` copying from `Sprite` now provides additional `pmaCloneTextureFormat` and `pmaCloneMipmaps` parameters to explicitly specify the texture format of a newly created PMA texture.
|
||||
* Spine property Inspector fields (`Animation Name`, `Bone Name`, `Slot` and similar) now display the name in red when the respective animation/bone/etc no longer exists at the skeleton data. This may be helpful when such items have been renamed or deleted.
|
||||
|
||||
* **Breaking changes**
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ fi
|
||||
echo "Spine exe: $SPINE_EXE"
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Enter the Spine editor version to use for the export (eg 3.8.99):"
|
||||
echo "Enter the Spine editor version to use for the export (eg 4.1.xx):"
|
||||
read version
|
||||
else
|
||||
version=${1%/}
|
||||
@ -79,6 +79,11 @@ echo "Exporting assets..."
|
||||
-i ../mix-and-match/images -o ../mix-and-match/export -n mix-and-match -p atlas-0.5.json \
|
||||
-i ../mix-and-match/images -o ../mix-and-match/export -n mix-and-match-pma -p atlas-0.5-pma.json \
|
||||
\
|
||||
-i ../owl/owl-pro.spine -o ../owl/export -e json.json \
|
||||
-i ../owl/owl-pro.spine -o ../owl/export -e binary.json \
|
||||
-i ../owl/images -o ../owl/export -n owl -p atlas-0.5.json \
|
||||
-i ../owl/images -o ../owl/export -n owl-pma -p atlas-0.5-pma.json \
|
||||
\
|
||||
-i ../powerup/powerup-ess.spine -o ../powerup/export -e json.json \
|
||||
-i ../powerup/powerup-ess.spine -o ../powerup/export -e binary.json \
|
||||
-i ../powerup/powerup-pro.spine -o ../powerup/export -e json.json \
|
||||
@ -100,6 +105,7 @@ echo "Exporting assets..."
|
||||
-i ../spineboy/spineboy-ess.spine -o ../spineboy/export -e binary.json \
|
||||
-i ../spineboy/spineboy-pro.spine -o ../spineboy/export -e json.json \
|
||||
-i ../spineboy/spineboy-pro.spine -o ../spineboy/export -e binary.json \
|
||||
-i ../spineboy/spineboy-pro.spine -o ../spineboy/export/spineboy-run.atlas -e png-0.5-frame-by-frame.json \
|
||||
-i ../spineboy/images -o ../spineboy/export -n spineboy -p atlas-0.5.json \
|
||||
-i ../spineboy/images -o ../spineboy/export -n spineboy-pma -p atlas-0.5-pma.json \
|
||||
\
|
||||
@ -126,14 +132,10 @@ echo "Exporting assets..."
|
||||
-i ../windmill/images -o ../windmill/export -n windmill -p atlas-0.5.json \
|
||||
-i ../windmill/images -o ../windmill/export -n windmill-pma -p atlas-0.5-pma.json
|
||||
|
||||
# Owl needs separate export, as cleaning would kill keys in idle animation, which
|
||||
# would lead to incorrect additive animation blending.
|
||||
# spineboy-old.spine needs separate export, as its images are in an atlas.
|
||||
"$SPINE_EXE" \
|
||||
-u $version ${@:2} \
|
||||
-i ../owl/owl-pro.spine -o ../owl/export -e json.json \
|
||||
-i ../owl/owl-pro.spine -o ../owl/export -e binary.json \
|
||||
-i ../owl/images -o ../owl/export -n owl -p atlas-0.5.json \
|
||||
-i ../owl/images -o ../owl/export -n owl-pma -p atlas-0.5-pma.json \
|
||||
-i ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/spineboy-old.spine -o ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old -e json.json
|
||||
|
||||
# Export Unity Assets
|
||||
UNITY_BASE_DIR=../spine-unity
|
||||
|
||||
87
examples/export/png-0.5-frame-by-frame.json
Normal file
87
examples/export/png-0.5-frame-by-frame.json
Normal file
@ -0,0 +1,87 @@
|
||||
{
|
||||
"class": "export-png",
|
||||
"exportType": "animation",
|
||||
"skeletonType": "single",
|
||||
"skeleton": "spineboy-pro",
|
||||
"animationType": "single",
|
||||
"animation": "run",
|
||||
"skinType": "current",
|
||||
"skinNone": false,
|
||||
"skin": null,
|
||||
"maxBounds": false,
|
||||
"renderImages": true,
|
||||
"renderBones": false,
|
||||
"renderOthers": false,
|
||||
"scale": 50,
|
||||
"fitWidth": 0,
|
||||
"fitHeight": 0,
|
||||
"enlarge": false,
|
||||
"background": null,
|
||||
"fps": 15,
|
||||
"lastFrame": false,
|
||||
"cropWidth": 0,
|
||||
"cropHeight": 0,
|
||||
"rangeStart": -1,
|
||||
"rangeEnd": -1,
|
||||
"packAtlas": {
|
||||
"stripWhitespaceX": true,
|
||||
"stripWhitespaceY": true,
|
||||
"rotation": true,
|
||||
"alias": true,
|
||||
"ignoreBlankImages": false,
|
||||
"alphaThreshold": 3,
|
||||
"minWidth": 16,
|
||||
"minHeight": 16,
|
||||
"maxWidth": 2048,
|
||||
"maxHeight": 2048,
|
||||
"pot": false,
|
||||
"multipleOfFour": false,
|
||||
"square": false,
|
||||
"outputFormat": "png",
|
||||
"jpegQuality": 0.9,
|
||||
"premultiplyAlpha": true,
|
||||
"bleed": false,
|
||||
"scale": [ 1 ],
|
||||
"scaleSuffix": [ "" ],
|
||||
"scaleResampling": [ "bicubic" ],
|
||||
"paddingX": 2,
|
||||
"paddingY": 2,
|
||||
"edgePadding": true,
|
||||
"duplicatePadding": false,
|
||||
"filterMin": "Linear",
|
||||
"filterMag": "Linear",
|
||||
"wrapX": "ClampToEdge",
|
||||
"wrapY": "ClampToEdge",
|
||||
"format": "RGBA8888",
|
||||
"atlasExtension": ".atlas",
|
||||
"combineSubdirectories": false,
|
||||
"flattenPaths": false,
|
||||
"useIndexes": true,
|
||||
"debug": false,
|
||||
"fast": false,
|
||||
"limitMemory": true,
|
||||
"currentProject": true,
|
||||
"packing": "rectangles",
|
||||
"prettyPrint": true,
|
||||
"legacyOutput": false,
|
||||
"webp": null,
|
||||
"bleedIterations": 2,
|
||||
"ignore": false,
|
||||
"separator": "_",
|
||||
"silent": false
|
||||
},
|
||||
"compression": 9,
|
||||
"bruteForce": true,
|
||||
"quantize": true,
|
||||
"quality": 100,
|
||||
"speed": 1,
|
||||
"dither": 0,
|
||||
"maxColors": 256,
|
||||
"pad": false,
|
||||
"msaa": 4,
|
||||
"smoothing": 8,
|
||||
"renderSelection": false,
|
||||
"cropX": 0,
|
||||
"cropY": 0,
|
||||
"open": false
|
||||
}
|
||||
Binary file not shown.
60
examples/spineboy/export/spineboy-run.atlas
Normal file
60
examples/spineboy/export/spineboy-run.atlas
Normal file
@ -0,0 +1,60 @@
|
||||
spineboy-run.png
|
||||
size: 1181, 687
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
spineboy-pro-run
|
||||
index: 8
|
||||
bounds: 2, 371, 303, 314
|
||||
offsets: 11, 22, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 9
|
||||
bounds: 2, 44, 278, 325
|
||||
offsets: 30, 2, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 0
|
||||
bounds: 307, 439, 246, 320
|
||||
offsets: 67, 1, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 3
|
||||
bounds: 629, 443, 242, 320
|
||||
offsets: 12, 20, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 7
|
||||
bounds: 951, 389, 228, 296
|
||||
offsets: 36, 33, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 4
|
||||
bounds: 307, 195, 242, 320
|
||||
offsets: 2, 4, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 5
|
||||
bounds: 629, 200, 241, 316
|
||||
offsets: 8, 3, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 1
|
||||
bounds: 282, 2, 191, 318
|
||||
offsets: 70, 3, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 2
|
||||
bounds: 947, 81, 226, 306
|
||||
offsets: 34, 26, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 6
|
||||
bounds: 629, 4, 194, 316
|
||||
offsets: 68, 4, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
BIN
examples/spineboy/export/spineboy-run.png
Normal file
BIN
examples/spineboy/export/spineboy-run.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 336 KiB |
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=Cp1252
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: com/badlogic/gdx/utils/arial-15.fnt } },
|
||||
com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: com/badlogic/gdx/utils/lsans-15.fnt } },
|
||||
com.badlogic.gdx.graphics.Color: {
|
||||
green: { a: 1, b: 0, g: 1, r: 0 },
|
||||
white: { a: 1, b: 1, g: 1, r: 1 },
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,60 @@
|
||||
spineboy-run.png
|
||||
size: 1181, 687
|
||||
filter: Linear, Linear
|
||||
pma: true
|
||||
spineboy-pro-run
|
||||
index: 8
|
||||
bounds: 2, 371, 303, 314
|
||||
offsets: 11, 22, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 9
|
||||
bounds: 2, 44, 278, 325
|
||||
offsets: 30, 2, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 0
|
||||
bounds: 307, 439, 246, 320
|
||||
offsets: 67, 1, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 3
|
||||
bounds: 629, 443, 242, 320
|
||||
offsets: 12, 20, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 7
|
||||
bounds: 951, 389, 228, 296
|
||||
offsets: 36, 33, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 4
|
||||
bounds: 307, 195, 242, 320
|
||||
offsets: 2, 4, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 5
|
||||
bounds: 629, 200, 241, 316
|
||||
offsets: 8, 3, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 1
|
||||
bounds: 282, 2, 191, 318
|
||||
offsets: 70, 3, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 2
|
||||
bounds: 947, 81, 226, 306
|
||||
offsets: 34, 26, 316, 341
|
||||
origin: 142, 3
|
||||
spineboy-pro-run
|
||||
index: 6
|
||||
bounds: 629, 4, 194, 316
|
||||
offsets: 68, 4, 316, 341
|
||||
rotate: 90
|
||||
origin: 142, 3
|
||||
BIN
spine-libgdx/spine-libgdx-tests/assets/spineboy/spineboy-run.png
Normal file
BIN
spine-libgdx/spine-libgdx-tests/assets/spineboy/spineboy-run.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 336 KiB |
@ -50,6 +50,7 @@ import com.esotericsoftware.spine.attachments.PointAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.Sequence;
|
||||
|
||||
/** Unit tests to ensure {@link AnimationState} is working as expected. */
|
||||
public class AnimationStateTests {
|
||||
final SkeletonJson json = new SkeletonJson(new AttachmentLoader() {
|
||||
public RegionAttachment newRegionAttachment (Skin skin, String name, String path, @Null Sequence sequence) {
|
||||
|
||||
@ -35,7 +35,7 @@ import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
||||
import com.esotericsoftware.spine.Animation.Timeline;
|
||||
import com.esotericsoftware.spine.attachments.Attachment;
|
||||
|
||||
/** Unit tests for {@link AttachmentTimeline}. */
|
||||
/** Unit tests to ensure {@link AttachmentTimeline} is working as expected. */
|
||||
public class AttachmentTimelineTests {
|
||||
private final SkeletonData skeletonData;
|
||||
private final Skeleton skeleton;
|
||||
|
||||
@ -43,9 +43,10 @@ import com.esotericsoftware.spine.attachments.PointAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.Sequence;
|
||||
|
||||
/** Demonstrates loading skeleton data without an atlas and plotting bone transform for each animation. */
|
||||
public class BonePlotting {
|
||||
static public void main (String[] args) throws Exception {
|
||||
// This example shows how to load skeleton data and plot a bone transform for each animation.
|
||||
// Create a skeleton loader that doesn't use an atlas and doesn't create any attachments.
|
||||
SkeletonJson json = new SkeletonJson(new AttachmentLoader() {
|
||||
public RegionAttachment newRegionAttachment (Skin skin, String name, String path, @Null Sequence sequence) {
|
||||
return null;
|
||||
@ -71,17 +72,22 @@ public class BonePlotting {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
SkeletonData skeletonData = json.readSkeletonData(new FileHandle("assets/spineboy/spineboy-ess.json"));
|
||||
Skeleton skeleton = new Skeleton(skeletonData);
|
||||
Bone bone = skeleton.findBone("gun-tip");
|
||||
|
||||
// Pose the skeleton at regular intervals throughout each animation.
|
||||
float fps = 1 / 15f;
|
||||
for (Animation animation : skeletonData.getAnimations()) {
|
||||
float time = 0;
|
||||
while (time < animation.getDuration()) {
|
||||
animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in);
|
||||
skeleton.updateWorldTransform();
|
||||
System.out
|
||||
.println(animation.getName() + "," + bone.getWorldX() + "," + bone.getWorldY() + "," + bone.getWorldRotationX());
|
||||
|
||||
System.out.println(animation.getName() + "," //
|
||||
+ bone.getWorldX() + "," + bone.getWorldY() + "," + bone.getWorldRotationX());
|
||||
|
||||
time += fps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.attachments.Sequence;
|
||||
|
||||
/** Demonstrates positioning physics bodies for a skeleton. */
|
||||
public class Box2DExample extends ApplicationAdapter {
|
||||
SpriteBatch batch;
|
||||
ShapeRenderer renderer;
|
||||
@ -84,8 +85,8 @@ public class Box2DExample extends ApplicationAdapter {
|
||||
|
||||
atlas = new TextureAtlas(Gdx.files.internal("spineboy/spineboy-pma.atlas"));
|
||||
|
||||
// This loader creates Box2dAttachments instead of RegionAttachments for an easy way to keep
|
||||
// track of the Box2D body for each attachment.
|
||||
// This loader creates Box2dAttachments instead of RegionAttachments for an easy way to keep track of the Box2D body for
|
||||
// each attachment.
|
||||
AtlasAttachmentLoader atlasLoader = new AtlasAttachmentLoader(atlas) {
|
||||
public RegionAttachment newRegionAttachment (Skin skin, String name, String path, @Null Sequence sequence) {
|
||||
Box2dAttachment attachment = new Box2dAttachment(name);
|
||||
@ -154,7 +155,7 @@ public class Box2DExample extends ApplicationAdapter {
|
||||
|
||||
batch.end();
|
||||
|
||||
// Position each attachment body.
|
||||
// Position the physics body for each attachment.
|
||||
for (Slot slot : skeleton.getSlots()) {
|
||||
if (!(slot.getAttachment() instanceof Box2dAttachment)) continue;
|
||||
Box2dAttachment attachment = (Box2dAttachment)slot.getAttachment();
|
||||
@ -182,25 +183,19 @@ public class Box2DExample extends ApplicationAdapter {
|
||||
PolygonShape shape = new PolygonShape();
|
||||
shape.set(vertices);
|
||||
|
||||
// next we create a static ground platform. This platform
|
||||
// is not moveable and will not react to any influences from
|
||||
// outside. It will however influence other bodies. First we
|
||||
// create a PolygonShape that holds the form of the platform.
|
||||
// it will be 100 meters wide and 2 meters high, centered
|
||||
// around the origin
|
||||
// Next we create a static ground platform. This platform is not moveable and will not react to any outside influences. It
|
||||
// will however influence other bodies. First we create a PolygonShape that holds the form of the platform. It will be
|
||||
// 100 meters wide and 2 meters high, centered around the origin.
|
||||
PolygonShape groundPoly = new PolygonShape();
|
||||
groundPoly.setAsBox(50, 1);
|
||||
|
||||
// next we create the body for the ground platform. It's
|
||||
// simply a static body.
|
||||
// Next we create the body for the ground platform. It's simply a static body.
|
||||
BodyDef groundBodyDef = new BodyDef();
|
||||
groundBodyDef.type = BodyType.StaticBody;
|
||||
groundBody = world.createBody(groundBodyDef);
|
||||
|
||||
// finally we add a fixture to the body using the polygon
|
||||
// defined above. Note that we have to dispose PolygonShapes
|
||||
// and CircleShapes once they are no longer used. This is the
|
||||
// only time you have to care explicitely for memomry managment.
|
||||
// Finally we add a fixture to the body using the polygon defined above. Note that we have to dispose PolygonShapes and
|
||||
// CircleShapes once they are no longer used. This is the only time you have to care explicitely for memomry managment.
|
||||
FixtureDef fixtureDef = new FixtureDef();
|
||||
fixtureDef.shape = groundPoly;
|
||||
fixtureDef.filter.groupIndex = 0;
|
||||
@ -210,12 +205,10 @@ public class Box2DExample extends ApplicationAdapter {
|
||||
PolygonShape boxPoly = new PolygonShape();
|
||||
boxPoly.setAsBox(1, 1);
|
||||
|
||||
// Next we create the 50 box bodies using the PolygonShape we just
|
||||
// defined. This process is similar to the one we used for the ground
|
||||
// body. Note that we reuse the polygon for each body fixture.
|
||||
// Next we create the 50 box bodies using the PolygonShape we just defined. This process is similar to the one we used for
|
||||
// the ground body. Note that we reuse the polygon for each body fixture.
|
||||
for (int i = 0; i < 45; i++) {
|
||||
// Create the BodyDef, set a random position above the
|
||||
// ground and create a new body
|
||||
// Create the BodyDef, set a random position above the ground and create a new body.
|
||||
BodyDef boxBodyDef = new BodyDef();
|
||||
boxBodyDef.type = BodyType.DynamicBody;
|
||||
boxBodyDef.position.x = -24 + (float)(Math.random() * 48);
|
||||
@ -225,7 +218,7 @@ public class Box2DExample extends ApplicationAdapter {
|
||||
boxBody.createFixture(boxPoly, 1);
|
||||
}
|
||||
|
||||
// we are done, all that's left is disposing the boxPoly
|
||||
// We are done, all that's left is disposing the boxPoly.
|
||||
boxPoly.dispose();
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ import com.esotericsoftware.spine.Animation.EventTimeline;
|
||||
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||
import com.esotericsoftware.spine.Animation.MixDirection;
|
||||
|
||||
/** Unit tests for {@link EventTimeline}. */
|
||||
/** Unit tests to ensure {@link EventTimeline} is working as expected. */
|
||||
public class EventTimelineTests {
|
||||
private final SkeletonData skeletonData;
|
||||
private final Skeleton skeleton;
|
||||
|
||||
@ -44,6 +44,7 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
|
||||
|
||||
/** Demonstrates rendering an animation to a frame buffer (FBO) and then rendering the FBO to the screen. */
|
||||
public class FboTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
TwoColorPolygonBatch batch;
|
||||
|
||||
@ -46,32 +46,22 @@ public class FrameByFrameTest extends ApplicationAdapter {
|
||||
|
||||
TextureAtlas atlas;
|
||||
float time;
|
||||
Animation<AtlasSprite> walkAnimation, deathAnimation, current;
|
||||
Animation<AtlasSprite> walkAnimation, current;
|
||||
|
||||
public void create () {
|
||||
camera = new OrthographicCamera();
|
||||
batch = new PolygonSpriteBatch();
|
||||
|
||||
atlas = new TextureAtlas("spineboy/frame-by-frame.atlas");
|
||||
atlas = new TextureAtlas("spineboy/spineboy-run.atlas");
|
||||
|
||||
walkAnimation = new Animation(1 / 20f, atlas.createSprites("spineboy-pro-walk"));
|
||||
walkAnimation = new Animation(1 / 15f, atlas.createSprites("spineboy-pro-run"));
|
||||
walkAnimation.setPlayMode(PlayMode.LOOP);
|
||||
|
||||
deathAnimation = new Animation(1 / 20f, atlas.createSprites("spineboy-pro-death"));
|
||||
|
||||
current = walkAnimation;
|
||||
}
|
||||
|
||||
public void render () {
|
||||
time += Gdx.graphics.getDeltaTime();
|
||||
if (current == deathAnimation && current.isAnimationFinished(time)) {
|
||||
current = walkAnimation;
|
||||
time = 0;
|
||||
}
|
||||
if (Gdx.input.justTouched()) {
|
||||
current = deathAnimation;
|
||||
time = 0;
|
||||
}
|
||||
|
||||
AtlasSprite frame = current.getKeyFrame(time);
|
||||
float x = Math.round(Gdx.graphics.getWidth() / 2), y = 25;
|
||||
|
||||
@ -37,7 +37,8 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
public class SkinBonesMixAndMatchTest extends ApplicationAdapter {
|
||||
/** Demonstrates creating and configuring a new skin at runtime. */
|
||||
public class MixAndMatchTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
PolygonSpriteBatch batch;
|
||||
SkeletonRenderer renderer;
|
||||
@ -67,13 +68,11 @@ public class SkinBonesMixAndMatchTest extends ApplicationAdapter {
|
||||
AnimationStateData stateData = new AnimationStateData(skeletonData); // Defines mixing (crossfading) between animations.
|
||||
state = new AnimationState(stateData); // Holds the animation state for a skeleton (current animation, time, etc).
|
||||
|
||||
// Queue animations on track 0.
|
||||
// Set animations on track 0.
|
||||
state.setAnimation(0, "dance", 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.
|
||||
// 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.
|
||||
Skin mixAndMatchSkin = new Skin("custom-girl");
|
||||
mixAndMatchSkin.addSkin(skeletonData.findSkin("skin-base"));
|
||||
mixAndMatchSkin.addSkin(skeletonData.findSkin("nose/short"));
|
||||
@ -113,6 +112,6 @@ public class SkinBonesMixAndMatchTest extends ApplicationAdapter {
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
new Lwjgl3Application(new SkinBonesMixAndMatchTest());
|
||||
new Lwjgl3Application(new MixAndMatchTest());
|
||||
}
|
||||
}
|
||||
@ -59,6 +59,9 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||
import com.esotericsoftware.spine.Animation.MixDirection;
|
||||
|
||||
/** Demonstrates simplistic usage of lighting with normal maps.
|
||||
* <p>
|
||||
* Note the normals are not rotated when bones are rotated, making lighting incorrect. */
|
||||
public class NormalMapTest extends ApplicationAdapter {
|
||||
String skeletonPath, animationName;
|
||||
SpriteBatch batch;
|
||||
|
||||
@ -0,0 +1,138 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, 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.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE 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
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||
import com.badlogic.gdx.graphics.PixmapIO;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||
import com.esotericsoftware.spine.Animation.MixDirection;
|
||||
import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
|
||||
|
||||
/** Demonstrates rendering an animation to a frame buffer (FBO) and then writing each frame as a PNG. */
|
||||
public class PngExportTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
TwoColorPolygonBatch batch;
|
||||
SkeletonRenderer renderer;
|
||||
BitmapFont font;
|
||||
|
||||
TextureAtlas atlas;
|
||||
Skeleton skeleton;
|
||||
|
||||
FrameBuffer fbo;
|
||||
TextureRegion fboRegion;
|
||||
boolean drawFbo = true;
|
||||
|
||||
public void create () {
|
||||
camera = new OrthographicCamera();
|
||||
batch = new TwoColorPolygonBatch();
|
||||
renderer = new SkeletonRenderer();
|
||||
renderer.setPremultipliedAlpha(true);
|
||||
font = new BitmapFont();
|
||||
font.setColor(Color.BLACK);
|
||||
|
||||
// Load the atlas and skeleton.
|
||||
atlas = new TextureAtlas(Gdx.files.internal("spineboy/spineboy-pma.atlas"));
|
||||
SkeletonJson json = new SkeletonJson(atlas);
|
||||
json.setScale(0.66f);
|
||||
SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("spineboy/spineboy-ess.json"));
|
||||
|
||||
// Create a skeleton instance, set the position of its root bone, and update its world transform.
|
||||
skeleton = new Skeleton(skeletonData);
|
||||
skeleton.setPosition(250, 20);
|
||||
skeleton.updateWorldTransform();
|
||||
|
||||
// Create an FBO and a texture region.
|
||||
fbo = new FrameBuffer(Pixmap.Format.RGBA8888, 512, 512, false);
|
||||
fboRegion = new TextureRegion(fbo.getColorBufferTexture());
|
||||
|
||||
// Create a pixmap of the same size.
|
||||
Pixmap pixmap = new Pixmap(fbo.getWidth(), fbo.getHeight(), Format.RGBA8888);
|
||||
|
||||
// Configure the camera and batch for rendering to the FBO's size.
|
||||
camera.setToOrtho(true, fbo.getWidth(), fbo.getHeight());
|
||||
camera.update();
|
||||
batch.getProjectionMatrix().set(camera.combined);
|
||||
|
||||
// Start rendering to the FBO.
|
||||
fbo.begin();
|
||||
|
||||
// Pose the skeleton at regular intervals throughout the animation.
|
||||
Animation animation = skeletonData.findAnimation("run");
|
||||
float fps = 1 / 15f, time = 0;
|
||||
int frame = 1;
|
||||
while (time < animation.getDuration()) {
|
||||
animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in);
|
||||
skeleton.updateWorldTransform();
|
||||
|
||||
// Render the skeleton to the FBO.
|
||||
ScreenUtils.clear(0, 0, 0, 0);
|
||||
batch.begin();
|
||||
renderer.draw(batch, skeleton);
|
||||
batch.end();
|
||||
|
||||
// Copy the FBO to the pixmap and write it to a PNG file.
|
||||
String name = animation.getName() + "_" + frame + ".png";
|
||||
System.out.println(name);
|
||||
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); // Have glReadPixels use byte alignment for each pixel row.
|
||||
Gdx.gl.glReadPixels(0, 0, fbo.getWidth(), fbo.getHeight(), GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixmap.getPixels());
|
||||
PixmapIO.writePNG(new FileHandle(name), pixmap);
|
||||
|
||||
frame++;
|
||||
time += fps;
|
||||
}
|
||||
|
||||
pixmap.dispose();
|
||||
fbo.end();
|
||||
|
||||
// Terminate without showing a window.
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
static public void main (String[] args) throws Exception {
|
||||
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
|
||||
config.setInitialVisible(false);
|
||||
new Lwjgl3Application(new PngExportTest(), config);
|
||||
}
|
||||
}
|
||||
@ -35,8 +35,11 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
|
||||
import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
|
||||
|
||||
/** Demonstrates loading, animating, and rendering a skeleton.
|
||||
* @see SkeletonAssetManagerTest */
|
||||
public class SimpleTest1 extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
TwoColorPolygonBatch batch;
|
||||
|
||||
@ -38,11 +38,13 @@ import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
import com.esotericsoftware.spine.AnimationState.AnimationStateListener;
|
||||
import com.esotericsoftware.spine.AnimationState.TrackEntry;
|
||||
import com.esotericsoftware.spine.attachments.BoundingBoxAttachment;
|
||||
import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
|
||||
|
||||
/** Demonstrates loading, animating, and rendering a skeleton with hit detectiong using a bounding box attachment. */
|
||||
public class SimpleTest2 extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
TwoColorPolygonBatch batch;
|
||||
|
||||
@ -37,6 +37,7 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
/** Demonstrates applying multiple animations at once using {@link AnimationState} tracks. */
|
||||
public class SimpleTest3 extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
PolygonSpriteBatch batch;
|
||||
@ -61,7 +62,7 @@ public class SimpleTest3 extends ApplicationAdapter {
|
||||
|
||||
SkeletonJson loader = new SkeletonJson(atlas); // This loads skeleton JSON data, which is stateless.
|
||||
// SkeletonLoader loader = new SkeletonBinary(atlas); // Or use SkeletonBinary to load binary data.
|
||||
loader.setScale(0.1f); // Load the skeleton at 50% the size it was in Spine.
|
||||
loader.setScale(0.5f); // Load the skeleton at 50% the size it was in Spine.
|
||||
SkeletonData skeletonData = loader.readSkeletonData(Gdx.files.internal("raptor/raptor-pro.json"));
|
||||
|
||||
skeleton = new Skeleton(skeletonData); // Skeleton holds skeleton state (bone positions, slot attachments, etc).
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, 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.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE 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
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
|
||||
|
||||
public class SimpleTest4 extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
TwoColorPolygonBatch batch;
|
||||
SkeletonRenderer renderer;
|
||||
SkeletonRendererDebug debugRenderer;
|
||||
|
||||
TextureAtlas atlas;
|
||||
Skeleton skeleton;
|
||||
AnimationState state;
|
||||
|
||||
public void create () {
|
||||
camera = new OrthographicCamera();
|
||||
batch = new TwoColorPolygonBatch();
|
||||
renderer = new SkeletonRenderer();
|
||||
renderer.setPremultipliedAlpha(true); // PMA results in correct blending without outlines.
|
||||
debugRenderer = new SkeletonRendererDebug();
|
||||
debugRenderer.setBoundingBoxes(false);
|
||||
debugRenderer.setRegionAttachments(false);
|
||||
|
||||
atlas = new TextureAtlas(Gdx.files.internal("goblins/goblins-pma.atlas"));
|
||||
|
||||
SkeletonJson loader = new SkeletonJson(atlas); // This loads skeleton JSON data, which is stateless.
|
||||
// SkeletonLoader loader = new SkeletonBinary(atlas); // Or use SkeletonBinary to load binary data.
|
||||
loader.setScale(1.3f); // Load the skeleton at 130% the size it was in Spine.
|
||||
SkeletonData skeletonData = loader.readSkeletonData(Gdx.files.internal("goblins/goblins-pro.json"));
|
||||
|
||||
skeleton = new Skeleton(skeletonData); // Skeleton holds skeleton state (bone positions, slot attachments, etc).
|
||||
skeleton.setPosition(250, 20);
|
||||
|
||||
AnimationStateData stateData = new AnimationStateData(skeletonData); // Defines mixing (crossfading) between animations.
|
||||
|
||||
state = new AnimationState(stateData); // Holds the animation state for a skeleton (current animation, time, etc).
|
||||
state.setTimeScale(0.5f); // Slow all animations down to 50% speed.
|
||||
|
||||
// Queue animations on track 0.
|
||||
state.setAnimation(0, "walk", true);
|
||||
|
||||
// Create an empty skin and copy the goblingirl skin into it.
|
||||
Skin skin = new Skin("test");
|
||||
skin.copySkin(skeletonData.findSkin("goblingirl"));
|
||||
skeleton.setSkin(skin);
|
||||
skeleton.setSlotsToSetupPose();
|
||||
}
|
||||
|
||||
public void render () {
|
||||
state.update(Gdx.graphics.getDeltaTime()); // Update the animation time.
|
||||
|
||||
ScreenUtils.clear(0, 0, 0, 0);
|
||||
|
||||
state.apply(skeleton); // Poses skeleton using current animations. This sets the bones' local SRT.
|
||||
skeleton.updateWorldTransform(); // Uses the bones' local SRT to compute their world SRT.
|
||||
|
||||
// Configure the camera, SpriteBatch, and SkeletonRendererDebug.
|
||||
camera.update();
|
||||
batch.getProjectionMatrix().set(camera.combined);
|
||||
debugRenderer.getShapeRenderer().setProjectionMatrix(camera.combined);
|
||||
|
||||
batch.begin();
|
||||
renderer.draw(batch, skeleton); // Draw the skeleton images.
|
||||
batch.end();
|
||||
|
||||
debugRenderer.draw(skeleton); // Draw debug lines.
|
||||
}
|
||||
|
||||
public void resize (int width, int height) {
|
||||
camera.setToOrtho(false); // Update camera with new size.
|
||||
}
|
||||
|
||||
public void dispose () {
|
||||
atlas.dispose();
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
new Lwjgl3Application(new SimpleTest4());
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.esotericsoftware.spine.utils.SkeletonDataLoader;
|
||||
import com.esotericsoftware.spine.utils.SkeletonDataLoader.SkeletonDataParameter;
|
||||
|
||||
/** Like {@link SimpleTest1}, but using {@link AssetManager} to load the atlas and skeleton data. */
|
||||
/** Demonstrates loading an atlas and skeleton using {@link AssetManager}. */
|
||||
public class SkeletonAssetManagerTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
PolygonSpriteBatch batch;
|
||||
@ -85,8 +85,8 @@ public class SkeletonAssetManagerTest extends ApplicationAdapter {
|
||||
skeleton = new Skeleton(skeletonData); // Skeleton holds skeleton state (bone positions, slot attachments, etc).
|
||||
skeleton.setPosition(250, 20);
|
||||
|
||||
AnimationStateData stateData = new AnimationStateData(skeletonData); // Defines mixing (crossfading) between
|
||||
// animations.
|
||||
// Define the default mixing (crossfading) between animations.
|
||||
AnimationStateData stateData = new AnimationStateData(skeletonData);
|
||||
stateData.setMix("run", "jump", 0.2f);
|
||||
stateData.setMix("jump", "run", 0.2f);
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.attachments.SkeletonAttachment;
|
||||
|
||||
/** Demonstrates using {@link SkeletonAttachment} to use an entire skeleton as an attachment. */
|
||||
public class SkeletonAttachmentTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
PolygonSpriteBatch batch;
|
||||
|
||||
@ -42,6 +42,7 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.vertexeffects.SwirlEffect;
|
||||
|
||||
/** Boilerplate for basic skeleton rendering, used for various testing. */
|
||||
public class TestHarness extends ApplicationAdapter {
|
||||
// static String JSON = "coin/coin-pro.json";
|
||||
// static String ATLAS = "coin/coin-pma.atlas";
|
||||
|
||||
@ -40,7 +40,10 @@ import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.esotericsoftware.spine.Animation.MixBlend;
|
||||
import com.esotericsoftware.spine.Animation.MixDirection;
|
||||
|
||||
public class MixTest extends ApplicationAdapter {
|
||||
/** Demonstrates using the timeline API. See {@link SimpleTest1} for a higher level API using {@link AnimationState}.
|
||||
* <p>
|
||||
* See: http://esotericsoftware.com/spine-applying-animations */
|
||||
public class TimelineApiTest extends ApplicationAdapter {
|
||||
SpriteBatch batch;
|
||||
float time;
|
||||
Array<Event> events = new Array();
|
||||
@ -139,6 +142,6 @@ public class MixTest extends ApplicationAdapter {
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
new Lwjgl3Application(new MixTest());
|
||||
new Lwjgl3Application(new TimelineApiTest());
|
||||
}
|
||||
}
|
||||
@ -39,8 +39,10 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
|
||||
import com.esotericsoftware.spine.SkeletonRenderer.VertexEffect;
|
||||
import com.esotericsoftware.spine.vertexeffects.SwirlEffect;
|
||||
|
||||
/** Demonstrates applying a {@link VertexEffect}. */
|
||||
public class VertexEffectTest extends ApplicationAdapter {
|
||||
OrthographicCamera camera;
|
||||
PolygonSpriteBatch batch;
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=Cp1252
|
||||
@ -364,6 +364,18 @@ public class Skeleton {
|
||||
public void updateWorldTransform (Bone parent) {
|
||||
if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
|
||||
|
||||
Object[] bones = this.bones.items;
|
||||
for (int i = 1, n = this.bones.size; i < n; i++) { // Skip root bone.
|
||||
Bone bone = (Bone)bones[i];
|
||||
bone.ax = bone.x;
|
||||
bone.ay = bone.y;
|
||||
bone.arotation = bone.rotation;
|
||||
bone.ascaleX = bone.scaleX;
|
||||
bone.ascaleY = bone.scaleY;
|
||||
bone.ashearX = bone.shearX;
|
||||
bone.ashearY = bone.shearY;
|
||||
}
|
||||
|
||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||
Bone rootBone = getRootBone();
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=Cp1252
|
||||
@ -455,7 +455,7 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
if (cc.changed) {
|
||||
targetSkeletonDataAsset.FillStateData();
|
||||
targetSkeletonDataAsset.FillStateData(quiet: true);
|
||||
EditorUtility.SetDirty(targetSkeletonDataAsset);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
@ -61,11 +61,34 @@ namespace Spine.Unity.Editor {
|
||||
return noneLabel;
|
||||
}
|
||||
|
||||
static GUIStyle errorPopupStyle;
|
||||
GUIStyle ErrorPopupStyle {
|
||||
get {
|
||||
if (errorPopupStyle == null) errorPopupStyle = new GUIStyle(EditorStyles.popup);
|
||||
errorPopupStyle.normal.textColor = Color.red;
|
||||
errorPopupStyle.hover.textColor = Color.red;
|
||||
errorPopupStyle.focused.textColor = Color.red;
|
||||
errorPopupStyle.active.textColor = Color.red;
|
||||
return errorPopupStyle;
|
||||
}
|
||||
}
|
||||
|
||||
protected T TargetAttribute { get { return (T)attribute; } }
|
||||
protected SerializedProperty SerializedProperty { get; private set; }
|
||||
|
||||
protected abstract Texture2D Icon { get; }
|
||||
|
||||
protected bool IsValueValid (SerializedProperty property) {
|
||||
if (skeletonDataAsset != null) {
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (skeletonData != null && !string.IsNullOrEmpty(property.stringValue))
|
||||
return IsValueValid(skeletonData, property);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) { return true; }
|
||||
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
SerializedProperty = property;
|
||||
|
||||
@ -123,8 +146,10 @@ namespace Spine.Unity.Editor {
|
||||
position = EditorGUI.PrefixLabel(position, label);
|
||||
|
||||
Texture2D image = Icon;
|
||||
GUIStyle usedStyle = IsValueValid(property) ? EditorStyles.popup : ErrorPopupStyle;
|
||||
string propertyStringValue = (property.hasMultipleDifferentValues) ? SpineInspectorUtility.EmDash : property.stringValue;
|
||||
if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : SpineInspectorUtility.TempContent(propertyStringValue, image), EditorStyles.popup))
|
||||
if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) :
|
||||
SpineInspectorUtility.TempContent(propertyStringValue, image), usedStyle))
|
||||
Selector(property);
|
||||
}
|
||||
|
||||
@ -174,6 +199,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.slot; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindSlot(property.stringValue) != null;
|
||||
}
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineSlot targetAttribute, SkeletonData data) {
|
||||
if (TargetAttribute.includeNone)
|
||||
menu.AddItem(new GUIContent(NoneString), !property.hasMultipleDifferentValues && string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property));
|
||||
@ -223,6 +252,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
internal override string NoneString { get { return TargetAttribute.defaultAsEmptyString ? DefaultSkinName : NoneStringConstant; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindSkin(property.stringValue) != null;
|
||||
}
|
||||
|
||||
public static void GetSkinMenuItems (SkeletonData data, List<string> outputNames, List<GUIContent> outputMenuItems, bool includeNone = true) {
|
||||
if (data == null) return;
|
||||
if (outputNames == null) return;
|
||||
@ -269,6 +302,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.animation; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindAnimation(property.stringValue) != null;
|
||||
}
|
||||
|
||||
public static void GetAnimationMenuItems (SkeletonData data, List<string> outputNames, List<GUIContent> outputMenuItems, bool includeNone = true) {
|
||||
if (data == null) return;
|
||||
if (outputNames == null) return;
|
||||
@ -311,6 +348,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.userEvent; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindEvent(property.stringValue) != null;
|
||||
}
|
||||
|
||||
public static void GetEventMenuItems (SkeletonData data, List<string> eventNames, List<GUIContent> menuItems, bool includeNone = true) {
|
||||
if (data == null) return;
|
||||
|
||||
@ -356,6 +397,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintIK; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindIkConstraint(property.stringValue) != null;
|
||||
}
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineIkConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).IkConstraints;
|
||||
|
||||
@ -376,6 +421,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintTransform; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindTransformConstraint(property.stringValue) != null;
|
||||
}
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineTransformConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).TransformConstraints;
|
||||
|
||||
@ -395,6 +444,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintPath; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindPathConstraint(property.stringValue) != null;
|
||||
}
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpinePathConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).PathConstraints;
|
||||
|
||||
@ -516,6 +569,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.bone; } }
|
||||
|
||||
protected override bool IsValueValid (SkeletonData skeletonData, SerializedProperty property) {
|
||||
return skeletonData.FindBone(property.stringValue) != null;
|
||||
}
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineBone targetAttribute, SkeletonData data) {
|
||||
menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name));
|
||||
menu.AddSeparator("");
|
||||
|
||||
@ -349,6 +349,8 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
AddDependentAtlasIfImageChanged(atlasPaths, imagePaths);
|
||||
|
||||
// Import atlases first.
|
||||
var newAtlases = new List<AtlasAssetBase>();
|
||||
foreach (string ap in atlasPaths) {
|
||||
@ -453,6 +455,18 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
static void AddDependentAtlasIfImageChanged (List<string> atlasPaths, List<string> imagePaths) {
|
||||
foreach (var imagePath in imagePaths) {
|
||||
string atlasPath = imagePath.Replace(".png", ".atlas.txt");
|
||||
if (!System.IO.File.Exists(atlasPath))
|
||||
continue;
|
||||
|
||||
if (!atlasPaths.Contains(atlasPath)) {
|
||||
atlasPaths.Add(atlasPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AddDependentSkeletonIfAtlasChanged (List<PathAndProblemInfo> skeletonPaths, List<string> atlasPaths) {
|
||||
foreach (var atlasPath in atlasPaths) {
|
||||
string skeletonPathJson = atlasPath.Replace(".atlas.txt", ".json");
|
||||
|
||||
@ -217,14 +217,30 @@ namespace Spine.Unity {
|
||||
FillStateData();
|
||||
}
|
||||
|
||||
public void FillStateData () {
|
||||
public void FillStateData (bool quiet = false) {
|
||||
if (stateData != null) {
|
||||
stateData.DefaultMix = defaultMix;
|
||||
|
||||
for (int i = 0, n = fromAnimation.Length; i < n; i++) {
|
||||
if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
|
||||
string fromAnimationName = fromAnimation[i];
|
||||
string toAnimationName = toAnimation[i];
|
||||
if (fromAnimationName.Length == 0 || toAnimationName.Length == 0)
|
||||
continue;
|
||||
stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
|
||||
#if UNITY_EDITOR
|
||||
if (skeletonData.FindAnimation(fromAnimationName) == null) {
|
||||
if (!quiet) Debug.LogError(
|
||||
string.Format("Custom Mix Durations: Animation '{0}' not found, was it renamed?",
|
||||
fromAnimationName), this);
|
||||
continue;
|
||||
}
|
||||
if (skeletonData.FindAnimation(toAnimationName) == null) {
|
||||
if (!quiet) Debug.LogError(
|
||||
string.Format("Custom Mix Durations: Animation '{0}' not found, was it renamed?",
|
||||
toAnimationName), this);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
stateData.SetMix(fromAnimationName, toAnimationName, duration[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,14 +52,23 @@ namespace Spine.Unity.AttachmentTools {
|
||||
/// <param name="useOriginalRegionScale">If <c>true</c> and the original Attachment is a RegionAttachment, then
|
||||
/// the original region's scale value is used instead of the Sprite's pixels per unit property. Since uniform scale is used,
|
||||
/// x scale of the original attachment (width scale) is used, scale in y direction (height scale) is ignored.</param>
|
||||
/// <param name="pmaCloneTextureFormat">If <c>premultiplyAlpha</c> is <c>true></c>, the TextureFormat of the
|
||||
/// newly created PMA attachment Texture.</param>
|
||||
/// <param name="pmaCloneMipmaps">If <c>premultiplyAlpha</c> is <ctrue></c>, whether the newly created
|
||||
/// PMA attachment Texture has mipmaps enabled.</param>
|
||||
/// <remarks>When parameter <c>premultiplyAlpha</c> is set to <c>true</c>, a premultiply alpha clone of the
|
||||
/// original texture will be created. Additionally, this PMA Texture clone is cached for later re-use,
|
||||
/// which might steadily increase the Texture memory footprint when used excessively.
|
||||
/// See <see cref="AtlasUtilities.ClearCache()"/> on how to clear these cached textures.</remarks>
|
||||
public static Attachment GetRemappedClone (this Attachment o, Sprite sprite, Material sourceMaterial,
|
||||
bool premultiplyAlpha = true, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false,
|
||||
bool pivotShiftsMeshUVCoords = true, bool useOriginalRegionScale = false) {
|
||||
var atlasRegion = premultiplyAlpha ? sprite.ToAtlasRegionPMAClone(sourceMaterial) : sprite.ToAtlasRegion(new Material(sourceMaterial) { mainTexture = sprite.texture });
|
||||
bool pivotShiftsMeshUVCoords = true, bool useOriginalRegionScale = false,
|
||||
TextureFormat pmaCloneTextureFormat = AtlasUtilities.SpineTextureFormat,
|
||||
bool pmaCloneMipmaps = AtlasUtilities.UseMipMaps) {
|
||||
|
||||
var atlasRegion = premultiplyAlpha ?
|
||||
sprite.ToAtlasRegionPMAClone(sourceMaterial, pmaCloneTextureFormat, pmaCloneMipmaps) :
|
||||
sprite.ToAtlasRegion(new Material(sourceMaterial) { mainTexture = sprite.texture });
|
||||
if (!pivotShiftsMeshUVCoords && o is MeshAttachment) {
|
||||
// prevent non-central sprite pivot setting offsetX/Y and shifting uv coords out of mesh bounds
|
||||
atlasRegion.offsetX = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user