//描画頂点データに対してForeachして、funcitionをコールバックとして呼ぶ public void ForeachVertexList(Rect position, Rect uvRect, bool skipTransParentCell, DicingTextures textures, Action <Rect, Rect> function) { //縮尺 Vector2 scale = new Vector2(position.width / this.Width, position.height / this.Height); ForeachVertexList(uvRect, skipTransParentCell, textures, (r1, r2) => { r1.xMin *= scale.x; r1.xMax *= scale.x; r1.x += position.x; r1.yMin *= scale.y; r1.yMax *= scale.y; r1.y += position.y; function(r1, r2); }); }
public void ForeachVertexList(Rect uvRect, bool skipTransParentCell, DicingTextures textures, Action <Rect, Rect> function) {
//描画頂点データに対してForeachして、funcitionをコールバックとして呼ぶ //UVが(0,0,1,1)の範囲であるのが必須 //指定のUV座標に対してのもの void ForeachVertexListSub(Rect uvRect, bool skipTransParentCell, DicingTextures textures, Action <Rect, Rect> function) { Texture2D texture = textures.GetTexture(this.AtlasName); float textureW = texture.width; float textureH = texture.height; //頂点データを取得 List <DicingTextureData.QuadVerts> verts = GetVerts(textures); //UV指定を考慮して、描画ピクセルの矩形を取得 Rect pixcelRect = new Rect(uvRect.x * this.Width, uvRect.y * this.Height, uvRect.width * this.Width, uvRect.height * this.Height); for (int i = 0; i < verts.Count; ++i) { var vert = verts[i]; //透明ならスキップ if (skipTransParentCell && vert.isAllTransparent) { continue; } //上下左右の座標 float left = vert.v.x; float right = vert.v.z; float top = vert.v.y; float bottom = vert.v.w; Rect uv = vert.uvRect; if (left > pixcelRect.xMax || top > pixcelRect.yMax || right < pixcelRect.x || bottom < pixcelRect.y) { //全体が切り取り矩形の外 continue; } else { //一部が切り取り矩形の外なら、頂点とUV値を調整して矩形内に収める if (left < pixcelRect.x) { uv.xMin += (pixcelRect.x - left) / textureW; left = pixcelRect.x; } if (right > pixcelRect.xMax) { uv.xMax += (pixcelRect.xMax - right) / textureW; right = pixcelRect.xMax; } if (top < pixcelRect.y) { uv.yMin += (pixcelRect.y - top) / textureH; top = pixcelRect.y; } if (bottom > pixcelRect.yMax) { uv.yMax += (pixcelRect.yMax - bottom) / textureH; bottom = pixcelRect.yMax; } } function(new Rect(left, top, right - left, bottom - top), uv); } }
//描画頂点データに対してForeachして、funcitionをコールバックとして呼ぶ //UV座標が1以上で、リピートする場合や、UVスクロールする場合を想定して //テクスチャ1枚ぶんで描ける矩形ごとに分割して描画 //例えば、UV値が(-0.25,0,1,1)で横にUVスクロールしているなら、2分割になり、 //例えば、UV値が(0,0,2,2)なら、4分割する public void ForeachVertexList(Rect uvRect, bool skipTransParentCell, DicingTextures textures, Action <Rect, Rect> function) { if (uvRect.width == 0 || uvRect.height == 0) { return; } if (uvRect.xMin < 0) { uvRect.x += Mathf.CeilToInt(-uvRect.xMin); } if (uvRect.yMin < 0) { uvRect.y += Mathf.CeilToInt(-uvRect.yMin); } bool flipX = false; if (uvRect.width < 0) { uvRect.width *= -1; flipX = true; } bool flipY = false; if (uvRect.height < 0) { uvRect.height *= -1; flipY = true; } float scaleX = 1.0f / uvRect.width; float fipOffsetX = 0; if (flipX) { scaleX *= -1; fipOffsetX = this.Width; } float scaleY = 1.0f / uvRect.height; float fipOffsetY = 0; if (flipY) { scaleY *= -1; fipOffsetY = this.Height; } float vBegin = uvRect.yMin % 1; float vEnd = uvRect.yMax % 1; if (vEnd == 0) { vEnd = 1; } float offsetY = 0; bool isFirstV = true; bool isEndV = false; Rect rect = new Rect(); do { rect.yMin = isFirstV ? vBegin : 0; isEndV = (offsetY + 1 - rect.yMin) >= uvRect.height; rect.yMax = isEndV ? vEnd : 1; float uBegin = uvRect.xMin % 1; float uEnd = uvRect.xMax % 1; if (uEnd == 0) { uEnd = 1; } float offsetX = 0; bool isFirstU = true; bool isEndU = false; do { rect.xMin = isFirstU ? uBegin : 0; isEndU = (offsetX + 1 - rect.xMin) >= uvRect.width; rect.xMax = isEndU ? uEnd : 1; ForeachVertexListSub(rect, skipTransParentCell, textures, (r1, r2) => { r1.xMin *= scaleX; r1.xMax *= scaleX; r1.x += (offsetX - rect.xMin) * scaleX * this.Width + fipOffsetX; r1.yMin *= scaleY; r1.yMax *= scaleY; r1.y += (offsetY - rect.yMin) * scaleY * this.Height + fipOffsetY; function(r1, r2); }); offsetX += rect.width; isFirstU = false; } while (!isEndU); offsetY += rect.height; isFirstV = false; } while (!isEndV); }
//アトラス画像とデータを出力して、インポートするターゲットをリビルド static void RebuildTarget(AssetBuildTimeStamp buildTimeStamp, DicingTextures target, List <Atlas> atlasList) { List <string> outputTexturePathList = new List <string>(); List <DicingTextureData> textureDataList = new List <DicingTextureData>(); //アトラス画像をファイルとして出力 string dir = AssetDatabase.GetAssetPath(target.OutputDir); int count = 0; foreach (var atlas in atlasList) { ++count; Texture2D texture = atlas.MakeAtlasTexture(); string path = FilePathUtil.Combine(dir, atlas.Name + ".png"); outputTexturePathList.Add(path); atlas.Write(path, texture); Object.DestroyImmediate(texture); DisplayProgressBar(target, 0.7f + 0.2f * count / atlasList.Count, "Make AtlasTexture"); //元テクスチャを再現するための、頂点データやアトラス画像に対するUV値を作成 textureDataList.AddRange(atlas.MakeImportData()); DisplayProgressBar(target, 0.7f + 0.29f * count / atlasList.Count, "Make AtlasTexture"); } textureDataList.Sort((a, b) => string.Compare(a.Name, b.Name)); //新しいテクスチャをロード List <Texture2D> newTextureList = new List <Texture2D>(); foreach (var path in outputTexturePathList) { Texture2D texture = AssetDatabase.LoadAssetAtPath <Texture2D>(path); if (texture == null) { AssetDatabase.ImportAsset(path); texture = AssetDatabase.LoadAssetAtPath <Texture2D>(path); } newTextureList.Add(texture); } //登録済みのテクスチャのうち、使わなくなったものを削除 List <Texture2D> removeTextureList = new List <Texture2D>(); foreach (var texture in target.AtlasTextures) { if (!newTextureList.Contains(texture)) { removeTextureList.Add(texture); } } //テクスチャを設定 target.Build(buildTimeStamp, newTextureList, textureDataList); //インポート設定を上書き foreach (var path in outputTexturePathList) { AssetDatabase.ImportAsset(path); OverrideAtlasTextureImportSetting(path, target); } //使わなくなったものを削除 foreach (var texture in removeTextureList) { Debug.Log("Remove " + texture.name); AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(texture)); } }
//進行状況のプログレスバーを表示 static void DisplayProgressBar(DicingTextures target, float progress, string info = "") { EditorUtility.DisplayProgressBar(target.name + " Paking Dicing Textures", info, progress); }