static void UpdateVertexCache(tk2dSpriteCollection gen, float scale, tk2dEditor.Atlas.Data[] packers, tk2dSpriteCollectionData coll, List<SpriteLut> spriteLuts)
{
for (int i = 0; i < sourceTextures.Length; ++i)
{
SpriteLut _lut = null;
for (int j = 0; j < spriteLuts.Count; ++j)
{
if (spriteLuts[j].source == i)
{
_lut = spriteLuts[j];
break;
}
}
int padAmount = GetPadAmount(gen, i);
tk2dSpriteCollectionDefinition thisTexParam = gen.textureParams[i];
tk2dEditor.Atlas.Data packer = null;
tk2dEditor.Atlas.Entry atlasEntry = null;
int atlasIndex = 0;
foreach (var p in packers)
{
if ((atlasEntry = p.FindEntryWithIndex(_lut.atlasIndex)) != null)
{
packer = p;
break;
}
++atlasIndex;
}
float fwidth = packer.width;
float fheight = packer.height;
int tx = atlasEntry.x + padAmount, ty = atlasEntry.y + padAmount, tw = atlasEntry.w - padAmount * 2, th = atlasEntry.h - padAmount * 2;
int sd_y = packer.height - ty - th;
float uvOffsetX = 0.001f / fwidth;
float uvOffsetY = 0.001f / fheight;
Vector2 v0 = new Vector2(tx / fwidth + uvOffsetX, 1.0f - (sd_y + th) / fheight + uvOffsetY);
Vector2 v1 = new Vector2((tx + tw) / fwidth - uvOffsetX, 1.0f - sd_y / fheight - uvOffsetY);
Mesh mesh = null;
Transform meshTransform = null;
GameObject instantiated = null;
Vector3 colliderOrigin = new Vector3();
if (thisTexParam.overrideMesh)
{
// Disabled
instantiated = GameObject.Instantiate(thisTexParam.overrideMesh) as GameObject;
MeshFilter meshFilter = instantiated.GetComponentInChildren<MeshFilter>();
if (meshFilter == null)
{
Debug.LogError("Unable to find mesh");
GameObject.DestroyImmediate(instantiated);
}
else
{
mesh = meshFilter.sharedMesh;
meshTransform = meshFilter.gameObject.transform;
}
}
Vector3 untrimmedPos0 = Vector3.zero, untrimmedPos1 = Vector3.one;
if (mesh)
{
coll.spriteDefinitions[i].positions = new Vector3[mesh.vertices.Length];
coll.spriteDefinitions[i].uvs = new Vector2[mesh.vertices.Length];
for (int j = 0; j < mesh.vertices.Length; ++j)
{
coll.spriteDefinitions[i].positions[j] = meshTransform.TransformPoint(mesh.vertices[j]);
coll.spriteDefinitions[i].uvs[j] = new Vector2(v0.x + (v1.x - v0.x) * mesh.uv[j].x, v0.y + (v1.y - v0.y) * mesh.uv[j].y);
}
coll.spriteDefinitions[i].indices = new int[mesh.triangles.Length];
for (int j = 0; j < mesh.triangles.Length; ++j)
{
coll.spriteDefinitions[i].indices[j] = mesh.triangles[j];
}
GameObject.DestroyImmediate(instantiated);
}
else
{
Texture2D thisTextureRef = sourceTextures[i];
int texHeightI = thisTextureRef?thisTextureRef.height:2;
int texWidthI = thisTextureRef?thisTextureRef.width:2;
float texHeight = texHeightI;
float texWidth = texWidthI;
float h = thisTextureRef?thisTextureRef.height:64;
float w = thisTextureRef?thisTextureRef.width:64;
h *= thisTexParam.scale.y;
w *= thisTexParam.scale.x;
float scaleX = w * scale;
float scaleY = h * scale;
// anchor coordinate system is (0, 0) = top left, to keep it the same as photoshop, etc.
switch (thisTexParam.anchor)
{
case tk2dSpriteCollectionDefinition.Anchor.LowerLeft: thisTexParam.anchorX = 0; thisTexParam.anchorY = texHeightI; break;
case tk2dSpriteCollectionDefinition.Anchor.LowerCenter: thisTexParam.anchorX = texWidthI / 2; thisTexParam.anchorY = texHeightI; break;
case tk2dSpriteCollectionDefinition.Anchor.LowerRight: thisTexParam.anchorX = texWidthI; thisTexParam.anchorY = texHeightI; break;
case tk2dSpriteCollectionDefinition.Anchor.MiddleLeft: thisTexParam.anchorX = 0; thisTexParam.anchorY = texHeightI / 2; break;
case tk2dSpriteCollectionDefinition.Anchor.MiddleCenter: thisTexParam.anchorX = texWidthI / 2; thisTexParam.anchorY = texHeightI / 2; break;
case tk2dSpriteCollectionDefinition.Anchor.MiddleRight: thisTexParam.anchorX = texWidthI; thisTexParam.anchorY = texHeightI / 2; break;
case tk2dSpriteCollectionDefinition.Anchor.UpperLeft: thisTexParam.anchorX = 0; thisTexParam.anchorY = 0; break;
case tk2dSpriteCollectionDefinition.Anchor.UpperCenter: thisTexParam.anchorX = texWidthI / 2; thisTexParam.anchorY = 0; break;
case tk2dSpriteCollectionDefinition.Anchor.UpperRight: thisTexParam.anchorX = texWidthI; thisTexParam.anchorY = 0; break;
}
Vector3 pos0 = new Vector3(-thisTexParam.anchorX * thisTexParam.scale.x * scale, 0, -(h - thisTexParam.anchorY * thisTexParam.scale.y) * scale);
colliderOrigin = new Vector3(pos0.x, pos0.z, 0.0f);
Vector3 pos1 = pos0 + new Vector3(scaleX, 0, scaleY);
untrimmedPos0 = new Vector3(pos0.x, pos0.z);
untrimmedPos1 = new Vector3(pos1.x, pos1.z);
List<Vector3> positions = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
// build mesh
if (_lut.isSplit)
{
coll.spriteDefinitions[i].flipped = false; // each split could be rotated, but not consistently
for (int j = 0; j < spriteLuts.Count; ++j)
{
if (spriteLuts[j].source == i)
{
_lut = spriteLuts[j];
int thisAtlasIndex = 0;
foreach (var p in packers)
{
if ((atlasEntry = p.FindEntryWithIndex(_lut.atlasIndex)) != null)
{
packer = p;
break;
}
++thisAtlasIndex;
}
if (thisAtlasIndex != atlasIndex)
{
// This is a serious problem, dicing is not supported when multi atlas output is selected
Debug.Break();
}
fwidth = packer.width;
fheight = packer.height;
tx = atlasEntry.x + padAmount;
ty = atlasEntry.y + padAmount;
tw = atlasEntry.w - padAmount * 2;
th = atlasEntry.h - padAmount * 2;
sd_y = packer.height - ty - th;
v0 = new Vector2(tx / fwidth + uvOffsetX, 1.0f - (sd_y + th) / fheight + uvOffsetY);
v1 = new Vector2((tx + tw) / fwidth - uvOffsetX, 1.0f - sd_y / fheight - uvOffsetY);
float x0 = _lut.rx / texWidth;
float y0 = _lut.ry / texHeight;
float x1 = (_lut.rx + _lut.rw) / texWidth;
float y1 = (_lut.ry + _lut.rh) / texHeight;
Vector3 dpos0 = new Vector3(Mathf.Lerp(pos0.x, pos1.x, x0), 0.0f, Mathf.Lerp(pos0.z, pos1.z, y0));
Vector3 dpos1 = new Vector3(Mathf.Lerp(pos0.x, pos1.x, x1), 0.0f, Mathf.Lerp(pos0.z, pos1.z, y1));
positions.Add(new Vector3(dpos0.x, dpos0.z, 0));
positions.Add(new Vector3(dpos1.x, dpos0.z, 0));
positions.Add(new Vector3(dpos0.x, dpos1.z, 0));
positions.Add(new Vector3(dpos1.x, dpos1.z, 0));
if (atlasEntry.flipped)
{
uvs.Add(new Vector2(v0.x,v0.y));
uvs.Add(new Vector2(v0.x,v1.y));
uvs.Add(new Vector2(v1.x,v0.y));
uvs.Add(new Vector2(v1.x,v1.y));
}
else
{
uvs.Add(new Vector2(v0.x,v0.y));
uvs.Add(new Vector2(v1.x,v0.y));
uvs.Add(new Vector2(v0.x,v1.y));
uvs.Add(new Vector2(v1.x,v1.y));
}
}
}
}
else if (thisTexParam.customSpriteGeometry)
{
coll.spriteDefinitions[i].flipped = atlasEntry.flipped;
List<int> indices = new List<int>();
foreach (var island in thisTexParam.geometryIslands)
{
int baseIndex = positions.Count;
for (int x = 0; x < island.points.Length; ++x)
{
var v = island.points[x];
Vector2 origin = new Vector2(pos0.x, pos0.z);
positions.Add(new Vector2(v.x * thisTexParam.scale.x, (texHeight - v.y) * thisTexParam.scale.y) * scale + new Vector2(origin.x, origin.y));
tx = atlasEntry.x + padAmount;
ty = atlasEntry.y + padAmount;
tw = atlasEntry.w - padAmount * 2;
th = atlasEntry.h - padAmount * 2;
//v0 = new Vector2(tx / fwidth + uvOffsetX, 1.0f - (sd_y + th) / fheight + uvOffsetY);
//v1 = new Vector2((tx + tw) / fwidth - uvOffsetX, 1.0f - sd_y / fheight - uvOffsetY);
Vector2 uv = new Vector2();
if (atlasEntry.flipped)
{
uv.x = (tx - _lut.ry + texHeight - v.y) / fwidth + uvOffsetX;
uv.y = (ty - _lut.rx + v.x) / fheight + uvOffsetY;
}
else
{
uv.x = (tx - _lut.rx + v.x) / fwidth + uvOffsetX;
uv.y = (ty - _lut.ry + texHeight - v.y) / fheight + uvOffsetY ;
}
uvs.Add(uv);
}
tk2dEditor.Triangulator triangulator = new tk2dEditor.Triangulator(island.points);
int[] localIndices = triangulator.Triangulate();
//for (int x = localIndices.Length - 1; x >= 0; --x)
for (int x = 0; x < localIndices.Length; x += 3)
{
indices.Add(baseIndex + localIndices[x + 2]);
indices.Add(baseIndex + localIndices[x + 1]);
indices.Add(baseIndex + localIndices[x + 0]);
}
}
coll.spriteDefinitions[i].indices = indices.ToArray();
}
else
{
coll.spriteDefinitions[i].flipped = atlasEntry.flipped;
float x0 = _lut.rx / texWidth;
float y0 = _lut.ry / texHeight;
float x1 = (_lut.rx + _lut.rw) / texWidth;
float y1 = (_lut.ry + _lut.rh) / texHeight;
Vector3 dpos0 = new Vector3(Mathf.Lerp(pos0.x, pos1.x, x0), 0.0f, Mathf.Lerp(pos0.z, pos1.z, y0));
Vector3 dpos1 = new Vector3(Mathf.Lerp(pos0.x, pos1.x, x1), 0.0f, Mathf.Lerp(pos0.z, pos1.z, y1));
positions.Add(new Vector3(dpos0.x, dpos0.z, 0));
positions.Add(new Vector3(dpos1.x, dpos0.z, 0));
positions.Add(new Vector3(dpos0.x, dpos1.z, 0));
positions.Add(new Vector3(dpos1.x, dpos1.z, 0));
if (atlasEntry.flipped)
{
uvs.Add(new Vector2(v0.x,v0.y));
uvs.Add(new Vector2(v0.x,v1.y));
uvs.Add(new Vector2(v1.x,v0.y));
uvs.Add(new Vector2(v1.x,v1.y));
}
else
{
uvs.Add(new Vector2(v0.x,v0.y));
uvs.Add(new Vector2(v1.x,v0.y));
uvs.Add(new Vector2(v0.x,v1.y));
uvs.Add(new Vector2(v1.x,v1.y));
}
}
// build sprite definition
if (!thisTexParam.customSpriteGeometry)
{
coll.spriteDefinitions[i].indices = new int[ 6 * (positions.Count / 4) ];
for (int j = 0; j < positions.Count / 4; ++j)
{
coll.spriteDefinitions[i].indices[j * 6 + 0] = j * 4 + 0;
coll.spriteDefinitions[i].indices[j * 6 + 1] = j * 4 + 3;
coll.spriteDefinitions[i].indices[j * 6 + 2] = j * 4 + 1;
coll.spriteDefinitions[i].indices[j * 6 + 3] = j * 4 + 2;
coll.spriteDefinitions[i].indices[j * 6 + 4] = j * 4 + 3;
coll.spriteDefinitions[i].indices[j * 6 + 5] = j * 4 + 0;
}
coll.spriteDefinitions[i].complexGeometry = false;
}
else
{
coll.spriteDefinitions[i].complexGeometry = true;
}
// This doesn't seem to be necessary in UNITY_3_5_3
#if (UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5_0 || UNITY_3_5_1 || UNITY_3_5_2)
if (positions.Count > 0)
{
// http://forum.unity3d.com/threads/98781-Compute-mesh-inertia-tensor-failed-for-one-of-the-actor-Behaves-differently-in-3.4
Vector3 p = positions[positions.Count - 1];
p.z -= 0.001f;
positions[positions.Count - 1] = p;
}
#endif
coll.spriteDefinitions[i].positions = new Vector3[positions.Count];
coll.spriteDefinitions[i].uvs = new Vector2[uvs.Count];
for (int j = 0; j < positions.Count; ++j)
{
coll.spriteDefinitions[i].positions[j] = positions[j];
coll.spriteDefinitions[i].uvs[j] = uvs[j];
}
// empty out to a sensible default, which corresponds to what Unity does by default
coll.spriteDefinitions[i].normals = new Vector3[0];
coll.spriteDefinitions[i].tangents = new Vector4[0];
// fill out tangents and normals
if (gen.normalGenerationMode != tk2dSpriteCollection.NormalGenerationMode.None)
{
Mesh tmpMesh = new Mesh();
tmpMesh.vertices = coll.spriteDefinitions[i].positions;
tmpMesh.uv = coll.spriteDefinitions[i].uvs;
tmpMesh.triangles = coll.spriteDefinitions[i].indices;
tmpMesh.RecalculateNormals();
coll.spriteDefinitions[i].normals = tmpMesh.normals;
if (gen.normalGenerationMode != tk2dSpriteCollection.NormalGenerationMode.NormalsOnly)
{
coll.spriteDefinitions[i].tangents = tmpMesh.tangents;
}
}
}
// fixup in case something went wrong
if (coll.allowMultipleAtlases)
{
coll.spriteDefinitions[i].material = gen.atlasMaterials[atlasIndex];
}
else
{
coll.spriteDefinitions[i].material = gen.altMaterials[thisTexParam.materialId];
coll.spriteDefinitions[i].materialId = thisTexParam.materialId;
if (coll.spriteDefinitions[i].material == null) // fall back gracefully in case something went wrong
{
coll.spriteDefinitions[i].material = gen.atlasMaterials[atlasIndex];
coll.spriteDefinitions[i].materialId = 0;
}
}
Vector3 boundsMin = new Vector3(1.0e32f, 1.0e32f, 1.0e32f);
Vector3 boundsMax = new Vector3(-1.0e32f, -1.0e32f, -1.0e32f);
foreach (Vector3 v in coll.spriteDefinitions[i].positions)
{
boundsMin = Vector3.Min(boundsMin, v);
boundsMax = Vector3.Max(boundsMax, v);
}
coll.spriteDefinitions[i].boundsData = new Vector3[2];
coll.spriteDefinitions[i].boundsData[0] = (boundsMax + boundsMin) / 2.0f;
coll.spriteDefinitions[i].boundsData[1] = (boundsMax - boundsMin);
// this is the dimension of exactly one pixel, scaled to match sprite dimensions and scale
coll.spriteDefinitions[i].texelSize = new Vector3(scale * thisTexParam.scale.x, scale * thisTexParam.scale.y, 0.0f);
coll.spriteDefinitions[i].untrimmedBoundsData = new Vector3[2];
if (mesh)
{
// custom meshes aren't trimmed, the untrimmed bounds are exactly the same as the regular ones
coll.spriteDefinitions[i].untrimmedBoundsData[0] = coll.spriteDefinitions[i].boundsData[0];
coll.spriteDefinitions[i].untrimmedBoundsData[1] = coll.spriteDefinitions[i].boundsData[1];
}
else
{
boundsMin = Vector3.Min(untrimmedPos0, untrimmedPos1);
boundsMax = Vector3.Max(untrimmedPos0, untrimmedPos1);
coll.spriteDefinitions[i].untrimmedBoundsData[0] = (boundsMax + boundsMin) / 2.0f;
coll.spriteDefinitions[i].untrimmedBoundsData[1] = (boundsMax - boundsMin);
}
coll.spriteDefinitions[i].name = gen.textureParams[i].name;
// Generate collider data here
UpdateColliderData(gen, scale, coll, i, colliderOrigin);
}
}