From 5cae4737b524b6160ecacb8f7156fdb1d9673318 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Wed, 3 Jul 2024 17:39:22 +0200 Subject: [PATCH] Add `SetupPoseBounds` and implement canvas transforms --- .../esotericsoftware/spine/MainActivity.kt | 6 +-- .../spine/android/SkeletonRenderer.java | 5 +- .../spine/android/SpineView.java | 46 +++++++++++++++- .../spine/android/bounds/Alignment.java | 29 ++++++++++ .../spine/android/bounds/Bounds.java | 54 +++++++++++++++++++ .../spine/android/bounds/BoundsProvider.java | 7 +++ .../spine/android/bounds/SetupPoseBounds.java | 20 +++++++ 7 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Alignment.java create mode 100644 spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Bounds.java create mode 100644 spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/BoundsProvider.java create mode 100644 spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SetupPoseBounds.java diff --git a/spine-android/app/src/main/java/com/esotericsoftware/spine/MainActivity.kt b/spine-android/app/src/main/java/com/esotericsoftware/spine/MainActivity.kt index 6751fe525..8704e7cde 100644 --- a/spine-android/app/src/main/java/com/esotericsoftware/spine/MainActivity.kt +++ b/spine-android/app/src/main/java/com/esotericsoftware/spine/MainActivity.kt @@ -46,11 +46,7 @@ fun SpineViewComposable(modifier: Modifier = Modifier.fillMaxSize()) { "spineboy.atlas", "spineboy-pro.json", SpineController { - it.skeleton.scaleY = -1f - it.skeleton.setToSetupPose() - - it.animationStateData.defaultMix = 0.2f - it.animationState.setAnimation(0, "hoverboard", true) + it.animationState.setAnimation(0, "walk", true) } ) } diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SkeletonRenderer.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SkeletonRenderer.java index c3dda2ea1..8362ede18 100644 --- a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SkeletonRenderer.java +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SkeletonRenderer.java @@ -205,15 +205,12 @@ public class SkeletonRenderer { return commandList; } - public void render (Canvas canvas, Skeleton skeleton, float x, float y) { - canvas.save(); - canvas.translate(x, y); + public void render (Canvas canvas, Skeleton skeleton) { Array commands = render(skeleton); for (int i = 0; i < commands.size; i++) { RenderCommand command = commands.get(i); canvas.drawVertices(Canvas.VertexMode.TRIANGLES, command.vertices.size, command.vertices.items, 0, command.uvs.items, 0, command.colors.items, 0, command.indices.items, 0, command.indices.size, command.texture.getPaint(command.blendMode)); } - canvas.restore(); } } diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineView.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineView.java index 6f6759de4..f863d3e0b 100644 --- a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineView.java +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/SpineView.java @@ -29,6 +29,11 @@ package com.esotericsoftware.spine.android; +import com.badlogic.gdx.math.Vector2; +import com.esotericsoftware.spine.android.bounds.Alignment; +import com.esotericsoftware.spine.android.bounds.Bounds; +import com.esotericsoftware.spine.android.bounds.BoundsProvider; +import com.esotericsoftware.spine.android.bounds.SetupPoseBounds; import com.esotericsoftware.spine.android.utils.AndroidSkeletonDrawableLoader; import android.content.Context; @@ -47,9 +52,21 @@ import java.net.URL; public class SpineView extends View implements Choreographer.FrameCallback { private long lastTime = 0; private float delta = 0; + private float offsetX = 0; + private float offsetY = 0; + private float scaleX = 1; + private float scaleY = 1; + private float x = 0; + private float y = 0; + SkeletonRenderer renderer = new SkeletonRenderer(); SpineController controller; + BoundsProvider boundsProvider = new SetupPoseBounds(); + + Bounds computedBounds = new Bounds(); + Alignment alignment = Alignment.CENTER; + public SpineView (Context context) { super(context); } @@ -82,6 +99,9 @@ public class SpineView extends View implements Choreographer.FrameCallback { Thread backgroundThread = new Thread(() -> { final AndroidSkeletonDrawable skeletonDrawable = loader.load(); mainHandler.post(() -> { + computedBounds = boundsProvider.computeBounds(skeletonDrawable); + updateCanvasTransform(); + controller.init(skeletonDrawable); Choreographer.getInstance().postFrameCallback(SpineView.this); }); @@ -98,9 +118,31 @@ public class SpineView extends View implements Choreographer.FrameCallback { controller.getDrawable().update(delta); - // TODO: Calculate scaling + position + canvas.save(); + canvas.translate(offsetX, offsetY); + canvas.scale(scaleX, scaleY * -1); + canvas.translate(x, y); - renderer.render(canvas, controller.getSkeleton(), 500f, 1000f); + renderer.render(canvas, controller.getSkeleton()); + + canvas.restore(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + updateCanvasTransform(); + } + + private void updateCanvasTransform() { + x = (float) (-computedBounds.getX() - computedBounds.getWidth() / 2.0 - (alignment.getX() * computedBounds.getWidth() / 2.0)); + y = (float) (-computedBounds.getY() - computedBounds.getHeight() / 2.0 - (alignment.getY() * computedBounds.getHeight() / 2.0)); + + // contain + scaleX = scaleY = (float) Math.min(getWidth() / computedBounds.getWidth(), getHeight() / computedBounds.getHeight()); + + offsetX = (float) (getWidth() / 2.0 + (alignment.getX() * getWidth() / 2.0)); + offsetY = (float) (getHeight() / 2.0 + (alignment.getY() * getHeight() / 2.0)); } // Choreographer.FrameCallback diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Alignment.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Alignment.java new file mode 100644 index 000000000..53f3b6711 --- /dev/null +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Alignment.java @@ -0,0 +1,29 @@ +package com.esotericsoftware.spine.android.bounds; + +public enum Alignment { + TOP_LEFT(-1.0f, -1.0f), + TOP_CENTER(0.0f, -1.0f), + TOP_RIGHT(1.0f, -1.0f), + CENTER_LEFT(-1.0f, 0.0f), + CENTER(0.0f, 0.0f), + CENTER_RIGHT(1.0f, 0.0f), + BOTTOM_LEFT(-1.0f, 1.0f), + BOTTOM_CENTER(0.0f, 1.0f), + BOTTOM_RIGHT(1.0f, 1.0f); + + private final float x; + private final float y; + + Alignment(float x, float y) { + this.x = x; + this.y = y; + } + + public float getX() { + return x; + } + + public float getY() { + return y; + } +} diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Bounds.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Bounds.java new file mode 100644 index 000000000..c0676b627 --- /dev/null +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/Bounds.java @@ -0,0 +1,54 @@ +package com.esotericsoftware.spine.android.bounds; + +public class Bounds { + private double x; + private double y; + private double width; + private double height; + + public Bounds() { + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + } + + public Bounds(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getWidth() { + return width; + } + + public void setWidth(double width) { + this.width = width; + } + + public double getHeight() { + return height; + } + + public void setHeight(double height) { + this.height = height; + } +} diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/BoundsProvider.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/BoundsProvider.java new file mode 100644 index 000000000..7b0ace6b7 --- /dev/null +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/BoundsProvider.java @@ -0,0 +1,7 @@ +package com.esotericsoftware.spine.android.bounds; + +import com.esotericsoftware.spine.android.AndroidSkeletonDrawable; + +public interface BoundsProvider { + Bounds computeBounds(AndroidSkeletonDrawable drawable); +} diff --git a/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SetupPoseBounds.java b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SetupPoseBounds.java new file mode 100644 index 000000000..c0497b78e --- /dev/null +++ b/spine-android/spine-android/src/main/java/com/esotericsoftware/spine/android/bounds/SetupPoseBounds.java @@ -0,0 +1,20 @@ +package com.esotericsoftware.spine.android.bounds; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.FloatArray; +import com.esotericsoftware.spine.android.AndroidSkeletonDrawable; + +public class SetupPoseBounds implements BoundsProvider { + + @Override + public Bounds computeBounds(AndroidSkeletonDrawable drawable) { + + Vector2 offset = new Vector2(0, 0); + Vector2 size = new Vector2(0, 0); + FloatArray floatArray = new FloatArray(); + + drawable.getSkeleton().getBounds(offset, size, floatArray); + + return new Bounds(offset.x, offset.y, size.x, size.y); + } +}