static float GetYAnchorForHeight(float textHeight, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int heightAnchor = (int)data.anchor / 3; float lineHeight = (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; switch (heightAnchor) { case 0: return(-lineHeight); case 1: { float y = -textHeight / 2.0f - lineHeight; if (_fontInst.version >= 2) { float ty = _fontInst.texelSize.y * data.scale.y; return(Mathf.Floor(y / ty) * ty); } else { return(y); } } case 2: return(-textHeight - lineHeight); } return(-lineHeight); }
public static GeomData Data(tk2dTextMeshData textMeshData, tk2dFontData fontData, string formattedText) { tmpData.textMeshData = textMeshData; tmpData.fontInst = fontData; tmpData.formattedText = formattedText; return tmpData; }
// Use this to get a correctly set up textgeomdata object // This uses a static global tmpData object and is not thread safe // Fortunately for us, neither is the rest of Unity. public static GeomData Data(tk2dTextMeshData textMeshData, tk2dFontData fontData, string formattedText) { tmpData.textMeshData = textMeshData; tmpData.fontInst = fontData; tmpData.formattedText = formattedText; return(tmpData); }
public static void GetTextMeshGeomDesc(out int numVertices, out int numIndices, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; numVertices = data.maxChars * 4; numIndices = data.maxChars * 6; }
static float GetXAnchorForWidth(float lineWidth, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; int widthAnchor = (int)data.anchor % 3; switch (widthAnchor) { case 0: return(0.0f); // left case 1: // center { float x = -lineWidth / 2.0f; if (_fontInst.version >= 2) { float tx = _fontInst.texelSize.x * data.scale.x; return(Mathf.Floor(x / tx) * tx); } return(x); } case 2: return(-lineWidth); // right } return(0.0f); }
// this function is static to ensure that no fields are changed during this call private static tk2dColoredText FormatTextImpl(string txt, tk2dTextMeshData meshData) { string localizedString = LocalisationManager.LocalizedStringOrSource(txt); tk2dColoredText result = new tk2dColoredText(localizedString, meshData.colorS); ConvertString(result, meshData); return(result); }
public static void SetTextMeshIndices(int[] indices, int offset, int vStart, GeomData geomData, int target) { tk2dTextMeshData data = geomData.textMeshData; for (int i = 0; i < data.maxChars; ++i) { indices[offset + i * 6 + 0] = vStart + i * 4 + 0; indices[offset + i * 6 + 1] = vStart + i * 4 + 1; indices[offset + i * 6 + 2] = vStart + i * 4 + 3; indices[offset + i * 6 + 3] = vStart + i * 4 + 2; indices[offset + i * 6 + 4] = vStart + i * 4 + 0; indices[offset + i * 6 + 5] = vStart + i * 4 + 3; } }
/// <summary> /// Calculates the mesh dimensions for the given string /// and returns a width and height. /// </summary> public static Vector2 GetMeshDimensionsForString(this tk2dTextMeshData geomData, tk2dColoredText inputText, int startIdx, int count) { tk2dTextMeshData data = geomData; tk2dFontData _fontInst = data.FontInst; float maxWidth = 0.0f; float cursorX = 0.0f; float cursorY = 0.0f; for (int i = startIdx; (i < inputText.Length) && (i < (startIdx + count)); ++i) { int idx = inputText[i]; if (idx == '\n') { maxWidth = Mathf.Max(cursorX, maxWidth); cursorX = 0.0f; cursorY -= data.ActualLineSpaceHeight; } else { // Get the character from dictionary / array tk2dFontChar chr = _fontInst.GetCharForIndex(idx, 0); cursorX += (chr.advance + data.Spacing) * data.TotalScale.x; if (data.kerning && i < inputText.Length - 1) { foreach (var k in _fontInst.kerning) { if (k.c0 == inputText[i] && k.c1 == inputText[i + 1]) { cursorX += k.amount * data.TotalScale.x; break; } } } } } maxWidth = Mathf.Max(cursorX, maxWidth); cursorY -= data.ActualLineHeight; return(new Vector2(maxWidth, cursorY)); }
public static float GetYAnchorForHeight(this tk2dTextMeshData geomData, float textHeight) { tk2dTextMeshData data = geomData; tk2dFontData _fontInst = data.FontInst; float lineHeight = data.ActualLineHeight; switch (data.anchor) { case TextAnchor.UpperCenter: case TextAnchor.UpperLeft: case TextAnchor.UpperRight: return(-lineHeight); case TextAnchor.MiddleCenter: case TextAnchor.MiddleLeft: case TextAnchor.MiddleRight: { float y = -textHeight / 2.0f - lineHeight; if (_fontInst.version >= 2) { float ty = _fontInst.texelSize.y * data.TotalScale.y; return(Mathf.Floor(y / ty) * ty); } else { return(y); } } case TextAnchor.LowerCenter: case TextAnchor.LowerLeft: case TextAnchor.LowerRight: return(-textHeight - lineHeight); } return(-lineHeight); }
public static int SetTextMeshGeom(Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData fontInst = geomData.fontInst; string formattedText = geomData.formattedText; meshTopColor = new Color32(255, 255, 255, 255); meshBottomColor = new Color32(255, 255, 255, 255); meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curGradientCount = fontInst.gradientCount; Vector2 dims = GetMeshDimensionsForString(geomData.formattedText, geomData); float offsetY = GetYAnchorForHeight(dims.y, geomData); float cursorX = 0.0f; float cursorY = 0.0f; int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < data.maxChars; ++i) { int idx = formattedText[i]; tk2dFontChar chr; bool inlineHatChar = (idx == '^'); if (fontInst.useDictionary) { if (!fontInst.charDict.ContainsKey(idx)) { idx = 0; } chr = fontInst.charDict[idx]; } else { if (idx >= fontInst.chars.Length) { idx = 0; // should be space } chr = fontInst.chars[idx]; } if (inlineHatChar) { idx = '^'; } if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= (fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^') { if (i + 1 < formattedText.Length && formattedText[i + 1] == '^') { ++i; } else { i += HandleStyleCommand(formattedText.Substring(i + 1)); continue; } } } pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p0.y * data.scale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.scale.x, offsetY + cursorY + chr.p1.y * data.scale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = meshTopColor; color[offset + target * 4 + 1] = meshTopColor; color[offset + target * 4 + 2] = meshBottomColor; color[offset + target * 4 + 3] = meshBottomColor; } cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i + 1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = GetXAnchorForWidth(lineWidth, geomData); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < data.maxChars; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } if (!fontInst.isPacked) { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = meshTopColor; color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = meshBottomColor; } else { color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } } return(target); }
/// <summary> /// Calculates the mesh dimensions for the given string /// and returns a width and height. /// </summary> public static Vector2 GetMeshDimensionsForString(string str, GeomData geomData) { tk2dTextMeshData data = geomData.textMeshData; tk2dFontData _fontInst = geomData.fontInst; float maxWidth = 0.0f; float cursorX = 0.0f; float cursorY = 0.0f; bool ignoreNextCharacter = false; int target = 0; for (int i = 0; i < str.Length && target < data.maxChars; ++i) { if (ignoreNextCharacter) { ignoreNextCharacter = false; continue; } int idx = str[i]; if (idx == '\n') { maxWidth = Mathf.Max(cursorX, maxWidth); cursorX = 0.0f; cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; continue; } else if (data.inlineStyling) { if (idx == '^' && i + 1 < str.Length) { if (str[i + 1] == '^') { ignoreNextCharacter = true; } else { int cmdLength = 0; switch (str[i + 1]) { case 'c': cmdLength = 5; break; case 'C': cmdLength = 9; break; case 'g': cmdLength = 9; break; case 'G': cmdLength = 17; break; } i += cmdLength; continue; } } } bool inlineHatChar = (idx == '^'); // Get the character from dictionary / array tk2dFontChar chr; if (_fontInst.useDictionary) { if (!_fontInst.charDict.ContainsKey(idx)) { idx = 0; } chr = _fontInst.charDict[idx]; } else { if (idx >= _fontInst.chars.Length) { idx = 0; // should be space } chr = _fontInst.chars[idx]; } if (inlineHatChar) { idx = '^'; } cursorX += (chr.advance + data.spacing) * data.scale.x; if (data.kerning && i < str.Length - 1) { foreach (var k in _fontInst.kerning) { if (k.c0 == str[i] && k.c1 == str[i + 1]) { cursorX += k.amount * data.scale.x; break; } } } ++target; } maxWidth = Mathf.Max(cursorX, maxWidth); cursorY -= (_fontInst.lineHeight + data.lineSpacing) * data.scale.y; return(new Vector2(maxWidth, cursorY)); }
void DrawEditorGUI() { if (GUILayout.Button("Commit")) { // Select all children, EXCLUDING self Transform[] allTransforms = batcher.transform.GetComponentsInChildren <Transform>(); allTransforms = (from t in allTransforms where t != batcher.transform select t).ToArray(); // sort sprites, smaller to larger z if (batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.SortToCamera)) { tk2dCamera tk2dCam = tk2dCamera.CameraForLayer(batcher.gameObject.layer); Camera cam = tk2dCam ? tk2dCam.GetComponent <Camera>() : Camera.main; allTransforms = (from t in allTransforms orderby cam.WorldToScreenPoint((t.GetComponent <Renderer>() != null) ? t.GetComponent <Renderer>().bounds.center : t.position).z descending select t).ToArray(); } else { allTransforms = (from t in allTransforms orderby t.GetComponent <Renderer>().bounds.center.z descending select t).ToArray(); } // and within the z sort by material if (allTransforms.Length == 0) { EditorUtility.DisplayDialog("StaticSpriteBatcher", "Error: No child objects found", "Ok"); return; } Dictionary <Transform, int> batchedSpriteLookup = new Dictionary <Transform, int>(); batchedSpriteLookup[batcher.transform] = -1; Matrix4x4 batcherWorldToLocal = batcher.transform.worldToLocalMatrix; batcher.spriteCollection = null; batcher.batchedSprites = new tk2dBatchedSprite[allTransforms.Length]; List <tk2dTextMeshData> allTextMeshData = new List <tk2dTextMeshData>(); int currBatchedSprite = 0; foreach (var t in allTransforms) { tk2dBaseSprite baseSprite = t.GetComponent <tk2dBaseSprite>(); tk2dTextMesh textmesh = t.GetComponent <tk2dTextMesh>(); tk2dBatchedSprite bs = new tk2dBatchedSprite(); bs.name = t.gameObject.name; bs.position = t.localPosition; bs.rotation = t.localRotation; bs.relativeMatrix = batcherWorldToLocal * t.localToWorldMatrix; if (baseSprite) { bs.baseScale = Vector3.one; bs.localScale = new Vector3(t.localScale.x * baseSprite.scale.x, t.localScale.y * baseSprite.scale.y, t.localScale.z * baseSprite.scale.z); FillBatchedSprite(bs, t.gameObject); // temp redundant - just incase batcher expects to point to a valid one, somewhere we've missed batcher.spriteCollection = baseSprite.Collection; } else if (textmesh) { bs.spriteCollection = null; bs.type = tk2dBatchedSprite.Type.TextMesh; bs.color = textmesh.color; bs.baseScale = textmesh.scale; bs.renderLayer = textmesh.SortingOrder; bs.localScale = new Vector3(t.localScale.x * textmesh.scale.x, t.localScale.y * textmesh.scale.y, t.localScale.z * textmesh.scale.z); bs.FormattedText = textmesh.FormattedText; tk2dTextMeshData tmd = new tk2dTextMeshData(); tmd.font = textmesh.font; tmd.text = textmesh.text; tmd.color = textmesh.color; tmd.color2 = textmesh.color2; tmd.useGradient = textmesh.useGradient; tmd.textureGradient = textmesh.textureGradient; tmd.anchor = textmesh.anchor; tmd.kerning = textmesh.kerning; tmd.maxChars = textmesh.maxChars; tmd.inlineStyling = textmesh.inlineStyling; tmd.formatting = textmesh.formatting; tmd.wordWrapWidth = textmesh.wordWrapWidth; tmd.spacing = textmesh.Spacing; tmd.lineSpacing = textmesh.LineSpacing; bs.xRefId = allTextMeshData.Count; allTextMeshData.Add(tmd); } else { // Empty GameObject bs.spriteId = -1; bs.baseScale = Vector3.one; bs.localScale = t.localScale; bs.type = tk2dBatchedSprite.Type.EmptyGameObject; } batchedSpriteLookup[t] = currBatchedSprite; batcher.batchedSprites[currBatchedSprite++] = bs; } batcher.allTextMeshData = allTextMeshData.ToArray(); int idx = 0; foreach (var t in allTransforms) { var bs = batcher.batchedSprites[idx]; bs.parentId = batchedSpriteLookup[t.parent]; t.parent = batcher.transform; // unparent ++idx; } Transform[] directChildren = (from t in allTransforms where t.parent == batcher.transform select t).ToArray(); foreach (var t in directChildren) { GameObject.DestroyImmediate(t.gameObject); } Vector3 inverseScale = new Vector3(1.0f / batcher.scale.x, 1.0f / batcher.scale.y, 1.0f / batcher.scale.z); batcher.transform.localScale = Vector3.Scale(batcher.transform.localScale, inverseScale); batcher.Build(); EditorUtility.SetDirty(target); } }
void DrawEditorGUI() { if (GUILayout.Button("Commit")) { // Select all children, EXCLUDING self Transform[] allTransforms = batcher.transform.GetComponentsInChildren <Transform>(); List <Transform> tempAllTransforms = new List <Transform>(); foreach (Transform t in allTransforms) { if (t != batcher.transform) { tempAllTransforms.Add(t); } } allTransforms = tempAllTransforms.ToArray(); #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) Renderer[] allRenderers = batcher.transform.GetComponentsInChildren <Renderer>(); List <Renderer> tempAllRenderers = new List <Renderer>(); foreach (Renderer r in allRenderers) { if (r != batcher.GetComponent <Renderer>()) { tempAllRenderers.Add(r); } } allRenderers = tempAllRenderers.ToArray(); if (allRenderers.Length > 0) { string sortingLayerName = allRenderers[0].sortingLayerName; int sortingOrder = allRenderers[0].sortingOrder; foreach (Renderer r in allRenderers) { if (sortingLayerName != r.sortingLayerName || sortingOrder != r.sortingOrder) { EditorUtility.DisplayDialog("StaticSpriteBatcher", "Error: Child objects use different sorting layer names and/or sorting orders.\n\nOnly one sorting layer and order is permitted in a static sprite batcher.", "Ok"); return; } } } #endif List <KeyValuePair <Transform, float> > tempList = new List <KeyValuePair <Transform, float> >(); // sort sprites, smaller to larger z if (batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.SortToCamera)) { tk2dCamera tk2dCam = tk2dCamera.CameraForLayer(batcher.gameObject.layer); Camera cam = tk2dCam ? tk2dCam.GetComponent <Camera>() : Camera.main; foreach (Transform t in allTransforms) { tempList.Add(new KeyValuePair <Transform, float>(t, cam.WorldToScreenPoint((t.GetComponent <Renderer>() != null) ? t.GetComponent <Renderer>().bounds.center : t.position).z)); } } else { foreach (Transform t in allTransforms) { tempList.Add(new KeyValuePair <Transform, float>(t, ((t.GetComponent <Renderer>() != null) ? t.GetComponent <Renderer>().bounds.center : t.position).z)); } } tempList.Sort((a, b) => a.Value.CompareTo(b.Value)); List <Transform> tr = new List <Transform>(); foreach (KeyValuePair <Transform, float> pair in tempList) { tr.Add(pair.Key); } allTransforms = tr.ToArray(); // and within the z sort by material if (allTransforms.Length == 0) { EditorUtility.DisplayDialog("StaticSpriteBatcher", "Error: No child objects found", "Ok"); return; } #if !(UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2) MeshCollider[] childMeshColliders = GetComponentsInChildrenExcludeSelf <MeshCollider>(batcher.transform); BoxCollider[] childBoxColliders = GetComponentsInChildrenExcludeSelf <BoxCollider>(batcher.transform); BoxCollider2D[] childBoxCollider2Ds = GetComponentsInChildrenExcludeSelf <BoxCollider2D>(batcher.transform); EdgeCollider2D[] childEdgeCollider2Ds = GetComponentsInChildrenExcludeSelf <EdgeCollider2D>(batcher.transform); PolygonCollider2D[] childPolygonCollider2Ds = GetComponentsInChildrenExcludeSelf <PolygonCollider2D>(batcher.transform); if ((childMeshColliders.Length > 0 || childBoxColliders.Length > 0) && (childBoxCollider2Ds.Length > 0 || childEdgeCollider2Ds.Length > 0 || childPolygonCollider2Ds.Length > 0)) { EditorUtility.DisplayDialog("StaticSpriteBatcher", "Error: Can't mix 2D and 3D colliders", "Ok"); return; } #endif Dictionary <Transform, int> batchedSpriteLookup = new Dictionary <Transform, int>(); batchedSpriteLookup[batcher.transform] = -1; Matrix4x4 batcherWorldToLocal = batcher.transform.worldToLocalMatrix; batcher.spriteCollection = null; batcher.batchedSprites = new tk2dBatchedSprite[allTransforms.Length]; List <tk2dTextMeshData> allTextMeshData = new List <tk2dTextMeshData>(); int currBatchedSprite = 0; foreach (var t in allTransforms) { tk2dBaseSprite baseSprite = t.GetComponent <tk2dBaseSprite>(); tk2dTextMesh textmesh = t.GetComponent <tk2dTextMesh>(); tk2dBatchedSprite bs = new tk2dBatchedSprite(); bs.name = t.gameObject.name; bs.position = t.localPosition; bs.rotation = t.localRotation; bs.relativeMatrix = batcherWorldToLocal * t.localToWorldMatrix; if (baseSprite) { bs.baseScale = Vector3.one; bs.localScale = new Vector3(t.localScale.x * baseSprite.scale.x, t.localScale.y * baseSprite.scale.y, t.localScale.z * baseSprite.scale.z); FillBatchedSprite(bs, t.gameObject); // temp redundant - just incase batcher expects to point to a valid one, somewhere we've missed batcher.spriteCollection = baseSprite.Collection; } else if (textmesh) { bs.spriteCollection = null; bs.type = tk2dBatchedSprite.Type.TextMesh; bs.color = textmesh.color; bs.baseScale = textmesh.scale; bs.renderLayer = textmesh.SortingOrder; bs.localScale = new Vector3(t.localScale.x * textmesh.scale.x, t.localScale.y * textmesh.scale.y, t.localScale.z * textmesh.scale.z); bs.FormattedText = textmesh.FormattedText; tk2dTextMeshData tmd = new tk2dTextMeshData(); tmd.Font = textmesh.font; tmd.Text = textmesh.text; tmd.color = textmesh.color; tmd.color2 = textmesh.color2; tmd.useGradient = textmesh.useGradient; tmd.textureGradient = textmesh.textureGradient; tmd.anchor = textmesh.anchor; tmd.kerning = textmesh.kerning; tmd.Spacing = textmesh.Spacing; tmd.LineSpacing = textmesh.LineSpacing; bs.xRefId = allTextMeshData.Count; allTextMeshData.Add(tmd); } else { // Empty GameObject bs.spriteId = -1; bs.baseScale = Vector3.one; bs.localScale = t.localScale; bs.type = tk2dBatchedSprite.Type.EmptyGameObject; } batchedSpriteLookup[t] = currBatchedSprite; batcher.batchedSprites[currBatchedSprite++] = bs; } batcher.allTextMeshData = allTextMeshData.ToArray(); int idx = 0; foreach (var t in allTransforms) { var bs = batcher.batchedSprites[idx]; bs.parentId = batchedSpriteLookup[t.parent]; t.parent = batcher.transform; // unparent ++idx; } //Transform[] directChildren = (from t in allTransforms where t.parent == batcher.transform select t).ToArray(); List <Transform> tempdirectChildren = new List <Transform>(); foreach (Transform t in allTransforms) { if (t.parent == batcher.transform) { tempdirectChildren.Add(t); } } Transform[] directChildren = tempdirectChildren.ToArray(); foreach (var t in directChildren) { GameObject.DestroyImmediate(t.gameObject); } Vector3 inverseScale = new Vector3(1.0f / batcher.scale.x, 1.0f / batcher.scale.y, 1.0f / batcher.scale.z); batcher.transform.localScale = Vector3.Scale(batcher.transform.localScale, inverseScale); batcher.Build(); EditorUtility.SetDirty(target); } }
// this function is static to ensure that no fields are changed during this call private static void ConvertString(tk2dColoredText formattedText, tk2dTextMeshData meshData) { const char NonBreakableSpace = (char)17; if (meshData.UseShortNumbers) { formattedText.ApplyShortNumber(); } if (!meshData.DisableNumberGrouping) { int currentNumberCount = 0; for (int i = formattedText.Length - 1; i >= 0; i--) { var curChar = formattedText[i]; if (curChar >= '0' && curChar <= '9') { currentNumberCount += 1; } else { currentNumberCount = 0; } if (currentNumberCount == 4) { // add device control char -> if you add normal space -> // code lower will make new lines formattedText.Insert(i + 1, new string(NonBreakableSpace, 1)); currentNumberCount = 1; } } } // reset line break scale before calculate the dimentions meshData.lineBreakScale = Vector3.one; Vector2 dims = meshData.GetMeshDimensionsForString(formattedText); if (dims.x > meshData.maxTextLength) { if (meshData.maxTextLength > 0.0f) { switch (meshData.BreakMode) { case LineBreakMode.ScaleDown: { float curScale = meshData.maxTextLength / dims.x; meshData.lineBreakScale.Set(curScale, curScale, curScale); } break; case LineBreakMode.ThreeDots: { formattedText.Append("..."); for (int i = formattedText.Length - 4; i >= 0 && meshData.GetMeshDimensionsForString(formattedText).x > meshData.MaxTextLength; i--) { formattedText.Remove(i); } } break; case LineBreakMode.LineBreak: { int curStartIndex = 0; int curFinishIndex = 0; while (curFinishIndex < (formattedText.Length - 1)) { int curNextSpace = formattedText.IndexOf(' ', curFinishIndex + 1); int curLastIndex = (curNextSpace != -1) ? curNextSpace : (formattedText.Length - 1); if (meshData.GetMeshDimensionsForString(formattedText, curStartIndex, (curLastIndex - curStartIndex + 1)).x > meshData.maxTextLength) { int actualFinishIndex = (curFinishIndex > curStartIndex) ? curFinishIndex : curLastIndex; formattedText[actualFinishIndex] = '\n'; curFinishIndex = curStartIndex = actualFinishIndex + 1; } else { curFinishIndex = curLastIndex; } } } break; } } } float dimsY = Mathf.Abs(meshData.GetMeshDimensionsForString(formattedText).y); if (dimsY > meshData.maxTextHeight) { if (meshData.maxTextHeight > 0.0f) { float curScale = meshData.lineBreakScale.x; float newScale = meshData.maxTextHeight / dimsY; curScale = Math.Min(curScale, newScale); meshData.lineBreakScale.Set(curScale, curScale, curScale); } } if (meshData.ShouldScaleInCellSize) { float newScale = Mathf.Min(meshData.maxTextLength / dims.x, meshData.MaxTextHeight / Mathf.Abs(dims.y)); meshData.lineBreakScale.Set(newScale, newScale, newScale); } formattedText.Replace(NonBreakableSpace, ' '); }
public static void SetTextMeshGeom(this GeomData geomData, Vector3[] pos, Vector2[] uv, Vector2[] uv2, Color32[] color, int offset) { tk2dTextMeshData data = geomData.TextMeshData; tk2dFontData fontInst = data.FontInst; tk2dColoredText formattedText = data.FormattedText; InlineStyler curStyler = new InlineStyler(); curStyler.meshTopColor = new Color32(255, 255, 255, 255); curStyler.meshBottomColor = new Color32(255, 255, 255, 255); curStyler.meshGradientTexU = (float)data.textureGradient / (float)((fontInst.gradientCount > 0) ? fontInst.gradientCount : 1); curStyler.curGradientCount = fontInst.gradientCount; Vector2 dims = data.GetMeshDimensionsForString(formattedText); float offsetY = data.GetYAnchorForHeight(dims.y); float cursorX = 0.0f; float cursorY = 0.0f; // target is required due to invisible '\n' character int target = 0; int alignStartTarget = 0; for (int i = 0; i < formattedText.Length && target < geomData.CurrentAllocatedCharacters; ++i) { formattedText.ApplyColorCommand(curStyler, i); int idx = formattedText[i]; tk2dFontChar chr = fontInst.GetCharForIndex(idx, 0); if (idx == '\n') { float lineWidth = cursorX; int alignEndTarget = target; // this is one after the last filled character if (alignStartTarget != target) { float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } alignStartTarget = target; cursorX = 0.0f; cursorY -= data.ActualLineSpaceHeight; } else { pos[offset + target * 4 + 0] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 1] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p0.y * data.TotalScale.y, 0); pos[offset + target * 4 + 2] = new Vector3(cursorX + chr.p0.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); pos[offset + target * 4 + 3] = new Vector3(cursorX + chr.p1.x * data.TotalScale.x, offsetY + cursorY + chr.p1.y * data.TotalScale.y, 0); if (chr.flipped) { uv[offset + target * 4 + 0] = new Vector2(chr.uv1.x, chr.uv1.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv0.x, chr.uv0.y); } else { uv[offset + target * 4 + 0] = new Vector2(chr.uv0.x, chr.uv0.y); uv[offset + target * 4 + 1] = new Vector2(chr.uv1.x, chr.uv0.y); uv[offset + target * 4 + 2] = new Vector2(chr.uv0.x, chr.uv1.y); uv[offset + target * 4 + 3] = new Vector2(chr.uv1.x, chr.uv1.y); } if (fontInst.textureGradients) { uv2[offset + target * 4 + 0] = chr.gradientUv[0] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 1] = chr.gradientUv[1] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 2] = chr.gradientUv[2] + new Vector2(curStyler.meshGradientTexU, 0); uv2[offset + target * 4 + 3] = chr.gradientUv[3] + new Vector2(curStyler.meshGradientTexU, 0); } if (fontInst.isPacked) { Color32 c = channelSelectColors[chr.channel]; color[offset + target * 4 + 0] = c; color[offset + target * 4 + 1] = c; color[offset + target * 4 + 2] = c; color[offset + target * 4 + 3] = c; } else { color[offset + target * 4 + 0] = curStyler.meshTopColor; color[offset + target * 4 + 1] = curStyler.meshTopColor; color[offset + target * 4 + 2] = curStyler.meshBottomColor; color[offset + target * 4 + 3] = curStyler.meshBottomColor; } cursorX += (chr.advance + data.Spacing) * data.TotalScale.x; if (data.kerning && i < formattedText.Length - 1) { foreach (var k in fontInst.kerning) { if (k.c0 == formattedText[i] && k.c1 == formattedText[i + 1]) { cursorX += k.amount * data.TotalScale.x; break; } } } target++; } } if (alignStartTarget != target) { float lineWidth = cursorX; int alignEndTarget = target; float xOffset = data.GetXAnchorForWidth(lineWidth); PostAlignTextData(pos, offset, alignStartTarget, alignEndTarget, xOffset); } for (int i = target; i < geomData.CurrentAllocatedCharacters; ++i) { pos[offset + i * 4 + 0] = pos[offset + i * 4 + 1] = pos[offset + i * 4 + 2] = pos[offset + i * 4 + 3] = Vector3.zero; uv[offset + i * 4 + 0] = uv[offset + i * 4 + 1] = uv[offset + i * 4 + 2] = uv[offset + i * 4 + 3] = Vector2.zero; if (fontInst.textureGradients) { uv2[offset + i * 4 + 0] = uv2[offset + i * 4 + 1] = uv2[offset + i * 4 + 2] = uv2[offset + i * 4 + 3] = Vector2.zero; } color[offset + i * 4 + 0] = color[offset + i * 4 + 1] = color[offset + i * 4 + 2] = color[offset + i * 4 + 3] = Color.clear; } }
// Use this to get a correctly set up textgeomdata object // This uses a static global tmpData object and is not thread safe // Fortunately for us, neither is the rest of Unity. public GeomData(tk2dTextMeshData _textMeshData, int _currentAllocatedCharacters) { textMeshData = _textMeshData; currentAllocatedCharacters = _currentAllocatedCharacters; }
void DrawEditorGUI() { if (GUILayout.Button("Commit")) { // Select all children, EXCLUDING self Transform[] allTransforms = batcher.transform.GetComponentsInChildren<Transform>(); allTransforms = (from t in allTransforms where t != batcher.transform select t).ToArray(); // sort sprites, smaller to larger z if (batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.SortToCamera)) { tk2dCamera tk2dCam = tk2dCamera.CameraForLayer( batcher.gameObject.layer ); Camera cam = tk2dCam ? tk2dCam.camera : Camera.main; allTransforms = (from t in allTransforms orderby cam.WorldToScreenPoint((t.renderer != null) ? t.renderer.bounds.center : t.position).z descending select t).ToArray(); } else { allTransforms = (from t in allTransforms orderby t.position.z descending select t).ToArray(); } // and within the z sort by material if (allTransforms.Length == 0) { EditorUtility.DisplayDialog("StaticSpriteBatcher", "Error: No child objects found", "Ok"); return; } Dictionary<Transform, int> batchedSpriteLookup = new Dictionary<Transform, int>(); batchedSpriteLookup[batcher.transform] = -1; Matrix4x4 batcherWorldToLocal = batcher.transform.worldToLocalMatrix; batcher.spriteCollection = null; batcher.batchedSprites = new tk2dBatchedSprite[allTransforms.Length]; List<tk2dTextMeshData> allTextMeshData = new List<tk2dTextMeshData>(); int currBatchedSprite = 0; foreach (var t in allTransforms) { tk2dBaseSprite baseSprite = t.GetComponent<tk2dBaseSprite>(); tk2dTextMesh textmesh = t.GetComponent<tk2dTextMesh>(); tk2dBatchedSprite bs = new tk2dBatchedSprite(); bs.name = t.gameObject.name; bs.position = t.localPosition; bs.rotation = t.localRotation; bs.relativeMatrix = batcherWorldToLocal * t.localToWorldMatrix; if (baseSprite) { bs.baseScale = Vector3.one; bs.localScale = new Vector3(t.localScale.x * baseSprite.scale.x, t.localScale.y * baseSprite.scale.y, t.localScale.z * baseSprite.scale.z); FillBatchedSprite(bs, t.gameObject); // temp redundant - just incase batcher expects to point to a valid one, somewhere we've missed batcher.spriteCollection = baseSprite.Collection; } else if (textmesh) { bs.spriteCollection = null; bs.type = tk2dBatchedSprite.Type.TextMesh; bs.color = textmesh.color; bs.baseScale = textmesh.scale; bs.localScale = new Vector3(t.localScale.x * textmesh.scale.x, t.localScale.y * textmesh.scale.y, t.localScale.z * textmesh.scale.z); bs.FormattedText = textmesh.FormattedText; tk2dTextMeshData tmd = new tk2dTextMeshData(); tmd.font = textmesh.font; tmd.text = textmesh.text; tmd.color = textmesh.color; tmd.color2 = textmesh.color2; tmd.useGradient = textmesh.useGradient; tmd.textureGradient = textmesh.textureGradient; tmd.anchor = textmesh.anchor; tmd.kerning = textmesh.kerning; tmd.maxChars = textmesh.maxChars; tmd.inlineStyling = textmesh.inlineStyling; tmd.formatting = textmesh.formatting; tmd.wordWrapWidth = textmesh.wordWrapWidth; tmd.spacing = textmesh.Spacing; tmd.lineSpacing = textmesh.LineSpacing; bs.xRefId = allTextMeshData.Count; allTextMeshData.Add(tmd); } else { // Empty GameObject bs.spriteId = -1; bs.baseScale = Vector3.one; bs.localScale = t.localScale; bs.type = tk2dBatchedSprite.Type.EmptyGameObject; } batchedSpriteLookup[t] = currBatchedSprite; batcher.batchedSprites[currBatchedSprite++] = bs; } batcher.allTextMeshData = allTextMeshData.ToArray(); int idx = 0; foreach (var t in allTransforms) { var bs = batcher.batchedSprites[idx]; bs.parentId = batchedSpriteLookup[t.parent]; t.parent = batcher.transform; // unparent ++idx; } Transform[] directChildren = (from t in allTransforms where t.parent == batcher.transform select t).ToArray(); foreach (var t in directChildren) { GameObject.DestroyImmediate(t.gameObject); } Vector3 inverseScale = new Vector3(1.0f / batcher.scale.x, 1.0f / batcher.scale.y, 1.0f / batcher.scale.z); batcher.transform.localScale = Vector3.Scale( batcher.transform.localScale, inverseScale ); batcher.Build(); EditorUtility.SetDirty(target); } }
void BuildRenderMesh() { List <Material> materials = new List <Material>(); List <List <int> > indices = new List <List <int> >(); bool needNormals = false; bool needTangents = false; bool needUV2 = false; bool flattenDepth = CheckFlag(Flags.FlattenDepth); foreach (var bs in batchedSprites) { var spriteDef = bs.GetSpriteDefinition(); if (spriteDef != null) { needNormals |= (spriteDef.normals != null && spriteDef.normals.Length > 0); needTangents |= (spriteDef.tangents != null && spriteDef.tangents.Length > 0); } if (bs.type == tk2dBatchedSprite.Type.TextMesh) { tk2dTextMeshData textMeshData = allTextMeshData[bs.xRefId]; if ((textMeshData.font != null) && textMeshData.font.inst.textureGradients) { needUV2 = true; } } } // just helpful to have these here, stop code being more messy List <int> bsNVerts = new List <int>(); List <int> bsNInds = new List <int>(); int numVertices = 0; foreach (var bs in batchedSprites) { if (!bs.IsDrawn) // when the first non-drawn child is found, it signals the end of the drawn list { break; } var spriteDef = bs.GetSpriteDefinition(); int nVerts = 0; int nInds = 0; switch (bs.type) { case tk2dBatchedSprite.Type.EmptyGameObject: break; case tk2dBatchedSprite.Type.Sprite: if (spriteDef != null) { tk2dSpriteGeomGen.GetSpriteGeomDesc(out nVerts, out nInds, spriteDef); } break; case tk2dBatchedSprite.Type.TiledSprite: if (spriteDef != null) { tk2dSpriteGeomGen.GetTiledSpriteGeomDesc(out nVerts, out nInds, spriteDef, bs.Dimensions); } break; case tk2dBatchedSprite.Type.SlicedSprite: if (spriteDef != null) { tk2dSpriteGeomGen.GetSlicedSpriteGeomDesc(out nVerts, out nInds, spriteDef, bs.CheckFlag(tk2dBatchedSprite.Flags.SlicedSprite_BorderOnly)); } break; case tk2dBatchedSprite.Type.ClippedSprite: if (spriteDef != null) { tk2dSpriteGeomGen.GetClippedSpriteGeomDesc(out nVerts, out nInds, spriteDef); } break; case tk2dBatchedSprite.Type.TextMesh: { tk2dTextMeshData textMeshData = allTextMeshData[bs.xRefId]; tk2dTextGeomGen.GetTextMeshGeomDesc(out nVerts, out nInds, tk2dTextGeomGen.Data(textMeshData, textMeshData.font.inst, bs.FormattedText)); break; } } numVertices += nVerts; bsNVerts.Add(nVerts); bsNInds.Add(nInds); } Vector3[] meshNormals = needNormals?new Vector3[numVertices]:null; Vector4[] meshTangents = needTangents?new Vector4[numVertices]:null; Vector3[] meshVertices = new Vector3[numVertices]; Color32[] meshColors = new Color32[numVertices]; Vector2[] meshUvs = new Vector2[numVertices]; Vector2[] meshUv2s = needUV2 ? new Vector2[numVertices] : null; int currVertex = 0; Material currentMaterial = null; List <int> currentIndices = null; Matrix4x4 scaleMatrix = Matrix4x4.identity; scaleMatrix.m00 = _scale.x; scaleMatrix.m11 = _scale.y; scaleMatrix.m22 = _scale.z; int bsIndex = 0; foreach (var bs in batchedSprites) { if (!bs.IsDrawn) // when the first non-drawn child is found, it signals the end of the drawn list { break; } if (bs.type == tk2dBatchedSprite.Type.EmptyGameObject) { ++bsIndex; // watch out for this continue; } var spriteDef = bs.GetSpriteDefinition(); int nVerts = bsNVerts[bsIndex]; int nInds = bsNInds[bsIndex]; Material material = GetMaterial(bs); // should have a material at this point if (material != currentMaterial) { if (currentMaterial != null) { materials.Add(currentMaterial); indices.Add(currentIndices); } currentMaterial = material; currentIndices = new List <int>(); } Vector3[] posData = new Vector3[nVerts]; Vector2[] uvData = new Vector2[nVerts]; Vector2[] uv2Data = needUV2 ? new Vector2[nVerts] : null; Color32[] colorData = new Color32[nVerts]; Vector3[] normalData = needNormals ? new Vector3[nVerts] : null; Vector4[] tangentData = needTangents ? new Vector4[nVerts] : null; int[] indData = new int[nInds]; Vector3 boundsCenter = Vector3.zero; Vector3 boundsExtents = Vector3.zero; switch (bs.type) { case tk2dBatchedSprite.Type.EmptyGameObject: break; case tk2dBatchedSprite.Type.Sprite: if (spriteDef != null) { tk2dSpriteGeomGen.SetSpriteGeom(posData, uvData, normalData, tangentData, 0, spriteDef, Vector3.one); tk2dSpriteGeomGen.SetSpriteIndices(indData, 0, currVertex, spriteDef); } break; case tk2dBatchedSprite.Type.TiledSprite: if (spriteDef != null) { tk2dSpriteGeomGen.SetTiledSpriteGeom(posData, uvData, 0, out boundsCenter, out boundsExtents, spriteDef, Vector3.one, bs.Dimensions, bs.anchor, bs.BoxColliderOffsetZ, bs.BoxColliderExtentZ); tk2dSpriteGeomGen.SetTiledSpriteIndices(indData, 0, currVertex, spriteDef, bs.Dimensions); } break; case tk2dBatchedSprite.Type.SlicedSprite: if (spriteDef != null) { tk2dSpriteGeomGen.SetSlicedSpriteGeom(posData, uvData, 0, out boundsCenter, out boundsExtents, spriteDef, Vector3.one, bs.Dimensions, bs.SlicedSpriteBorderBottomLeft, bs.SlicedSpriteBorderTopRight, bs.anchor, bs.BoxColliderOffsetZ, bs.BoxColliderExtentZ); tk2dSpriteGeomGen.SetSlicedSpriteIndices(indData, 0, currVertex, spriteDef, bs.CheckFlag(tk2dBatchedSprite.Flags.SlicedSprite_BorderOnly)); } break; case tk2dBatchedSprite.Type.ClippedSprite: if (spriteDef != null) { tk2dSpriteGeomGen.SetClippedSpriteGeom(posData, uvData, 0, out boundsCenter, out boundsExtents, spriteDef, Vector3.one, bs.ClippedSpriteRegionBottomLeft, bs.ClippedSpriteRegionTopRight, bs.BoxColliderOffsetZ, bs.BoxColliderExtentZ); tk2dSpriteGeomGen.SetClippedSpriteIndices(indData, 0, currVertex, spriteDef); } break; case tk2dBatchedSprite.Type.TextMesh: { tk2dTextMeshData textMeshData = allTextMeshData[bs.xRefId]; var geomData = tk2dTextGeomGen.Data(textMeshData, textMeshData.font.inst, bs.FormattedText); int target = tk2dTextGeomGen.SetTextMeshGeom(posData, uvData, uv2Data, colorData, 0, geomData); if (!geomData.fontInst.isPacked) { Color32 topColor = textMeshData.color; Color32 bottomColor = textMeshData.useGradient ? textMeshData.color2 : textMeshData.color; for (int i = 0; i < colorData.Length; ++i) { Color32 c = ((i % 4) < 2) ? topColor : bottomColor; byte red = (byte)(((int)colorData[i].r * (int)c.r) / 255); byte green = (byte)(((int)colorData[i].g * (int)c.g) / 255); byte blue = (byte)(((int)colorData[i].b * (int)c.b) / 255); byte alpha = (byte)(((int)colorData[i].a * (int)c.a) / 255); if (geomData.fontInst.premultipliedAlpha) { red = (byte)(((int)red * (int)alpha) / 255); green = (byte)(((int)green * (int)alpha) / 255); blue = (byte)(((int)blue * (int)alpha) / 255); } colorData[i] = new Color32(red, green, blue, alpha); } } tk2dTextGeomGen.SetTextMeshIndices(indData, 0, currVertex, geomData, target); break; } } bs.CachedBoundsCenter = boundsCenter; bs.CachedBoundsExtents = boundsExtents; if (nVerts > 0 && bs.type != tk2dBatchedSprite.Type.TextMesh) { bool premulAlpha = (bs.spriteCollection != null) ? bs.spriteCollection.premultipliedAlpha : false; tk2dSpriteGeomGen.SetSpriteColors(colorData, 0, nVerts, bs.color, premulAlpha); } Matrix4x4 mat = scaleMatrix * bs.relativeMatrix; for (int i = 0; i < nVerts; ++i) { Vector3 pos = Vector3.Scale(posData[i], bs.baseScale); pos = mat.MultiplyPoint(pos); if (flattenDepth) { pos.z = 0; } meshVertices[currVertex + i] = pos; meshUvs[currVertex + i] = uvData[i]; if (needUV2) { meshUv2s[currVertex + i] = uv2Data[i]; } meshColors[currVertex + i] = colorData[i]; if (needNormals) { meshNormals[currVertex + i] = bs.rotation * normalData[i]; } if (needTangents) { Vector3 tang = new Vector3(tangentData[i].x, tangentData[i].y, tangentData[i].z); tang = bs.rotation * tang; meshTangents[currVertex + i] = new Vector4(tang.x, tang.y, tang.z, tangentData[i].w); } } currentIndices.AddRange(indData); currVertex += nVerts; ++bsIndex; } if (currentIndices != null) { materials.Add(currentMaterial); indices.Add(currentIndices); } if (mesh) { mesh.vertices = meshVertices; mesh.uv = meshUvs; if (needUV2) { mesh.uv2 = meshUv2s; } mesh.colors32 = meshColors; if (needNormals) { mesh.normals = meshNormals; } if (needTangents) { mesh.tangents = meshTangents; } mesh.subMeshCount = indices.Count; for (int i = 0; i < indices.Count; ++i) { mesh.SetTriangles(indices[i].ToArray(), i); } mesh.RecalculateBounds(); } GetComponent <Renderer>().sharedMaterials = materials.ToArray(); }
public static Vector2 GetMeshDimensionsForString(this tk2dTextMeshData geomData, tk2dColoredText inputText) { return(GetMeshDimensionsForString(geomData, inputText, 0, inputText.Length)); }
void DrawInstanceGUI() { if (GUILayout.Button("Edit")) { Vector3 batcherPos = batcher.transform.position; Quaternion batcherRotation = batcher.transform.rotation; batcher.transform.position = Vector3.zero; batcher.transform.rotation = Quaternion.identity; batcher.transform.localScale = Vector3.Scale(batcher.transform.localScale, batcher.scale); Dictionary <int, Transform> parents = new Dictionary <int, Transform>(); List <Transform> children = new List <Transform>(); List <GameObject> gos = new List <GameObject>(); int id; id = 0; foreach (var bs in batcher.batchedSprites) { GameObject go = new GameObject(bs.name); parents[id++] = go.transform; children.Add(go.transform); gos.Add(go); } id = 0; foreach (var bs in batcher.batchedSprites) { Transform parent = batcher.transform; if (bs.parentId != -1) { parents.TryGetValue(bs.parentId, out parent); } children[id++].parent = parent; } id = 0; foreach (var bs in batcher.batchedSprites) { GameObject go = gos[id]; go.transform.localPosition = bs.position; go.transform.localRotation = bs.rotation; { float sx = bs.localScale.x / ((Mathf.Abs(bs.baseScale.x) > Mathf.Epsilon) ? bs.baseScale.x : 1.0f); float sy = bs.localScale.y / ((Mathf.Abs(bs.baseScale.y) > Mathf.Epsilon) ? bs.baseScale.y : 1.0f); float sz = bs.localScale.z / ((Mathf.Abs(bs.baseScale.z) > Mathf.Epsilon) ? bs.baseScale.z : 1.0f); go.transform.localScale = new Vector3(sx, sy, sz); } if (bs.type == tk2dBatchedSprite.Type.TextMesh) { tk2dTextMesh s = go.AddComponent <tk2dTextMesh>(); if (batcher.allTextMeshData == null || bs.xRefId == -1) { Debug.LogError("Unable to find text mesh ref"); } else { tk2dTextMeshData tmd = batcher.allTextMeshData[bs.xRefId]; s.font = tmd.font; s.scale = bs.baseScale; s.SortingOrder = bs.renderLayer; s.text = tmd.text; s.color = bs.color; s.color2 = tmd.color2; s.useGradient = tmd.useGradient; s.textureGradient = tmd.textureGradient; s.anchor = tmd.anchor; s.scale = bs.baseScale; s.kerning = tmd.kerning; s.maxChars = tmd.maxChars; s.inlineStyling = tmd.inlineStyling; s.formatting = tmd.formatting; s.wordWrapWidth = tmd.wordWrapWidth; s.Spacing = tmd.spacing; s.LineSpacing = tmd.lineSpacing; s.Commit(); } } else { RestoreBatchedSprite(go, bs); } ++id; } batcher.batchedSprites = null; batcher.Build(); EditorUtility.SetDirty(target); batcher.transform.position = batcherPos; batcher.transform.rotation = batcherRotation; } batcher.scale = EditorGUILayout.Vector3Field("Scale", batcher.scale); batcher.SetFlag(tk2dStaticSpriteBatcher.Flags.GenerateCollider, EditorGUILayout.Toggle("Generate Collider", batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.GenerateCollider))); batcher.SetFlag(tk2dStaticSpriteBatcher.Flags.FlattenDepth, EditorGUILayout.Toggle("Flatten Depth", batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.FlattenDepth))); batcher.SetFlag(tk2dStaticSpriteBatcher.Flags.SortToCamera, EditorGUILayout.Toggle("Sort to Camera", batcher.CheckFlag(tk2dStaticSpriteBatcher.Flags.SortToCamera))); MeshFilter meshFilter = batcher.GetComponent <MeshFilter>(); MeshRenderer meshRenderer = batcher.GetComponent <MeshRenderer>(); if (meshFilter != null && meshFilter.sharedMesh != null && meshRenderer != null) { GUILayout.Label("Stats", EditorStyles.boldLabel); int numIndices = 0; Mesh mesh = meshFilter.sharedMesh; for (int i = 0; i < mesh.subMeshCount; ++i) { numIndices += mesh.GetTriangles(i).Length; } GUILayout.Label(string.Format("Triangles: {0}\nMaterials: {1}", numIndices / 3, meshRenderer.sharedMaterials.Length)); } }
public static Vector2 GetMeshDimensionsForString(this tk2dTextMeshData geomData, string inputString) { return(GetMeshDimensionsForString(geomData, new tk2dColoredText(inputString, Color.white))); }