diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java index 41aae0872..c9d835844 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java @@ -54,8 +54,8 @@ public class AttachmentTimelineTests { Attachment attachment2 = new Attachment("attachment2") {}; Skin skin = new Skin("skin"); - skin.addAttachment(0, "attachment1", attachment1); - skin.addAttachment(0, "attachment2", attachment2); + skin.setAttachment(0, "attachment1", attachment1); + skin.setAttachment(0, "attachment2", attachment2); skeletonData.setDefaultSkin(skin); skeleton = new Skeleton(skeletonData); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 819167734..c254dd0ee 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -30,15 +30,14 @@ package com.esotericsoftware.spine; -import static com.esotericsoftware.spine.utils.SpineUtils.*; +import static com.esotericsoftware.spine.utils.SpineUtils.cosDeg; +import static com.esotericsoftware.spine.utils.SpineUtils.sinDeg; 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.ObjectMap.Entry; - -import com.esotericsoftware.spine.Skin.Key; +import com.esotericsoftware.spine.Skin.SkinEntry; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.MeshAttachment; import com.esotericsoftware.spine.attachments.PathAttachment; @@ -279,8 +278,8 @@ public class Skeleton { } private void sortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) { - for (Entry entry : skin.attachments.entries()) - if (entry.key.slotIndex == slotIndex) sortPathConstraintAttachment(entry.value, slotBone); + for (SkinEntry entry : skin.attachments.keys()) + if (entry.getSlotIndex() == slotIndex) sortPathConstraintAttachment(entry.getAttachment(), slotBone); } private void sortPathConstraintAttachment (Attachment attachment, Bone slotBone) { 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 3652ee824..8b313b6d1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -362,7 +362,7 @@ public class SkeletonBinary { for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { String name = input.readString(); Attachment attachment = readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); - if (attachment != null) skin.addAttachment(slotIndex, name, attachment); + if (attachment != null) skin.setAttachment(slotIndex, name, attachment); } } return skin; 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 e61592f97..9114058f4 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -294,7 +294,7 @@ public class SkeletonJson { for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) { try { Attachment attachment = readAttachment(entry, skin, slot.index, entry.name, skeletonData); - if (attachment != null) skin.addAttachment(slot.index, entry.name, attachment); + if (attachment != null) skin.setAttachment(slot.index, entry.name, attachment); } catch (Throwable ex) { throw new SerializationException("Error reading attachment: " + entry.name + ", skin: " + skin, ex); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java index 9d9addcb9..7a6712068 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java @@ -32,9 +32,6 @@ package com.esotericsoftware.spine; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectMap.Entry; -import com.badlogic.gdx.utils.Pool; - import com.esotericsoftware.spine.attachments.Attachment; /** Stores attachments by slot index and attachment name. @@ -43,15 +40,10 @@ import com.esotericsoftware.spine.attachments.Attachment; * Runtime skins in the Spine Runtimes Guide. */ public class Skin { final String name; - final ObjectMap attachments = new ObjectMap(); + final ObjectMap attachments = new ObjectMap(); final Array bones = new Array(); final Array constraints = new Array(); - private final Key lookup = new Key(); - final Pool keyPool = new Pool(64) { - protected Object newObject () { - return new Key(); - } - }; + private final SkinEntry lookup = new SkinEntry(); public Skin (String name) { if (name == null) throw new IllegalArgumentException("name cannot be null."); @@ -59,53 +51,49 @@ public class Skin { } /** Adds an attachment to the skin for the specified slot index and name. */ - public void addAttachment (int slotIndex, String name, Attachment attachment) { + public void setAttachment (int slotIndex, String name, Attachment attachment) { if (attachment == null) throw new IllegalArgumentException("attachment cannot be null."); if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); - Key key = keyPool.obtain(); - key.set(slotIndex, name); - attachments.put(key, attachment); + attachments.put(new SkinEntry(slotIndex, name, attachment), attachment); } /** Adds all attachments from the specified skin to this skin. */ - public void addAttachments (Skin skin) { - for (Entry entry : skin.attachments.entries()) - addAttachment(entry.key.slotIndex, entry.key.name, entry.value); + public void addSkin (Skin skin) { + for (SkinEntry entry : skin.attachments.keys()) + setAttachment(entry.getSlotIndex(), entry.getName(), entry.getAttachment()); } /** Returns the attachment for the specified slot index and name, or null. */ public Attachment getAttachment (int slotIndex, String name) { if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); - lookup.set(slotIndex, name); + lookup.set(slotIndex, name, null); return attachments.get(lookup); } /** Removes the attachment in the skin for the specified slot index and name, if any. */ public void removeAttachment (int slotIndex, String name) { if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); - Key key = keyPool.obtain(); - key.set(slotIndex, name); - attachments.remove(key); - keyPool.free(key); + lookup.set(slotIndex, name, null); + attachments.remove(lookup); } - public void findNamesForSlot (int slotIndex, Array names) { - if (names == null) throw new IllegalArgumentException("names cannot be null."); - if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); - for (Key key : attachments.keys()) - if (key.slotIndex == slotIndex) names.add(key.name); + /** Returns all attachments contained in this skin. */ + public Array getAttachments () { + Array entries = new Array(); + for (SkinEntry entry : this.attachments.keys()) + entries.add(entry); + return entries; } - public void findAttachmentsForSlot (int slotIndex, Array attachments) { - if (attachments == null) throw new IllegalArgumentException("attachments cannot be null."); - if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0."); - for (Entry entry : this.attachments.entries()) - if (entry.key.slotIndex == slotIndex) attachments.add(entry.value); + /** Returns all {@link SkinEntry} instances for the given slot contained in this skin. */ + public Array getEntries (int slotIndex) { + Array entries = new Array(); + for (SkinEntry entry : this.attachments.keys()) + if (entry.getSlotIndex() == slotIndex) entries.add(entry); + return entries; } public void clear () { - for (Key key : attachments.keys()) - keyPool.free(key); attachments.clear(1024); bones.clear(); constraints.clear(); @@ -134,26 +122,49 @@ public class Skin { /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ void attachAll (Skeleton skeleton, Skin oldSkin) { - for (Entry entry : oldSkin.attachments.entries()) { - int slotIndex = entry.key.slotIndex; + for (SkinEntry entry : oldSkin.attachments.keys()) { + int slotIndex = entry.getSlotIndex(); Slot slot = skeleton.slots.get(slotIndex); - if (slot.attachment == entry.value) { - Attachment attachment = getAttachment(slotIndex, entry.key.name); + if (slot.attachment == entry.getAttachment()) { + Attachment attachment = getAttachment(slotIndex, entry.getName()); if (attachment != null) slot.setAttachment(attachment); } } } - static class Key { - int slotIndex; - String name; - int hashCode; + /** Stores an entry in the skin consisting of the slot index, name, and attachment **/ + public static class SkinEntry { + private int slotIndex; + private String name; + private Attachment attachment; + private int hashCode; - public void set (int slotIndex, String name) { + SkinEntry () { + set(0, "", null); + } + + SkinEntry (int slotIndex, String name, Attachment attachment) { + set(slotIndex, name, attachment); + } + + void set (int slotIndex, String name, Attachment attachment) { if (name == null) throw new IllegalArgumentException("name cannot be null."); this.slotIndex = slotIndex; this.name = name; - hashCode = name.hashCode() + slotIndex * 37; + this.attachment = attachment; + this.hashCode = name.hashCode() + slotIndex * 37; + } + + public int getSlotIndex () { + return slotIndex; + } + + public String getName () { + return name; + } + + public Attachment getAttachment () { + return attachment; } public int hashCode () { @@ -162,7 +173,7 @@ public class Skin { public boolean equals (Object object) { if (object == null) return false; - Key other = (Key)object; + SkinEntry other = (SkinEntry)object; if (slotIndex != other.slotIndex) return false; if (!name.equals(other.name)) return false; return true; 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 979d47eb3..6890ebf31 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 @@ -47,4 +47,7 @@ abstract public class Attachment { public String toString () { return getName(); } + + /** Returns a copy of the attachment. **/ + public abstract Attachment copy (); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/BoundingBoxAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/BoundingBoxAttachment.java index 7e449edb3..3928fb471 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/BoundingBoxAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/BoundingBoxAttachment.java @@ -51,4 +51,11 @@ public class BoundingBoxAttachment extends VertexAttachment { public Color getColor () { return color; } + + public Attachment copy () { + BoundingBoxAttachment copy = new BoundingBoxAttachment(name); + copyTo(copy); + copy.color.set(color); + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/ClippingAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/ClippingAttachment.java index 57bd0ab13..5e3b18e3c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/ClippingAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/ClippingAttachment.java @@ -59,4 +59,12 @@ public class ClippingAttachment extends VertexAttachment { public Color getColor () { return color; } + + public Attachment copy () { + ClippingAttachment copy = new ClippingAttachment(name); + copyTo(copy); + copy.endSlot = endSlot; + copy.color.set(color); + return copy; + } } 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 3040635e0..ea5e3bfa5 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 @@ -33,7 +33,6 @@ package com.esotericsoftware.spine.attachments; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; - import com.esotericsoftware.spine.Animation.DeformTimeline; /** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not @@ -253,4 +252,35 @@ public class MeshAttachment extends VertexAttachment { public void setInheritDeform (boolean inheritDeform) { this.inheritDeform = inheritDeform; } + + public Attachment copy () { + MeshAttachment copy = new MeshAttachment(name); + copy.region = region; + copy.path = path; + + if (parentMesh == null) { + copyTo(copy); + copy.regionUVs = new float[regionUVs.length]; + System.arraycopy(regionUVs, 0, copy.regionUVs, 0, regionUVs.length); + copy.uvs = new float[uvs.length]; + System.arraycopy(uvs, 0, copy.uvs, 0, uvs.length); + copy.triangles = new short[triangles.length]; + System.arraycopy(triangles, 0, copy.triangles, 0, triangles.length); + copy.color.set(color); + copy.hullLength = hullLength; + + copy.inheritDeform = inheritDeform; + + // Nonessential. + if (edges != null) { + copy.edges = new short[edges.length]; + System.arraycopy(edges, 0, copy.edges, 0, edges.length); + } + copy.width = width; + copy.height = height; + } else + copy.setParentMesh(parentMesh); + + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PathAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PathAttachment.java index a1747c408..69b1c6ce6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PathAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PathAttachment.java @@ -80,4 +80,14 @@ public class PathAttachment extends VertexAttachment { public Color getColor () { return color; } + + public Attachment copy () { + PathAttachment copy = new PathAttachment(name); + copyTo(copy); + copy.lengths = new float[lengths.length]; + System.arraycopy(lengths, 0, copy.lengths, 0, lengths.length); + copy.closed = closed; + copy.constantSpeed = constantSpeed; + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java index 403aca66e..931969b27 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java @@ -30,7 +30,9 @@ package com.esotericsoftware.spine.attachments; -import static com.badlogic.gdx.math.MathUtils.*; +import static com.badlogic.gdx.math.MathUtils.cosDeg; +import static com.badlogic.gdx.math.MathUtils.radDeg; +import static com.badlogic.gdx.math.MathUtils.sinDeg; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; @@ -93,4 +95,14 @@ public class PointAttachment extends Attachment { float y = cos * bone.getC() + sin * bone.getD(); return (float)Math.atan2(y, x) * radDeg; } + + public Attachment copy () { + PointAttachment copy = new PointAttachment(name); + copy.name = name; + copy.x = x; + copy.y = y; + copy.rotation = rotation; + copy.color.set(color); + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java index ad18eb36b..3405757a7 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java @@ -264,4 +264,21 @@ public class RegionAttachment extends Attachment { public void setPath (String path) { this.path = path; } + + public Attachment copy () { + RegionAttachment copy = new RegionAttachment(name); + copy.region = region; + copy.path = path; + copy.x = x; + copy.y = y; + copy.scaleX = scaleX; + copy.scaleY = scaleY; + copy.rotation = rotation; + copy.width = width; + copy.height = height; + System.arraycopy(uvs, 0, copy.uvs, 0, uvs.length); + System.arraycopy(offset, 0, copy.offset, 0, offset.length); + copy.color.set(color); + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/SkeletonAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/SkeletonAttachment.java index d899f3bdd..29b3edc37 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/SkeletonAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/SkeletonAttachment.java @@ -49,4 +49,10 @@ public class SkeletonAttachment extends Attachment { public void setSkeleton (Skeleton skeleton) { this.skeleton = skeleton; } + + public Attachment copy () { + SkeletonAttachment copy = new SkeletonAttachment(name); + copy.skeleton = skeleton; + return copy; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java index 90991fa15..606df4375 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java @@ -31,14 +31,13 @@ package com.esotericsoftware.spine.attachments; import com.badlogic.gdx.utils.FloatArray; - import com.esotericsoftware.spine.Bone; import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Slot; /** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's * {@link Slot#getDeform()}. */ -public class VertexAttachment extends Attachment { +public abstract class VertexAttachment extends Attachment { static private int nextID; private final int id = (nextID() & 65535) << 11; @@ -162,6 +161,24 @@ public class VertexAttachment extends Attachment { return id; } + /** Internal method used by VertexAttachment subclasses to copy basic data. Does not copy id (generated) and name (set on + * construction). **/ + void copyTo (VertexAttachment attachment) { + if (bones != null) { + attachment.bones = new int[bones.length]; + System.arraycopy(bones, 0, attachment.bones, 0, bones.length); + } else + attachment.bones = null; + + if (vertices != null) { + attachment.vertices = new float[vertices.length]; + System.arraycopy(vertices, 0, attachment.vertices, 0, vertices.length); + } else + attachment.vertices = null; + + attachment.worldVerticesLength = worldVerticesLength; + } + static private synchronized int nextID () { return nextID++; }