diff --git a/spine-libgdx/spine-libgdx/.classpath b/spine-libgdx/spine-libgdx/.classpath index ee6f3e443..9105c7891 100644 --- a/spine-libgdx/spine-libgdx/.classpath +++ b/spine-libgdx/spine-libgdx/.classpath @@ -1,7 +1,7 @@ - + diff --git a/spine-libgdx/spine-libgdx/.settings/org.eclipse.jdt.core.prefs b/spine-libgdx/spine-libgdx/.settings/org.eclipse.jdt.core.prefs index 6a57c0f46..b1afb4ec3 100644 --- a/spine-libgdx/spine-libgdx/.settings/org.eclipse.jdt.core.prefs +++ b/spine-libgdx/spine-libgdx/.settings/org.eclipse.jdt.core.prefs @@ -6,9 +6,9 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -96,4 +96,4 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 59c77c6e7..eb27c3bcb 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -36,6 +36,7 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; import com.esotericsoftware.spine.attachments.Attachment; +import com.esotericsoftware.spine.attachments.FfdAttachment; public class Animation { final String name; @@ -671,7 +672,8 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, Array firedEvents, float alpha) { Slot slot = skeleton.slots.get(slotIndex); - if (slot.getAttachment() != attachment) return; + Attachment slotAttachment = slot.getAttachment(); + if (!(slotAttachment instanceof FfdAttachment) || !((FfdAttachment)slotAttachment).applyFFD(attachment)) return; float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index bd7808e78..74e00e365 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -52,6 +52,7 @@ import com.esotericsoftware.spine.Animation.RotateTimeline; import com.esotericsoftware.spine.Animation.ScaleTimeline; import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Animation.TranslateTimeline; +import com.esotericsoftware.spine.SkeletonJson.LinkedMesh; import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.AttachmentLoader; @@ -76,6 +77,7 @@ public class SkeletonBinary { private final AttachmentLoader attachmentLoader; private float scale = 1; + private Array linkedMeshes = new Array(); public SkeletonBinary (TextureAtlas atlas) { attachmentLoader = new AtlasAttachmentLoader(atlas); @@ -181,6 +183,24 @@ public class SkeletonBinary { for (int i = 0, n = input.readInt(true); i < n; i++) skeletonData.skins.add(readSkin(input, input.readString(), nonessential)); + // Linked meshes. + for (int i = 0, n = linkedMeshes.size; i < n; i++) { + LinkedMesh linkedMesh = linkedMeshes.get(i); + Skin skin = linkedMesh.skin == null ? skeletonData.getDefaultSkin() : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) throw new SerializationException("Skin not found: " + linkedMesh.skin); + Attachment parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (linkedMesh.mesh instanceof MeshAttachment) { + MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh; + mesh.setParentMesh((MeshAttachment)parent); + mesh.updateUVs(); + } else { + WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh; + mesh.setParentMesh((WeightedMeshAttachment)parent); + mesh.updateUVs(); + } + } + linkedMeshes.clear(); + // Events. for (int i = 0, n = input.readInt(true); i < n; i++) { EventData eventData = new EventData(input.readString()); @@ -221,74 +241,117 @@ public class SkeletonBinary { int slotIndex = input.readInt(true); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { String name = input.readString(); - skin.addAttachment(slotIndex, name, readAttachment(input, skin, name, nonessential)); + skin.addAttachment(slotIndex, name, readAttachment(input, skin, slotIndex, name, nonessential)); } } return skin; } - private Attachment readAttachment (DataInput input, Skin skin, String attachmentName, boolean nonessential) + private Attachment readAttachment (DataInput input, Skin skin, int slotIndex, String attachmentName, boolean nonessential) throws IOException { float scale = this.scale; String name = input.readString(); if (name == null) name = attachmentName; - switch (AttachmentType.values[input.readByte()]) { + AttachmentType type = AttachmentType.values[input.readByte()]; + switch (type) { case region: { String path = input.readString(); + float x = input.readFloat(); + float y = input.readFloat(); + float scaleX = input.readFloat(); + float scaleY = input.readFloat(); + float rotation = input.readFloat(); + float width = input.readFloat(); + float height = input.readFloat(); + int color = input.readInt(); + if (path == null) path = name; RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path); if (region == null) return null; region.setPath(path); - region.setX(input.readFloat() * scale); - region.setY(input.readFloat() * scale); - region.setScaleX(input.readFloat()); - region.setScaleY(input.readFloat()); - region.setRotation(input.readFloat()); - region.setWidth(input.readFloat() * scale); - region.setHeight(input.readFloat() * scale); - Color.rgba8888ToColor(region.getColor(), input.readInt()); + region.setX(x * scale); + region.setY(y * scale); + region.setScaleX(scaleX); + region.setScaleY(scaleY); + region.setRotation(rotation); + region.setWidth(width); + region.setHeight(height); + Color.rgba8888ToColor(region.getColor(), color); region.updateOffset(); return region; } case boundingbox: { + float[] vertices = readFloatArray(input, scale); BoundingBoxAttachment box = attachmentLoader.newBoundingBoxAttachment(skin, name); if (box == null) return null; - box.setVertices(readFloatArray(input, scale)); + box.setVertices(vertices); return box; } case mesh: { String path = input.readString(); + int color = input.readInt(); + int hullLength = 0; + float[] uvs = readFloatArray(input, 1); + short[] triangles = readShortArray(input); + float[] vertices = readFloatArray(input, scale); + hullLength = input.readInt(true); + int[] edges = null; + float width = 0, height = 0; + if (nonessential) { + edges = readIntArray(input); + width = input.readFloat(); + height = input.readFloat(); + } + if (path == null) path = name; MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path); if (mesh == null) return null; mesh.setPath(path); - float[] uvs = readFloatArray(input, 1); - short[] triangles = readShortArray(input); - float[] vertices = readFloatArray(input, scale); + Color.rgba8888ToColor(mesh.getColor(), color); mesh.setVertices(vertices); mesh.setTriangles(triangles); mesh.setRegionUVs(uvs); mesh.updateUVs(); - Color.rgba8888ToColor(mesh.getColor(), input.readInt()); - mesh.setHullLength(input.readInt(true) * 2); + mesh.setHullLength(hullLength * 2); if (nonessential) { - mesh.setEdges(readIntArray(input)); - mesh.setWidth(input.readFloat() * scale); - mesh.setHeight(input.readFloat() * scale); + mesh.setEdges(edges); + mesh.setWidth(width * scale); + mesh.setHeight(height * scale); } return mesh; } + case linkedmesh: { + String path = input.readString(); + int color = input.readInt(); + String skinName = input.readString(); + String parent = input.readString(); + boolean inheritFFD = input.readBoolean(); + float width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + + if (path == null) path = name; + MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path); + if (mesh == null) return null; + mesh.setPath(path); + Color.rgba8888ToColor(mesh.getColor(), color); + mesh.setInheritFFD(inheritFFD); + if (nonessential) { + mesh.setWidth(width * scale); + mesh.setHeight(height * scale); + } + linkedMeshes.add(new LinkedMesh(mesh, skinName, slotIndex, parent)); + return mesh; + } case weightedmesh: { String path = input.readString(); - if (path == null) path = name; - WeightedMeshAttachment mesh = attachmentLoader.newWeightedMeshAttachment(skin, name, path); - if (mesh == null) return null; - mesh.setPath(path); + int color = input.readInt(); float[] uvs = readFloatArray(input, 1); short[] triangles = readShortArray(input); - int vertexCount = input.readInt(true); FloatArray weights = new FloatArray(uvs.length * 3 * 3); IntArray bones = new IntArray(uvs.length * 3); @@ -302,18 +365,57 @@ public class SkeletonBinary { weights.add(input.readFloat()); } } + int hullLength = input.readInt(true); + int[] edges = null; + float width = 0, height = 0; + if (nonessential) { + edges = readIntArray(input); + width = input.readFloat(); + height = input.readFloat(); + } + + if (path == null) path = name; + WeightedMeshAttachment mesh = attachmentLoader.newWeightedMeshAttachment(skin, name, path); + if (mesh == null) return null; + mesh.setPath(path); + Color.rgba8888ToColor(mesh.getColor(), color); mesh.setBones(bones.toArray()); mesh.setWeights(weights.toArray()); mesh.setTriangles(triangles); mesh.setRegionUVs(uvs); mesh.updateUVs(); - Color.rgba8888ToColor(mesh.getColor(), input.readInt()); - mesh.setHullLength(input.readInt(true) * 2); + mesh.setHullLength(hullLength * 2); if (nonessential) { - mesh.setEdges(readIntArray(input)); - mesh.setWidth(input.readFloat() * scale); - mesh.setHeight(input.readFloat() * scale); + mesh.setEdges(edges); + mesh.setWidth(width * scale); + mesh.setHeight(height * scale); } + // BOZO - Store to look up source attachment later. + return mesh; + } + case weightedlinkedmesh: { + String path = input.readString(); + int color = input.readInt(); + String skinName = input.readString(); + String parent = input.readString(); + boolean inheritFFD = input.readBoolean(); + float width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + + if (path == null) path = name; + WeightedMeshAttachment mesh = attachmentLoader.newWeightedMeshAttachment(skin, name, path); + if (mesh == null) return null; + mesh.setPath(path); + Color.rgba8888ToColor(mesh.getColor(), color); + mesh.setInheritFFD(inheritFFD); + if (nonessential) { + mesh.setWidth(width * scale); + mesh.setHeight(height * scale); + } + linkedMeshes.add(new LinkedMesh(mesh, skinName, slotIndex, parent)); return mesh; } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 81af5e583..d35014f9e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -63,6 +63,7 @@ import com.esotericsoftware.spine.attachments.WeightedMeshAttachment; public class SkeletonJson { private final AttachmentLoader attachmentLoader; private float scale = 1; + private Array linkedMeshes = new Array(); public SkeletonJson (TextureAtlas atlas) { attachmentLoader = new AtlasAttachmentLoader(atlas); @@ -188,7 +189,7 @@ public class SkeletonJson { int slotIndex = skeletonData.findSlotIndex(slotEntry.name); if (slotIndex == -1) throw new SerializationException("Slot not found: " + slotEntry.name); for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) { - Attachment attachment = readAttachment(skin, entry.name, entry); + Attachment attachment = readAttachment(skin, slotIndex, entry.name, entry); if (attachment != null) skin.addAttachment(slotIndex, entry.name, attachment); } } @@ -196,6 +197,24 @@ public class SkeletonJson { if (skin.name.equals("default")) skeletonData.defaultSkin = skin; } + // Linked meshes. + for (int i = 0, n = linkedMeshes.size; i < n; i++) { + LinkedMesh linkedMesh = linkedMeshes.get(i); + Skin skin = linkedMesh.skin == null ? skeletonData.getDefaultSkin() : skeletonData.findSkin(linkedMesh.skin); + if (skin == null) throw new SerializationException("Skin not found: " + linkedMesh.skin); + Attachment parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (linkedMesh.mesh instanceof MeshAttachment) { + MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh; + mesh.setParentMesh((MeshAttachment)parent); + mesh.updateUVs(); + } else { + WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh; + mesh.setParentMesh((WeightedMeshAttachment)parent); + mesh.updateUVs(); + } + } + linkedMeshes.clear(); + // Events. for (JsonValue eventMap = root.getChild("events"); eventMap != null; eventMap = eventMap.next) { EventData eventData = new EventData(eventMap.name); @@ -218,7 +237,7 @@ public class SkeletonJson { return skeletonData; } - private Attachment readAttachment (Skin skin, String name, JsonValue map) { + private Attachment readAttachment (Skin skin, int slotIndex, String name, JsonValue map) { float scale = this.scale; name = map.getString("name", name); String path = map.getString("path", name); @@ -255,61 +274,79 @@ public class SkeletonJson { box.setVertices(vertices); return box; } - case mesh: { + case mesh: + case linkedmesh: { MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path); if (mesh == null) return null; mesh.setPath(path); - float[] vertices = map.require("vertices").asFloatArray(); - if (scale != 1) { - for (int i = 0, n = vertices.length; i < n; i++) - vertices[i] *= scale; - } - mesh.setVertices(vertices); - mesh.setTriangles(map.require("triangles").asShortArray()); - mesh.setRegionUVs(map.require("uvs").asFloatArray()); - mesh.updateUVs(); String color = map.getString("color", null); if (color != null) mesh.getColor().set(Color.valueOf(color)); - if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); - if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); mesh.setWidth(map.getFloat("width", 0) * scale); mesh.setHeight(map.getFloat("height", 0) * scale); + + String parent = map.getString("parent", null); + if (parent == null) { + float[] vertices = map.require("vertices").asFloatArray(); + if (scale != 1) { + for (int i = 0, n = vertices.length; i < n; i++) + vertices[i] *= scale; + } + mesh.setVertices(vertices); + mesh.setTriangles(map.require("triangles").asShortArray()); + mesh.setRegionUVs(map.require("uvs").asFloatArray()); + mesh.updateUVs(); + + if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); + if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); + } else { + mesh.setInheritFFD(map.getBoolean("ffd", true)); + linkedMeshes.add(new LinkedMesh(mesh, map.getString("skin", null), slotIndex, parent)); + } return mesh; } - case weightedmesh: { + case weightedmesh: + case weightedlinkedmesh: { WeightedMeshAttachment mesh = attachmentLoader.newWeightedMeshAttachment(skin, name, path); if (mesh == null) return null; mesh.setPath(path); - float[] uvs = map.require("uvs").asFloatArray(); - float[] vertices = map.require("vertices").asFloatArray(); - FloatArray weights = new FloatArray(uvs.length * 3 * 3); - IntArray bones = new IntArray(uvs.length * 3); - for (int i = 0, n = vertices.length; i < n;) { - int boneCount = (int)vertices[i++]; - bones.add(boneCount); - for (int nn = i + boneCount * 4; i < nn;) { - bones.add((int)vertices[i]); - weights.add(vertices[i + 1] * scale); - weights.add(vertices[i + 2] * scale); - weights.add(vertices[i + 3]); - i += 4; - } - } - mesh.setBones(bones.toArray()); - mesh.setWeights(weights.toArray()); - mesh.setTriangles(map.require("triangles").asShortArray()); - mesh.setRegionUVs(uvs); - mesh.updateUVs(); String color = map.getString("color", null); if (color != null) mesh.getColor().set(Color.valueOf(color)); - if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); - if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); mesh.setWidth(map.getFloat("width", 0) * scale); mesh.setHeight(map.getFloat("height", 0) * scale); + + String parent = map.getString("parent", null); + if (parent == null) { + float[] uvs = map.require("uvs").asFloatArray(); + float[] vertices = map.require("vertices").asFloatArray(); + FloatArray weights = new FloatArray(uvs.length * 3 * 3); + IntArray bones = new IntArray(uvs.length * 3); + for (int i = 0, n = vertices.length; i < n;) { + int boneCount = (int)vertices[i++]; + bones.add(boneCount); + for (int nn = i + boneCount * 4; i < nn;) { + bones.add((int)vertices[i]); + weights.add(vertices[i + 1] * scale); + weights.add(vertices[i + 2] * scale); + weights.add(vertices[i + 3]); + i += 4; + } + } + mesh.setBones(bones.toArray()); + mesh.setWeights(weights.toArray()); + mesh.setTriangles(map.require("triangles").asShortArray()); + mesh.setRegionUVs(uvs); + mesh.updateUVs(); + + if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); + if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); + } else { + mesh.setInheritFFD(map.getBoolean("ffd", true)); + linkedMeshes.add(new LinkedMesh(mesh, map.getString("skin", null), slotIndex, parent)); + } return mesh; } } @@ -550,4 +587,18 @@ public class SkeletonJson { timeline.setCurve(frameIndex, curve.getFloat(0), curve.getFloat(1), curve.getFloat(2), curve.getFloat(3)); } } + + static class LinkedMesh { + String parent, skin; + int slotIndex; + Attachment mesh; + + public LinkedMesh (Attachment mesh, String skin, int slotIndex, String parent) { + super(); + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Attachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Attachment.java index dcd5ccf3c..d01b24d84 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Attachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Attachment.java @@ -32,7 +32,7 @@ package com.esotericsoftware.spine.attachments; abstract public class Attachment { - final String name; + String name; public Attachment (String name) { if (name == null) throw new IllegalArgumentException("name cannot be null."); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/AttachmentType.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/AttachmentType.java index 05aa84b55..bf8f446e6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/AttachmentType.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/AttachmentType.java @@ -32,7 +32,7 @@ package com.esotericsoftware.spine.attachments; public enum AttachmentType { - region, boundingbox, mesh, weightedmesh; + region, boundingbox, mesh, weightedmesh, linkedmesh, weightedlinkedmesh; static public AttachmentType[] values = values(); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/FfdAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/FfdAttachment.java new file mode 100644 index 000000000..88e045dbb --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/FfdAttachment.java @@ -0,0 +1,6 @@ + +package com.esotericsoftware.spine.attachments; + +public interface FfdAttachment { + public boolean applyFFD (Attachment sourceAttachment); +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java index bbfb90189..9f6515d5f 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java @@ -31,18 +31,17 @@ package com.esotericsoftware.spine.attachments; -import com.esotericsoftware.spine.Bone; -import com.esotericsoftware.spine.Skeleton; -import com.esotericsoftware.spine.Slot; - import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.NumberUtils; +import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.Skeleton; +import com.esotericsoftware.spine.Slot; /** Attachment that displays a texture region. */ -public class MeshAttachment extends Attachment { +public class MeshAttachment extends Attachment implements FfdAttachment { private TextureRegion region; private String path; private float[] vertices, regionUVs; @@ -50,6 +49,8 @@ public class MeshAttachment extends Attachment { private float[] worldVertices; private final Color color = new Color(1, 1, 1, 1); private int hullLength; + private MeshAttachment parentMesh; + private boolean inheritFFD; // Nonessential. private int[] edges; @@ -129,6 +130,10 @@ public class MeshAttachment extends Attachment { return worldVertices; } + public boolean applyFFD (Attachment sourceAttachment) { + return this == sourceAttachment || (inheritFFD && parentMesh == sourceAttachment); + } + public float[] getWorldVertices () { return worldVertices; } @@ -200,4 +205,28 @@ public class MeshAttachment extends Attachment { public void setHeight (float height) { this.height = height; } + + /** Returns the source mesh if this is a linked mesh, else returns null. */ + public MeshAttachment getParentMesh () { + return parentMesh; + } + + /** @param parentMesh May be null. */ + public void setParentMesh (MeshAttachment parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + vertices = parentMesh.vertices; + regionUVs = parentMesh.regionUVs; + triangles = parentMesh.triangles; + hullLength = parentMesh.hullLength; + } + } + + public boolean getInheritFFD () { + return inheritFFD; + } + + public void setInheritFFD (boolean inheritFFD) { + this.inheritFFD = inheritFFD; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/WeightedMeshAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/WeightedMeshAttachment.java index c2484dfe6..12bf4eeec 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/WeightedMeshAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/WeightedMeshAttachment.java @@ -42,7 +42,7 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.NumberUtils; /** Attachment that displays a texture region. */ -public class WeightedMeshAttachment extends Attachment { +public class WeightedMeshAttachment extends Attachment implements FfdAttachment { private TextureRegion region; private String path; private int[] bones; @@ -51,6 +51,8 @@ public class WeightedMeshAttachment extends Attachment { private float[] worldVertices; private final Color color = new Color(1, 1, 1, 1); private int hullLength; + private WeightedMeshAttachment parentMesh; + private boolean inheritFFD; // Nonessential. private int[] edges; @@ -153,6 +155,10 @@ public class WeightedMeshAttachment extends Attachment { return worldVertices; } + public boolean applyFFD (Attachment sourceAttachment) { + return this == sourceAttachment || (inheritFFD && parentMesh == sourceAttachment); + } + public float[] getWorldVertices () { return worldVertices; } @@ -237,4 +243,29 @@ public class WeightedMeshAttachment extends Attachment { public void setHeight (float height) { this.height = height; } + + /** Returns the source mesh if this is a linked mesh, else returns null. */ + public WeightedMeshAttachment getParentMesh () { + return parentMesh; + } + + /** @param parentMesh May be null. */ + public void setParentMesh (WeightedMeshAttachment parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + bones = parentMesh.bones; + weights = parentMesh.weights; + regionUVs = parentMesh.regionUVs; + triangles = parentMesh.triangles; + hullLength = parentMesh.hullLength; + } + } + + public boolean getInheritFFD () { + return inheritFFD; + } + + public void setInheritFFD (boolean inheritFFD) { + this.inheritFFD = inheritFFD; + } } diff --git a/spine-libgdx/spine-skeletonviewer/.classpath b/spine-libgdx/spine-skeletonviewer/.classpath index 22cde12f4..cd9d52970 100644 --- a/spine-libgdx/spine-skeletonviewer/.classpath +++ b/spine-libgdx/spine-skeletonviewer/.classpath @@ -2,7 +2,7 @@ - + diff --git a/spine-libgdx/spine-skeletonviewer/.settings/org.eclipse.jdt.core.prefs b/spine-libgdx/spine-skeletonviewer/.settings/org.eclipse.jdt.core.prefs index 6a57c0f46..b1afb4ec3 100644 --- a/spine-libgdx/spine-skeletonviewer/.settings/org.eclipse.jdt.core.prefs +++ b/spine-libgdx/spine-skeletonviewer/.settings/org.eclipse.jdt.core.prefs @@ -6,9 +6,9 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -96,4 +96,4 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.source=1.7