public void Set(exBitmapFont _bitmapFont) { bitmapFont = _bitmapFont; #if UNITY_EDITOR type = TypeForEditor.Bitmap; #endif }
// ------------------------------------------------------------------ /// \param _bitmapFont the bitmap font asset /// \param _fontInfo the font info txt file /// build the bitmap font // ------------------------------------------------------------------ public static void Build(this exBitmapFont _bitmapFont, Object _fontInfo) { try { EditorUtility.DisplayProgressBar("Building BitmapFont...", "Build BitmapFont " + _bitmapFont.name, 0.0f); // _bitmapFont.pageInfos.Clear(); _bitmapFont.charInfos.Clear(); _bitmapFont.kernings.Clear(); // TODO { // _bitmapFont.fontInfoGUIDs.Clear(); // } TODO end ParseFontInfo(_bitmapFont, _fontInfo); EditorUtility.ClearProgressBar(); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } // _bitmapFont.editorNeedRebuild = false; EditorUtility.SetDirty(_bitmapFont); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void OnInspectorUpdate() { if (curEdit == null) { return; } for (int i = curEdit.textureInfos.Count - 1; i >= 0; --i) { exTextureInfo textureInfo = curEdit.textureInfos[i]; if (textureInfo == null) { curEdit.textureInfos.RemoveAt(i); } } for (int i = curEdit.bitmapFonts.Count - 1; i >= 0; --i) { exBitmapFont bitmapFont = curEdit.bitmapFonts[i]; if (bitmapFont == null) { curEdit.bitmapFonts.RemoveAt(i); } } for (int i = selectedObjects.Count - 1; i >= 0; --i) { Object obj = selectedObjects[i]; if (obj == null) { selectedObjects.RemoveAt(i); } } Repaint(); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void CreateNewBitmapFont(string _path, string _name, Object _fontInfo) { try { // create atlas info EditorUtility.DisplayProgressBar("Creating BitmapFont...", "Creating BitmapFont Asset...", 0.1f); // check if there have exBitmapFont bitmapFont = exBitmapFontUtility.Create(_path, _name); // check if we have the texture and textasset with the same name of bitmapfont EditorUtility.DisplayProgressBar("Creating BitmapFont...", "Check building ...", 0.2f); // if we have enough information, try to build the exBitmapFont asset bitmapFont.Build(_fontInfo); EditorUtility.ClearProgressBar(); // Selection.activeObject = bitmapFont; EditorGUIUtility.PingObject(bitmapFont); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } }
// ------------------------------------------------------------------ /// \param _obj /// Check if the object is valid bitmap font and open it in bitmap font editor. // ------------------------------------------------------------------ public void Edit( Object _obj ) { // check if repaint if ( curEdit != _obj ) { // check if we have exBitmapFont in the same directory Object obj = _obj; if ( obj != null ) { string assetPath = AssetDatabase.GetAssetPath(obj); if ( string.IsNullOrEmpty(assetPath) == false ) { string dirname = Path.GetDirectoryName(assetPath); string filename = Path.GetFileNameWithoutExtension(assetPath); obj = (exBitmapFont)AssetDatabase.LoadAssetAtPath( Path.Combine( dirname, filename ) + ".asset", typeof(exBitmapFont) ); } if ( obj == null ) { obj = _obj; } } // if this is another bitmapfont, swtich to it. if ( obj is exBitmapFont && obj != curEdit ) { curEdit = obj as exBitmapFont; Init(); Repaint (); return; } } }
// ------------------------------------------------------------------ /// \param _obj /// Check if the object is valid bitmap font and open it in bitmap font editor. // ------------------------------------------------------------------ public void Edit(Object _obj) { // check if repaint if (curEdit != _obj) { // check if we have exBitmapFont in the same directory Object obj = _obj; if (obj != null) { string assetPath = AssetDatabase.GetAssetPath(obj); if (string.IsNullOrEmpty(assetPath) == false) { string dirname = Path.GetDirectoryName(assetPath); string filename = Path.GetFileNameWithoutExtension(assetPath); obj = (exBitmapFont)AssetDatabase.LoadAssetAtPath(Path.Combine(dirname, filename) + ".asset", typeof(exBitmapFont)); } if (obj == null) { obj = _obj; } } // if this is another bitmapfont, swtich to it. if (obj is exBitmapFont && obj != curEdit) { curEdit = obj as exBitmapFont; Init(); Repaint(); return; } } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void UpdateSelection() { if (curEdit != null) { bool needRepaint = false; selectedObjects.Clear(); foreach (Object obj in Selection.objects) { exTextureInfo textureInfo = obj as exTextureInfo; if (textureInfo != null && curEdit.textureInfos.IndexOf(textureInfo) != -1) { selectedObjects.Add(textureInfo); needRepaint = true; } exBitmapFont bitmapFont = obj as exBitmapFont; if (bitmapFont != null && curEdit.bitmapFonts.IndexOf(bitmapFont) != -1) { selectedObjects.Add(bitmapFont); needRepaint = true; } } if (needRepaint) { Repaint(); } } }
// ------------------------------------------------------------------ /// \param _path the directory path to save the atlas /// \param _name the name of the atlas /// \return the bitmap font /// create the bitmap font in the _path, save it as _name. // ------------------------------------------------------------------ public static exBitmapFont Create(string _path, string _name) { // if (new DirectoryInfo(_path).Exists == false) { Debug.LogError("can't create asset, path not found"); return(null); } if (string.IsNullOrEmpty(_name)) { Debug.LogError("can't create asset, the name is empty"); return(null); } string assetPath = Path.Combine(_path, _name + ".asset"); exBitmapFont newBitmapFont = null; FileInfo fileInfo = new FileInfo(assetPath); if (fileInfo.Exists) { newBitmapFont = (exBitmapFont)AssetDatabase.LoadAssetAtPath(assetPath, typeof(exBitmapFont)); } else { newBitmapFont = ScriptableObject.CreateInstance <exBitmapFont>(); AssetDatabase.CreateAsset(newBitmapFont, assetPath); } // Selection.activeObject = newBitmapFont; return(newBitmapFont); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void ProcessEvents() { int controlID = GUIUtility.GetControlID(exAtlasEditorHash, FocusType.Passive); Event e = Event.current; switch (e.GetTypeForControl(controlID)) { case EventType.ScrollWheel: if (e.control) { curEdit.scale += -e.delta.y * 0.1f; Repaint(); e.Use(); } break; case EventType.KeyDown: if (e.keyCode == KeyCode.Backspace || e.keyCode == KeyCode.Delete) { if (selectedObjects.Count > 0) { AssetDatabase.StartAssetEditing(); foreach (Object obj in selectedObjects) { exTextureInfo textureInfo = obj as exTextureInfo; if (textureInfo) { int i = curEdit.textureInfos.IndexOf(textureInfo); if (i != -1) { curEdit.textureInfos.RemoveAt(i); curEdit.needRebuild = true; AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(textureInfo)); } } exBitmapFont bitmapFont = obj as exBitmapFont; if (bitmapFont) { int i = curEdit.bitmapFonts.IndexOf(bitmapFont); if (i != -1) { curEdit.bitmapFonts.RemoveAt(i); curEdit.needRebuild = true; AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(bitmapFont)); } } } AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(curEdit)); AssetDatabase.StopAssetEditing(); selectedObjects.Clear(); Repaint(); e.Use(); } } break; } }
// ------------------------------------------------------------------ /// Clear the text, fontInfo, material and mesh of the sprite font, make it empty // ------------------------------------------------------------------ public void Clear() { fontInfo_ = null; if (GetComponent <Renderer>() != null) { GetComponent <Renderer>().sharedMaterial = null; } if (meshFilter) { DestroyImmediate(meshFilter_.sharedMesh, true); meshFilter_.sharedMesh = null; } }
// ------------------------------------------------------------------ /// Clear the text, fontInfo, material and mesh of the sprite font, make it empty // ------------------------------------------------------------------ public void Clear() { fontInfo_ = null; if (renderer != null) { renderer.sharedMaterial = null; } if (meshFilter) { DestroyImmediate(meshFilter_.sharedMesh, true); meshFilter_.sharedMesh = null; } }
public static exSpriteFont NewSpriteFont(GameObject _go, exBitmapFont _font, Color _color, string _text) { exSpriteFont spriteFont = _go.GetComponent <exSpriteFont>(); if (spriteFont == null) { spriteFont = _go.AddComponent <exSpriteFont>(); } if (spriteFont.shader == null) { spriteFont.shader = Shader.Find("ex2D/Alpha Blended"); } spriteFont.SetFont(_font); spriteFont.color = _color; spriteFont.text = _text; return(spriteFont); }
// ------------------------------------------------------------------ /// \param _fontInfo the font info you want to remove /// Find and remove the font info from the atlas // ------------------------------------------------------------------ public void RemoveBitmapFont(exBitmapFont _fontInfo) { for (int i = 0; i < elements.Count; ++i) { exAtlasInfo.Element el = elements[i]; if (el.isFontElement == false) { continue; } if (el.destFontInfo == _fontInfo) { RemoveElement(el); --i; } } bitmapFonts.Remove(_fontInfo); EditorUtility.SetDirty(this); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ public override void OnInspectorGUI() { DrawDefaultInspector(); EditorGUILayout.Space(); exBitmapFont bitmapFont = target as exBitmapFont; Object oldRef = exEditorUtility.LoadAssetFromGUID <Object>(bitmapFont.rawFontGUID); Object newRef = EditorGUILayout.ObjectField("Import Data" , oldRef , typeof(Object) , false); if (oldRef != newRef) { bitmapFont.rawFontGUID = exEditorUtility.AssetToGUID(newRef); } GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); // Select if (GUILayout.Button("Select...", GUILayout.Width(60), GUILayout.Height(20))) { Object obj = exEditorUtility.LoadAssetFromGUID <Object>(bitmapFont.rawFontGUID); EditorGUIUtility.PingObject(obj); } // Rebuild if (GUILayout.Button("Rebuild...", GUILayout.Width(80), GUILayout.Height(20))) { if (exBitmapFontUtility.IsFontInfo(newRef) == false) { Debug.LogError("The file you choose to parse is not a font-info file. Must be \".txt\", \".fnt\" file"); return; } exBitmapFontUtility.Parse(bitmapFont, newRef); } GUILayout.Space(5); GUILayout.EndHorizontal(); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ protected Element AddFontElement(exBitmapFont _srcFontInfo, exBitmapFont _destFontInfo, exBitmapFont.CharInfo _charInfo) { exAtlasInfo.Element el = new exAtlasInfo.Element(); el.isFontElement = true; el.srcFontInfo = _srcFontInfo; el.destFontInfo = _destFontInfo; el.charInfo = _charInfo; el.trimRect = new Rect(_charInfo.x, _charInfo.y, _charInfo.width, _charInfo.height); el.rotated = false; el.trim = true; el.atlasInfo = this; el.texture = _srcFontInfo.pageInfos[0].texture; el.coord[0] = 0; el.coord[1] = 0; exBitmapFont.CharInfo destCharInfo = el.destFontInfo.GetCharInfo(el.charInfo.id); if (destCharInfo != null) { destCharInfo.id = el.charInfo.id; destCharInfo.x = el.charInfo.x; destCharInfo.y = el.charInfo.y; destCharInfo.width = el.charInfo.width; destCharInfo.height = el.charInfo.height; destCharInfo.xoffset = el.charInfo.xoffset; destCharInfo.yoffset = el.charInfo.yoffset; destCharInfo.xadvance = el.charInfo.xadvance; destCharInfo.page = el.charInfo.page; destCharInfo.uv0 = el.charInfo.uv0; } else { Debug.LogError("can't not find char info with ID " + el.charInfo.id); } elements.Add(el); needRebuild = true; EditorUtility.SetDirty(this); return(el); }
static void Create_BitmapFont_FromSelected() { Object fontInfo = Selection.activeObject; // font info is a ".txt" or ".fnt" text file // check if this is a font info if (exBitmapFontUtility.IsFontInfo(fontInfo) == false) { Debug.LogError("The file you choose to parse is not a font-info file. Must be \".txt\", \".fnt\" file"); return; } // check if the bitmapfont asset already exists string fontInfoPath = AssetDatabase.GetAssetPath(fontInfo); string dirPath = Path.GetDirectoryName(fontInfoPath); string path = Path.Combine(dirPath, fontInfo.name + ".asset"); FileInfo fileInfo = new FileInfo(path); bool doCreate = true; if (fileInfo.Exists) { doCreate = EditorUtility.DisplayDialog(fontInfo.name + " already exists.", "Do you want to overwrite the old one?", "Yes", "No"); } if (doCreate == false) { return; } // parse the bitmap font exBitmapFont bitmapFont = exGenericAssetUtility <exBitmapFont> .LoadExistsOrCreate(dirPath, fontInfo.name); bool result = exBitmapFontUtility.Parse(bitmapFont, fontInfo); if (result == false) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(bitmapFont)); return; } AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(bitmapFont)); Selection.activeObject = bitmapFont; }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ protected Element AddFontElement( exBitmapFont _srcFontInfo, exBitmapFont _destFontInfo, exBitmapFont.CharInfo _charInfo ) { exAtlasInfo.Element el = new exAtlasInfo.Element(); el.isFontElement = true; el.srcFontInfo = _srcFontInfo; el.destFontInfo = _destFontInfo; el.charInfo = _charInfo; el.trimRect = new Rect( _charInfo.x, _charInfo.y, _charInfo.width, _charInfo.height ); el.rotated = false; el.trim = true; el.atlasInfo = this; el.texture = _srcFontInfo.pageInfos[0].texture; el.coord[0] = 0; el.coord[1] = 0; exBitmapFont.CharInfo destCharInfo = el.destFontInfo.GetCharInfo(el.charInfo.id); if ( destCharInfo != null ) { destCharInfo.id = el.charInfo.id; destCharInfo.x = el.charInfo.x; destCharInfo.y = el.charInfo.y; destCharInfo.width = el.charInfo.width; destCharInfo.height = el.charInfo.height; destCharInfo.xoffset = el.charInfo.xoffset; destCharInfo.yoffset = el.charInfo.yoffset; destCharInfo.xadvance = el.charInfo.xadvance; destCharInfo.page = el.charInfo.page; destCharInfo.uv0 = el.charInfo.uv0; } else { Debug.LogError ( "can't not find char info with ID " + el.charInfo.id ); } elements.Add(el); needRebuild = true; EditorUtility.SetDirty(this); return el; }
// ------------------------------------------------------------------ /// \param _fontInfo the font info you want to remove /// Find and remove the font info from the atlas // ------------------------------------------------------------------ public void RemoveBitmapFont( exBitmapFont _fontInfo ) { for ( int i = 0; i < elements.Count; ++i ) { exAtlasInfo.Element el = elements[i]; if ( el.isFontElement == false ) continue; if ( el.destFontInfo == _fontInfo ) { RemoveElement (el); --i; } } bitmapFonts.Remove(_fontInfo); EditorUtility.SetDirty(this); }
// ------------------------------------------------------------------ // Desc: This only calculate result in one line // ------------------------------------------------------------------ public static void BuildTextLine(Vector3[] _vertices, Vector2[] _uvs, string _text, exBitmapFont _font, int _lineHeight, int _fontSize, int _wordSpacing, int _letterSpacing) { int cur_x = 0; int cur_y = 0; // for (int i = 0; i < _text.Length; ++i) { char cur_char = _text[i]; // NOTE: we skip new-line operation, since we believe this function only have one-line text if (cur_char == '\n') { continue; } // generate mesh exBitmapFont.CharInfo charInfo = _font.GetCharInfo(cur_char); if (charInfo != null) { int idx = 4 * i; float x = cur_x + charInfo.xoffset; float y = cur_y + charInfo.yoffset; Vector2 texelSize = _font.texture.texelSize; Vector2 start = new Vector2(charInfo.x * texelSize.x, charInfo.y * texelSize.y); Vector2 end = new Vector2((charInfo.x + charInfo.rotatedWidth) * texelSize.x, (charInfo.y + charInfo.rotatedHeight) * texelSize.y); // build vertices _vertices[idx + 0] = new Vector3(x, y, 0.0f); _vertices[idx + 1] = new Vector3(x + charInfo.width, y, 0.0f); _vertices[idx + 2] = new Vector3(x + charInfo.width, y + charInfo.height, 0.0f); _vertices[idx + 3] = new Vector3(x, y + charInfo.height, 0.0f); // build uv if (charInfo.rotated) { _uvs[idx + 0] = new Vector2(end.x, start.y); _uvs[idx + 1] = new Vector2(end.x, end.y); _uvs[idx + 2] = new Vector2(start.x, end.y); _uvs[idx + 3] = new Vector2(start.x, start.y); } else { _uvs[idx + 0] = new Vector2(start.x, end.y); _uvs[idx + 1] = new Vector2(end.x, end.y); _uvs[idx + 2] = new Vector2(end.x, start.y); _uvs[idx + 3] = new Vector2(start.x, start.y); } // advance x cur_x += (int)charInfo.xadvance + _letterSpacing; if (cur_char == ' ') { cur_x += _wordSpacing; } } } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ Rect MapCharInfo( Rect _atlasRect, exBitmapFont.CharInfo _charInfo ) { Rect rect = new Rect ( _charInfo.x * curEdit.scale, _charInfo.y * curEdit.scale, _charInfo.rotatedWidth * curEdit.scale, _charInfo.rotatedHeight * curEdit.scale ); rect.x = _atlasRect.x + rect.x; rect.y = _atlasRect.y + _atlasRect.height - rect.y - rect.height; rect = exGeometryUtility.Rect_FloorToInt(rect); return rect; }
/////////////////////////////////////////////////////////////////////////////// // Other Functions /////////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ public void SetFont(exBitmapFont _bitmapFont) { font_.Set(_bitmapFont); UpdateTexture(); }
// ------------------------------------------------------------------ /// Clear the text, fontInfo, material and mesh of the sprite font, make it empty // ------------------------------------------------------------------ public void Clear() { fontInfo_ = null; if ( renderer != null ) renderer.sharedMaterial = null; if ( meshFilter ) { DestroyImmediate( meshFilter_.sharedMesh, true ); meshFilter_.sharedMesh = null; } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ public static bool Parse(exBitmapFont _bitmapFont, Object _fontInfo) { _bitmapFont.Reset(); string fontInfoPath = AssetDatabase.GetAssetPath(_fontInfo); string dirname = Path.GetDirectoryName(fontInfoPath); string line; FileInfo fileInfo = new FileInfo(fontInfoPath); StreamReader reader = fileInfo.OpenText(); int textureHeight = -1; while ((line = reader.ReadLine()) != null) { string[] words = line.Split(' '); if (words[0] == "info") { _bitmapFont.size = int.Parse(ParseValue(words, "size")); } else if (words[0] == "common") { _bitmapFont.lineHeight = int.Parse(ParseValue(words, "lineHeight")); _bitmapFont.baseLine = int.Parse(ParseValue(words, "base")); // _bitmapFont.width = int.Parse ( ParseValue( words, "scaleW" ) ); // _bitmapFont.height = int.Parse ( ParseValue( words, "scaleH" ) ); int pages = int.Parse(ParseValue(words, "pages")); if (pages != 1) { Debug.LogError("Parse Error: only support one page"); return(false); } } else if (words[0] == "page") { // load texture from file string filename = ParseValue(words, "file"); filename = filename.Substring(1, filename.Length - 2); // remove the "" in "foobar.png" string texturePath = Path.Combine(dirname, filename); Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); if (texture == null) { Debug.LogError("Parse Failed: The texture " + filename + " not found."); return(false); } if (exEditorUtility.IsValidForBitmapFont(texture) == false) { exEditorUtility.ImportTextureForBitmapFont(texture); } textureHeight = texture.height; // add page info _bitmapFont.texture = texture; } else if (words[0] == "char") { exBitmapFont.CharInfo charInfo = new exBitmapFont.CharInfo(); charInfo.id = int.Parse(ParseValue(words, "id")); charInfo.width = int.Parse(ParseValue(words, "width")); charInfo.height = int.Parse(ParseValue(words, "height")); charInfo.trim_x = int.Parse(ParseValue(words, "x")); charInfo.trim_y = int.Parse(ParseValue(words, "y")); charInfo.xoffset = int.Parse(ParseValue(words, "xoffset")); charInfo.yoffset = int.Parse(ParseValue(words, "yoffset")); charInfo.xadvance = int.Parse(ParseValue(words, "xadvance")); charInfo.rotated = false; // charInfo.page = int.Parse ( ParseValue( words, "page" ) ); // add char info _bitmapFont.charInfos.Add(charInfo); } else if (words[0] == "kerning") { exBitmapFont.KerningInfo kerningInfo = new exBitmapFont.KerningInfo(); kerningInfo.first = int.Parse(ParseValue(words, "first")); kerningInfo.second = int.Parse(ParseValue(words, "second")); kerningInfo.amount = int.Parse(ParseValue(words, "amount")); _bitmapFont.kernings.Add(kerningInfo); } } reader.Close(); _bitmapFont.rawFontGUID = exEditorUtility.AssetToGUID(_fontInfo); _bitmapFont.rawTextureGUID = exEditorUtility.AssetToGUID(_bitmapFont.texture); // revert charInfo uv-y to fit the Unity's uv-coordination. foreach (exBitmapFont.CharInfo charInfo in _bitmapFont.charInfos) { charInfo.trim_y = textureHeight - (charInfo.trim_y + charInfo.height); charInfo.x = charInfo.trim_x; charInfo.y = charInfo.trim_y; } EditorUtility.SetDirty(_bitmapFont); return(true); }
// ------------------------------------------------------------------ /// Clear the text, fontInfo, material and mesh of the sprite font, make it empty // ------------------------------------------------------------------ public void Clear() { text_ = ""; fontInfo_ = null; if ( renderer != null ) renderer.sharedMaterial = null; if ( meshFilter == null ) meshFilter = GetComponent<MeshFilter>(); if ( meshFilter != null ) meshFilter.sharedMesh = null; }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void ParseFontInfo( exBitmapFont _bitmapFont, Object _fontInfo ) { EditorUtility.DisplayProgressBar( "Building BitmapFont...", "Parsing font info...", 0.1f ); string fontInfoPath = AssetDatabase.GetAssetPath(_fontInfo); string dirname = Path.GetDirectoryName(fontInfoPath); // TODO { // _bitmapFont.fontInfoGUIDs.Add(exEditorHelper.AssetToGUID(_fontInfo)); // } TODO end // DELME { // string[] lines = _textAsset.text.Split ('\n'); // foreach ( string line in lines ) { // } DELME end string line; FileInfo fileInfo = new FileInfo(fontInfoPath); StreamReader reader = fileInfo.OpenText(); while ( (line = reader.ReadLine()) != null ) { // DISABLE: it is too slow { // EditorUtility.DisplayProgressBar( "Building BitmapFont...", // "Parsing line " + i, // (float)i/(float)lines.Length ); // } DISABLE end string[] words = line.Split(' '); if ( words[0] == "info" ) { _bitmapFont.size = int.Parse ( ParseValue( words, "size" ) ); } else if ( words[0] == "common" ) { _bitmapFont.lineHeight = int.Parse ( ParseValue( words, "lineHeight" ) ); // _bitmapFont.width = int.Parse ( ParseValue( words, "scaleW" ) ); // _bitmapFont.height = int.Parse ( ParseValue( words, "scaleH" ) ); int pages = int.Parse( ParseValue( words, "pages" ) ); _bitmapFont.pageInfos = new List<exBitmapFont.PageInfo>(pages); for ( int i = 0; i < pages; ++i ) { _bitmapFont.pageInfos.Add(new exBitmapFont.PageInfo()); } // DISABLE { // if ( pages != 1 ) { // Debug.LogError ( "Parse Error: only support one page" ); // return; // } // } DISABLE end } else if ( words[0] == "page" ) { // check if id is valid int id = int.Parse ( ParseValue( words, "id" ) ); if ( id >= _bitmapFont.pageInfos.Count ) { Debug.LogError("Parse Failed: The page id is exceed the page number"); return; } // load texture from file string filename = ParseValue( words, "file" ); filename = filename.Substring( 1, filename.Length-2 ); // remove the "" in "foobar.png" string texturePath = Path.Combine( dirname, filename ); Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath( texturePath, typeof(Texture2D) ); if ( texture == null ) { Debug.LogError("Parse Failed: The texture " + filename + " not found."); return; } // load material, if not exists, create a new one. string filenameNoExt = Path.GetFileNameWithoutExtension(texturePath); string materialPath = Path.Combine( dirname, filenameNoExt ) + ".mat"; Material material = (Material)AssetDatabase.LoadAssetAtPath( materialPath, typeof(Material) ); if ( material == null ) { material = new Material( Shader.Find("ex2D/Alpha Blended") ); material.mainTexture = texture; AssetDatabase.CreateAsset( material, materialPath ); } // add page info _bitmapFont.pageInfos[id].texture = texture; _bitmapFont.pageInfos[id].material = material; } else if ( words[0] == "char" ) { exBitmapFont.CharInfo charInfo = new exBitmapFont.CharInfo(); charInfo.id = int.Parse ( ParseValue( words, "id" ) ); charInfo.x = int.Parse ( ParseValue( words, "x" ) ); charInfo.y = int.Parse ( ParseValue( words, "y" ) ); charInfo.width = int.Parse ( ParseValue( words, "width" ) ); charInfo.height = int.Parse ( ParseValue( words, "height" ) ); charInfo.xoffset = int.Parse ( ParseValue( words, "xoffset" ) ); charInfo.yoffset = int.Parse ( ParseValue( words, "yoffset" ) ); charInfo.xadvance = int.Parse ( ParseValue( words, "xadvance" ) ); charInfo.page = int.Parse ( ParseValue( words, "page" ) ); exBitmapFont.PageInfo pageInfo = _bitmapFont.pageInfos[charInfo.page]; charInfo.uv0 = new Vector2 ( (float)charInfo.x / pageInfo.texture.width, (pageInfo.texture.height - (float)charInfo.y - charInfo.height) / pageInfo.texture.height ); _bitmapFont.charInfos.Add(charInfo); } else if ( words[0] == "kerning" ) { exBitmapFont.KerningInfo kerningInfo = new exBitmapFont.KerningInfo(); kerningInfo.first = int.Parse ( ParseValue( words, "first" ) ); kerningInfo.second = int.Parse ( ParseValue( words, "second" ) ); kerningInfo.amount = int.Parse ( ParseValue( words, "amount" ) ); _bitmapFont.kernings.Add(kerningInfo); } } _bitmapFont.RebuildIdToCharInfoTable(); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ public static bool Parse( exBitmapFont _bitmapFont, Object _fontInfo ) { _bitmapFont.Reset(); string fontInfoPath = AssetDatabase.GetAssetPath(_fontInfo); string dirname = Path.GetDirectoryName(fontInfoPath); string line; FileInfo fileInfo = new FileInfo(fontInfoPath); StreamReader reader = fileInfo.OpenText(); int textureHeight = -1; while ( (line = reader.ReadLine()) != null ) { string[] words = line.Split(' '); if ( words[0] == "info" ) { _bitmapFont.size = int.Parse ( ParseValue( words, "size" ) ); } else if ( words[0] == "common" ) { _bitmapFont.lineHeight = int.Parse ( ParseValue( words, "lineHeight" ) ); _bitmapFont.baseLine = int.Parse ( ParseValue( words, "base" ) ); // _bitmapFont.width = int.Parse ( ParseValue( words, "scaleW" ) ); // _bitmapFont.height = int.Parse ( ParseValue( words, "scaleH" ) ); int pages = int.Parse( ParseValue( words, "pages" ) ); if ( pages != 1 ) { Debug.LogError ( "Parse Error: only support one page" ); return false; } } else if ( words[0] == "page" ) { // load texture from file string filename = ParseValue( words, "file" ); filename = filename.Substring( 1, filename.Length-2 ); // remove the "" in "foobar.png" string texturePath = Path.Combine( dirname, filename ); Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath( texturePath, typeof(Texture2D) ); if ( texture == null ) { Debug.LogError("Parse Failed: The texture " + filename + " not found."); return false; } if ( exEditorUtility.IsValidForBitmapFont(texture) == false ) { exEditorUtility.ImportTextureForBitmapFont(texture); } textureHeight = texture.height; // add page info _bitmapFont.texture = texture; } else if ( words[0] == "char" ) { exBitmapFont.CharInfo charInfo = new exBitmapFont.CharInfo(); charInfo.id = int.Parse ( ParseValue( words, "id" ) ); charInfo.width = int.Parse ( ParseValue( words, "width" ) ); charInfo.height = int.Parse ( ParseValue( words, "height" ) ); charInfo.trim_x = int.Parse ( ParseValue( words, "x" ) ); charInfo.trim_y = int.Parse ( ParseValue( words, "y" ) ); charInfo.xoffset = int.Parse ( ParseValue( words, "xoffset" ) ); charInfo.yoffset = int.Parse ( ParseValue( words, "yoffset" ) ); charInfo.xadvance = int.Parse ( ParseValue( words, "xadvance" ) ); charInfo.rotated = false; // charInfo.page = int.Parse ( ParseValue( words, "page" ) ); // add char info _bitmapFont.charInfos.Add(charInfo); } else if ( words[0] == "kerning" ) { exBitmapFont.KerningInfo kerningInfo = new exBitmapFont.KerningInfo(); kerningInfo.first = int.Parse ( ParseValue( words, "first" ) ); kerningInfo.second = int.Parse ( ParseValue( words, "second" ) ); kerningInfo.amount = int.Parse ( ParseValue( words, "amount" ) ); _bitmapFont.kernings.Add(kerningInfo); } } reader.Close(); _bitmapFont.rawFontGUID = exEditorUtility.AssetToGUID(_fontInfo); _bitmapFont.rawTextureGUID = exEditorUtility.AssetToGUID(_bitmapFont.texture); // revert charInfo uv-y to fit the Unity's uv-coordination. foreach ( exBitmapFont.CharInfo charInfo in _bitmapFont.charInfos ) { charInfo.trim_y = textureHeight - (charInfo.trim_y + charInfo.height); charInfo.x = charInfo.trim_x; charInfo.y = charInfo.trim_y; } EditorUtility.SetDirty(_bitmapFont); return true; }
// ------------------------------------------------------------------ /// \param _objects /// get the Texture2D and exBitmapFont from a list of objects, import them into atlas // ------------------------------------------------------------------ public void ImportObjects(Object[] _objects) { bool dirty = false; foreach (Object o in _objects) { if (o is Texture2D) { Texture2D t = o as Texture2D; exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(t); if (elInfo == null) { AddElement(t, trimElements); dirty = true; } else { Debug.LogError("The texture [" + t.name + "]" + " has already been added in atlas: " + AssetDatabase.GUIDToAssetPath(elInfo.guidAtlasInfo)); } } else if (o is exBitmapFont) { exBitmapFont f = o as exBitmapFont; if (f.inAtlas) { // NOTE: it is still possible we have atlas font in the obj list since we use Selection.GetFiltered(). continue; } // multi-page atlas font is forbit if (f.pageInfos.Count > 1) { Debug.LogError("Can't not create atlas font from " + f.name + ", it has multiple page info."); continue; } // check if we have resource in the project string assetPath = AssetDatabase.GetAssetPath(texture); string dirname = Path.GetDirectoryName(assetPath); string filename = Path.GetFileNameWithoutExtension(assetPath); string bitmapFontPath = Path.Combine(dirname, filename + " - " + f.name + ".asset"); exBitmapFont f2 = (exBitmapFont)AssetDatabase.LoadAssetAtPath(bitmapFontPath, typeof(exBitmapFont)); if (f2 == null) { f2 = (exBitmapFont)ScriptableObject.CreateInstance(typeof(exBitmapFont)); f2.inAtlas = true; f2.name = f.name; f2.lineHeight = f.lineHeight; // add page info exBitmapFont.PageInfo pageInfo = new exBitmapFont.PageInfo(); pageInfo.texture = texture; pageInfo.material = material; f2.pageInfos.Add(pageInfo); // add char info foreach (exBitmapFont.CharInfo c in f.charInfos) { exBitmapFont.CharInfo c2 = new exBitmapFont.CharInfo(c); f2.charInfos.Add(c2); } // add kerning info foreach (exBitmapFont.KerningInfo k in f.kernings) { f2.kernings.Add(k); } AssetDatabase.CreateAsset(f2, bitmapFontPath); // foreach (exBitmapFont.CharInfo c in f2.charInfos) { if (c.id == -1) { continue; } AddFontElement(f, f2, c); } } else { Debug.LogError("You already add the BitmapFont in this Atlas"); } // if (bitmapFonts.IndexOf(f2) == -1) { bitmapFonts.Add(f2); } dirty = true; } if (dirty) { EditorUtility.SetDirty(this); } } }
public static exSpriteFont NewSpriteFont( GameObject _go, exBitmapFont _font, Color _color, string _text ) { exSpriteFont spriteFont = _go.GetComponent<exSpriteFont>(); if ( spriteFont == null ) { spriteFont = _go.AddComponent<exSpriteFont>(); } if ( spriteFont.shader == null ) spriteFont.shader = Shader.Find("ex2D/Alpha Blended"); spriteFont.SetFont (_font); spriteFont.color = _color; spriteFont.text = _text; return spriteFont; }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void OnGUI() { EditorGUI.indentLevel = 0; if (curEdit == null) { GUILayout.Space(10); GUILayout.Label("Please select an Atlas Info"); // DISABLE: this.ShowNotification( new GUIContent("Please select an Atlas Info")); return; } // ======================================================== // toolbar // ======================================================== GUILayout.BeginHorizontal(EditorStyles.toolbar); GUILayout.FlexibleSpace(); // ======================================================== // Select // ======================================================== GUI.enabled = selectedElements.Count != 0; if (GUILayout.Button("Select In Project...", EditorStyles.toolbarButton)) { List <Object> selects = new List <Object>(curEdit.elements.Count); foreach (exAtlasInfo.Element el in selectedElements) { if (selects.IndexOf(el.texture) == -1) { selects.Add(el.texture); } } if (selects.Count != 0) { selectIdx = (selectIdx + 1) % selects.Count; Selection.objects = selects.ToArray(); EditorGUIUtility.PingObject(Selection.objects[selectIdx]); } } GUI.enabled = true; GUILayout.Space(5); // ======================================================== // zoom in/out slider // ======================================================== GUILayout.Label("Zoom"); GUILayout.Space(5); curEdit.scale = GUILayout.HorizontalSlider(curEdit.scale, 0.1f, 2.0f, GUILayout.MaxWidth(150)); GUILayout.Space(5); curEdit.scale = EditorGUILayout.FloatField(curEdit.scale, EditorStyles.toolbarTextField, GUILayout.Width(50)); curEdit.scale = Mathf.Clamp(curEdit.scale, 0.1f, 2.0f); // ======================================================== // Build // ======================================================== GUI.enabled = curEdit.needRebuild; if (GUILayout.Button("Build", EditorStyles.toolbarButton, GUILayout.Width(80))) { // build atlas info to atals exAtlasInfoUtility.Build(curEdit); // build sprite animclip that used this atlasInfo exAtlasInfoUtility.BuildSpAnimClipsFromRebuildList(curEdit); // update scene sprites List <string> rebuildAtlasInfos = new List <string>(); rebuildAtlasInfos.Add(exEditorHelper.AssetToGUID(curEdit)); exSceneHelper.UpdateSprites(rebuildAtlasInfos); // NOTE: without this you will got leaks message EditorUtility.UnloadUnusedAssets(); } GUI.enabled = true; // ======================================================== // Help // ======================================================== if (GUILayout.Button(exEditorHelper.HelpTexture(), EditorStyles.toolbarButton)) { Help.BrowseURL("http://www.ex-dev.com/ex2d/wiki/doku.php?id=manual:atlas_editor"); } GUILayout.EndHorizontal(); // ======================================================== // scroll view // ======================================================== float toolbarHeight = EditorStyles.toolbar.CalcHeight(new GUIContent(""), 0); scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Width(position.width), GUILayout.Height(position.height - toolbarHeight)); Rect lastRect = new Rect(10, 0, 1, 1); GUILayout.Space(5); // DISABLE { // // draw label // GUILayout.Label ( AssetDatabase.GetAssetPath(curEdit) ); // } DISABLE end // ======================================================== // atlas info // ======================================================== Object newAtlasInfo = EditorGUILayout.ObjectField("Atlas Info" , curEdit , typeof(exAtlasInfo) , false , GUILayout.Width(300) ); if (newAtlasInfo != curEdit) { Selection.activeObject = newAtlasInfo; } // ======================================================== // settings area // ======================================================== GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayout.MaxWidth(200)); // ======================================================== // canvas // ======================================================== curEdit.foldCanvas = EditorGUILayout.Foldout(curEdit.foldCanvas, "Canvas"); if (curEdit.foldCanvas) { GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); // width and height int width = curEdit.width; int height = curEdit.height; WidthAndHeightField(ref width, ref height); // Check if we need to Reset width & height if (width != curEdit.width || height != curEdit.height) { curEdit.width = width; curEdit.height = height; if (curEdit.texture) { // NOTE: if we don't write data to disk, all changes will go back. string path = AssetDatabase.GetAssetPath(curEdit.texture); exTextureHelper.SetReadable(curEdit.texture, true); curEdit.texture.Resize(width, height); curEdit.ClearAtlasTexture(); // NOTE: we can not write back directly since the texture format problem Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false); for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { tex.SetPixel(i, j, new Color(1.0f, 1.0f, 1.0f, 0.0f)); } } tex.Apply(false); byte[] pngData = tex.EncodeToPNG(); if (pngData != null) { File.WriteAllBytes(path, pngData); } Object.DestroyImmediate(tex); TextureImporter importSettings = TextureImporter.GetAtPath(path) as TextureImporter; importSettings.maxTextureSize = Mathf.Max(width, height); importSettings.wrapMode = TextureWrapMode.Clamp; importSettings.isReadable = curEdit.readable; AssetDatabase.ImportAsset(path); } curEdit.needRebuild = true; } curEdit.bgColor = EditorGUILayout.ColorField("Bg Color", curEdit.bgColor); curEdit.showCheckerboard = EditorGUILayout.Toggle("Show Checkerboard", curEdit.showCheckerboard); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.Space(20); // ======================================================== // layout // ======================================================== curEdit.foldLayout = EditorGUILayout.Foldout(curEdit.foldLayout, "Layout"); if (curEdit.foldLayout) { GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); // algorithm curEdit.algorithm = (exAtlasInfo.Algorithm)EditorGUILayout.EnumPopup("Algorithm", curEdit.algorithm); // sortBy curEdit.sortBy = (exAtlasInfo.SortBy)EditorGUILayout.EnumPopup("Sort By", curEdit.sortBy); // sortOrder curEdit.sortOrder = (exAtlasInfo.SortOrder)EditorGUILayout.EnumPopup("Sort Order", curEdit.sortOrder); // padding curEdit.paddingMode = (exAtlasInfo.PaddingMode)EditorGUILayout.EnumPopup("Padding", curEdit.paddingMode); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUI.enabled = (curEdit.paddingMode == exAtlasInfo.PaddingMode.Custom); curEdit.customPadding = Math.Max(EditorGUILayout.IntField("Pixels", curEdit.actualPadding), 0); // Clamp to 0 GUI.enabled = true; GUILayout.EndHorizontal(); // TODO: have bug, just disable it { // allow rotate GUI.enabled = false; curEdit.allowRotate = false; curEdit.allowRotate = EditorGUILayout.Toggle("Allow Rotate", curEdit.allowRotate); GUI.enabled = true; // } TODO end if (GUILayout.Button("Apply")) { try { EditorUtility.DisplayProgressBar("Layout Elements...", "Layout Elements...", 0.5f); // register undo Undo.RegisterUndo(curEdit, "Apply.LayoutElements"); curEdit.LayoutElements(); EditorUtility.ClearProgressBar(); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } } // GUI.enabled = true; GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.Space(20); // ======================================================== // Element // ======================================================== curEdit.foldElement = EditorGUILayout.Foldout(curEdit.foldElement, "Element"); if (curEdit.foldElement) { GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); // sprite background color curEdit.elementBgColor = EditorGUILayout.ColorField("Bg Color", curEdit.elementBgColor); curEdit.elementSelectColor = EditorGUILayout.ColorField("Select Color", curEdit.elementSelectColor); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.Space(40); // ======================================================== // atlas texture and material // ======================================================== GUILayout.BeginHorizontal(); GUILayout.Space(10); GUILayout.BeginVertical(); GUI.enabled = false; string assetPath = AssetDatabase.GetAssetPath(curEdit); string dir = Path.GetDirectoryName(assetPath); // ======================================================== // texture // ======================================================== if (curEdit.texture) { curEdit.texture = (Texture2D)EditorGUILayout.ObjectField("Texture" , curEdit.texture , typeof(Texture2D) , false , GUILayout.Width(100) , GUILayout.Height(100) ); } else { GUI.enabled = true; if (GUILayout.Button("Create Texture...")) { // create texture Texture2D tex = new Texture2D(curEdit.width, curEdit.height, TextureFormat.ARGB32, false); for (int i = 0; i < curEdit.width; ++i) { for (int j = 0; j < curEdit.height; ++j) { tex.SetPixel(i, j, new Color(1.0f, 1.0f, 1.0f, 0.0f)); } } tex.Apply(false); // save texture to png string atlasTexturePath = Path.Combine(dir, curEdit.atlasName + ".png"); byte[] pngData = tex.EncodeToPNG(); if (pngData != null) { File.WriteAllBytes(atlasTexturePath, pngData); } Object.DestroyImmediate(tex); // import texture AssetDatabase.ImportAsset(atlasTexturePath); TextureImporter importSettings = TextureImporter.GetAtPath(atlasTexturePath) as TextureImporter; importSettings.maxTextureSize = Mathf.Max(curEdit.width, curEdit.height); importSettings.textureFormat = TextureImporterFormat.AutomaticTruecolor; importSettings.isReadable = true; importSettings.wrapMode = TextureWrapMode.Clamp; importSettings.mipmapEnabled = false; importSettings.textureType = TextureImporterType.Default; importSettings.npotScale = TextureImporterNPOTScale.None; AssetDatabase.ImportAsset(atlasTexturePath); curEdit.texture = (Texture2D)AssetDatabase.LoadAssetAtPath(atlasTexturePath, typeof(Texture2D)); if (curEdit.material) { curEdit.material.mainTexture = curEdit.texture; } EditorUtility.SetDirty(curEdit); } GUI.enabled = false; } // GUILayout.Space(5); // ======================================================== // material // ======================================================== if (curEdit.material) { curEdit.material = (Material)EditorGUILayout.ObjectField("Material" , curEdit.material , typeof(Material) , false ); } else { GUI.enabled = true; if (GUILayout.Button("Create Material...")) { Material newMaterial = new Material(Shader.Find("ex2D/Alpha Blended")); AssetDatabase.CreateAsset(newMaterial, Path.Combine(dir, curEdit.atlasName + ".mat")); curEdit.material = newMaterial; curEdit.material.mainTexture = curEdit.texture; EditorUtility.SetDirty(curEdit); } GUI.enabled = false; } // GUILayout.Space(5); // ======================================================== // atlas // ======================================================== if (curEdit.atlas) { curEdit.atlas = (exAtlas)EditorGUILayout.ObjectField("Atlas" , curEdit.atlas , typeof(exAtlas) , false ); } else { GUI.enabled = true; if (GUILayout.Button("Create Atlas...")) { exAtlas newAtlas = exAtlasInfoUtility.CreateAtlas(dir, curEdit.atlasName); curEdit.atlas = newAtlas; EditorUtility.SetDirty(curEdit); } GUI.enabled = false; } GUI.enabled = true; // GUILayout.Space(5); // ======================================================== // build color // ======================================================== GUILayout.BeginHorizontal(); bool newUseBuildColor = GUILayout.Toggle(curEdit.useBuildColor, "Use Build Color"); if (newUseBuildColor != curEdit.useBuildColor) { curEdit.useBuildColor = newUseBuildColor; curEdit.needRebuild = true; GUI.changed = true; } GUI.enabled = curEdit.useBuildColor; Color newBuildColor = EditorGUILayout.ColorField(curEdit.buildColor); if (newBuildColor != curEdit.buildColor) { curEdit.buildColor = newBuildColor; curEdit.needRebuild = true; GUI.changed = true; } GUI.enabled = true; GUILayout.EndHorizontal(); // ======================================================== // contour bleed // ======================================================== GUI.enabled = !curEdit.useBuildColor; GUILayout.BeginHorizontal(); bool newUseContourBleed = GUILayout.Toggle(curEdit.useContourBleed, new GUIContent("Use Contour Bleed", "Prevents artifacts around the silhouette of artwork due to bilinear filtering (requires Build Color to be turned off)")) && !curEdit.useBuildColor; if (newUseContourBleed != curEdit.useContourBleed) { curEdit.useContourBleed = newUseContourBleed; curEdit.needRebuild = true; GUI.changed = true; } GUILayout.EndHorizontal(); GUI.enabled = true; // ======================================================== // padding bleed // ======================================================== GUI.enabled = (curEdit.paddingMode == exAtlasInfo.PaddingMode.Auto) || (curEdit.actualPadding >= 2); GUILayout.BeginHorizontal(); bool newUsePaddingBleed = GUILayout.Toggle(curEdit.usePaddingBleed, new GUIContent("Use Padding Bleed", "Prevents artifacts and seams around the outer bounds of a texture due to bilinear filtering (requires at least Padding of 2)")) && GUI.enabled; if (newUsePaddingBleed != curEdit.usePaddingBleed) { curEdit.usePaddingBleed = newUsePaddingBleed; curEdit.needRebuild = true; GUI.changed = true; } GUILayout.EndHorizontal(); GUI.enabled = true; // ======================================================== // trim elements // ======================================================== bool newTrimElements = GUILayout.Toggle(curEdit.trimElements, "Trimmed Elements"); if (newTrimElements != curEdit.trimElements) { curEdit.trimElements = newTrimElements; foreach (exAtlasInfo.Element el in curEdit.elements) { curEdit.UpdateElement(el.texture, newTrimElements); } curEdit.needRebuild = true; GUI.changed = true; } // ======================================================== // readable // ======================================================== bool newReadable = GUILayout.Toggle(curEdit.readable, "Read/Write Enabled"); if (newReadable != curEdit.readable) { curEdit.readable = newReadable; GUI.changed = true; exTextureHelper.SetReadable(curEdit.texture, curEdit.readable); } // ======================================================== // bitmap fonts // ======================================================== GUILayout.Space(20); GUILayout.Label("Atlas Fonts"); for (int i = 0; i < curEdit.bitmapFonts.Count; ++i) { GUILayout.BeginHorizontal(); exBitmapFont bmfont = curEdit.bitmapFonts[i]; EditorGUILayout.ObjectField(bmfont , typeof(exBitmapFont) , false ); if (GUILayout.Button("Delete", GUILayout.MaxWidth(80))) { curEdit.RemoveBitmapFont(bmfont); AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(bmfont)); --i; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); // ======================================================== // space // ======================================================== GUILayout.Space(40); lastRect = GUILayoutUtility.GetLastRect(); // ======================================================== // atlas area // ======================================================== GUILayout.BeginVertical(); GUILayout.Space(10); // exAtlas Border and Background lastRect = GUILayoutUtility.GetLastRect(); int borderSize = 1; atlasInfoRect = new Rect(lastRect.xMax + borderSize, lastRect.yMax + borderSize, curEdit.width * curEdit.scale, curEdit.height * curEdit.scale); AtlasInfoField(atlasInfoRect, borderSize, curEdit); GUILayout.EndVertical(); GUILayout.EndHorizontal(); // ======================================================== // draw select rect // ======================================================== if (inRectSelectState && (selectRect.width != 0.0f || selectRect.height != 0.0f)) { exEditorHelper.DrawRect(selectRect, new Color(0.0f, 0.5f, 1.0f, 0.2f), new Color(0.0f, 0.5f, 1.0f, 1.0f)); } // ======================================================== Event e = Event.current; // ======================================================== // mouse down if (e.type == EventType.MouseDown && e.button == 0 && e.clickCount == 1) { GUIUtility.keyboardControl = -1; // remove any keyboard control mouseDownPos = e.mousePosition; inRectSelectState = true; UpdateSelectRect(); ConfirmRectSelection(); Repaint(); e.Use(); } // rect select if (inRectSelectState) { if (e.type == EventType.MouseDrag) { UpdateSelectRect(); ConfirmRectSelection(); Repaint(); e.Use(); } else if (e.type == EventType.MouseUp && e.button == 0) { inRectSelectState = false; ConfirmRectSelection(); Repaint(); e.Use(); } } // dragging selected if (inDraggingElementState) { if (e.type == EventType.MouseDrag) { MoveSelections(e.delta / curEdit.scale); Repaint(); e.Use(); } else if (e.type == EventType.MouseUp && e.button == 0) { if (curEdit.needUpdateAnimClips) { foreach (exAtlasInfo.Element el in selectedElements) { curEdit.AddSpriteAnimClipForRebuilding(el); } curEdit.needUpdateAnimClips = false; } inDraggingElementState = false; accDeltaMove = Vector2.zero; e.Use(); } } // key events if (e.isKey) { if (e.type == EventType.KeyDown) { if (e.keyCode == KeyCode.Backspace || e.keyCode == KeyCode.Delete) { RemoveSelectedElements(); Repaint(); e.Use(); } } } EditorGUILayout.EndScrollView(); // ======================================================== // do imports // ======================================================== if (doImport) { doImport = false; ImportObjects(); Selection.activeObject = oldSelActiveObject; Selection.objects = oldSelObjects.ToArray(); oldSelObjects.Clear(); oldSelActiveObject = null; Repaint(); } // if (GUI.changed) { EditorUtility.SetDirty(curEdit); } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ public override void OnInspectorGUI() { // ======================================================== // Base GUI // ======================================================== base.OnInspectorGUI(); GUILayout.Space(20); // ======================================================== // // ======================================================== // DELME { // bool needRebuild = false; // } DELME end EditorGUIUtility.LookLikeInspector(); // ======================================================== // pt size // ======================================================== GUI.enabled = false; int pt_size = 0; if (editSpriteFont.fontInfo != null) { pt_size = editSpriteFont.fontInfo.size; } EditorGUILayout.IntField("Pt Size", pt_size); GUI.enabled = true; // ======================================================== // Use multiline // ======================================================== editSpriteFont.useMultiline = EditorGUILayout.Toggle("Use Multi-Line", editSpriteFont.useMultiline); // ======================================================== // text // ======================================================== GUI.enabled = !inAnimMode; if (editSpriteFont.useMultiline == false) { editSpriteFont.text = EditorGUILayout.TextField("Text", editSpriteFont.text); } else { EditorGUILayout.LabelField("Text"); editSpriteFont.text = EditorGUILayout.TextArea(editSpriteFont.text, EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).textArea); // EditorGUIUtility.LookLikeControls (); // EditorGUILayout.LabelField ( "Text", "" ); // GUILayout.BeginHorizontal(); // GUILayout.Space (30); // if ( Event.current.Equals ( Event.KeyboardEvent ("^return") ) || // Event.current.Equals ( Event.KeyboardEvent ("%return") ) ) // { // GUIUtility.keyboardControl = -1; // remove any keyboard control // Repaint(); // } // string newText = EditorGUILayout.TextArea ( editSpriteFont.text, GUILayout.Height(textAreaHeight + 3) ); // if ( newText != editSpriteFont.text ) { // editSpriteFont.text = newText; // long lines = exStringHelper.CountLinesInString(editSpriteFont.text); // textAreaHeight = lines * EditorStyles.textField.lineHeight; // } // GUILayout.Space (10); // GUILayout.EndHorizontal(); // EditorGUIUtility.LookLikeInspector (); } GUI.enabled = true; // ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ if (editSpriteFont.useMultiline) { GUILayout.BeginHorizontal(); GUILayout.Space(20); editSpriteFont.textAlign = (exSpriteFont.TextAlign)GUILayout.Toolbar((int)editSpriteFont.textAlign, textAlignStrings, GUILayout.Width(150)); GUILayout.EndHorizontal(); } // ======================================================== // font info // ======================================================== GUI.enabled = !inAnimMode; GUILayout.BeginHorizontal(); exBitmapFont newFontInfo = (exBitmapFont)EditorGUILayout.ObjectField("Font Info" , editSpriteFont.fontInfo , typeof(exBitmapFont) , false ); if (editSpriteFont.fontInfo != newFontInfo) { editSpriteFont.Clear(); // this will prevent leak of mesh editSpriteFont.fontInfo = newFontInfo; } if (GUILayout.Button("Edit...", GUILayout.Width(40), GUILayout.Height(15))) { exBitmapFontEditor editor = exBitmapFontEditor.NewWindow(); editor.Edit(editSpriteFont.fontInfo); } GUILayout.EndHorizontal(); GUI.enabled = true; // ======================================================== // use kerning // ======================================================== bool haveKerning = (editSpriteFont.fontInfo != null) && (editSpriteFont.fontInfo.kernings.Count != 0); GUI.enabled = !inAnimMode && haveKerning; editSpriteFont.useKerning = EditorGUILayout.Toggle("Use Kerning", editSpriteFont.useKerning); GUI.enabled = true; // ======================================================== // tracking // ======================================================== editSpriteFont.tracking = EditorGUILayout.FloatField("Tracking", editSpriteFont.tracking); // ======================================================== // line spacing // ======================================================== editSpriteFont.lineSpacing = EditorGUILayout.FloatField("Line Spacing", editSpriteFont.lineSpacing); /////////////////////////////////////////////////////////////////////////////// // normal color option /////////////////////////////////////////////////////////////////////////////// // ======================================================== // top color // ======================================================== editSpriteFont.topColor = EditorGUILayout.ColorField("Top Color", editSpriteFont.topColor); // ======================================================== // bot color // ======================================================== editSpriteFont.botColor = EditorGUILayout.ColorField("Bot Color", editSpriteFont.botColor); /////////////////////////////////////////////////////////////////////////////// // outline option /////////////////////////////////////////////////////////////////////////////// // ======================================================== // use outline // ======================================================== editSpriteFont.useOutline = EditorGUILayout.Toggle("Use Outline", editSpriteFont.useOutline); GUI.enabled = editSpriteFont.useOutline; ++EditorGUI.indentLevel; // ======================================================== // Outline Width // ======================================================== editSpriteFont.outlineWidth = EditorGUILayout.FloatField("Outline Width", editSpriteFont.outlineWidth); // ======================================================== // Outline Color // ======================================================== editSpriteFont.outlineColor = EditorGUILayout.ColorField("Outline Color", editSpriteFont.outlineColor); --EditorGUI.indentLevel; GUI.enabled = true; /////////////////////////////////////////////////////////////////////////////// // shadow option /////////////////////////////////////////////////////////////////////////////// editSpriteFont.useShadow = EditorGUILayout.Toggle("Use Shadow", editSpriteFont.useShadow); GUI.enabled = editSpriteFont.useShadow; ++EditorGUI.indentLevel; // ======================================================== // Shadow Bias // ======================================================== EditorGUILayout.LabelField("Shadow Bias", ""); ++EditorGUI.indentLevel; float newShadowBiasX = EditorGUILayout.FloatField("X", editSpriteFont.shadowBias.x); float newShadowBiasY = EditorGUILayout.FloatField("Y", editSpriteFont.shadowBias.y); if (newShadowBiasX != editSpriteFont.shadowBias.x || newShadowBiasY != editSpriteFont.shadowBias.y) { editSpriteFont.shadowBias = new Vector2(newShadowBiasX, newShadowBiasY); } --EditorGUI.indentLevel; // ======================================================== // Shadow Color // ======================================================== editSpriteFont.shadowColor = EditorGUILayout.ColorField("Shadow Color", editSpriteFont.shadowColor); --EditorGUI.indentLevel; GUI.enabled = true; // ======================================================== // Rebuild button // ======================================================== GUI.enabled = !inAnimMode; GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Rebuild...", GUILayout.Height(20))) { // needRebuild = true; } GUILayout.EndHorizontal(); GUI.enabled = true; GUILayout.Space(5); // if dirty, build it. if (!EditorApplication.isPlaying && !AnimationUtility.InAnimationMode()) { // DELME { // if ( needRebuild ) { // EditorUtility.ClearProgressBar(); // editSpriteFont.Build(); // } // else // } DELME end if (GUI.changed) { if (editSpriteFont.meshFilter.sharedMesh != null) { editSpriteFont.UpdateMesh(editSpriteFont.meshFilter.sharedMesh); } EditorUtility.SetDirty(editSpriteFont); } } }
// ------------------------------------------------------------------ // Desc: This only calculate result in one line // ------------------------------------------------------------------ public static void BuildTextLine( Vector3[] _vertices, Vector2[] _uvs, string _text, exBitmapFont _font, int _lineHeight, int _fontSize, int _wordSpacing, int _letterSpacing ) { int cur_x = 0; int cur_y = 0; // for ( int i = 0; i < _text.Length; ++i ) { char cur_char = _text[i]; // NOTE: we skip new-line operation, since we believe this function only have one-line text if ( cur_char == '\n' ) { continue; } // generate mesh exBitmapFont.CharInfo charInfo = _font.GetCharInfo(cur_char); if ( charInfo != null ) { int idx = 4*i; float x = cur_x + charInfo.xoffset; float y = cur_y + charInfo.yoffset; Vector2 texelSize = _font.texture.texelSize; Vector2 start = new Vector2( charInfo.x * texelSize.x, charInfo.y * texelSize.y ); Vector2 end = new Vector2( (charInfo.x + charInfo.rotatedWidth) * texelSize.x, (charInfo.y + charInfo.rotatedHeight) * texelSize.y ); // build vertices _vertices[idx + 0] = new Vector3(x, y, 0.0f); _vertices[idx + 1] = new Vector3(x + charInfo.width, y, 0.0f); _vertices[idx + 2] = new Vector3(x + charInfo.width, y + charInfo.height, 0.0f); _vertices[idx + 3] = new Vector3(x, y + charInfo.height, 0.0f); // build uv if ( charInfo.rotated ) { _uvs[idx + 0] = new Vector2(end.x, start.y); _uvs[idx + 1] = new Vector2(end.x, end.y); _uvs[idx + 2] = new Vector2(start.x, end.y); _uvs[idx + 3] = new Vector2(start.x, start.y); } else { _uvs[idx + 0] = new Vector2(start.x, end.y); _uvs[idx + 1] = new Vector2(end.x, end.y); _uvs[idx + 2] = new Vector2(end.x, start.y); _uvs[idx + 3] = new Vector2(start.x, start.y); } // advance x cur_x += (int)charInfo.xadvance + _letterSpacing; if ( cur_char == ' ' ) cur_x += _wordSpacing; } } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void ParseFontInfo(exBitmapFont _bitmapFont, Object _fontInfo) { EditorUtility.DisplayProgressBar("Building BitmapFont...", "Parsing font info...", 0.1f); string fontInfoPath = AssetDatabase.GetAssetPath(_fontInfo); string dirname = Path.GetDirectoryName(fontInfoPath); // TODO { // _bitmapFont.fontInfoGUIDs.Add(exEditorHelper.AssetToGUID(_fontInfo)); // } TODO end // DELME { // string[] lines = _textAsset.text.Split ('\n'); // foreach ( string line in lines ) { // } DELME end string line; FileInfo fileInfo = new FileInfo(fontInfoPath); StreamReader reader = fileInfo.OpenText(); while ((line = reader.ReadLine()) != null) { // DISABLE: it is too slow { // EditorUtility.DisplayProgressBar( "Building BitmapFont...", // "Parsing line " + i, // (float)i/(float)lines.Length ); // } DISABLE end string[] words = line.Split(' '); if (words[0] == "info") { _bitmapFont.size = int.Parse(ParseValue(words, "size")); } else if (words[0] == "common") { _bitmapFont.lineHeight = int.Parse(ParseValue(words, "lineHeight")); // _bitmapFont.width = int.Parse ( ParseValue( words, "scaleW" ) ); // _bitmapFont.height = int.Parse ( ParseValue( words, "scaleH" ) ); int pages = int.Parse(ParseValue(words, "pages")); _bitmapFont.pageInfos = new List <exBitmapFont.PageInfo>(pages); for (int i = 0; i < pages; ++i) { _bitmapFont.pageInfos.Add(new exBitmapFont.PageInfo()); } // DISABLE { // if ( pages != 1 ) { // Debug.LogError ( "Parse Error: only support one page" ); // return; // } // } DISABLE end } else if (words[0] == "page") { // check if id is valid int id = int.Parse(ParseValue(words, "id")); if (id >= _bitmapFont.pageInfos.Count) { Debug.LogError("Parse Failed: The page id is exceed the page number"); return; } // load texture from file string filename = ParseValue(words, "file"); filename = filename.Substring(1, filename.Length - 2); // remove the "" in "foobar.png" string texturePath = Path.Combine(dirname, filename); Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); if (texture == null) { Debug.LogError("Parse Failed: The texture " + filename + " not found."); return; } // load material, if not exists, create a new one. string filenameNoExt = Path.GetFileNameWithoutExtension(texturePath); string materialPath = Path.Combine(dirname, filenameNoExt) + ".mat"; Material material = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); if (material == null) { material = new Material(Shader.Find("ex2D/Alpha Blended")); material.mainTexture = texture; AssetDatabase.CreateAsset(material, materialPath); } // add page info _bitmapFont.pageInfos[id].texture = texture; _bitmapFont.pageInfos[id].material = material; } else if (words[0] == "char") { exBitmapFont.CharInfo charInfo = new exBitmapFont.CharInfo(); charInfo.id = int.Parse(ParseValue(words, "id")); charInfo.x = int.Parse(ParseValue(words, "x")); charInfo.y = int.Parse(ParseValue(words, "y")); charInfo.width = int.Parse(ParseValue(words, "width")); charInfo.height = int.Parse(ParseValue(words, "height")); charInfo.xoffset = int.Parse(ParseValue(words, "xoffset")); charInfo.yoffset = int.Parse(ParseValue(words, "yoffset")); charInfo.xadvance = int.Parse(ParseValue(words, "xadvance")); charInfo.page = int.Parse(ParseValue(words, "page")); exBitmapFont.PageInfo pageInfo = _bitmapFont.pageInfos[charInfo.page]; charInfo.uv0 = new Vector2((float)charInfo.x / pageInfo.texture.width, (pageInfo.texture.height - (float)charInfo.y - charInfo.height) / pageInfo.texture.height); _bitmapFont.charInfos.Add(charInfo); } else if (words[0] == "kerning") { exBitmapFont.KerningInfo kerningInfo = new exBitmapFont.KerningInfo(); kerningInfo.first = int.Parse(ParseValue(words, "first")); kerningInfo.second = int.Parse(ParseValue(words, "second")); kerningInfo.amount = int.Parse(ParseValue(words, "amount")); _bitmapFont.kernings.Add(kerningInfo); } } _bitmapFont.RebuildIdToCharInfoTable(); }
public static void DoInspectorGUI(exSpriteBaseInspector _inspector, SerializedProperty _textProp, SerializedProperty _textAlignProp, SerializedProperty _useKerningProp, SerializedProperty _wrapWordProp, SerializedProperty _lineHeightProp, SerializedProperty _customLineHeightProp, SerializedProperty _letterSpacingProp, SerializedProperty _wordSpacingProp, SerializedProperty _topColorProp, SerializedProperty _botColorProp) { _inspector.customSizeProp.boolValue = true; { // font exISpriteFont sp = _inspector.serializedObject.targetObject as exISpriteFont; if (sp != null) { EditorGUI.BeginChangeCheck(); exFont.TypeForEditor fontType = (exFont.TypeForEditor)EditorGUILayout.EnumPopup("Font Type", sp.fontType); int oldFontSize = sp.fontSize; if (EditorGUI.EndChangeCheck()) { sp.fontType = fontType; if (fontType == exFont.TypeForEditor.Dynamic) { if (sp.dynamicFont == null) { sp.SetFont(Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font); } sp.fontSize = oldFontSize; } EditorUtility.SetDirty(sp as Object); sp.lineHeight = sp.fontSize; // 自动重设行高 } EditorGUI.indentLevel++; if (fontType == exFont.TypeForEditor.Bitmap) { EditorGUI.BeginChangeCheck(); exBitmapFont font = EditorGUILayout.ObjectField("Font", sp.bitmapFont, typeof(exBitmapFont), false) as exBitmapFont; if (EditorGUI.EndChangeCheck()) { sp.SetFont(font); EditorUtility.SetDirty(sp as Object); sp.lineHeight = sp.fontSize; // 自动重设行高 } } else { EditorGUI.BeginChangeCheck(); Font font = EditorGUILayout.ObjectField("Font", sp.dynamicFont, typeof(Font), false) as Font; if (EditorGUI.EndChangeCheck()) { sp.SetFont(font); EditorUtility.SetDirty(sp as Object); sp.lineHeight = sp.fontSize; // 自动重设行高 } EditorGUI.BeginChangeCheck(); var fontStyle = (FontStyle)EditorGUILayout.EnumPopup("Font Style", sp.fontStyle); var fontSize = EditorGUILayout.IntField("Font Size", sp.fontSize); //sp.lineHeight = EditorGUILayout.IntField("Line Height", sp.lineHeight); if (EditorGUI.EndChangeCheck()) { sp.fontStyle = fontStyle; sp.fontSize = fontSize; EditorUtility.SetDirty(sp as Object); } } EditorGUI.indentLevel--; } } // text EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_textProp, new GUIContent("Text")); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.text = _textProp.stringValue; EditorUtility.SetDirty(sp as Object); } } } // textAlign EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_textAlignProp, new GUIContent("Text Align")); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.textAlign = (TextAlignment)_textAlignProp.enumValueIndex; EditorUtility.SetDirty(sp as Object); } } } // useKerning EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_useKerningProp, new GUIContent("Use Kerning")); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.useKerning = _useKerningProp.boolValue; EditorUtility.SetDirty(obj); } } } // wrap word EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_wrapWordProp, new GUIContent("Wrap Word"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.wrapWord = _wrapWordProp.boolValue; EditorUtility.SetDirty(obj); } } } // custom line height EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_customLineHeightProp, new GUIContent("Custom Line Height"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.customLineHeight = _customLineHeightProp.boolValue; EditorUtility.SetDirty(obj); } } } if (_customLineHeightProp.boolValue) { EditorGUI.indentLevel++; // line height EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_lineHeightProp, new GUIContent("Line Height"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.lineHeight = _lineHeightProp.intValue; EditorUtility.SetDirty(obj); } } } EditorGUI.indentLevel--; } // letter spacing EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_letterSpacingProp, new GUIContent("Letter Spacing"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.letterSpacing = _letterSpacingProp.intValue; EditorUtility.SetDirty(obj); } } } // word spacing EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_wordSpacingProp, new GUIContent("Word Spacing"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.wordSpacing = _wordSpacingProp.intValue; EditorUtility.SetDirty(obj); } } } // topColor EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_topColorProp, new GUIContent("Top Color"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.topColor = _topColorProp.colorValue; EditorUtility.SetDirty(obj); } } } // botColor EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_botColorProp, new GUIContent("Bot Color"), true); if (EditorGUI.EndChangeCheck()) { foreach (Object obj in _inspector.serializedObject.targetObjects) { exISpriteFont sp = obj as exISpriteFont; if (sp != null) { sp.botColor = _botColorProp.colorValue; EditorUtility.SetDirty(obj); } } } }