Rename files and document SpineController

This commit is contained in:
Denis Andrasec 2024-07-19 11:09:12 +02:00
parent 3428662684
commit 093ba489cc
9 changed files with 131 additions and 24 deletions

View File

@ -44,7 +44,7 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Null;
import com.esotericsoftware.spine.android.utils.SpineHttpUtils;
import com.esotericsoftware.spine.android.utils.HttpUtils;
import android.content.Context;
import android.content.res.AssetManager;
@ -149,7 +149,7 @@ public class AndroidTextureAtlas {
}
static public AndroidTextureAtlas fromHttp(URL atlasUrl, File targetDirectory) {
File atlasFile = SpineHttpUtils.downloadFrom(atlasUrl, targetDirectory);
File atlasFile = HttpUtils.downloadFrom(atlasUrl, targetDirectory);
TextureAtlasData data;
try {
data = loadTextureAtlasData(atlasFile);
@ -166,7 +166,7 @@ public class AndroidTextureAtlas {
File imageFile;
try {
URL imageUrl = new URL(atlasUrl.getProtocol(), atlasUrl.getHost(), atlasUrl.getPort(), imagePath);
imageFile = SpineHttpUtils.downloadFrom(imageUrl, targetDirectory);
imageFile = HttpUtils.downloadFrom(imageUrl, targetDirectory);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}

View File

@ -10,12 +10,41 @@ import com.esotericsoftware.spine.AnimationState;
import com.esotericsoftware.spine.AnimationStateData;
import com.esotericsoftware.spine.Skeleton;
import com.esotericsoftware.spine.SkeletonData;
import com.esotericsoftware.spine.android.utils.SpineControllerAfterPaintCallback;
import com.esotericsoftware.spine.android.utils.SpineControllerBeforePaintCallback;
import com.esotericsoftware.spine.android.utils.SpineControllerCallback;
import com.esotericsoftware.spine.android.callbacks.SpineControllerAfterPaintCallback;
import com.esotericsoftware.spine.android.callbacks.SpineControllerBeforePaintCallback;
import com.esotericsoftware.spine.android.callbacks.SpineControllerCallback;
/**
* Controls how the skeleton of a {@link SpineView} is animated and rendered.
*
* Upon initialization of a {@link SpineView}, the provided {@code onInitialized} callback method is called once. This method can be used
* to set up the initial animation(s) of the skeleton, among other things.
*
* After initialization is complete, the {@link SpineView} is rendered at the screen refresh rate. In each frame,
* the {@link AnimationState} is updated and applied to the {@link Skeleton}.
*
* Next, the optionally provided method {@code onBeforeUpdateWorldTransforms} is called, which can modify the
* skeleton before its current pose is calculated using {@link Skeleton#updateWorldTransform(Skeleton.Physics)}. After
* {@link Skeleton#updateWorldTransform(Skeleton.Physics)} has completed, the optional {@code onAfterUpdateWorldTransforms} method is
* called, which can modify the current pose before rendering the skeleton.
*
* Before the skeleton's current pose is rendered by the {@link SpineView}, the optional {@code onBeforePaint} is called,
* which allows rendering backgrounds or other objects that should go behind the skeleton on the {@link Canvas}. The
* {@link SpineView} then renders the skeleton's current pose and finally calls the optional {@code onAfterPaint}, which
* can render additional objects on top of the skeleton.
*
* The underlying {@link AndroidTextureAtlas}, {@link SkeletonData}, {@link Skeleton}, {@link AnimationStateData}, {@link AnimationState}, and {@link AndroidSkeletonDrawable}
* can be accessed through their respective getters to inspect and/or modify the skeleton and its associated data. Accessing
* this data is only allowed if the {@link SpineView} and its data have been initialized and have not been disposed of yet.
*
* By default, the widget updates and renders the skeleton every frame. The {@code pause} method can be used to pause updating
* and rendering the skeleton. The {@link SpineController#resume()} method resumes updating and rendering the skeleton. The {@link SpineController#isPlaying()} getter
* reports the current state.
*/
public class SpineController {
/**
* Used to create a {@link SpineController} instance.
* */
public static class Builder {
private final SpineControllerCallback onInitialized;
private SpineControllerCallback onBeforeUpdateWorldTransforms;
@ -23,25 +52,51 @@ public class SpineController {
private SpineControllerBeforePaintCallback onBeforePaint;
private SpineControllerAfterPaintCallback onAfterPaint;
/**
* Instantiate a {@link Builder} for {@link SpineController}, which controls how the skeleton of a {@link SpineView}
* is animated and rendered. Upon initialization of a {@link SpineView}, the provided {@code onInitialized} callback
* method is called once. This method can be used to set up the initial animation(s) of the skeleton, among other things.
*
* @param onInitialized Upon initialization of a {@link SpineView}, the provided {@code onInitialized} callback
* method is called once. This method can be used to set up the initial animation(s) of the skeleton,
* among other things.
*/
public Builder(SpineControllerCallback onInitialized) {
this.onInitialized = onInitialized;
}
/**
* Sets the {@code onBeforeUpdateWorldTransforms} callback. It is called before the skeleton's current pose is calculated
* using {@link Skeleton#updateWorldTransform(Skeleton.Physics)}. It can be used to modify the skeleton before the pose calculation.
*/
public Builder setOnBeforeUpdateWorldTransforms(SpineControllerCallback onBeforeUpdateWorldTransforms) {
this.onBeforeUpdateWorldTransforms = onBeforeUpdateWorldTransforms;
return this;
}
/**
* Sets the {@code onAfterUpdateWorldTransforms} callback. This method is called after the skeleton's current pose is calculated using
* {@link Skeleton#updateWorldTransform(Skeleton.Physics)}. It can be used to modify the current pose before rendering the skeleton.
*/
public Builder setOnAfterUpdateWorldTransforms(SpineControllerCallback onAfterUpdateWorldTransforms) {
this.onAfterUpdateWorldTransforms = onAfterUpdateWorldTransforms;
return this;
}
/**
* Sets the {@code onBeforePaint} callback. It is called before the skeleton's current pose is rendered by the
* {@link SpineView}. It allows rendering backgrounds or other objects that should go behind the skeleton on the
* {@link Canvas}.
*/
public Builder setOnBeforePaint(SpineControllerBeforePaintCallback onBeforePaint) {
this.onBeforePaint = onBeforePaint;
return this;
}
/**
* Sets the {@code onAfterPaint} callback. It is called after the skeleton's current pose is rendered by the
* {@link SpineView}. It allows rendering additional objects on top of the skeleton.
*/
public Builder setOnAfterPaint(SpineControllerAfterPaintCallback onAfterPaint) {
this.onAfterPaint = onAfterPaint;
return this;
@ -69,6 +124,15 @@ public class SpineController {
private double scaleX = 1;
private double scaleY = 1;
/**
* Instantiate a {@link SpineController}, which controls how the skeleton of a {@link SpineView} is animated and rendered.
* Upon initialization of a {@link SpineView}, the provided {@code onInitialized} callback method is called once.
* This method can be used to set up the initial animation(s) of the skeleton, among other things.
*
* @param onInitialized Upon initialization of a {@link SpineView}, the provided {@code onInitialized} callback
* method is called once. This method can be used to set up the initial animation(s) of the skeleton,
* among other things.
*/
public SpineController(SpineControllerCallback onInitialized) {
this.onInitialized = onInitialized;
}
@ -80,74 +144,127 @@ public class SpineController {
}
}
/**
* The {@link AndroidTextureAtlas} from which images to render the skeleton are sourced.
*/
public AndroidTextureAtlas getAtlas() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable.getAtlas();
}
/**
* The setup-pose data used by the skeleton.
*/
public SkeletonData getSkeletonDate() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable.getSkeletonData();
}
/**
* The {@link Skeleton}.
*/
public Skeleton getSkeleton() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable.getSkeleton();
}
/**
* The mixing information used by the {@link AnimationState}.
*/
public AnimationStateData getAnimationStateData() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable.getAnimationStateData();
}
/**
* The {@link AnimationState} used to manage animations that are being applied to the
* skeleton.
*/
public AnimationState getAnimationState() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable.getAnimationState();
}
/**
* The {@link AndroidSkeletonDrawable}.
*/
public AndroidSkeletonDrawable getDrawable() {
if (drawable == null) throw new RuntimeException("Controller is not initialized yet.");
return drawable;
}
/**
* Checks if the {@link SpineView} is initialized.
*/
public boolean isInitialized() {
return drawable != null;
}
/**
* Checks if the animation is currently playing.
*/
public boolean isPlaying() {
return playing;
}
/**
* Pauses updating and rendering the skeleton.
*/
public void pause() {
if (playing) {
playing = false;
}
}
/**
* Resumes updating and rendering the skeleton.
*/
public void resume() {
if (!playing) {
playing = true;
}
}
/**
* Transforms the coordinates given in the {@link SpineView} coordinate system in {@code position} to
* the skeleton coordinate system. See the {@code IKFollowing.kt} example for how to use this
* to move a bone based on user touch input.
*/
public Point toSkeletonCoordinates(Point position) {
int x = position.x;
int y = position.y;
return new Point((int) (x / scaleX - offsetX), (int) (y / scaleY - offsetY));
}
/**
* Sets the {@code onBeforeUpdateWorldTransforms} callback. It is called before the skeleton's current pose is calculated
* using {@link Skeleton#updateWorldTransform(Skeleton.Physics)}. It can be used to modify the skeleton before the pose calculation.
*/
public void setOnBeforeUpdateWorldTransforms(@Nullable SpineControllerCallback onBeforeUpdateWorldTransforms) {
this.onBeforeUpdateWorldTransforms = onBeforeUpdateWorldTransforms;
}
/**
* Sets the {@code onAfterUpdateWorldTransforms} callback. This method is called after the skeleton's current pose is calculated using
* {@link Skeleton#updateWorldTransform(Skeleton.Physics)}. It can be used to modify the current pose before rendering the skeleton.
*/
public void setOnAfterUpdateWorldTransforms(@Nullable SpineControllerCallback onAfterUpdateWorldTransforms) {
this.onAfterUpdateWorldTransforms = onAfterUpdateWorldTransforms;
}
/**
* Sets the {@code onBeforePaint} callback. It is called before the skeleton's current pose is rendered by the
* {@link SpineView}. It allows rendering backgrounds or other objects that should go behind the skeleton on the
* {@link Canvas}.
*/
public void setOnBeforePaint(@Nullable SpineControllerBeforePaintCallback onBeforePaint) {
this.onBeforePaint = onBeforePaint;
}
/**
* Sets the {@code onAfterPaint} callback. It is called after the skeleton's current pose is rendered by the
* {@link SpineView}. It allows rendering additional objects on top of the skeleton.
*/
public void setOnAfterPaint(@Nullable SpineControllerAfterPaintCallback onAfterPaint) {
this.onAfterPaint = onAfterPaint;
}

View File

@ -35,27 +35,20 @@ import com.esotericsoftware.spine.android.bounds.Bounds;
import com.esotericsoftware.spine.android.bounds.BoundsProvider;
import com.esotericsoftware.spine.android.bounds.ContentMode;
import com.esotericsoftware.spine.android.bounds.SetupPoseBounds;
import com.esotericsoftware.spine.android.utils.AndroidSkeletonDrawableLoader;
import com.esotericsoftware.spine.android.callbacks.AndroidSkeletonDrawableLoader;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Choreographer;
import android.view.View;
import androidx.annotation.NonNull;
import java.io.Console;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
public class SpineView extends View implements Choreographer.FrameCallback {

View File

@ -1,4 +1,4 @@
package com.esotericsoftware.spine.android.utils;
package com.esotericsoftware.spine.android.callbacks;
import com.esotericsoftware.spine.android.AndroidSkeletonDrawable;

View File

@ -1,4 +1,4 @@
package com.esotericsoftware.spine.android.utils;
package com.esotericsoftware.spine.android.callbacks;
import com.esotericsoftware.spine.android.SpineController;

View File

@ -12,7 +12,7 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
public class SpineHttpUtils {
public class HttpUtils {
public static File downloadFrom(URL url, File targetDirectory) throws RuntimeException {
HttpURLConnection urlConnection = null;

View File

@ -13,13 +13,10 @@ import com.esotericsoftware.spine.android.AndroidTextureAtlas;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import kotlin.NotImplementedError;
public class SkeletonDataUtils {
public static SkeletonData fromAsset(AndroidTextureAtlas atlas, String skeletonFileName, Context context) {
@ -56,7 +53,7 @@ public class SkeletonDataUtils {
}
public static SkeletonData fromHttp(AndroidTextureAtlas atlas, URL skeletonUrl, File targetDirectory) {
File skeletonFile = SpineHttpUtils.downloadFrom(skeletonUrl, targetDirectory);
File skeletonFile = HttpUtils.downloadFrom(skeletonUrl, targetDirectory);
return fromFile(atlas, skeletonFile);
}
}