mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 15:24:55 +08:00
Add more documentation
This commit is contained in:
parent
ae5ae1e1a1
commit
42be887994
@ -112,11 +112,11 @@ fun DressUp(nav: NavHostController) {
|
||||
skeleton.setToSetupPose()
|
||||
skeleton.update(0f)
|
||||
skeleton.updateWorldTransform(Skeleton.Physics.update)
|
||||
skinImages[skin.getName()] = drawable.renderToBitmap(
|
||||
renderer,
|
||||
skinImages[skin.getName()] = renderer.renderToBitmap(
|
||||
with(localDensity) { thumbnailSize.dp.toPx() },
|
||||
with(localDensity) { thumbnailSize.dp.toPx() },
|
||||
0xffffffff.toInt()
|
||||
0xffffffff.toInt(),
|
||||
skeleton,
|
||||
).asImageBitmap()
|
||||
selectedSkins[skin.getName()] = false
|
||||
}
|
||||
|
||||
@ -7,7 +7,9 @@ import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.esotericsoftware.spine.Animation;
|
||||
import com.esotericsoftware.spine.AnimationState;
|
||||
import com.esotericsoftware.spine.AnimationStateData;
|
||||
import com.esotericsoftware.spine.Skeleton;
|
||||
@ -17,6 +19,25 @@ import com.esotericsoftware.spine.android.utils.SkeletonDataUtils;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* A {@link AndroidSkeletonDrawable} bundles loading updating updating an {@link AndroidTextureAtlas}, {@link Skeleton}, and {@link AnimationState}
|
||||
* into a single easy-to-use class.
|
||||
*
|
||||
* Use the {@link AndroidSkeletonDrawable#fromAsset(String, String, Context)}, {@link AndroidSkeletonDrawable#fromFile(File, File)},
|
||||
* or {@link AndroidSkeletonDrawable#fromHttp(URL, URL, File)} methods to construct a {@link AndroidSkeletonDrawable}. To have
|
||||
* multiple skeleton drawable instances share the same {@link AndroidTextureAtlas} and {@link SkeletonData}, use the constructor.
|
||||
*
|
||||
* You can then directly access the {@link AndroidSkeletonDrawable#getAtlas()}, {@link AndroidSkeletonDrawable#getSkeletonData()},
|
||||
* {@link AndroidSkeletonDrawable#getSkeleton()}, {@link AndroidSkeletonDrawable#getAnimationStateData()}, and {@link AndroidSkeletonDrawable#getAnimationState()}
|
||||
* to query and animate the skeleton. Use the {@link AnimationState} to queue animations on one or more tracks
|
||||
* via {@link AnimationState#setAnimation(int, Animation, boolean)} or {@link AnimationState#addAnimation(int, Animation, boolean, float)}.
|
||||
*
|
||||
* To update the {@link AnimationState} and apply it to the {@link Skeleton}, call the {@link AndroidSkeletonDrawable#update(float)} function, providing it
|
||||
* a delta time in seconds to advance the animations.
|
||||
*
|
||||
* To render the current pose of the {@link Skeleton}, use {@link SkeletonRenderer#render(Skeleton)}, {@link SkeletonRenderer#renderToCanvas(Canvas, Array)},
|
||||
* {@link SkeletonRenderer#renderToBitmap(float, float, int, Skeleton)}, depending on your needs.
|
||||
*/
|
||||
public class AndroidSkeletonDrawable {
|
||||
|
||||
private final AndroidTextureAtlas atlas;
|
||||
@ -29,6 +50,9 @@ public class AndroidSkeletonDrawable {
|
||||
|
||||
private final AnimationState animationState;
|
||||
|
||||
/**
|
||||
* Constructs a new skeleton drawable from the given (possibly shared) {@link AndroidTextureAtlas} and {@link SkeletonData}.
|
||||
*/
|
||||
public AndroidSkeletonDrawable(AndroidTextureAtlas atlas, SkeletonData skeletonData) {
|
||||
this.atlas = atlas;
|
||||
this.skeletonData = skeletonData;
|
||||
@ -40,6 +64,11 @@ public class AndroidSkeletonDrawable {
|
||||
skeleton.updateWorldTransform(Skeleton.Physics.none);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link AnimationState} using the {@code delta} time given in seconds, applies the
|
||||
* animation state to the {@link Skeleton} and updates the world transforms of the skeleton
|
||||
* to calculate its current pose.
|
||||
*/
|
||||
public void update(float delta) {
|
||||
animationState.update(delta);
|
||||
animationState.apply(skeleton);
|
||||
@ -48,71 +77,71 @@ public class AndroidSkeletonDrawable {
|
||||
skeleton.updateWorldTransform(Skeleton.Physics.update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link AndroidTextureAtlas}
|
||||
*/
|
||||
public AndroidTextureAtlas getAtlas() {
|
||||
return atlas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Skeleton}
|
||||
*/
|
||||
public Skeleton getSkeleton() {
|
||||
return skeleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link SkeletonData}
|
||||
*/
|
||||
public SkeletonData getSkeletonData() {
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link AnimationStateData}
|
||||
*/
|
||||
public AnimationStateData getAnimationStateData() {
|
||||
return animationStateData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link AnimationState}
|
||||
*/
|
||||
public AnimationState getAnimationState() {
|
||||
return animationState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new skeleton drawable from the {@code atlasFileName} and {@code skeletonFileName} from the the apps resources using {@link Context}.
|
||||
*
|
||||
* Throws an exception in case the data could not be loaded.
|
||||
*/
|
||||
public static AndroidSkeletonDrawable fromAsset (String atlasFileName, String skeletonFileName, Context context) {
|
||||
AndroidTextureAtlas atlas = AndroidTextureAtlas.fromAsset(atlasFileName, context);
|
||||
SkeletonData skeletonData = SkeletonDataUtils.fromAsset(atlas, skeletonFileName, context);
|
||||
return new AndroidSkeletonDrawable(atlas, skeletonData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new skeleton drawable from the {@code atlasFile} and {@code skeletonFile}.
|
||||
*
|
||||
* Throws an exception in case the data could not be loaded.
|
||||
*/
|
||||
public static AndroidSkeletonDrawable fromFile (File atlasFile, File skeletonFile) {
|
||||
AndroidTextureAtlas atlas = AndroidTextureAtlas.fromFile(atlasFile);
|
||||
SkeletonData skeletonData = SkeletonDataUtils.fromFile(atlas, skeletonFile);
|
||||
return new AndroidSkeletonDrawable(atlas, skeletonData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new skeleton drawable from the {@code atlasUrl} and {@code skeletonUrl}.
|
||||
*
|
||||
* Throws an exception in case the data could not be loaded.
|
||||
*/
|
||||
public static AndroidSkeletonDrawable fromHttp (URL atlasUrl, URL skeletonUrl, File targetDirectory) {
|
||||
AndroidTextureAtlas atlas = AndroidTextureAtlas.fromHttp(atlasUrl, targetDirectory);
|
||||
SkeletonData skeletonData = SkeletonDataUtils.fromHttp(atlas, skeletonUrl, targetDirectory);
|
||||
return new AndroidSkeletonDrawable(atlas, skeletonData);
|
||||
}
|
||||
|
||||
public Bitmap renderToBitmap(SkeletonRenderer renderer, float width, float height, int bgColor) {
|
||||
Vector2 offset = new Vector2(0, 0);
|
||||
Vector2 size = new Vector2(0, 0);
|
||||
FloatArray floatArray = new FloatArray();
|
||||
|
||||
getSkeleton().getBounds(offset, size, floatArray);
|
||||
|
||||
RectF bounds = new RectF(offset.x, offset.y, offset.x + size.x, offset.y + size.y);
|
||||
float scale = (1 / (bounds.width() > bounds.height() ? bounds.width() / width : bounds.height() / height));
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(bgColor);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
||||
// Draw background
|
||||
canvas.drawRect(0, 0, width, height, paint);
|
||||
|
||||
// Transform canvas
|
||||
canvas.translate(width / 2, height / 2);
|
||||
canvas.scale(scale, -scale);
|
||||
canvas.translate(-(bounds.left + bounds.width() / 2), -(bounds.top + bounds.height() / 2));
|
||||
|
||||
renderer.render(canvas, renderer.render(skeleton));
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,10 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Shader;
|
||||
|
||||
/**
|
||||
* A class holding an {@link Bitmap} of an {@link AndroidTextureAtlas} page image with it's associated
|
||||
* blend modes and paints.
|
||||
*/
|
||||
public class AndroidTexture extends Texture {
|
||||
private Bitmap bitmap;
|
||||
private ObjectMap<BlendMode, Paint> paints = new ObjectMap<>();
|
||||
|
||||
@ -49,16 +49,25 @@ import com.esotericsoftware.spine.android.utils.HttpUtils;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Build;
|
||||
|
||||
/**
|
||||
* Atlas data loaded from a `.atlas` file and its corresponding `.png` files. For each atlas image,
|
||||
* a corresponding {@link Bitmap} and {@link Paint} is constructed, which are used when rendering a skeleton
|
||||
* that uses this atlas.
|
||||
*
|
||||
* Use the static methods {@link AndroidTextureAtlas#fromAsset(String, Context)}, {@link AndroidTextureAtlas#fromFile(File)},
|
||||
* and {@link AndroidTextureAtlas#fromHttp(URL, File)} to load an atlas.
|
||||
*/
|
||||
public class AndroidTextureAtlas {
|
||||
private static interface BitmapLoader {
|
||||
private interface BitmapLoader {
|
||||
Bitmap load (String path);
|
||||
}
|
||||
|
||||
private Array<AndroidTexture> textures = new Array<>();
|
||||
private Array<AtlasRegion> regions = new Array<>();
|
||||
private final Array<AndroidTexture> textures = new Array<>();
|
||||
private final Array<AtlasRegion> regions = new Array<>();
|
||||
|
||||
private AndroidTextureAtlas (TextureAtlasData data, BitmapLoader bitmapLoader) {
|
||||
for (TextureAtlasData.Page page : data.getPages()) {
|
||||
@ -85,8 +94,10 @@ public class AndroidTextureAtlas {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the first region found with the specified name. This method uses string comparison to find the region, so the
|
||||
* result should be cached rather than calling this method multiple times. */
|
||||
/**
|
||||
* Returns the first region found with the specified name. This method uses string comparison to find the region, so the
|
||||
* result should be cached rather than calling this method multiple times.
|
||||
*/
|
||||
public @Null AtlasRegion findRegion (String name) {
|
||||
for (int i = 0, n = regions.size; i < n; i++)
|
||||
if (regions.get(i).name.equals(name)) return regions.get(i);
|
||||
@ -101,7 +112,12 @@ public class AndroidTextureAtlas {
|
||||
return regions;
|
||||
}
|
||||
|
||||
static public AndroidTextureAtlas fromAsset(String atlasFileName, Context context) {
|
||||
/**
|
||||
* Loads an {@link AndroidTextureAtlas} from the file {@code atlasFileName} from assets using {@link Context}.
|
||||
*
|
||||
* Throws a {@link RuntimeException} in case the atlas could not be loaded.
|
||||
*/
|
||||
public static AndroidTextureAtlas fromAsset(String atlasFileName, Context context) {
|
||||
TextureAtlasData data = new TextureAtlasData();
|
||||
AssetManager assetManager = context.getAssets();
|
||||
|
||||
@ -131,7 +147,12 @@ public class AndroidTextureAtlas {
|
||||
});
|
||||
}
|
||||
|
||||
static public AndroidTextureAtlas fromFile(File atlasFile) {
|
||||
/**
|
||||
* Loads an {@link AndroidTextureAtlas} from the file {@code atlasFileName}.
|
||||
*
|
||||
* Throws a {@link RuntimeException} in case the atlas could not be loaded.
|
||||
*/
|
||||
public static AndroidTextureAtlas fromFile(File atlasFile) {
|
||||
TextureAtlasData data;
|
||||
try {
|
||||
data = loadTextureAtlasData(atlasFile);
|
||||
@ -148,7 +169,12 @@ public class AndroidTextureAtlas {
|
||||
});
|
||||
}
|
||||
|
||||
static public AndroidTextureAtlas fromHttp(URL atlasUrl, File targetDirectory) {
|
||||
/**
|
||||
* Loads an {@link AndroidTextureAtlas} from the URL {@code atlasURL}.
|
||||
*
|
||||
* Throws a {@link Exception} in case the atlas could not be loaded.
|
||||
*/
|
||||
public static AndroidTextureAtlas fromHttp(URL atlasUrl, File targetDirectory) {
|
||||
File atlasFile = HttpUtils.downloadFrom(atlasUrl, targetDirectory);
|
||||
TextureAtlasData data;
|
||||
try {
|
||||
@ -188,7 +214,7 @@ public class AndroidTextureAtlas {
|
||||
}
|
||||
}
|
||||
|
||||
static private TextureAtlasData loadTextureAtlasData(File atlasFile) {
|
||||
private static TextureAtlasData loadTextureAtlasData(File atlasFile) {
|
||||
TextureAtlasData data = new TextureAtlasData();
|
||||
FileHandle inputFile = new FileHandle() {
|
||||
@Override
|
||||
|
||||
@ -7,6 +7,10 @@ import android.graphics.RectF;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.esotericsoftware.spine.Bone;
|
||||
|
||||
/**
|
||||
* Renders debug information for a {@link AndroidSkeletonDrawable}, like bone locations, to a {@link Canvas}.
|
||||
* See {@link DebugRenderer#render}.
|
||||
*/
|
||||
public class DebugRenderer {
|
||||
|
||||
public void render(AndroidSkeletonDrawable drawable, Canvas canvas, Array<SkeletonRenderer.RenderCommand> commands) {
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
package com.esotericsoftware.spine.android;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
@ -44,9 +45,22 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
|
||||
import com.esotericsoftware.spine.attachments.RegionAttachment;
|
||||
import com.esotericsoftware.spine.utils.SkeletonClipping;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
/**
|
||||
* Is responsible to transform the {@link Skeleton} with its current pose to {@link SkeletonRenderer.RenderCommand} commands
|
||||
* and render them to a {@link Canvas}.
|
||||
*/
|
||||
public class SkeletonRenderer {
|
||||
|
||||
/**
|
||||
* Stores the vertices, indices, and atlas page index to be used for rendering one or more attachments
|
||||
* of a {@link Skeleton} to a {@link Canvas}. See the implementation of {@link SkeletonRenderer#render(Skeleton)} and
|
||||
* {@link SkeletonRenderer#renderToCanvas(Canvas, Array)} on how to use this data to render it to a {@link Canvas}.
|
||||
*/
|
||||
public static class RenderCommand implements Pool.Poolable {
|
||||
FloatArray vertices = new FloatArray(32);
|
||||
FloatArray uvs = new FloatArray(32);
|
||||
@ -76,7 +90,10 @@ public class SkeletonRenderer {
|
||||
};
|
||||
private final Array<RenderCommand> commandList = new Array<RenderCommand>();
|
||||
|
||||
public Array<RenderCommand> render (Skeleton skeleton) {
|
||||
/**
|
||||
* Created the {@link RenderCommand} commands from the skeletons current pose.
|
||||
*/
|
||||
public Array<RenderCommand> render(Skeleton skeleton) {
|
||||
Color color = null, skeletonColor = skeleton.getColor();
|
||||
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
|
||||
|
||||
@ -211,7 +228,11 @@ public class SkeletonRenderer {
|
||||
return commandList;
|
||||
}
|
||||
|
||||
public void render (Canvas canvas, Array<RenderCommand> commands) {
|
||||
/**
|
||||
* Renders the {@link RenderCommand} commands created from the skeleton current pose to the given {@link Canvas}.
|
||||
* Does not perform any scaling or fitting.
|
||||
*/
|
||||
public void renderToCanvas(Canvas canvas, Array<RenderCommand> commands) {
|
||||
for (int i = 0; i < commands.size; i++) {
|
||||
RenderCommand command = commands.get(i);
|
||||
|
||||
@ -219,4 +240,42 @@ public class SkeletonRenderer {
|
||||
command.colors.items, 0, command.indices.items, 0, command.indices.size, command.texture.getPaint(command.blendMode));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@link Skeleton} with its current pose to a {@link Bitmap}.
|
||||
*
|
||||
* @param width The width of the bitmap in pixels.
|
||||
* @param height The height of the bitmap in pixels.
|
||||
* @param bgColor The background color.
|
||||
* @param skeleton The skeleton to render.
|
||||
*/
|
||||
public Bitmap renderToBitmap(float width, float height, int bgColor, Skeleton skeleton) {
|
||||
Vector2 offset = new Vector2(0, 0);
|
||||
Vector2 size = new Vector2(0, 0);
|
||||
FloatArray floatArray = new FloatArray();
|
||||
|
||||
skeleton.getBounds(offset, size, floatArray);
|
||||
|
||||
RectF bounds = new RectF(offset.x, offset.y, offset.x + size.x, offset.y + size.y);
|
||||
float scale = (1 / (bounds.width() > bounds.height() ? bounds.width() / width : bounds.height() / height));
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(bgColor);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
||||
// Draw background
|
||||
canvas.drawRect(0, 0, width, height, paint);
|
||||
|
||||
// Transform canvas
|
||||
canvas.translate(width / 2, height / 2);
|
||||
canvas.scale(scale, -scale);
|
||||
canvas.translate(-(bounds.left + bounds.width() / 2), -(bounds.top + bounds.height() / 2));
|
||||
|
||||
renderToCanvas(canvas, render(skeleton));
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +424,7 @@ public class SpineView extends View implements Choreographer.FrameCallback {
|
||||
|
||||
controller.callOnBeforePaint(canvas);
|
||||
Array<SkeletonRenderer.RenderCommand> commands = renderer.render(controller.getSkeleton());
|
||||
renderer.render(canvas, commands);
|
||||
renderer.renderToCanvas(canvas, commands);
|
||||
controller.callOnAfterPaint(canvas, commands);
|
||||
|
||||
canvas.restore();
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package com.esotericsoftware.spine.android.bounds;
|
||||
|
||||
/**
|
||||
* How a view should be aligned within another view.
|
||||
*/
|
||||
public enum Alignment {
|
||||
TOP_LEFT(-1.0f, -1.0f),
|
||||
TOP_CENTER(0.0f, -1.0f),
|
||||
|
||||
@ -4,6 +4,10 @@ import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.esotericsoftware.spine.Skeleton;
|
||||
|
||||
/**
|
||||
* Bounds denoted by the top left corner coordinates {@code x} and {@code y}
|
||||
* and the {@code width} and {@code height}.
|
||||
*/
|
||||
public class Bounds {
|
||||
private double x;
|
||||
private double y;
|
||||
|
||||
@ -2,6 +2,10 @@ package com.esotericsoftware.spine.android.bounds;
|
||||
|
||||
import com.esotericsoftware.spine.android.AndroidSkeletonDrawable;
|
||||
|
||||
/**
|
||||
* A {@link BoundsProvider} that calculates the bounding box of the skeleton based on the visible
|
||||
* attachments in the setup pose.
|
||||
*/
|
||||
public interface BoundsProvider {
|
||||
Bounds computeBounds(AndroidSkeletonDrawable drawable);
|
||||
}
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
package com.esotericsoftware.spine.android.bounds;
|
||||
|
||||
/**
|
||||
* How a view should be inscribed into another view.
|
||||
*/
|
||||
public enum ContentMode {
|
||||
/**
|
||||
* As large as possible while still containing the source view entirely within the target view.
|
||||
*/
|
||||
FIT,
|
||||
FILL;
|
||||
/**
|
||||
* Fill the target view by distorting the source's aspect ratio.
|
||||
*/
|
||||
FILL
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package com.esotericsoftware.spine.android.bounds;
|
||||
import com.esotericsoftware.spine.android.AndroidSkeletonDrawable;
|
||||
|
||||
/**
|
||||
* A {@link BoundsProvider} that returns fixed bounds.
|
||||
*/
|
||||
public class RawBounds implements BoundsProvider {
|
||||
final Double x;
|
||||
final Double y;
|
||||
final Double width;
|
||||
final Double height;
|
||||
|
||||
public RawBounds(Double x, Double y, Double width, Double height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bounds computeBounds(AndroidSkeletonDrawable drawable) {
|
||||
return new Bounds(x, y, width, height);
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,10 @@ import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.esotericsoftware.spine.android.AndroidSkeletonDrawable;
|
||||
|
||||
/**
|
||||
* A {@link BoundsProvider} that calculates the bounding box of the skeleton based on the visible
|
||||
* attachments in the setup pose.
|
||||
*/
|
||||
public class SetupPoseBounds implements BoundsProvider {
|
||||
|
||||
@Override
|
||||
|
||||
@ -8,22 +8,40 @@ import com.esotericsoftware.spine.android.AndroidSkeletonDrawable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link BoundsProvider} that calculates the bounding box needed for a combination of skins
|
||||
* and an animation.
|
||||
*/
|
||||
public class SkinAndAnimationBounds implements BoundsProvider {
|
||||
private final List<String> skins;
|
||||
private final String animation;
|
||||
private final double stepTime;
|
||||
|
||||
// Constructor
|
||||
/**
|
||||
* Constructs a new provider that will use the given {@code skins} and {@code animation} to calculate
|
||||
* the bounding box of the skeleton. If no skins are given, the default skin is used.
|
||||
* The {@code stepTime}, given in seconds, defines at what interval the bounds should be sampled
|
||||
* across the entire animation.
|
||||
*/
|
||||
public SkinAndAnimationBounds(List<String> skins, String animation, double stepTime) {
|
||||
this.skins = (skins == null || skins.isEmpty()) ? Collections.singletonList("default") : skins;
|
||||
this.animation = animation;
|
||||
this.stepTime = stepTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new provider that will use the given {@code skins} and {@code animation} to calculate
|
||||
* the bounding box of the skeleton. If no skins are given, the default skin is used.
|
||||
* The {@code stepTime} has default value 0.1.
|
||||
*/
|
||||
public SkinAndAnimationBounds(List<String> skins, String animation) {
|
||||
this(skins, animation, 0.1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new provider that will use the given {@code skins} and {@code animation} to calculate
|
||||
* the bounding box of the skeleton. The default skin is used. The {@code stepTime} has default value 0.1.
|
||||
*/
|
||||
public SkinAndAnimationBounds(String animation) {
|
||||
this(Collections.emptyList(), animation, 0.1);
|
||||
}
|
||||
|
||||
@ -12,8 +12,14 @@ import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Helper to load http resources.
|
||||
*/
|
||||
public class HttpUtils {
|
||||
|
||||
/**
|
||||
* Download a file from an url into a target directory. It keeps the name from the {@code url}.
|
||||
* This should NOT be executed on the main run loop.
|
||||
*/
|
||||
public static File downloadFrom(URL url, File targetDirectory) throws RuntimeException {
|
||||
HttpURLConnection urlConnection = null;
|
||||
InputStream inputStream = null;
|
||||
|
||||
@ -17,8 +17,17 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Helper to load {@link SkeletonData} from assets.
|
||||
*/
|
||||
public class SkeletonDataUtils {
|
||||
|
||||
/**
|
||||
* Loads a {@link SkeletonData} from the file {@code skeletonFile} in assets using {@link Context}.
|
||||
* Uses the provided {@link AndroidTextureAtlas} to resolve attachment images.
|
||||
*
|
||||
* Throws a {@link RuntimeException} in case the skeleton data could not be loaded.
|
||||
*/
|
||||
public static SkeletonData fromAsset(AndroidTextureAtlas atlas, String skeletonFileName, Context context) {
|
||||
AndroidAtlasAttachmentLoader attachmentLoader = new AndroidAtlasAttachmentLoader(atlas);
|
||||
|
||||
@ -39,6 +48,12 @@ public class SkeletonDataUtils {
|
||||
}
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a {@link SkeletonData} from the file {@code skeletonFile}. Uses the provided {@link AndroidTextureAtlas} to resolve attachment images.
|
||||
*
|
||||
* Throws a {@link RuntimeException} in case the skeleton data could not be loaded.
|
||||
*/
|
||||
public static SkeletonData fromFile(AndroidTextureAtlas atlas, File skeletonFile) {
|
||||
AndroidAtlasAttachmentLoader attachmentLoader = new AndroidAtlasAttachmentLoader(atlas);
|
||||
|
||||
@ -52,6 +67,11 @@ public class SkeletonDataUtils {
|
||||
return skeletonLoader.readSkeletonData(new FileHandle(skeletonFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a {@link SkeletonData} from the URL {@code skeletonURL}. Uses the provided {@link AndroidTextureAtlas} to resolve attachment images.
|
||||
*
|
||||
* Throws a {@link RuntimeException} in case the skeleton data could not be loaded.
|
||||
*/
|
||||
public static SkeletonData fromHttp(AndroidTextureAtlas atlas, URL skeletonUrl, File targetDirectory) {
|
||||
File skeletonFile = HttpUtils.downloadFrom(skeletonUrl, targetDirectory);
|
||||
return fromFile(atlas, skeletonFile);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user