mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 06:29:02 +08:00
Refactored skin API, see #841. This commit is missing Skin#copy(Skin) which has to handle linked mesh attachments properly.
This commit is contained in:
parent
6205e51752
commit
86c3aa02ba
@ -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);
|
||||
|
||||
@ -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<Key, Attachment> 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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
* <a href="http://esotericsoftware.com/spine-runtime-skins">Runtime skins</a> in the Spine Runtimes Guide. */
|
||||
public class Skin {
|
||||
final String name;
|
||||
final ObjectMap<Key, Attachment> attachments = new ObjectMap();
|
||||
final ObjectMap<SkinEntry, Attachment> attachments = new ObjectMap();
|
||||
final Array<BoneData> bones = new Array();
|
||||
final Array<ConstraintData> constraints = new Array();
|
||||
private final Key lookup = new Key();
|
||||
final Pool<Key> 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<Key, Attachment> 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<String> 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<SkinEntry> getAttachments () {
|
||||
Array<SkinEntry> entries = new Array();
|
||||
for (SkinEntry entry : this.attachments.keys())
|
||||
entries.add(entry);
|
||||
return entries;
|
||||
}
|
||||
|
||||
public void findAttachmentsForSlot (int slotIndex, Array<Attachment> attachments) {
|
||||
if (attachments == null) throw new IllegalArgumentException("attachments cannot be null.");
|
||||
if (slotIndex < 0) throw new IllegalArgumentException("slotIndex must be >= 0.");
|
||||
for (Entry<Key, Attachment> 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<SkinEntry> getEntries (int slotIndex) {
|
||||
Array<SkinEntry> 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<Key, Attachment> 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;
|
||||
|
||||
@ -47,4 +47,7 @@ abstract public class Attachment {
|
||||
public String toString () {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/** Returns a copy of the attachment. **/
|
||||
public abstract Attachment copy ();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user