override public void PopulateRenderLayer() { if (_isOnStage && _firstFacetIndex != -1) { _isMeshDirty = false; Vector3[] vertices = _renderLayer.vertices; Vector2[] uvs = _renderLayer.uvs; Color[] colors = _renderLayer.colors; int vertexIndex0 = _firstFacetIndex * 4; int vertexIndex1 = vertexIndex0 + 1; int vertexIndex2 = vertexIndex0 + 2; int vertexIndex3 = vertexIndex0 + 3; int lineCount = _letterQuadLines.Length; for (int i = 0; i < lineCount; i++) { FLetterQuad[] quads = _letterQuadLines[i].quads; int quadCount = quads.Length; for (int q = 0; q < quadCount; q++) { FLetterQuad quad = quads[q]; FCharInfo charInfo = quad.charInfo; _concatenatedMatrix.ApplyVector3FromLocalVector2(ref vertices[vertexIndex0], quad.topLeft, 0); _concatenatedMatrix.ApplyVector3FromLocalVector2(ref vertices[vertexIndex1], quad.topRight, 0); _concatenatedMatrix.ApplyVector3FromLocalVector2(ref vertices[vertexIndex2], quad.bottomRight, 0); _concatenatedMatrix.ApplyVector3FromLocalVector2(ref vertices[vertexIndex3], quad.bottomLeft, 0); uvs[vertexIndex0] = charInfo.uvTopLeft; uvs[vertexIndex1] = charInfo.uvTopRight; uvs[vertexIndex2] = charInfo.uvBottomRight; uvs[vertexIndex3] = charInfo.uvBottomLeft; colors[vertexIndex0] = _alphaColor; colors[vertexIndex1] = _alphaColor; colors[vertexIndex2] = _alphaColor; colors[vertexIndex3] = _alphaColor; vertexIndex0 += 4; vertexIndex1 += 4; vertexIndex2 += 4; vertexIndex3 += 4; } } _renderLayer.HandleVertsChange(); } }
private void LoadAndParseConfigFile() { TextAsset asset = (TextAsset) Resources.Load(_configPath, typeof(TextAsset)); if(asset == null) { throw new FutileException("Couldn't find font config file " + _configPath); } string[] separators = new string[1]; separators[0] = "\n"; //osx string[] lines = asset.text.Split(separators,StringSplitOptions.RemoveEmptyEntries); if(lines.Length <= 1) //osx line endings didn't work, try windows { separators[0] = "\r\n"; lines = asset.text.Split(separators,StringSplitOptions.RemoveEmptyEntries); } if(lines.Length <= 1) //those line endings didn't work, so we're on a magical OS { separators[0] = "\r"; lines = asset.text.Split(separators,StringSplitOptions.RemoveEmptyEntries); } if(lines.Length <= 1) //WHAT { throw new FutileException("Your font file is messed up"); } int wordCount = 0; int c = 0; int k = 0; _charInfosByID = new Dictionary<uint, FCharInfo>(127); //insert an empty char to be used when a character isn't in the font data file FCharInfo emptyChar = new FCharInfo(); _charInfosByID[0] = emptyChar; float resourceScale = Futile.resourceScale; Vector2 textureSize = _element.atlas.textureSize; bool wasKerningFound = false; int lineCount = lines.Length; for(int n = 0; n<lineCount; ++n) { string line = lines[n]; string [] words = line.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); /* we don't care about these, or else they could be in the elseif if(words[0] == "info") //info face="Franchise Bold" size=160 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 { //do nothing } else if(words[0] == "page") //page id=0 file="FranchiseLarge.png" { //do nothing } */ if(words[0] == "common") //common lineHeight=168 base=26 scaleW=1024 scaleH=1024 pages=1 packed=0 { //these are the height and width of the original atlas built by Hiero _configWidth = int.Parse(words[3].Split('=')[1]); //_configHeight = int.Parse(words[4].Split('=')[1]); //this is the ratio of the config vs the size of the actual texture element _configRatio = _element.sourceSize.x/_configWidth; _lineHeight = int.Parse(words[1].Split('=')[1]) * _configRatio; //_lineBase = int.Parse(words[2].Split('=')[1]) * _configRatio; } else if(words[0] == "chars") //chars count=92 { int charCount = int.Parse(words[1].Split('=')[1]); _charInfos = new FCharInfo[charCount+1]; //gotta add 1 because the charCount seems to be off by 1 } else if(words[0] == "char") //char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=120 xadvance=29 page=0 chnl=0 letter=a { FCharInfo charInfo = new FCharInfo(); wordCount = words.Length; for(int w = 1; w<wordCount; ++w) { string[] parts = words[w].Split('='); string partName = parts[0]; if(partName == "letter") { if(parts[1].Length >= 3) { charInfo.letter = parts[1].Substring(1,1); } continue; //we don't care about the letter } if(partName == "\r") continue; //something weird happened with linebreaks, meh! int partValue = int.Parse(parts[1]); if(partName == "id") { charInfo.charID = partValue; } else if(partName == "x") { charInfo.x = partValue*_configRatio - _element.sourceRect.x; //offset to account for the trimmed atlas } else if(partName == "y") { charInfo.y = partValue*_configRatio - _element.sourceRect.y; //offset to account for the trimmed atlas } else if(partName == "width") { charInfo.width = partValue*_configRatio; } else if(partName == "height") { charInfo.height = partValue*_configRatio; } else if(partName == "xoffset") { charInfo.offsetX = partValue*_configRatio; } else if(partName == "yoffset") { charInfo.offsetY = partValue*_configRatio; } else if(partName == "xadvance") { charInfo.xadvance = partValue*_configRatio; } else if(partName == "page") { charInfo.page = partValue; } } Rect uvRect = new Rect ( _element.uvRect.x + charInfo.x/textureSize.x*resourceScale, (textureSize.y-charInfo.y-charInfo.height)/textureSize.y*resourceScale - (1.0f - _element.uvRect.yMax), charInfo.width/textureSize.x*resourceScale, charInfo.height/textureSize.y*resourceScale ); charInfo.uvRect = uvRect; charInfo.uvTopLeft.Set(uvRect.xMin,uvRect.yMax); charInfo.uvTopRight.Set(uvRect.xMax,uvRect.yMax); charInfo.uvBottomRight.Set(uvRect.xMax,uvRect.yMin); charInfo.uvBottomLeft.Set(uvRect.xMin,uvRect.yMin); _charInfosByID[(uint)charInfo.charID] = charInfo; _charInfos[c] = charInfo; c++; } else if(words[0] == "kernings") //kernings count=169 { wasKerningFound = true; int kerningCount = int.Parse(words[1].Split('=')[1]); _kerningInfos = new FKerningInfo[kerningCount+100]; //kerning count can be wrong so just add 100 items of potential fudge factor } else if(words[0] == "kerning") //kerning first=56 second=57 amount=-1 { FKerningInfo kerningInfo = new FKerningInfo(); kerningInfo.first = -1; wordCount = words.Length; for(int w = 1; w<wordCount; w++) { string[] parts = words[w].Split('='); if(parts.Length >= 2) { string partName = parts[0]; int partValue = int.Parse(parts[1]); if(partName == "first") { kerningInfo.first = partValue; } else if(partName == "second") { kerningInfo.second = partValue; } else if(partName == "amount") { kerningInfo.amount = partValue * _configRatio; } } } if(kerningInfo.first != -1) { _kerningInfos[k] = kerningInfo; } k++; } } _kerningCount = k; if(!wasKerningFound) //if there are no kernings at all (like in a pixel font), then make an empty kerning array { _kerningInfos = new FKerningInfo[0]; } //make sure the space character doesn't have offsetY and offsetX if(_charInfosByID[32] != null) { _charInfosByID[32].offsetX = 0; _charInfosByID[32].offsetY = 0; } }
private void LoadAndParseConfigFile() { TextAsset asset = (TextAsset)Resources.Load(_configPath, typeof(TextAsset)); if (asset == null) { throw new FutileException("Couldn't find font config file " + _configPath); } string[] separators = new string[1]; separators[0] = "\n"; //osx string[] lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); if (lines.Length <= 1) //osx line endings didn't work, try windows { separators[0] = "\r\n"; lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); } if (lines.Length <= 1) //those line endings didn't work, so we're on a magical OS { separators[0] = "\r"; lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); } if (lines.Length <= 1) //WHAT { throw new FutileException("Your font file is messed up"); } int wordCount = 0; int c = 0; int k = 0; _charInfosByID = new Dictionary <uint, FCharInfo>(127); //insert an empty char to be used when a character isn't in the font data file FCharInfo emptyChar = new FCharInfo(); _charInfosByID[0] = emptyChar; float resourceScaleInverse = Futile.resourceScaleInverse; Vector2 textureSize = _element.atlas.textureSize; Debug.Log("texture width " + textureSize.x); bool wasKerningFound = false; int lineCount = lines.Length; for (int n = 0; n < lineCount; ++n) { string line = lines[n]; string [] words = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); /* we don't care about these, or else they could be in the elseif * if(words[0] == "info") //info face="Franchise Bold" size=160 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 * { * //do nothing * } * else if(words[0] == "page") //page id=0 file="FranchiseLarge" * { * //do nothing * } */ if (words[0] == "common") //common lineHeight=168 base=26 scaleW=1024 scaleH=1024 pages=1 packed=0 { //these are the height and width of the original atlas built by Hiero _configWidth = int.Parse(words[3].Split('=')[1]); //_configHeight = int.Parse(words[4].Split('=')[1]); //this is the ratio of the config vs the size of the actual texture element _configRatio = _element.sourcePixelSize.x / (float)_configWidth; _lineHeight = ((float)int.Parse(words[1].Split('=')[1])) * _configRatio * resourceScaleInverse; //_lineBase = int.Parse(words[2].Split('=')[1]) * _configRatio; } else if (words[0] == "chars") //chars count=92 { int charCount = int.Parse(words[1].Split('=')[1]); _charInfos = new FCharInfo[charCount + 1]; //gotta add 1 because the charCount seems to be off by 1 } else if (words[0] == "char") //char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=120 xadvance=29 page=0 chnl=0 letter=a { FCharInfo charInfo = new FCharInfo(); wordCount = words.Length; for (int w = 1; w < wordCount; ++w) { string[] parts = words[w].Split('='); string partName = parts[0]; if (partName == "letter") { if (parts[1].Length >= 3) { charInfo.letter = parts[1].Substring(1, 1); } continue; //we don't care about the letter } if (partName == "\r") { continue; //something weird happened with linebreaks, meh! } int partIntValue = int.Parse(parts[1]); float partFloatValue = (float)partIntValue; if (partName == "id") { charInfo.charID = partIntValue; } else if (partName == "x") { charInfo.x = partFloatValue * _configRatio - _element.sourceRect.x * Futile.resourceScale; //offset to account for the trimmed atlas } else if (partName == "y") { charInfo.y = partFloatValue * _configRatio - _element.sourceRect.y * Futile.resourceScale; //offset to account for the trimmed atlas } else if (partName == "width") { charInfo.width = partFloatValue * _configRatio; } else if (partName == "height") { charInfo.height = partFloatValue * _configRatio; } else if (partName == "xoffset") { charInfo.offsetX = partFloatValue * _configRatio; } else if (partName == "yoffset") { charInfo.offsetY = partFloatValue * _configRatio; } else if (partName == "xadvance") { charInfo.xadvance = partFloatValue * _configRatio; } else if (partName == "page") { charInfo.page = partIntValue; } } Rect uvRect = new Rect ( _element.uvRect.x + charInfo.x / textureSize.x, (textureSize.y - charInfo.y - charInfo.height) / textureSize.y - (1.0f - _element.uvRect.yMax), charInfo.width / textureSize.x, charInfo.height / textureSize.y ); charInfo.uvRect = uvRect; charInfo.uvTopLeft.Set(uvRect.xMin, uvRect.yMax); charInfo.uvTopRight.Set(uvRect.xMax, uvRect.yMax); charInfo.uvBottomRight.Set(uvRect.xMax, uvRect.yMin); charInfo.uvBottomLeft.Set(uvRect.xMin, uvRect.yMin); //scale them AFTER they've been used for uvs charInfo.width *= resourceScaleInverse; charInfo.height *= resourceScaleInverse; charInfo.offsetX *= resourceScaleInverse; charInfo.offsetY *= resourceScaleInverse; charInfo.xadvance *= resourceScaleInverse; _charInfosByID[(uint)charInfo.charID] = charInfo; _charInfos[c] = charInfo; c++; } else if (words[0] == "kernings") //kernings count=169 { wasKerningFound = true; int kerningCount = int.Parse(words[1].Split('=')[1]); _kerningInfos = new FKerningInfo[kerningCount + 100]; //kerning count can be wrong so just add 100 items of potential fudge factor } else if (words[0] == "kerning") //kerning first=56 second=57 amount=-1 { FKerningInfo kerningInfo = new FKerningInfo(); kerningInfo.first = -1; wordCount = words.Length; for (int w = 1; w < wordCount; w++) { string[] parts = words[w].Split('='); if (parts.Length >= 2) { string partName = parts[0]; int partValue = int.Parse(parts[1]); if (partName == "first") { kerningInfo.first = partValue; } else if (partName == "second") { kerningInfo.second = partValue; } else if (partName == "amount") { kerningInfo.amount = ((float)partValue) * _configRatio * resourceScaleInverse; } } } if (kerningInfo.first != -1) { _kerningInfos[k] = kerningInfo; } k++; } } _kerningCount = k; if (!wasKerningFound) //if there are no kernings at all (like in a pixel font), then make an empty kerning array { _kerningInfos = new FKerningInfo[0]; } //make sure the space character doesn't have offsetY and offsetX if (_charInfosByID.ContainsKey(ASCII_SPACE)) { _charInfosByID[ASCII_SPACE].offsetX = 0; _charInfosByID[ASCII_SPACE].offsetY = 0; } }
private void LoadAndParseConfigFile() { TextAsset asset = (TextAsset)Resources.Load(_configPath, typeof(TextAsset)); if (asset == null) { throw new Exception("Couldn't find font config file " + _configPath); } string[] separators = new string[1]; separators[0] = "\n"; //osx string[] lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); if (lines.Length <= 1) //osx line endings didn't work, try windows { separators[0] = "\r\n"; lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); } if (lines.Length <= 1) //those line endings didn't work, so we're on a magical OS { separators[0] = "\r"; lines = asset.text.Split(separators, StringSplitOptions.RemoveEmptyEntries); } if (lines.Length <= 1) //WHAT { throw new Exception("Your font file is messed up"); } int wordCount = 0; int c = 0; int k = 0; _charInfosByID = new FCharInfo[127]; float resourceScale = Futile.resourceScale; Vector2 textureSize = _element.atlas.textureSize; bool wasKerningFound = false; int lint = -1; foreach (string line in lines) { lint++; string [] words = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); /* we don't care about these, or else they could be in the elseif * if(words[0] == "info") //info face="Franchise Bold" size=160 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 * { * //do nothing * } * else if(words[0] == "page") //page id=0 file="FranchiseLarge.png" * { * //do nothing * } */ if (words[0] == "common") //common lineHeight=168 base=26 scaleW=1024 scaleH=1024 pages=1 packed=0 { //these are the height and width of the original atlas built by Hiero _configWidth = int.Parse(words[3].Split('=')[1]); //_configHeight = int.Parse(words[4].Split('=')[1]); //this is the ratio of the config vs the size of the actual texture element _configRatio = _element.sourceSize.x / _configWidth; _lineHeight = int.Parse(words[1].Split('=')[1]) * _configRatio; } else if (words[0] == "chars") //chars count=92 { int charCount = int.Parse(words[1].Split('=')[1]); _charInfos = new FCharInfo[charCount + 1]; //gotta add 1 because the charCount seems to be off by 1 } else if (words[0] == "char") //char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=120 xadvance=29 page=0 chnl=0 letter=a { FCharInfo charInfo = new FCharInfo(); wordCount = words.Length; for (int w = 1; w < wordCount; ++w) { string[] parts = words[w].Split('='); string partName = parts[0]; if (partName == "letter") { if (parts[1].Length >= 3) { charInfo.letter = parts[1].Substring(1, 1); } continue; //we don't care about the letter } if (partName == "\r") { continue; //something weird happened with linebreaks, meh! } int partValue = int.Parse(parts[1]); if (partName == "id") { charInfo.charID = partValue; } else if (partName == "x") { charInfo.x = partValue * _configRatio - _element.sourceRect.x; //offset to account for the trimmed atlas } else if (partName == "y") { charInfo.y = partValue * _configRatio - _element.sourceRect.y; //offset to account for the trimmed atlas } else if (partName == "width") { charInfo.width = partValue * _configRatio; } else if (partName == "height") { charInfo.height = partValue * _configRatio; } else if (partName == "xoffset") { charInfo.offsetX = partValue * _configRatio; } else if (partName == "yoffset") { charInfo.offsetY = partValue * _configRatio; } else if (partName == "xadvance") { charInfo.xadvance = partValue * _configRatio; } else if (partName == "page") { charInfo.page = partValue; } } if (element.isRotated) { Rect uvRect = new Rect ( _element.uvRect.x + _element.uvRect.width - ((charInfo.y + charInfo.height + 0.5f) / textureSize.x * resourceScale), _element.uvRect.y + _element.uvRect.height - ((charInfo.x + charInfo.width + 0.5f) / textureSize.y * resourceScale), charInfo.height / textureSize.x * resourceScale, charInfo.width / textureSize.y * resourceScale ); charInfo.uvRect = uvRect; charInfo.uvBottomLeft.Set(uvRect.xMin, uvRect.yMax); charInfo.uvTopLeft.Set(uvRect.xMax, uvRect.yMax); charInfo.uvTopRight.Set(uvRect.xMax, uvRect.yMin); charInfo.uvBottomRight.Set(uvRect.xMin, uvRect.yMin); } else { Rect uvRect = new Rect ( _element.uvRect.x + charInfo.x / textureSize.x * resourceScale, (textureSize.y - charInfo.y - charInfo.height) / textureSize.y * resourceScale - (1.0f - _element.uvRect.yMax), charInfo.width / textureSize.x * resourceScale, charInfo.height / textureSize.y * resourceScale ); charInfo.uvRect = uvRect; charInfo.uvTopLeft.Set(uvRect.xMin, uvRect.yMax); charInfo.uvTopRight.Set(uvRect.xMax, uvRect.yMax); charInfo.uvBottomRight.Set(uvRect.xMax, uvRect.yMin); charInfo.uvBottomLeft.Set(uvRect.xMin, uvRect.yMin); } _charInfosByID[charInfo.charID] = charInfo; _charInfos[c] = charInfo; c++; } else if (words[0] == "kernings") //kernings count=169 { wasKerningFound = true; int kerningCount = int.Parse(words[1].Split('=')[1]); _kerningInfos = new FKerningInfo[kerningCount + 1]; //gotta add 1 because it's off by 1 } else if (words[0] == "kerning") //kerning first=56 second=57 amount=-1 { FKerningInfo kerningInfo = new FKerningInfo(); wordCount = words.Length; for (int w = 1; w < wordCount; w++) { string[] parts = words[w].Split('='); string partName = parts[0]; int partValue = int.Parse(parts[1]); if (partName == "first") { kerningInfo.first = partValue; } else if (partName == "second") { kerningInfo.second = partValue; } else if (partName == "amount") { kerningInfo.amount = partValue * _configRatio; } } _kerningInfos[k] = kerningInfo; k++; } } if (!wasKerningFound) //if there are no kernings at all (like in a pixel font), then make an empty kerning array { _kerningInfos = new FKerningInfo[0]; } //make sure the space character doesn't have offsetY and offsetX _charInfosByID[32].offsetX = 0; _charInfosByID[32].offsetY = 0; }
override public void PopulateRenderLayer() { if (_isOnStage && _firstFacetIndex != -1) { _isMeshDirty = false; //check if the label is empty so we don't have to bother trying to draw anything if (_letterQuadLines.Length == 0 || _letterQuadLines[0].quads.Length == 0) { _renderLayer.HandleVertsChange(); return; } Vector3[] vertices = _renderLayer.vertices; Vector2[] uvs = _renderLayer.uvs; Color[] colors = _renderLayer.colors; int vertexIndex0 = _firstFacetIndex * 4; int vertexIndex1 = vertexIndex0 + 1; int vertexIndex2 = vertexIndex0 + 2; int vertexIndex3 = vertexIndex0 + 3; Vector2 topLeft = _letterQuadLines[0].quads[0].topLeft; FMatrix matrixToUse = _concatenatedMatrix; if (_shouldSnapToPixels) { matrixToUse = matrixToUse.Clone(); matrixToUse.tx += (Mathf.Round(topLeft.x * Futile.displayScale) * Futile.displayScaleInverse) - topLeft.x; matrixToUse.ty += (Mathf.Round(topLeft.y * Futile.displayScale) * Futile.displayScaleInverse) - topLeft.y; } int lineCount = _letterQuadLines.Length; for (int i = 0; i < lineCount; i++) { FLetterQuad[] quads = _letterQuadLines[i].quads; int quadCount = quads.Length; for (int q = 0; q < quadCount; q++) { FLetterQuad quad = quads[q]; FCharInfo charInfo = quad.charInfo; matrixToUse.ApplyVector3FromLocalVector2(ref vertices[vertexIndex0], quad.topLeft, 0); matrixToUse.ApplyVector3FromLocalVector2(ref vertices[vertexIndex1], quad.topRight, 0); matrixToUse.ApplyVector3FromLocalVector2(ref vertices[vertexIndex2], quad.bottomRight, 0); matrixToUse.ApplyVector3FromLocalVector2(ref vertices[vertexIndex3], quad.bottomLeft, 0); uvs[vertexIndex0] = charInfo.uvTopLeft; uvs[vertexIndex1] = charInfo.uvTopRight; uvs[vertexIndex2] = charInfo.uvBottomRight; uvs[vertexIndex3] = charInfo.uvBottomLeft; colors[vertexIndex0] = _alphaColor; colors[vertexIndex1] = _alphaColor; colors[vertexIndex2] = _alphaColor; colors[vertexIndex3] = _alphaColor; vertexIndex0 += 4; vertexIndex1 += 4; vertexIndex2 += 4; vertexIndex3 += 4; } } _renderLayer.HandleVertsChange(); } }