|
@@ -50,6 +50,7 @@ import com.badlogic.gdx.graphics.GL20;
|
|
import com.badlogic.gdx.graphics.Pixmap;
|
|
import com.badlogic.gdx.graphics.Pixmap;
|
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
|
import com.badlogic.gdx.graphics.Texture;
|
|
import com.badlogic.gdx.graphics.Texture;
|
|
|
|
+import com.badlogic.gdx.graphics.Texture.TextureFilter;
|
|
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
|
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
|
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
|
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
|
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
|
|
@@ -83,7 +84,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
UI ui;
|
|
UI ui;
|
|
|
|
|
|
PolygonSpriteBatch batch;
|
|
PolygonSpriteBatch batch;
|
|
- SkeletonRenderer renderer;
|
|
|
|
|
|
+ SkeletonMeshRenderer renderer;
|
|
SkeletonRendererDebug debugRenderer;
|
|
SkeletonRendererDebug debugRenderer;
|
|
SkeletonData skeletonData;
|
|
SkeletonData skeletonData;
|
|
Skeleton skeleton;
|
|
Skeleton skeleton;
|
|
@@ -96,38 +97,49 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
public void create () {
|
|
public void create () {
|
|
ui = new UI();
|
|
ui = new UI();
|
|
batch = new PolygonSpriteBatch();
|
|
batch = new PolygonSpriteBatch();
|
|
- renderer = new SkeletonRenderer();
|
|
|
|
|
|
+ renderer = new SkeletonMeshRenderer();
|
|
debugRenderer = new SkeletonRendererDebug();
|
|
debugRenderer = new SkeletonRendererDebug();
|
|
skeletonX = (int)(ui.window.getWidth() + (Gdx.graphics.getWidth() - ui.window.getWidth()) / 2);
|
|
skeletonX = (int)(ui.window.getWidth() + (Gdx.graphics.getWidth() - ui.window.getWidth()) / 2);
|
|
skeletonY = Gdx.graphics.getHeight() / 4;
|
|
skeletonY = Gdx.graphics.getHeight() / 4;
|
|
|
|
|
|
loadSkeleton(
|
|
loadSkeleton(
|
|
- Gdx.files.internal(Gdx.app.getPreferences("spine-skeletontest").getString("lastFile", "spineboy/spineboy.json")), false);
|
|
|
|
|
|
+ Gdx.files.internal(Gdx.app.getPreferences("spine-skeletonviewer").getString("lastFile", "spineboy/spineboy.json")),
|
|
|
|
+ false);
|
|
}
|
|
}
|
|
|
|
|
|
- void loadSkeleton (FileHandle skeletonFile, boolean reload) {
|
|
|
|
|
|
+ void loadSkeleton (final FileHandle skeletonFile, boolean reload) {
|
|
if (skeletonFile == null) return;
|
|
if (skeletonFile == null) return;
|
|
|
|
|
|
- // A regular texture atlas would normally usually be used. This returns a white image for images not found in the atlas.
|
|
|
|
- Pixmap pixmap = new Pixmap(32, 32, Format.RGBA8888);
|
|
|
|
- pixmap.setColor(new Color(1, 1, 1, 0.33f));
|
|
|
|
- pixmap.fill();
|
|
|
|
- final AtlasRegion fake = new AtlasRegion(new Texture(pixmap), 0, 0, 32, 32);
|
|
|
|
- pixmap.dispose();
|
|
|
|
-
|
|
|
|
- String atlasFileName = skeletonFile.nameWithoutExtension();
|
|
|
|
- if (atlasFileName.endsWith(".json")) atlasFileName = new FileHandle(atlasFileName).nameWithoutExtension();
|
|
|
|
- FileHandle atlasFile = skeletonFile.sibling(atlasFileName + ".atlas");
|
|
|
|
- if (!atlasFile.exists()) atlasFile = skeletonFile.sibling(atlasFileName + ".atlas.txt");
|
|
|
|
- TextureAtlasData data = !atlasFile.exists() ? null : new TextureAtlasData(atlasFile, atlasFile.parent(), false);
|
|
|
|
- TextureAtlas atlas = new TextureAtlas(data) {
|
|
|
|
- public AtlasRegion findRegion (String name) {
|
|
|
|
- AtlasRegion region = super.findRegion(name);
|
|
|
|
- return region != null ? region : fake;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
try {
|
|
try {
|
|
|
|
+ // A regular texture atlas would normally usually be used. This returns a white image for images not found in the atlas.
|
|
|
|
+ Pixmap pixmap = new Pixmap(32, 32, Format.RGBA8888);
|
|
|
|
+ pixmap.setColor(new Color(1, 1, 1, 0.33f));
|
|
|
|
+ pixmap.fill();
|
|
|
|
+ final AtlasRegion fake = new AtlasRegion(new Texture(pixmap), 0, 0, 32, 32);
|
|
|
|
+ pixmap.dispose();
|
|
|
|
+
|
|
|
|
+ String atlasFileName = skeletonFile.nameWithoutExtension();
|
|
|
|
+ if (atlasFileName.endsWith(".json")) atlasFileName = new FileHandle(atlasFileName).nameWithoutExtension();
|
|
|
|
+ FileHandle atlasFile = skeletonFile.sibling(atlasFileName + ".atlas");
|
|
|
|
+ if (!atlasFile.exists()) atlasFile = skeletonFile.sibling(atlasFileName + ".atlas.txt");
|
|
|
|
+ TextureAtlasData data = !atlasFile.exists() ? null : new TextureAtlasData(atlasFile, atlasFile.parent(), false);
|
|
|
|
+ TextureAtlas atlas = new TextureAtlas(data) {
|
|
|
|
+ public AtlasRegion findRegion (String name) {
|
|
|
|
+ AtlasRegion region = super.findRegion(name);
|
|
|
|
+ if (region == null) {
|
|
|
|
+ // Look for separate image file.
|
|
|
|
+ FileHandle file = skeletonFile.sibling(name + ".png");
|
|
|
|
+ if (file.exists()) {
|
|
|
|
+ Texture texture = new Texture(file);
|
|
|
|
+ texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
|
|
|
|
+ region = new AtlasRegion(texture, 0, 0, texture.getWidth(), texture.getHeight());
|
|
|
|
+ region.name = name;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return region != null ? region : fake;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
String extension = skeletonFile.extension();
|
|
String extension = skeletonFile.extension();
|
|
if (extension.equalsIgnoreCase("json") || extension.equalsIgnoreCase("txt")) {
|
|
if (extension.equalsIgnoreCase("json") || extension.equalsIgnoreCase("txt")) {
|
|
SkeletonJson json = new SkeletonJson(atlas);
|
|
SkeletonJson json = new SkeletonJson(atlas);
|
|
@@ -137,6 +149,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
SkeletonBinary binary = new SkeletonBinary(atlas);
|
|
SkeletonBinary binary = new SkeletonBinary(atlas);
|
|
binary.setScale(ui.scaleSlider.getValue());
|
|
binary.setScale(ui.scaleSlider.getValue());
|
|
skeletonData = binary.readSkeletonData(skeletonFile);
|
|
skeletonData = binary.readSkeletonData(skeletonFile);
|
|
|
|
+ if (skeletonData.getBones().size == 0) throw new Exception("No bones in skeleton data.");
|
|
}
|
|
}
|
|
} catch (Exception ex) {
|
|
} catch (Exception ex) {
|
|
ex.printStackTrace();
|
|
ex.printStackTrace();
|
|
@@ -153,7 +166,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
state = new AnimationState(new AnimationStateData(skeletonData));
|
|
state = new AnimationState(new AnimationStateData(skeletonData));
|
|
|
|
|
|
this.skeletonFile = skeletonFile;
|
|
this.skeletonFile = skeletonFile;
|
|
- Preferences prefs = Gdx.app.getPreferences("spine-skeletontest");
|
|
|
|
|
|
+ Preferences prefs = Gdx.app.getPreferences("spine-skeletonviewer");
|
|
prefs.putString("lastFile", skeletonFile.path());
|
|
prefs.putString("lastFile", skeletonFile.path());
|
|
prefs.flush();
|
|
prefs.flush();
|
|
lastModified = skeletonFile.lastModified();
|
|
lastModified = skeletonFile.lastModified();
|
|
@@ -161,7 +174,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
|
|
|
|
// Populate UI.
|
|
// Populate UI.
|
|
|
|
|
|
- ui.skeletonLabel.setText(skeletonFile.name());
|
|
|
|
|
|
+ ui.window.getTitleLabel().setText(skeletonFile.name());
|
|
{
|
|
{
|
|
Array<String> items = new Array();
|
|
Array<String> items = new Array();
|
|
for (Skin skin : skeletonData.getSkins())
|
|
for (Skin skin : skeletonData.getSkins())
|
|
@@ -177,8 +190,9 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
|
|
|
|
// Configure skeleton from UI.
|
|
// Configure skeleton from UI.
|
|
|
|
|
|
- skeleton.setSkin(ui.skinList.getSelected());
|
|
|
|
- state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked());
|
|
|
|
|
|
+ if (ui.skinList.getSelected() != null) skeleton.setSkin(ui.skinList.getSelected());
|
|
|
|
+ if (ui.animationList.getSelected() != null)
|
|
|
|
+ state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked());
|
|
|
|
|
|
if (reload) ui.toast("Reloaded.");
|
|
if (reload) ui.toast("Reloaded.");
|
|
}
|
|
}
|
|
@@ -217,6 +231,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
// skeleton.getRootBone().setY(skeletonY);
|
|
// skeleton.getRootBone().setY(skeletonY);
|
|
skeleton.updateWorldTransform();
|
|
skeleton.updateWorldTransform();
|
|
|
|
|
|
|
|
+ batch.setColor(Color.WHITE);
|
|
batch.begin();
|
|
batch.begin();
|
|
renderer.draw(batch, skeleton);
|
|
renderer.draw(batch, skeleton);
|
|
batch.end();
|
|
batch.end();
|
|
@@ -252,7 +267,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
|
batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
|
debugRenderer.getShapeRenderer().setProjectionMatrix(batch.getProjectionMatrix());
|
|
debugRenderer.getShapeRenderer().setProjectionMatrix(batch.getProjectionMatrix());
|
|
ui.stage.getViewport().update(width, height, true);
|
|
ui.stage.getViewport().update(width, height, true);
|
|
- if (!ui.minimizeButton.isChecked()) ui.window.setHeight(height);
|
|
|
|
|
|
+ if (!ui.minimizeButton.isChecked()) ui.window.setHeight(height + 8);
|
|
}
|
|
}
|
|
|
|
|
|
class UI {
|
|
class UI {
|
|
@@ -262,8 +277,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
|
|
|
|
Window window = new Window("Skeleton", skin);
|
|
Window window = new Window("Skeleton", skin);
|
|
Table root = new Table(skin);
|
|
Table root = new Table(skin);
|
|
- TextButton browseButton = new TextButton("Browse", skin);
|
|
|
|
- Label skeletonLabel = new Label("", skin);
|
|
|
|
|
|
+ TextButton openButton = new TextButton("Open", skin);
|
|
List<String> animationList = new List(skin);
|
|
List<String> animationList = new List(skin);
|
|
List<String> skinList = new List(skin);
|
|
List<String> skinList = new List(skin);
|
|
CheckBox loopCheckbox = new CheckBox(" Loop", skin);
|
|
CheckBox loopCheckbox = new CheckBox(" Loop", skin);
|
|
@@ -305,30 +319,24 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
|
|
|
|
window.setMovable(false);
|
|
window.setMovable(false);
|
|
window.setResizable(false);
|
|
window.setResizable(false);
|
|
|
|
+ window.setKeepWithinStage(false);
|
|
|
|
+ window.setX(-3);
|
|
|
|
+ window.setY(-2);
|
|
|
|
|
|
- minimizeButton.padTop(-2).padLeft(5);
|
|
|
|
- minimizeButton.getColor().a = 0.66f;
|
|
|
|
- window.getTitleTable().add(minimizeButton).size(20, 20);
|
|
|
|
|
|
+ window.getTitleTable().add(openButton).space(3);
|
|
|
|
+ window.getTitleTable().add(minimizeButton).width(20);
|
|
|
|
|
|
- ScrollPane skinScroll = new ScrollPane(skinList, skin);
|
|
|
|
|
|
+ ScrollPane skinScroll = new ScrollPane(skinList, skin, "bg");
|
|
skinScroll.setFadeScrollBars(false);
|
|
skinScroll.setFadeScrollBars(false);
|
|
|
|
|
|
- ScrollPane animationScroll = new ScrollPane(animationList, skin);
|
|
|
|
|
|
+ ScrollPane animationScroll = new ScrollPane(animationList, skin, "bg");
|
|
animationScroll.setFadeScrollBars(false);
|
|
animationScroll.setFadeScrollBars(false);
|
|
|
|
|
|
// Layout.
|
|
// Layout.
|
|
|
|
|
|
- root.pad(2, 4, 4, 4).defaults().space(6);
|
|
|
|
- root.columnDefaults(0).top().right();
|
|
|
|
|
|
+ root.defaults().space(6);
|
|
|
|
+ root.columnDefaults(0).top().right().padTop(3);
|
|
root.columnDefaults(1).left();
|
|
root.columnDefaults(1).left();
|
|
- root.row().padTop(6);
|
|
|
|
- root.add("Skeleton:");
|
|
|
|
- {
|
|
|
|
- Table table = table();
|
|
|
|
- table.add(skeletonLabel).fillX().expandX();
|
|
|
|
- table.add(browseButton);
|
|
|
|
- root.add(table).fill().row();
|
|
|
|
- }
|
|
|
|
root.add("Scale:");
|
|
root.add("Scale:");
|
|
{
|
|
{
|
|
Table table = table();
|
|
Table table = table();
|
|
@@ -378,7 +386,6 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
stage.addActor(table);
|
|
stage.addActor(table);
|
|
table.pad(10).bottom().right();
|
|
table.pad(10).bottom().right();
|
|
table.add(toasts);
|
|
table.add(toasts);
|
|
- table.debug();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Events.
|
|
// Events.
|
|
@@ -390,7 +397,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
- browseButton.addListener(new ChangeListener() {
|
|
|
|
|
|
+ openButton.addListener(new ChangeListener() {
|
|
public void changed (ChangeEvent event, Actor actor) {
|
|
public void changed (ChangeEvent event, Actor actor) {
|
|
FileDialog fileDialog = new FileDialog((Frame)null, "Choose skeleton file");
|
|
FileDialog fileDialog = new FileDialog((Frame)null, "Choose skeleton file");
|
|
fileDialog.setMode(FileDialog.LOAD);
|
|
fileDialog.setMode(FileDialog.LOAD);
|
|
@@ -427,11 +434,11 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
public void clicked (InputEvent event, float x, float y) {
|
|
public void clicked (InputEvent event, float x, float y) {
|
|
if (minimizeButton.isChecked()) {
|
|
if (minimizeButton.isChecked()) {
|
|
window.getCells().get(0).setActor(null);
|
|
window.getCells().get(0).setActor(null);
|
|
- window.setHeight(20);
|
|
|
|
|
|
+ window.setHeight(37);
|
|
minimizeButton.setText("+");
|
|
minimizeButton.setText("+");
|
|
} else {
|
|
} else {
|
|
window.getCells().get(0).setActor(root);
|
|
window.getCells().get(0).setActor(root);
|
|
- ui.window.setHeight(Gdx.graphics.getHeight());
|
|
|
|
|
|
+ ui.window.setHeight(Gdx.graphics.getHeight() + 8);
|
|
minimizeButton.setText("-");
|
|
minimizeButton.setText("-");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -466,7 +473,11 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
skinList.addListener(new ChangeListener() {
|
|
skinList.addListener(new ChangeListener() {
|
|
public void changed (ChangeEvent event, Actor actor) {
|
|
public void changed (ChangeEvent event, Actor actor) {
|
|
if (skeleton != null) {
|
|
if (skeleton != null) {
|
|
- skeleton.setSkin(skinList.getSelected());
|
|
|
|
|
|
+ String skinName = skinList.getSelected();
|
|
|
|
+ if (skinName == null)
|
|
|
|
+ skeleton.setSkin((Skin)null);
|
|
|
|
+ else
|
|
|
|
+ skeleton.setSkin(skinName);
|
|
skeleton.setSlotsToSetupPose();
|
|
skeleton.setSlotsToSetupPose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -504,7 +515,7 @@ public class SkeletonViewer extends ApplicationAdapter {
|
|
delay(5f), //
|
|
delay(5f), //
|
|
parallel(moveBy(0, table.getHeight(), 0.3f), fadeOut(0.3f)), //
|
|
parallel(moveBy(0, table.getHeight(), 0.3f), fadeOut(0.3f)), //
|
|
removeActor() //
|
|
removeActor() //
|
|
- ));
|
|
|
|
|
|
+ ));
|
|
for (Actor actor : toasts.getChildren())
|
|
for (Actor actor : toasts.getChildren())
|
|
actor.addAction(moveBy(0, table.getHeight(), 0.3f));
|
|
actor.addAction(moveBy(0, table.getHeight(), 0.3f));
|
|
toasts.addActor(table);
|
|
toasts.addActor(table);
|