Separated updateRegions() from setMesh() to facilitate lazy loading atlas regions.

Moved setting path into SkeletonJson.
This commit is contained in:
NathanSweet 2014-04-28 12:49:06 +02:00
parent fc60d4d6de
commit a76c396528
9 changed files with 71 additions and 41 deletions

View File

@ -43,7 +43,6 @@ namespace Spine {
AtlasRegion region = atlas.FindRegion(path); AtlasRegion region = atlas.FindRegion(path);
if (region == null) throw new Exception("Region not found in atlas: " + path + " (region attachment: " + name + ")"); if (region == null) throw new Exception("Region not found in atlas: " + path + " (region attachment: " + name + ")");
RegionAttachment attachment = new RegionAttachment(name); RegionAttachment attachment = new RegionAttachment(name);
attachment.Path = path;
attachment.RendererObject = region; attachment.RendererObject = region;
attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate); attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
attachment.regionOffsetX = region.offsetX; attachment.regionOffsetX = region.offsetX;
@ -59,7 +58,6 @@ namespace Spine {
AtlasRegion region = atlas.FindRegion(path); AtlasRegion region = atlas.FindRegion(path);
if (region == null) throw new Exception("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); if (region == null) throw new Exception("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
MeshAttachment attachment = new MeshAttachment(name); MeshAttachment attachment = new MeshAttachment(name);
attachment.Path = path;
attachment.RendererObject = region; attachment.RendererObject = region;
attachment.RegionU = region.u; attachment.RegionU = region.u;
attachment.RegionV = region.v; attachment.RegionV = region.v;
@ -79,7 +77,6 @@ namespace Spine {
AtlasRegion region = atlas.FindRegion(path); AtlasRegion region = atlas.FindRegion(path);
if (region == null) throw new Exception("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")"); if (region == null) throw new Exception("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")");
SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name); SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name);
attachment.Path = path;
attachment.RendererObject = region; attachment.RendererObject = region;
attachment.RegionU = region.u; attachment.RegionU = region.u;
attachment.RegionV = region.v; attachment.RegionV = region.v;

View File

@ -33,12 +33,13 @@ using System;
namespace Spine { namespace Spine {
/// <summary>Attachment that displays a texture region.</summary> /// <summary>Attachment that displays a texture region.</summary>
public class MeshAttachment : Attachment { public class MeshAttachment : Attachment {
internal float[] vertices, uvs; internal float[] vertices, uvs, regionUVs;
internal int[] triangles; internal int[] triangles;
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight; internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
internal float r = 1, g = 1, b = 1, a = 1; internal float r = 1, g = 1, b = 1, a = 1;
public float[] Vertices { get { return vertices; } set { vertices = value; } } public float[] Vertices { get { return vertices; } set { vertices = value; } }
public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
public float[] UVs { get { return uvs; } set { uvs = value; } } public float[] UVs { get { return uvs; } set { uvs = value; } }
public int[] Triangles { get { return triangles; } set { triangles = value; } } public int[] Triangles { get { return triangles; } set { triangles = value; } }
@ -71,20 +72,26 @@ namespace Spine {
: base(name) { : base(name) {
} }
public void SetMesh (float[] vertices, int[] triangles, float[] uvs) { public void SetMesh (float[] vertices, int[] triangles, float[] regionUVs) {
this.vertices = vertices; this.vertices = vertices;
this.triangles = triangles; this.triangles = triangles;
this.uvs = uvs; this.regionUVs = regionUVs;
this.uvs = new float[regionUVs.Length];
}
public void UpdateUVs () {
float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
float[] regionUVs = this.regionUVs;
float[] uvs = this.uvs;
if (RegionRotate) { if (RegionRotate) {
for (int i = 0, n = uvs.Length; i < n; i += 2) { for (int i = 0, n = uvs.Length; i < n; i += 2) {
uvs[i] = u + uvs[i + 1] * width; uvs[i] = u + regionUVs[i + 1] * width;
uvs[i + 1] = v + height - uvs[i] * height; uvs[i + 1] = v + height - regionUVs[i] * height;
} }
} else { } else {
for (int i = 0, n = uvs.Length; i < n; i += 2) { for (int i = 0, n = uvs.Length; i < n; i += 2) {
uvs[i] = u + uvs[i] * width; uvs[i] = u + regionUVs[i] * width;
uvs[i + 1] = v + uvs[i + 1] * height; uvs[i + 1] = v + regionUVs[i + 1] * height;
} }
} }
} }

View File

@ -35,13 +35,14 @@ namespace Spine {
/// <summary>Attachment that displays a texture region.</summary> /// <summary>Attachment that displays a texture region.</summary>
public class SkinnedMeshAttachment : Attachment { public class SkinnedMeshAttachment : Attachment {
internal int[] bones; internal int[] bones;
internal float[] weights, uvs; internal float[] weights, uvs, regionUVs;
internal int[] triangles; internal int[] triangles;
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight; internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
internal float r = 1, g = 1, b = 1, a = 1; internal float r = 1, g = 1, b = 1, a = 1;
public int[] Bones { get { return bones; } set { bones = value; } } public int[] Bones { get { return bones; } set { bones = value; } }
public float[] Weights { get { return weights; } set { weights = value; } } public float[] Weights { get { return weights; } set { weights = value; } }
public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
public float[] UVs { get { return uvs; } set { uvs = value; } } public float[] UVs { get { return uvs; } set { uvs = value; } }
public int[] Triangles { get { return triangles; } set { triangles = value; } } public int[] Triangles { get { return triangles; } set { triangles = value; } }
@ -74,21 +75,27 @@ namespace Spine {
: base(name) { : base(name) {
} }
public void SetMesh (int[] bones, float[] weights, int[] triangles, float[] uvs) { public void SetMesh (int[] bones, float[] weights, int[] triangles, float[] regionUVs) {
this.bones = bones; this.bones = bones;
this.weights = weights; this.weights = weights;
this.triangles = triangles; this.triangles = triangles;
this.uvs = uvs; this.regionUVs = regionUVs;
this.uvs = new float[regionUVs.Length];
}
public void UpdateUVs () {
float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
float[] regionUVs = this.regionUVs;
float[] uvs = this.uvs;
if (RegionRotate) { if (RegionRotate) {
for (int i = 0, n = uvs.Length; i < n; i += 2) { for (int i = 0, n = uvs.Length; i < n; i += 2) {
uvs[i] = u + uvs[i + 1] * width; uvs[i] = u + regionUVs[i + 1] * width;
uvs[i + 1] = v + height - uvs[i] * height; uvs[i + 1] = v + height - regionUVs[i] * height;
} }
} else { } else {
for (int i = 0, n = uvs.Length; i < n; i += 2) { for (int i = 0, n = uvs.Length; i < n; i += 2) {
uvs[i] = u + uvs[i] * width; uvs[i] = u + regionUVs[i] * width;
uvs[i + 1] = v + uvs[i + 1] * height; uvs[i + 1] = v + regionUVs[i + 1] * height;
} }
} }
} }

View File

@ -196,6 +196,7 @@ namespace Spine {
case AttachmentType.region: case AttachmentType.region:
RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
if (region == null) return null; if (region == null) return null;
region.Path = path;
region.x = GetFloat(map, "x", 0) * Scale; region.x = GetFloat(map, "x", 0) * Scale;
region.y = GetFloat(map, "y", 0) * Scale; region.y = GetFloat(map, "y", 0) * Scale;
region.scaleX = GetFloat(map, "scaleX", 1); region.scaleX = GetFloat(map, "scaleX", 1);
@ -218,10 +219,12 @@ namespace Spine {
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.Path = path;
float[] uvs = GetFloatArray(map, "uvs", 1); float[] uvs = GetFloatArray(map, "uvs", 1);
int[] triangles = GetIntArray(map, "triangles"); int[] triangles = GetIntArray(map, "triangles");
float[] vertices = GetFloatArray(map, "vertices", Scale); float[] vertices = GetFloatArray(map, "vertices", Scale);
mesh.SetMesh(vertices, triangles, uvs); mesh.SetMesh(vertices, triangles, uvs);
mesh.UpdateUVs();
if (map.ContainsKey("color")) { if (map.ContainsKey("color")) {
var color = (String)map["color"]; var color = (String)map["color"];
@ -242,6 +245,7 @@ namespace Spine {
SkinnedMeshAttachment mesh = attachmentLoader.NewSkinnedMeshAttachment(skin, name, path); SkinnedMeshAttachment mesh = attachmentLoader.NewSkinnedMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.Path = path;
float[] uvs = GetFloatArray(map, "uvs", 1); float[] uvs = GetFloatArray(map, "uvs", 1);
int[] triangles = GetIntArray(map, "triangles"); int[] triangles = GetIntArray(map, "triangles");
@ -261,6 +265,7 @@ namespace Spine {
} }
} }
mesh.SetMesh(bones.ToArray(), weights.ToArray(), triangles, uvs); mesh.SetMesh(bones.ToArray(), weights.ToArray(), triangles, uvs);
mesh.UpdateUVs();
if (map.ContainsKey("color")) { if (map.ContainsKey("color")) {
var color = (String)map["color"]; var color = (String)map["color"];

View File

@ -202,6 +202,7 @@ public class SkeletonBinary {
if (path == null) path = name; if (path == null) path = name;
RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path); RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path);
if (region == null) return null; if (region == null) return null;
region.setPath(path);
region.setX(input.readFloat() * scale); region.setX(input.readFloat() * scale);
region.setY(input.readFloat() * scale); region.setY(input.readFloat() * scale);
region.setScaleX(input.readFloat()); region.setScaleX(input.readFloat());
@ -224,10 +225,12 @@ public class SkeletonBinary {
if (path == null) path = name; if (path == null) path = name;
MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path); MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.setPath(path);
float[] uvs = readFloatArray(input, 1); float[] uvs = readFloatArray(input, 1);
short[] triangles = readShortArray(input); short[] triangles = readShortArray(input);
float[] vertices = readFloatArray(input, scale); float[] vertices = readFloatArray(input, scale);
mesh.setMesh(vertices, triangles, uvs); mesh.setMesh(vertices, triangles, uvs);
mesh.updateUVs();
Color.rgba8888ToColor(mesh.getColor(), input.readInt()); Color.rgba8888ToColor(mesh.getColor(), input.readInt());
if (nonessential) { if (nonessential) {
mesh.setEdges(readIntArray(input)); mesh.setEdges(readIntArray(input));
@ -242,6 +245,7 @@ public class SkeletonBinary {
if (path == null) path = name; if (path == null) path = name;
SkinnedMeshAttachment mesh = attachmentLoader.newSkinnedMeshAttachment(skin, name, path); SkinnedMeshAttachment mesh = attachmentLoader.newSkinnedMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.setPath(path);
float[] uvs = readFloatArray(input, 1); float[] uvs = readFloatArray(input, 1);
short[] triangles = readShortArray(input); short[] triangles = readShortArray(input);
@ -259,7 +263,7 @@ public class SkeletonBinary {
} }
} }
mesh.setMesh(bones.toArray(), weights.toArray(), triangles, uvs); mesh.setMesh(bones.toArray(), weights.toArray(), triangles, uvs);
mesh.updateUVs();
Color.rgba8888ToColor(mesh.getColor(), input.readInt()); Color.rgba8888ToColor(mesh.getColor(), input.readInt());
if (nonessential) { if (nonessential) {
mesh.setEdges(readIntArray(input)); mesh.setEdges(readIntArray(input));

View File

@ -176,6 +176,7 @@ public class SkeletonJson {
case region: case region:
RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path); RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path);
if (region == null) return null; if (region == null) return null;
region.setPath(path);
region.setX(map.getFloat("x", 0) * scale); region.setX(map.getFloat("x", 0) * scale);
region.setY(map.getFloat("y", 0) * scale); region.setY(map.getFloat("y", 0) * scale);
region.setScaleX(map.getFloat("scaleX", 1)); region.setScaleX(map.getFloat("scaleX", 1));
@ -203,6 +204,7 @@ public class SkeletonJson {
case mesh: { case mesh: {
MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path); MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.setPath(path);
float[] uvs = map.require("uvs").asFloatArray(); float[] uvs = map.require("uvs").asFloatArray();
short[] triangles = map.require("triangles").asShortArray(); short[] triangles = map.require("triangles").asShortArray();
@ -212,6 +214,7 @@ public class SkeletonJson {
vertices[i] *= scale; vertices[i] *= scale;
} }
mesh.setMesh(vertices, triangles, uvs); mesh.setMesh(vertices, triangles, uvs);
mesh.updateUVs();
if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2);
if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray());
@ -222,6 +225,7 @@ public class SkeletonJson {
case skinnedmesh: { case skinnedmesh: {
SkinnedMeshAttachment mesh = attachmentLoader.newSkinnedMeshAttachment(skin, name, path); SkinnedMeshAttachment mesh = attachmentLoader.newSkinnedMeshAttachment(skin, name, path);
if (mesh == null) return null; if (mesh == null) return null;
mesh.setPath(path);
float[] uvs = map.require("uvs").asFloatArray(); float[] uvs = map.require("uvs").asFloatArray();
short[] triangles = map.require("triangles").asShortArray(); short[] triangles = map.require("triangles").asShortArray();
@ -240,6 +244,7 @@ public class SkeletonJson {
} }
} }
mesh.setMesh(bones.toArray(), weights.toArray(), triangles, uvs); mesh.setMesh(bones.toArray(), weights.toArray(), triangles, uvs);
mesh.updateUVs();
if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2); if (map.has("hull")) mesh.setHullLength(map.require("hull").asInt() * 2);
if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray()); if (map.has("edges")) mesh.setEdges(map.require("edges").asIntArray());

View File

@ -48,7 +48,6 @@ public class AtlasAttachmentLoader implements AttachmentLoader {
if (region == null) if (region == null)
throw new RuntimeException("Region not found in atlas: " + path + " (region attachment: " + name + ")"); throw new RuntimeException("Region not found in atlas: " + path + " (region attachment: " + name + ")");
RegionAttachment attachment = new RegionAttachment(name); RegionAttachment attachment = new RegionAttachment(name);
attachment.setPath(path);
attachment.setRegion(region); attachment.setRegion(region);
return attachment; return attachment;
} }
@ -57,7 +56,6 @@ public class AtlasAttachmentLoader implements AttachmentLoader {
AtlasRegion region = atlas.findRegion(path); AtlasRegion region = atlas.findRegion(path);
if (region == null) throw new RuntimeException("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); if (region == null) throw new RuntimeException("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
MeshAttachment attachment = new MeshAttachment(name); MeshAttachment attachment = new MeshAttachment(name);
attachment.setPath(path);
attachment.setRegion(region); attachment.setRegion(region);
return attachment; return attachment;
} }
@ -67,7 +65,6 @@ public class AtlasAttachmentLoader implements AttachmentLoader {
if (region == null) if (region == null)
throw new RuntimeException("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")"); throw new RuntimeException("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")");
SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name); SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name);
attachment.setPath(path);
attachment.setRegion(region); attachment.setRegion(region);
return attachment; return attachment;
} }

View File

@ -44,7 +44,7 @@ import com.badlogic.gdx.utils.NumberUtils;
public class MeshAttachment extends Attachment { public class MeshAttachment extends Attachment {
private TextureRegion region; private TextureRegion region;
private String path; private String path;
private float[] vertices; private float[] vertices, regionUVs;
private short[] triangles; private short[] triangles;
private float[] worldVertices; private float[] worldVertices;
private final Color color = new Color(1, 1, 1, 1); private final Color color = new Color(1, 1, 1, 1);
@ -68,13 +68,16 @@ public class MeshAttachment extends Attachment {
return region; return region;
} }
public void setMesh (float[] vertices, short[] triangles, float[] uvs) { public void setMesh (float[] vertices, short[] triangles, float[] regionUVs) {
this.vertices = vertices; this.vertices = vertices;
this.triangles = triangles; this.triangles = triangles;
this.regionUVs = regionUVs;
int worldVerticesLength = vertices.length / 2 * 5; int worldVerticesLength = vertices.length / 2 * 5;
if (worldVertices == null || worldVertices.length != worldVerticesLength) worldVertices = new float[worldVerticesLength]; if (worldVertices == null || worldVertices.length != worldVerticesLength) worldVertices = new float[worldVerticesLength];
}
public void updateUVs () {
float u, v, width, height; float u, v, width, height;
if (region == null) { if (region == null) {
u = v = 0; u = v = 0;
@ -85,15 +88,16 @@ public class MeshAttachment extends Attachment {
width = region.getU2() - u; width = region.getU2() - u;
height = region.getV2() - v; height = region.getV2() - v;
} }
float[] regionUVs = this.regionUVs;
if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) { if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) {
for (int i = 0, w = 3, n = vertices.length; i < n; i += 2, w += 5) { for (int i = 0, w = 3, n = vertices.length; i < n; i += 2, w += 5) {
worldVertices[w] = u + uvs[i + 1] * width; worldVertices[w] = u + regionUVs[i + 1] * width;
worldVertices[w + 1] = v + height - uvs[i] * height; worldVertices[w + 1] = v + height - regionUVs[i] * height;
} }
} else { } else {
for (int i = 0, w = 3, n = vertices.length; i < n; i += 2, w += 5) { for (int i = 0, w = 3, n = vertices.length; i < n; i += 2, w += 5) {
worldVertices[w] = u + uvs[i] * width; worldVertices[w] = u + regionUVs[i] * width;
worldVertices[w + 1] = v + uvs[i + 1] * height; worldVertices[w + 1] = v + regionUVs[i + 1] * height;
} }
} }
} }

View File

@ -45,7 +45,7 @@ public class SkinnedMeshAttachment extends Attachment {
private TextureRegion region; private TextureRegion region;
private String path; private String path;
private int[] bones; private int[] bones;
private float[] weights; private float[] weights, regionUVs;
private short[] triangles; private short[] triangles;
private float[] worldVertices; private float[] worldVertices;
private final Color color = new Color(1, 1, 1, 1); private final Color color = new Color(1, 1, 1, 1);
@ -73,36 +73,40 @@ public class SkinnedMeshAttachment extends Attachment {
* boneIndex, ... * boneIndex, ...
* @param weights For each bone affecting the vertex, the vertex position in the bone's coordinate system and the weight for * @param weights For each bone affecting the vertex, the vertex position in the bone's coordinate system and the weight for
* the bone's influence. Ie: x, y, weight, ... * the bone's influence. Ie: x, y, weight, ...
* @param uvs For each vertex, a texure coordinate pair. Ie: u, v, ... * @param regionUVs For each vertex, a texure coordinate pair. Ie: u, v, ...
* @param triangles Vertex number triplets which describe the mesh's triangulation. */ * @param triangles Vertex number triplets which describe the mesh's triangulation. */
public void setMesh (int[] bones, float[] weights, short[] triangles, float[] uvs) { public void setMesh (int[] bones, float[] weights, short[] triangles, float[] regionUVs) {
this.bones = bones; this.bones = bones;
this.weights = weights; this.weights = weights;
this.triangles = triangles; this.triangles = triangles;
this.regionUVs = regionUVs;
int uvsLength = uvs.length; int uvsLength = regionUVs.length;
int worldVerticesLength = uvsLength / 2 * 5; int worldVerticesLength = uvsLength / 2 * 5;
if (worldVertices == null || worldVertices.length != worldVerticesLength) worldVertices = new float[worldVerticesLength]; if (worldVertices == null || worldVertices.length != worldVerticesLength) worldVertices = new float[worldVerticesLength];
}
float u, v, w, h; public void updateUVs () {
float u, v, width, height;
if (region == null) { if (region == null) {
u = v = 0; u = v = 0;
w = h = 1; width = height = 1;
} else { } else {
u = region.getU(); u = region.getU();
v = region.getV(); v = region.getV();
w = region.getU2() - u; width = region.getU2() - u;
h = region.getV2() - v; height = region.getV2() - v;
} }
float[] regionUVs = this.regionUVs;
if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) { if (region instanceof AtlasRegion && ((AtlasRegion)region).rotate) {
for (int i = 0, ii = 3; i < uvsLength; i += 2, ii += 5) { for (int i = 0, w = 3, n = regionUVs.length; i < n; i += 2, w += 5) {
worldVertices[ii] = u + uvs[i + 1] * w; worldVertices[w] = u + regionUVs[i + 1] * width;
worldVertices[ii + 1] = v + h - uvs[i] * h; worldVertices[w + 1] = v + height - regionUVs[i] * height;
} }
} else { } else {
for (int i = 0, ii = 3; i < uvsLength; i += 2, ii += 5) { for (int i = 0, w = 3, n = regionUVs.length; i < n; i += 2, w += 5) {
worldVertices[ii] = u + uvs[i] * w; worldVertices[w] = u + regionUVs[i] * width;
worldVertices[ii + 1] = v + uvs[i + 1] * h; worldVertices[w + 1] = v + regionUVs[i + 1] * height;
} }
} }
} }