// ------------------------------------------------------------------ /// \param _obj /// Check if the object is valid atlas and open it in atlas editor. // ------------------------------------------------------------------ public void Edit(Object _obj) { // check if repaint if (curEdit != _obj) { // check if we have atlas - editorinfo in the same directory Object obj = _obj; if (obj is exAtlas || obj is Texture2D || obj is Material) { string assetPath = AssetDatabase.GetAssetPath(obj); string dirname = Path.GetDirectoryName(assetPath); string filename = Path.GetFileNameWithoutExtension(assetPath); obj = (exAtlasInfo)AssetDatabase.LoadAssetAtPath(Path.Combine(dirname, filename + " - EditorInfo.asset"), typeof(exAtlasInfo)); if (obj == null) { obj = _obj; } } // if this is another atlas, swtich to it. if (obj is exAtlasInfo && obj != curEdit) { curEdit = obj as exAtlasInfo; Init(); Repaint(); return; } } }
// ------------------------------------------------------------------ /// \param _atlasInfo the atlas info /// build sprite animation clips from the exAtlasInfo.rebuildAnimClipGUIDs // ------------------------------------------------------------------ public static void BuildSpAnimClipsFromRebuildList(exAtlasInfo _atlasInfo) { try { EditorUtility.DisplayProgressBar("Building Sprite Animation Clips...", "Building Sprite Animation Clips...", 0.5f); for (int i = 0; i < _atlasInfo.rebuildAnimClipGUIDs.Count; ++i) { string guidAnimClip = _atlasInfo.rebuildAnimClipGUIDs[i]; exSpriteAnimClip sp = exEditorHelper.LoadAssetFromGUID <exSpriteAnimClip>(guidAnimClip); if (sp) { sp.editorNeedRebuild = true; sp.Build(); } } _atlasInfo.rebuildAnimClipGUIDs.Clear(); EditorUtility.ClearProgressBar(); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void CalculatePreviewScale() { // get the max width and max height float maxWidth = -1.0f; float maxHeight = -1.0f; foreach (exSpriteAnimClip.FrameInfo frameInfo in curEdit.frameInfos) { float fiWidth = 0.0f; float fiHeight = 0.0f; // exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(frameInfo.textureGUID); if (elInfo != null) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(elInfo.guidAtlasInfo); exAtlasInfo.Element el = atlasInfo.elements[elInfo.indexInAtlasInfo]; // fiWidth = el.trimRect.width; // fiHeight = el.trimRect.height; fiWidth = el.texture.width; fiHeight = el.texture.height; } else { string texturePath = AssetDatabase.GUIDToAssetPath(frameInfo.textureGUID); Texture2D tex2D = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); fiWidth = tex2D.width; fiHeight = tex2D.height; } // if (maxWidth <= fiWidth) { maxWidth = fiWidth; } if (maxHeight <= fiHeight) { maxHeight = fiHeight; } } // get the preview scale previewScale = 1.0f; float viewWidth = curEdit.editorPreviewSize; float viewHeight = curEdit.editorPreviewSize; if (maxWidth > viewWidth && maxHeight > viewHeight) { previewScale = Mathf.Min(viewWidth / maxWidth, viewHeight / maxHeight); } else if (maxWidth > viewWidth) { previewScale = viewWidth / maxWidth; } else if (maxHeight > viewHeight) { previewScale = viewHeight / maxHeight; } }
// ------------------------------------------------------------------ /// \param _a the atlas info you want to add /// add the atlas info to the atlas db // ------------------------------------------------------------------ public static void AddAtlasInfo( exAtlasInfo _a ) { Init(); string guid = exEditorHelper.AssetToGUID (_a); if ( db.atlasInfoGUIDs.Contains(guid) == false ) { db.atlasInfoGUIDs.Add(guid); for ( int i = 0; i < _a.elements.Count; ++i ) { ElementInfo elInfo = AddElementInfo( _a.elements[i], i); if ( elInfo != null ) db.elementInfos.Add(elInfo); } EditorUtility.SetDirty(db); } }
// ------------------------------------------------------------------ /// rebuild all atlas in the project // ------------------------------------------------------------------ public static void BuildAll() { if (db == null) { CreateDB(); } foreach (string guidAtlasInfo in db.atlasInfoGUIDs) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(guidAtlasInfo); exAtlasInfoUtility.Build(atlasInfo); atlasInfo = null; EditorUtility.UnloadUnusedAssetsIgnoreManagedReferences(); System.GC.Collect(); } }
// ------------------------------------------------------------------ /// \param _a the atlas info you want to add /// add the atlas info to the atlas db // ------------------------------------------------------------------ public static void AddAtlasInfo(exAtlasInfo _a) { Init(); string guid = exEditorHelper.AssetToGUID(_a); if (db.atlasInfoGUIDs.Contains(guid) == false) { db.atlasInfoGUIDs.Add(guid); for (int i = 0; i < _a.elements.Count; ++i) { ElementInfo elInfo = AddElementInfo(_a.elements[i], i); if (elInfo != null) { db.elementInfos.Add(elInfo); } } EditorUtility.SetDirty(db); } }
/////////////////////////////////////////////////////////////////////////////// // static /////////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------ /// \param _path the path of the directory you expect to save the atlas info /// \param _name the name of the atlas without extension you expect to save /// \return the new atlas info /// Create and save the atlas, atlas textures, atlas material and atlas info in the expect path then return it. // ------------------------------------------------------------------ public static exAtlasInfo 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"); // exAtlasInfo newAtlas = ScriptableObject.CreateInstance <exAtlasInfo>(); AssetDatabase.CreateAsset(newAtlas, assetPath); Selection.activeObject = newAtlas; return(newAtlas); }
// ------------------------------------------------------------------ /// \param _path the path start sync /// sync the atlas db file from the _path directory // ------------------------------------------------------------------ static void SyncDirectory(string _path) { // Process the list of files found in the directory. string [] files = Directory.GetFiles(_path, "*.asset"); foreach (string fileName in files) { exAtlasInfo atlasInfo = (exAtlasInfo)AssetDatabase.LoadAssetAtPath(fileName, typeof(exAtlasInfo)); if (atlasInfo) { AddAtlasInfo(atlasInfo); atlasInfo = null; EditorUtility.UnloadUnusedAssetsIgnoreManagedReferences(); System.GC.Collect(); } } // Recurse into subdirectories of this directory. string [] dirs = Directory.GetDirectories(_path); foreach (string dirName in dirs) { SyncDirectory(dirName); } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void FrameInfoField(Rect _rect, exSpriteAnimClip.FrameInfo _fi) { bool selected = selectedFrameInfos.IndexOf(_fi) != -1; exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(_fi.textureGUID); // ======================================================== // draw background // ======================================================== Color old = GUI.color; if (selected) { GUI.color = new Color(0.2f, 0.85f, 0.0f, 0.2f); } else if (elInfo == null) { GUI.color = new Color(1.0f, 0.0f, 0.0f, 0.2f); } else { GUI.color = new Color(1.0f, 0.0f, 0.85f, 0.2f); } GUI.DrawTexture(_rect, exEditorHelper.WhiteTexture()); GUI.color = old; // ======================================================== // draw texture // ======================================================== if (elInfo != null) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(elInfo.guidAtlasInfo); exAtlasInfo.Element el = atlasInfo.elements[elInfo.indexInAtlasInfo]; if (el.texture != null) { float width = el.texture.width; float height = el.texture.height; // get the scale float scale = 1.0f; if (width > _rect.width && height > _rect.height) { scale = Mathf.Min(_rect.width / width, _rect.height / height); } else if (width > _rect.width) { scale = _rect.width / width; } else if (height > _rect.height) { scale = _rect.height / height; } // draw Rect size = new Rect(-el.trimRect.x * scale, -el.trimRect.y * scale, width * scale, height * scale); GUI.BeginGroup(_rect); GUI.BeginGroup(new Rect((_rect.width - el.trimRect.width * scale) * 0.5f, (_rect.height - el.trimRect.height * scale) * 0.5f, el.trimRect.width * scale, el.trimRect.height * scale)); GUI.DrawTexture(size, el.texture); GUI.EndGroup(); GUI.EndGroup(); } } else { Texture2D tex2D = exEditorHelper.LoadAssetFromGUID <Texture2D>(_fi.textureGUID); if (tex2D != null) { float width = tex2D.width; float height = tex2D.height; // get the scale float scale = 1.0f; if (width > _rect.width && height > _rect.height) { scale = Mathf.Min(_rect.width / width, _rect.height / height); } else if (width > _rect.width) { scale = _rect.width / width; } else if (height > _rect.height) { scale = _rect.height / height; } // Rect size = new Rect(0.0f, 0.0f, width * scale, height * scale); Rect rect2 = new Rect((_rect.width - size.width) * 0.5f, (_rect.height - size.height) * 0.5f, size.width, size.height); // GUI.BeginGroup(_rect); GUI.BeginGroup(rect2); GUI.DrawTexture(size, tex2D); GUI.EndGroup(); GUI.EndGroup(); } } // ======================================================== // draw border // ======================================================== Color oldBGColor = GUI.backgroundColor; GUI.backgroundColor = Color.black; GUI.Box(_rect, GUIContent.none, exEditorHelper.RectBorderStyle()); GUI.backgroundColor = oldBGColor; }
// ------------------------------------------------------------------ /// \param _path the directory path to save the atlas info /// \param _name the name of the atlas info /// \param _width the width of the atlas texture /// \param _height the height of the atlas texture /// \return the atlas info /// create the atlas info in the _path, save it as _name. // ------------------------------------------------------------------ public static exAtlasInfo CreateAtlasInfo(string _path, string _name, int _width, int _height) { try { // create atlas info EditorUtility.DisplayProgressBar("Creating Atlas...", "Creating Atlas Asset...", 0.1f); exAtlasInfo newAtlasInfo = exAtlasInfo.Create(_path, _name + " - EditorInfo"); newAtlasInfo.width = _width; newAtlasInfo.height = _height; // create texture EditorUtility.DisplayProgressBar("Creating Atlas...", "Creating Atlas Texture...", 0.2f); Texture2D tex = new Texture2D(newAtlasInfo.width, newAtlasInfo.height, TextureFormat.ARGB32, false); Color32 buildColor = new Color(newAtlasInfo.buildColor.r, newAtlasInfo.buildColor.g, newAtlasInfo.buildColor.b, 0.0f); Color32[] colors = new Color32[newAtlasInfo.width * newAtlasInfo.height]; for (int i = 0; i < newAtlasInfo.width * newAtlasInfo.height; ++i) { colors[i] = buildColor; } tex.SetPixels32(colors); tex.Apply(false); // save texture to png EditorUtility.DisplayProgressBar("Creating Atlas...", "Saving Atlas Texture as PNG file...", 0.3f); string atlasTexturePath = Path.Combine(_path, _name + ".png"); byte[] pngData = tex.EncodeToPNG(); if (pngData != null) { File.WriteAllBytes(atlasTexturePath, pngData); } Object.DestroyImmediate(tex); AssetDatabase.ImportAsset(atlasTexturePath); // import texture EditorUtility.DisplayProgressBar("Creating Atlas...", "Import Texture " + atlasTexturePath + "...", 0.5f); TextureImporter importSettings = TextureImporter.GetAtPath(atlasTexturePath) as TextureImporter; importSettings.maxTextureSize = Mathf.Max(newAtlasInfo.width, newAtlasInfo.height); importSettings.textureFormat = TextureImporterFormat.AutomaticTruecolor; importSettings.wrapMode = TextureWrapMode.Clamp; // atlases should always be clamped, which allows to remove padding // around atlas and free up some pixel space importSettings.isReadable = false; importSettings.mipmapEnabled = false; importSettings.textureType = TextureImporterType.Advanced; importSettings.npotScale = TextureImporterNPOTScale.None; AssetDatabase.ImportAsset(atlasTexturePath); // create default material EditorUtility.DisplayProgressBar("Creating Atlas...", "Create New Material...", 0.7f); Material newMaterial = new Material(Shader.Find("ex2D/Alpha Blended")); AssetDatabase.CreateAsset(newMaterial, Path.Combine(_path, _name + ".mat")); // setup atlas info EditorUtility.DisplayProgressBar("Creating Atlas...", "Setup New Atlas Asset...", 0.9f); newAtlasInfo.atlasName = _name; newAtlasInfo.texture = (Texture2D)AssetDatabase.LoadAssetAtPath(atlasTexturePath, typeof(Texture2D)); newAtlasInfo.material = newMaterial; newAtlasInfo.material.mainTexture = newAtlasInfo.texture; // create new atlas and setup it for both atlas info and atlas asset exAtlas newAtlas = CreateAtlas(_path, _name); newAtlas.texture = newAtlasInfo.texture; newAtlas.material = newAtlasInfo.material; newAtlasInfo.atlas = newAtlas; // EditorUtility.SetDirty(newAtlasInfo); EditorUtility.UnloadUnusedAssets(); EditorUtility.ClearProgressBar(); // Selection.activeObject = newAtlasInfo; EditorGUIUtility.PingObject(newAtlasInfo); return(newAtlasInfo); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void FillAtlasTexture(Texture2D _tex, exAtlasInfo _atlasInfo, bool _noImport) { foreach (exAtlasInfo.Element el in _atlasInfo.elements) { // DISABLE: it is too slow { // EditorUtility.DisplayProgressBar( "Building Atlas...", // "Building Texture " + el.texture.name, // (float)i/(float)_atlasInfo.elements.Count - 0.1f ); // } DISABLE end Texture2D srcTexture = el.texture; int destX = el.coord[0]; if (el.isFontElement) { // build the font exBitmapFont.CharInfo charInfo = el.destFontInfo.GetCharInfo(el.charInfo.id); if (charInfo != null) { charInfo.uv0 = new Vector2((float)destX / _tex.width, (_tex.height - (float)el.coord[1] - charInfo.height) / _tex.height); EditorUtility.SetDirty(el.destFontInfo); } } // make the src texture readable if (exTextureHelper.IsValidForAtlas(srcTexture) == false) { if (_noImport) { Debug.LogError("The texture import settings of [" + AssetDatabase.GetAssetPath(srcTexture) + "] is invalid for atlas build"); continue; } else { exTextureHelper.ImportTextureForAtlas(srcTexture); } } // apply contour bleed if (_atlasInfo.useContourBleed) { srcTexture = exTextureHelper.ApplyContourBleed(srcTexture); } // copy element's texture into atlas texture int destY = _tex.height - el.coord[1] - el.Height(); exTextureHelper.Fill(_tex, new Vector2(destX, destY), srcTexture, el.trimRect, el.rotated ? exTextureHelper.RotateDirection.RotRight : exTextureHelper.RotateDirection.None, _atlasInfo.useBuildColor, _atlasInfo.buildColor); // apply padding bleed if (_atlasInfo.usePaddingBleed) { exTextureHelper.ApplyPaddingBleed(_tex, new Rect(destX, destY, el.trimRect.width, el.trimRect.height)); } // TODO { // Color32[] colors = srcTexture.GetPixels32(); // Color32[] colors_d = new Color32[_tex.width * _tex.height]; // for ( int r = 0; r < srcTexture.width; ++r ) { // for ( int c = 0; c < srcTexture.height; ++c ) { // colors_d[r+c*_tex.width] = colors[r+c*srcTexture.width]; // } // } // _tex.SetPixels32( colors_d ); // } TODO end } #if EX2D_EVALUATE // ======================================================== // Add water mark // ======================================================== // NOTE: onlly open it in evaluate version { // Make Water Make { // Texture2D texWaterMark = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/ex2D/Editor/Resource/water_mark.png", typeof(Texture2D)); // exTextureHelper.ImportTextureForAtlas(texWaterMark); // Color[] colors = texWaterMark.GetPixels(); // StreamWriter sw = new StreamWriter("Assets/TestFile.txt"); // Color32[] colors32 = texWaterMark.GetPixels32(); // for ( int r = 0; r < texWaterMark.height; ++r ) { // for ( int c = 0; c < texWaterMark.width; ++c ) { // Color32 cc = colors32[r*texWaterMark.width+c]; // sw.Write( "0x" + cc.r.ToString("X2") // + ", 0x" + cc.g.ToString("X2") // + ", 0x" + cc.b.ToString("X2") // + ", 0x" + cc.a.ToString("X2") // + ", " ); // } // sw.WriteLine(""); // } // sw.Close(); // } Make Water Make end int wa_width = 392; int wa_height = 40; Color[] colors = new Color[wa_width * wa_height]; for (int r = 0; r < wa_height; ++r) { for (int c = 0; c < wa_width; ++c) { colors[r * wa_width + c] = new Color(waterMark[(r * wa_width + c) * 4] / 255.0f, waterMark[(r * wa_width + c) * 4 + 1] / 255.0f, waterMark[(r * wa_width + c) * 4 + 2] / 255.0f, waterMark[(r * wa_width + c) * 4 + 3] / 255.0f); } } Color[] colors_d = _tex.GetPixels(); for (int r = 0; r < wa_height; ++r) { for (int c = 0; c < wa_width; ++c) { Color color_d = colors_d[r * _tex.width + c]; Color color = colors[r * wa_width + c]; // colors_d[r*_tex.width+(c+_tex.height-wa_height)] = colors_d[r * _tex.width + c] = color_d * (1.0f - color.a) + color * color.a; } } _tex.SetPixels(colors_d); // } NOTE end #endif // EX2D_EVALUATE _tex.Apply(false); }
// ------------------------------------------------------------------ /// \param _atlasInfo the atlas info /// \param _noImport if true, ex2D will not import the texture to fit for atlas /// build the atlas info to atlas // ------------------------------------------------------------------ public static void Build( exAtlasInfo _atlasInfo, bool _noImport = false ) { exAtlas atlas = _atlasInfo.atlas; Texture2D texture = _atlasInfo.texture; Material material = _atlasInfo.material; // check if the atlas info is valid for build if ( atlas == null ) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the atlas is missing!"); return; } if ( texture == null ) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the texture is missing!"); return; } if ( material == null ) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the material is missing!"); return; } // if ( _atlasInfo.needLayout ) { _atlasInfo.LayoutElements(); _atlasInfo.needLayout = false; } // create temp texture Color32 buildColor = new Color ( 0.0f, 0.0f, 0.0f, 0.0f ); if ( _atlasInfo.useBuildColor ) buildColor = new Color ( _atlasInfo.buildColor.r, _atlasInfo.buildColor.g, _atlasInfo.buildColor.b, 0.0f ); string path = AssetDatabase.GetAssetPath(texture); TextureImporter importer = TextureImporter.GetAtPath(path) as TextureImporter; // TextureImporterSettings textureImporterSettings = new TextureImporterSettings(); // importer.ReadTextureSettings(textureImporterSettings); // textureImporterSettings.readable = true; // importer.SetTextureSettings(textureImporterSettings); importer.wrapMode = TextureWrapMode.Clamp; importer.isReadable = true; AssetDatabase.ImportAsset( path ); Color32[] colors = new Color32[_atlasInfo.width*_atlasInfo.height]; for ( int i = 0; i < _atlasInfo.width * _atlasInfo.height; ++i ) colors[i] = buildColor; texture.SetPixels32( colors ); try { EditorUtility.DisplayProgressBar( "Building Atlas " + _atlasInfo.name, "Building Atlas...", 0.1f ); // build atlas texture _atlasInfo.elements.Sort( exAtlasInfo.CompareByName ); FillAtlasTexture ( texture, _atlasInfo, _noImport ); EditorUtility.DisplayProgressBar( "Building Atlas " + _atlasInfo.name, "Import Atlas", 0.9f ); // write to disk byte[] pngData = texture.EncodeToPNG(); if (pngData != null) File.WriteAllBytes(path, pngData); // now we finish atlas texture filling, we should turn off Read/Write settings, that will save memory a lot! TextureImporter importSettings = TextureImporter.GetAtPath(path) as TextureImporter; importSettings.wrapMode = TextureWrapMode.Clamp; importSettings.isReadable = _atlasInfo.readable; AssetDatabase.ImportAsset( path ); // atlas.elements = new exAtlas.Element[_atlasInfo.elements.Count]; for ( int i = 0; i < _atlasInfo.elements.Count; ++i ) { exAtlasInfo.Element el = _atlasInfo.elements[i]; exAtlas.Element el2 = new exAtlas.Element (); int coord_x = el.coord[0]; int coord_y = el.atlasInfo.height - el.coord[1] - (int)el.Height(); float xStart = (float)coord_x / (float)el.atlasInfo.width; float yStart = (float)coord_y / (float)el.atlasInfo.height; float xEnd = (float)(coord_x + el.Width()) / (float)el.atlasInfo.width; float yEnd = (float)(coord_y + el.Height()) / (float)el.atlasInfo.height; el2.name = el.texture.name; el2.coords = new Rect ( xStart, yStart, xEnd - xStart, yEnd - yStart ); el2.rotated = el.rotated; el2.originalWidth = el.texture.width; el2.originalHeight = el.texture.height; el2.trimRect = el.trimRect; atlas.elements[i] = el2; // update the index in exAtlasDB if ( el.isFontElement == false ) { exAtlasDB.UpdateElementInfo( el, i ); } } atlas.texture = texture; atlas.material = material; EditorUtility.SetDirty(atlas); EditorUtility.ClearProgressBar(); } catch ( System.Exception ) { EditorUtility.ClearProgressBar(); throw; } // save the needRebuild setting _atlasInfo.needRebuild = false; EditorUtility.SetDirty(_atlasInfo); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static ElementInfo AddElementInfo( exAtlasInfo.Element _el, int _index ) { Init(); if ( _el.isFontElement ) return null; string textureGUID = exEditorHelper.AssetToGUID(_el.texture); return AddElementInfo ( textureGUID, exEditorHelper.AssetToGUID(_el.atlasInfo.atlas), exEditorHelper.AssetToGUID(_el.atlasInfo), _index ); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void AtlasInfoField( Rect _rect, int _borderSize, exAtlasInfo _atlasInfo ) { Texture2D texCheckerboard = exEditorHelper.CheckerboardTexture(); float boxWidth = (float)_atlasInfo.width * _atlasInfo.scale + 2.0f * _borderSize; // box border float boxHeight = (float)_atlasInfo.height * _atlasInfo.scale + 2.0f * _borderSize; // box border Rect scaledRect = new Rect( _rect.x, _rect.y, boxWidth, boxHeight ); // ======================================================== // draw background textures // ======================================================== GUI.BeginGroup( new Rect(_rect.x, _rect.y, (float)_atlasInfo.width * _atlasInfo.scale, (float)_atlasInfo.height * _atlasInfo.scale) ); Color old = GUI.color; GUI.color = new Color ( _atlasInfo.bgColor.r, _atlasInfo.bgColor.g, _atlasInfo.bgColor.b, 1.0f ); if ( _atlasInfo.showCheckerboard ) { int col = Mathf.CeilToInt(_atlasInfo.width * _atlasInfo.scale / texCheckerboard.width); int row = Mathf.CeilToInt(_atlasInfo.height * _atlasInfo.scale / texCheckerboard.height); for ( int i = 0; i < col; ++i ) { for ( int j = 0; j < row; ++j ) { Rect size = new Rect( i * texCheckerboard.width, j * texCheckerboard.height, texCheckerboard.width, texCheckerboard.height ); GUI.DrawTexture( size, texCheckerboard ); } } } else { GUI.DrawTexture( new Rect( 0, 0, _atlasInfo.width * _atlasInfo.scale, _atlasInfo.height * _atlasInfo.scale ), exEditorHelper.WhiteTexture() ); } GUI.color = old; GUI.EndGroup(); // ======================================================== // draw the gui box // ======================================================== GUIContent bgContent = new GUIContent(); if ( _atlasInfo.elements.Count == 0 ) { bgContent.text = "Drag Textures On It"; bgContent.tooltip = "Drag Textures to create atlas"; } else { bgContent.text = ""; } Color oldBGColor = GUI.backgroundColor; GUI.backgroundColor = Color.black; GUI.Box ( new Rect( _rect.x - _borderSize, _rect.y - _borderSize, boxWidth, boxHeight), bgContent, exEditorHelper.RectBorderStyle() ); GUI.backgroundColor = oldBGColor; // ======================================================== // exAtlasInfo.Element // ======================================================== List<exAtlasInfo.Element> invalidElements = new List<exAtlasInfo.Element>(); foreach ( exAtlasInfo.Element el in _atlasInfo.elements ) { if ( el.texture == null ) { invalidElements.Add(el); continue; } if ( el.isFontElement && ( el.srcFontInfo == null || el.destFontInfo == null ) ) { invalidElements.Add(el); continue; } AtlasElementField ( scaledRect, _atlasInfo, el ); } foreach ( exAtlasInfo.Element el in invalidElements ) { _atlasInfo.RemoveElement(el); } // ======================================================== // handle drop event Event e = Event.current; // ======================================================== if ( scaledRect.Contains(e.mousePosition) ) { if ( e.type == EventType.DragUpdated ) { // Show a copy icon on the drag foreach ( Object o in DragAndDrop.objectReferences ) { if ( o is Texture2D || (o is exBitmapFont && (o as exBitmapFont).inAtlas == false) || exEditorHelper.IsDirectory(o) ) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; break; } } } else if ( e.type == EventType.DragPerform ) { DragAndDrop.AcceptDrag(); // NOTE: Unity3D have a problem in ImportTextureForAtlas, when a texture is an active selection, // no matter how you change your import settings, finally it will apply changes that in Inspector (shows when object selected) oldSelActiveObject = null; oldSelObjects.Clear(); foreach ( Object o in Selection.objects ) { oldSelObjects.Add(o); } oldSelActiveObject = Selection.activeObject; // NOTE: Selection.GetFiltered only affect on activeObject, but we may proceed non-active selections sometimes foreach ( Object o in DragAndDrop.objectReferences ) { if ( exEditorHelper.IsDirectory(o) ) { Selection.activeObject = o; // add Texture2D objects Object[] objs = Selection.GetFiltered( typeof(Texture2D), SelectionMode.DeepAssets); importObjects.AddRange(objs); // add exBitmapFont objects objs = Selection.GetFiltered( typeof(exBitmapFont), SelectionMode.DeepAssets); importObjects.AddRange(objs); } else if ( o is Texture2D || o is exBitmapFont ) { importObjects.Add(o); } } // Selection.activeObject = null; // doImport = true; Repaint(); } } // GUILayoutUtility.GetRect ( boxWidth, boxHeight ); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void AddSelected( exAtlasInfo.Element _el ) { if ( selectedElements.IndexOf(_el) == -1 ) { selectedElements.Add(_el); } }
// ------------------------------------------------------------------ /// \param _atlasInfoGUIDs the list of atlas info guid /// update sprites in current scene and in prefab by atlas info list // ------------------------------------------------------------------ public static void UpdateSprites(List <string> _atlasInfoGUIDs) { if (_atlasInfoGUIDs.Count == 0) { return; } try { EditorUtility.DisplayProgressBar("Update Scene Sprites With Changed Atlas...", "Scanning...", 0.0f); // exSpriteBase[] sprites = GameObject.FindObjectsOfType(typeof(exSpriteBase)) as exSpriteBase[]; exSpriteBase[] sprites = Resources.FindObjectsOfTypeAll(typeof(exSpriteBase)) as exSpriteBase[]; for (int i = 0; i < sprites.Length; ++i) { exSpriteBase spBase = sprites[i]; // ======================================================== // exSprite // ======================================================== if (spBase is exSprite) { exSprite sp = spBase as exSprite; exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(sp.textureGUID); bool needRebuild = false; // NOTE: we test sp.index is -1 or not instead of test atlas is null, because it is possible we delete an atlas and it will always be null if (elInfo != null) { if (sp.index == -1) { needRebuild = true; } else { // find if the sp's atalsInfo need rebuild foreach (string guidAtlasInfo in _atlasInfoGUIDs) { if (elInfo.guidAtlasInfo == guidAtlasInfo) { needRebuild = true; break; } } } } else { if (sp.index != -1) { needRebuild = true; } } // if (needRebuild) { exSpriteEditor.UpdateAtlas(sp, elInfo); #if UNITY_3_4 bool isPrefab = (EditorUtility.GetPrefabType(spBase) == PrefabType.Prefab); #else bool isPrefab = (PrefabUtility.GetPrefabType(spBase) == PrefabType.Prefab); #endif if (isPrefab == false) { Texture2D texture = null; if (sp.index == -1) { texture = exEditorHelper.LoadAssetFromGUID <Texture2D>(sp.textureGUID); } sp.Build(texture); } EditorUtility.SetDirty(sp); } } #if !(EX2D_EVALUATE) // ======================================================== // exSpriteFont // ======================================================== if (spBase is exSpriteFont) { exSpriteFont spFont = spBase as exSpriteFont; // bool needRebuild = false; if (spFont.fontInfo == null) { needRebuild = true; } else { foreach (string guidAtlasInfo in _atlasInfoGUIDs) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(guidAtlasInfo); // NOTE: it is possible we process this in delete stage if (atlasInfo == null) { continue; } foreach (exBitmapFont bmfont in atlasInfo.bitmapFonts) { if (spFont.fontInfo == bmfont) { needRebuild = true; break; } } } } // if (needRebuild) { spFont.Build(); } } // ======================================================== // exSpriteBorder // ======================================================== if (spBase is exSpriteBorder) { exSpriteBorder spBorder = spBase as exSpriteBorder; if (spBorder.guiBorder != null) { exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(spBorder.guiBorder.textureGUID); bool needRebuild = false; // NOTE: we test spBorder.index is -1 or not instead of test atlas is null, because it is possible we delete an atlas and it will always be null if (elInfo != null) { if (spBorder.index == -1) { needRebuild = true; } else { // find if the spBorder's atalsInfo need rebuild foreach (string guidAtlasInfo in _atlasInfoGUIDs) { if (elInfo.guidAtlasInfo == guidAtlasInfo) { needRebuild = true; break; } } } } else { if (spBorder.index != -1) { needRebuild = true; } } // if (needRebuild) { exSpriteBorderEditor.UpdateAtlas(spBorder, elInfo); #if UNITY_3_4 bool isPrefab = (EditorUtility.GetPrefabType(spBase) == PrefabType.Prefab); #else bool isPrefab = (PrefabUtility.GetPrefabType(spBase) == PrefabType.Prefab); #endif if (isPrefab == false) { Texture2D texture = null; if (spBorder.index == -1) { texture = exEditorHelper.LoadAssetFromGUID <Texture2D>(spBorder.guiBorder.textureGUID); } spBorder.Build(texture); } EditorUtility.SetDirty(spBorder); } } } #endif // !(EX2D_EVALUATE) // DISABLE: it is too slow { // float progress = (float)i/(float)sprites.Length; // EditorUtility.DisplayProgressBar( "Update Scene Sprites...", // "Update Sprite " + spBase.gameObject.name, progress ); // } DISABLE end } EditorUtility.ClearProgressBar(); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } }
/////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void OnPostprocessAllAssets(string[] _importedAssets, string[] _deletedAssets, string[] _movedAssets, string[] _movedFromAssetPaths) { List <exAtlasInfo> updateAtlasInfos = new List <exAtlasInfo>(); List <string> atlasInfoGUIDs = new List <string>(); // ======================================================== // import assets // ======================================================== foreach (string path in _importedAssets) { // check if we are .ex2D_AtlasDB or .ex2D_SpriteAnimationDB if (string.Equals(path, exAtlasDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase) || string.Equals(path, exSpriteAnimationDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase)) { continue; } // check if we are asset string ext = Path.GetExtension(path); if (ext != ".asset" && ext != ".png" && ext != ".jpg" && ext != ".tga") { continue; } // Object obj = (Object)AssetDatabase.LoadAssetAtPath(path, typeof(Object)); if (obj == null) { continue; } // ======================================================== // Texture2D // NOTE: if we are OnWillSaveAssets, it is possible we reimport // textures if they are not valid for atlas. and when import it will // trigger things here which will lead to infinite cycle. // ======================================================== if (ex.onSavingAssets == false && obj is Texture2D) { Texture2D tex2d = obj as Texture2D; exAtlasDB.ElementInfo ei = exAtlasDB.GetElementInfo(tex2d); if (ei != null) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(ei.guidAtlasInfo); atlasInfo.UpdateElement(tex2d, true, true); if (atlasInfo && updateAtlasInfos.IndexOf(atlasInfo) == -1) { atlasInfo.needLayout = true; updateAtlasInfos.Add(atlasInfo); } } continue; } // ======================================================== // exAtlasInfo // ======================================================== if (obj is exAtlasInfo) { exAtlasInfo atlasInfo = obj as exAtlasInfo; exAtlasDB.AddAtlasInfo(atlasInfo); // Debug.Log( "add atlas " + path ); // DEBUG } // ======================================================== // exSpriteAnimClip // ======================================================== if (obj is exSpriteAnimClip) { exSpriteAnimClip spAnimClip = obj as exSpriteAnimClip; exSpriteAnimationDB.AddSpriteAnimClip(spAnimClip); // Debug.Log( "add sprite anim clip " + path ); // DEBUG } } // build exAtlasInfo first foreach (exAtlasInfo atlasInfo in updateAtlasInfos) { // NOTE: Build atlas without import texture, without this, we will crash when changing import settings of a texture and rebuild it. exAtlasInfoUtility.Build(atlasInfo, true); // NOTE: no need to update scene sprite and sprite animation clip, because we didn't change index atlasInfoGUIDs.Add(exEditorHelper.AssetToGUID(atlasInfo)); } // ======================================================== // deleted assets // ======================================================== foreach (string path in _deletedAssets) { // check if we are .ex2D_AtlasDB or .ex2D_SpriteAnimationDB if (string.Equals(path, exAtlasDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase) || string.Equals(path, exSpriteAnimationDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase)) { continue; } // check if we are asset if (Path.GetExtension(path) != ".asset") { continue; } // string guid = AssetDatabase.AssetPathToGUID(path); // check if we have the guid in the exAtlasInfo if (exAtlasDB.HasAtlasInfoGUID(guid)) { exAtlasDB.RemoveAtlasInfo(guid); atlasInfoGUIDs.Add(guid); // Debug.Log( "remove atlas " + path ); // DEBUG } // check if we have the guid in the exSpriteAnimClip else if (exSpriteAnimationDB.HasSpriteAnimClipGUID(guid)) { exSpriteAnimationDB.RemoveSpriteAnimClip(guid); // Debug.Log( "remove sprite anim clip " + path ); // DEBUG } } exSceneHelper.UpdateSprites(atlasInfoGUIDs); // DISABLE { // for ( int i = 0; i < _movedAssets.Length; ++i ) // Debug.Log("Moved Asset: " + _movedAssets[i] + " from: " + _movedFromAssetPaths[i]); // } DISABLE end }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void OnWillSaveAssets(string[] _paths) { ex.onSavingAssets = true; List <exAtlasInfo> rebuildAtlasInfos = new List <exAtlasInfo>(); List <exSpriteAnimClip> rebuildSpriteAnimClips = new List <exSpriteAnimClip>(); List <exGUIBorder> rebuildGuiBorders = new List <exGUIBorder>(); // foreach (string path in _paths) { // check if we are .ex2D_AtlasDB or .ex2D_SpriteAnimationDB if (string.Equals(path, exAtlasDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase) || string.Equals(path, exSpriteAnimationDB.dbPath, System.StringComparison.CurrentCultureIgnoreCase)) { continue; } // check if we are asset if (Path.GetExtension(path) != ".asset") { continue; } Object obj = (Object)AssetDatabase.LoadAssetAtPath(path, typeof(Object)); if (obj == null) { continue; } // ======================================================== // build exAtlasInfo // ======================================================== if (obj is exAtlasInfo) { exAtlasInfo atlasInfo = obj as exAtlasInfo; if (atlasInfo.needRebuild && rebuildAtlasInfos.IndexOf(atlasInfo) == -1) { rebuildAtlasInfos.Add(atlasInfo); } } // ======================================================== // build exSpriteAnimClip // ======================================================== if (obj is exSpriteAnimClip) { exSpriteAnimClip spAnimClip = obj as exSpriteAnimClip; if (spAnimClip.editorNeedRebuild) { rebuildSpriteAnimClips.Add(spAnimClip); } } // TODO { // // ======================================================== // // build exBitmapFont // // ======================================================== // if ( obj is exBitmapFont ) { // exBitmapFont bitmapFont = obj as exBitmapFont; // if ( bitmapFont.editorNeedRebuild ) // Object fontInfo = exEditorHelper.LoadAssetFromGUID(bitmapFont.fontinfoGUID); // bitmapFont.Build( fontInfo ); // } // } TODO end // ======================================================== // build exGUIBorder // ======================================================== if (obj is exGUIBorder) { exGUIBorder guiBorder = obj as exGUIBorder; if (guiBorder.editorNeedRebuild && rebuildGuiBorders.IndexOf(guiBorder) == -1) { guiBorder.editorNeedRebuild = false; EditorUtility.SetDirty(guiBorder); rebuildGuiBorders.Add(guiBorder); } } } // NOTE: we need to make sure exAtlasInfo build before exSpriteAnimClip, // because during build, exAtlasDB will update ElementInfo, and exSpriteAnimClip need this for checking error. // ======================================================== // build exAtlasInfo first // ======================================================== foreach (exAtlasInfo atlasInfo in rebuildAtlasInfos) { exAtlasInfoUtility.Build(atlasInfo); // build sprite animclip that used this atlasInfo exAtlasInfoUtility.BuildSpAnimClipsFromRebuildList(atlasInfo); } // ======================================================== // build exSpriteAnimClip // ======================================================== foreach (exSpriteAnimClip spAnimClip in rebuildSpriteAnimClips) { // NOTE: it could be built in BuildSpAnimClipsFromRebuildList above if (spAnimClip.editorNeedRebuild) { spAnimClip.Build(); } } // ======================================================== // post build // ======================================================== // update scene sprites with rebuild atlasInfo list List <string> rebuildAtlasInfoGUIDs = new List <string>(); foreach (exAtlasInfo atlasInfo in rebuildAtlasInfos) { rebuildAtlasInfoGUIDs.Add(exEditorHelper.AssetToGUID(atlasInfo)); } exSceneHelper.UpdateSprites(rebuildAtlasInfoGUIDs); // update scene sprites with rebuild guiBorder list exSceneHelper.UpdateSpriteBorders(rebuildGuiBorders); // NOTE: without this you will got leaks message // EditorUtility.UnloadUnusedAssets(); ex.onSavingAssets = false; }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void PreviewField(Rect _rect) { // ======================================================== // preview // ======================================================== int borderSize = 1; int boxWidth = (int)_rect.width + 2 * borderSize; // box border int boxHeight = (int)_rect.height + 2 * borderSize; // box border Texture2D texCheckerboard = exEditorHelper.CheckerboardTexture(); GUI.BeginGroup(_rect); int col = Mathf.CeilToInt(_rect.width / texCheckerboard.width); int row = Mathf.CeilToInt(_rect.height / texCheckerboard.height); for (int j = 0; j < row; ++j) { for (int i = 0; i < col; ++i) { Rect size = new Rect(i * texCheckerboard.width, j * texCheckerboard.height, texCheckerboard.width, texCheckerboard.height); GUI.DrawTexture(size, texCheckerboard); } } GUI.EndGroup(); Color oldBGColor = GUI.backgroundColor; GUI.backgroundColor = Color.black; GUI.Box(new Rect(_rect.x - borderSize, _rect.y - borderSize, boxWidth, boxHeight), GUIContent.none, exEditorHelper.RectBorderStyle()); GUI.backgroundColor = oldBGColor; // ======================================================== // draw frame // ======================================================== if (curEdit != null) { // draw the preview exSpriteAnimClip.FrameInfo fi = curEdit.GetFrameInfoBySeconds(curSeconds, curEdit.wrapMode); if (fi != null) { exAtlasDB.ElementInfo elInfo = exAtlasDB.GetElementInfo(fi.textureGUID); if (elInfo != null) { exAtlasInfo atlasInfo = exEditorHelper.LoadAssetFromGUID <exAtlasInfo>(elInfo.guidAtlasInfo); exAtlasInfo.Element el = atlasInfo.elements[elInfo.indexInAtlasInfo]; if (el.texture != null) { float width = el.texture.width; float height = el.texture.height; float offsetX = (width - el.trimRect.width) * 0.5f - el.trimRect.x; float offsetY = (height - el.trimRect.height) * 0.5f - el.trimRect.y; // DELME { // Rect frameRect = new Rect( -el.trimRect.x * previewScale, // -el.trimRect.y * previewScale, // width * previewScale, // height * previewScale ); // } DELME end Rect rect2 = new Rect((_rect.width - el.trimRect.width * previewScale) * 0.5f - offsetX * previewScale, (_rect.height - el.trimRect.height * previewScale) * 0.5f - offsetY * previewScale, el.trimRect.width * previewScale, el.trimRect.height * previewScale); // DISABLE: because we can't make sure all texture have same size, so ScaleToFit may play large texture { // GUI.BeginGroup( _rect ); // GUI.DrawTexture( new Rect( 0.0f, 0.0f, _rect.width, _rect.height ), // el.texture, // ScaleMode.ScaleToFit ); // GUI.EndGroup(); // } DISABLE end GUI.BeginGroup(_rect); // DELME { // draw background // Color old = GUI.color; // GUI.color = new Color( 1.0f, 0.0f, 0.85f, 0.2f ); // GUI.DrawTexture( rect2, exEditorHelper.WhiteTexture() ); // GUI.color = old; // // draw texture // GUI.BeginGroup( rect2 ); // GUI.BeginGroup( new Rect( (rect2.width - el.trimRect.width * previewScale) * 0.5f, // (rect2.height - el.trimRect.height * previewScale) * 0.5f, // el.trimRect.width * previewScale, // el.trimRect.height * previewScale ) ); // GUI.DrawTexture( frameRect, el.texture ); // GUI.EndGroup(); // GUI.EndGroup(); // } DELME end Graphics.DrawTexture(rect2, el.texture, new Rect(el.trimRect.x / el.texture.width, (el.texture.height - el.trimRect.y - el.trimRect.height) / el.texture.height, el.trimRect.width / el.texture.width, el.trimRect.height / el.texture.height), 0, 0, 0, 0, Color.white / 2.0f); // DELME { // draw border // Color oldBGColor = GUI.backgroundColor; // GUI.backgroundColor = Color.black; // GUI.Box ( rect2, GUIContent.none, exEditorHelper.RectBorderStyle() ); // GUI.backgroundColor = oldBGColor; // } DELME end GUI.EndGroup(); } } else { string texturePath = AssetDatabase.GUIDToAssetPath(fi.textureGUID); Texture2D tex2D = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); if (tex2D != null) { Rect size = new Rect(0.0f, 0.0f, tex2D.width * previewScale, tex2D.height * previewScale); Rect rect2 = new Rect((_rect.width - size.width) * 0.5f, (_rect.height - size.height) * 0.5f, size.width, size.height); GUI.BeginGroup(_rect); GUI.BeginGroup(rect2); GUI.DrawTexture(size, tex2D); GUI.EndGroup(); GUI.EndGroup(); } } } } GUILayoutUtility.GetRect(_rect.width, _rect.height); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void AtlasInfoField(Rect _rect, int _borderSize, exAtlasInfo _atlasInfo) { Texture2D texCheckerboard = exEditorHelper.CheckerboardTexture(); float boxWidth = (float)_atlasInfo.width * _atlasInfo.scale + 2.0f * _borderSize; // box border float boxHeight = (float)_atlasInfo.height * _atlasInfo.scale + 2.0f * _borderSize; // box border Rect scaledRect = new Rect(_rect.x, _rect.y, boxWidth, boxHeight); // ======================================================== // draw background textures // ======================================================== GUI.BeginGroup(new Rect(_rect.x, _rect.y, (float)_atlasInfo.width * _atlasInfo.scale, (float)_atlasInfo.height * _atlasInfo.scale)); Color old = GUI.color; GUI.color = new Color(_atlasInfo.bgColor.r, _atlasInfo.bgColor.g, _atlasInfo.bgColor.b, 1.0f); if (_atlasInfo.showCheckerboard) { int col = Mathf.CeilToInt(_atlasInfo.width * _atlasInfo.scale / texCheckerboard.width); int row = Mathf.CeilToInt(_atlasInfo.height * _atlasInfo.scale / texCheckerboard.height); for (int i = 0; i < col; ++i) { for (int j = 0; j < row; ++j) { Rect size = new Rect(i * texCheckerboard.width, j * texCheckerboard.height, texCheckerboard.width, texCheckerboard.height); GUI.DrawTexture(size, texCheckerboard); } } } else { GUI.DrawTexture(new Rect(0, 0, _atlasInfo.width * _atlasInfo.scale, _atlasInfo.height * _atlasInfo.scale), exEditorHelper.WhiteTexture()); } GUI.color = old; GUI.EndGroup(); // ======================================================== // draw the gui box // ======================================================== GUIContent bgContent = new GUIContent(); if (_atlasInfo.elements.Count == 0) { bgContent.text = "Drag Textures On It"; bgContent.tooltip = "Drag Textures to create atlas"; } else { bgContent.text = ""; } Color oldBGColor = GUI.backgroundColor; GUI.backgroundColor = Color.black; GUI.Box(new Rect(_rect.x - _borderSize, _rect.y - _borderSize, boxWidth, boxHeight), bgContent, exEditorHelper.RectBorderStyle()); GUI.backgroundColor = oldBGColor; // ======================================================== // exAtlasInfo.Element // ======================================================== List <exAtlasInfo.Element> invalidElements = new List <exAtlasInfo.Element>(); foreach (exAtlasInfo.Element el in _atlasInfo.elements) { if (el.texture == null) { invalidElements.Add(el); continue; } if (el.isFontElement && (el.srcFontInfo == null || el.destFontInfo == null)) { invalidElements.Add(el); continue; } AtlasElementField(scaledRect, _atlasInfo, el); } foreach (exAtlasInfo.Element el in invalidElements) { _atlasInfo.RemoveElement(el); } // ======================================================== // handle drop event Event e = Event.current; // ======================================================== if (scaledRect.Contains(e.mousePosition)) { if (e.type == EventType.DragUpdated) { // Show a copy icon on the drag foreach (Object o in DragAndDrop.objectReferences) { if (o is Texture2D || (o is exBitmapFont && (o as exBitmapFont).inAtlas == false) || exEditorHelper.IsDirectory(o)) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; break; } } } else if (e.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); // NOTE: Unity3D have a problem in ImportTextureForAtlas, when a texture is an active selection, // no matter how you change your import settings, finally it will apply changes that in Inspector (shows when object selected) oldSelActiveObject = null; oldSelObjects.Clear(); foreach (Object o in Selection.objects) { oldSelObjects.Add(o); } oldSelActiveObject = Selection.activeObject; // NOTE: Selection.GetFiltered only affect on activeObject, but we may proceed non-active selections sometimes foreach (Object o in DragAndDrop.objectReferences) { if (exEditorHelper.IsDirectory(o)) { Selection.activeObject = o; // add Texture2D objects Object[] objs = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets); importObjects.AddRange(objs); // add exBitmapFont objects objs = Selection.GetFiltered(typeof(exBitmapFont), SelectionMode.DeepAssets); importObjects.AddRange(objs); } else if (o is Texture2D || o is exBitmapFont) { importObjects.Add(o); } } // Selection.activeObject = null; // doImport = true; Repaint(); } } // GUILayoutUtility.GetRect(boxWidth, boxHeight); }
// ------------------------------------------------------------------ /// \param _el the element in atlas info /// \param _index the index of the element /// update the index of the element info in atlas db // ------------------------------------------------------------------ public static void UpdateElementInfo( exAtlasInfo.Element _el, int _index ) { Init(); string textureGUID = exEditorHelper.AssetToGUID(_el.texture); ElementInfo elInfo = GetElementInfo(textureGUID); if ( elInfo == null ) { elInfo = AddElementInfo (_el, _index); if ( elInfo != null ) { db.elementInfos.Add(elInfo); EditorUtility.SetDirty(db); } } else { elInfo.indexInAtlas = _index; elInfo.indexInAtlasInfo = _index; EditorUtility.SetDirty(db); } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ static void FillAtlasTexture( Texture2D _tex, exAtlasInfo _atlasInfo, bool _noImport ) { foreach ( exAtlasInfo.Element el in _atlasInfo.elements ) { // DISABLE: it is too slow { // EditorUtility.DisplayProgressBar( "Building Atlas...", // "Building Texture " + el.texture.name, // (float)i/(float)_atlasInfo.elements.Count - 0.1f ); // } DISABLE end Texture2D srcTexture = el.texture; int destX = el.coord[0]; if ( el.isFontElement ) { // build the font exBitmapFont.CharInfo charInfo = el.destFontInfo.GetCharInfo(el.charInfo.id); if ( charInfo != null ) { charInfo.uv0 = new Vector2 ( (float)destX / _tex.width, (_tex.height - (float)el.coord[1] - charInfo.height) / _tex.height ); EditorUtility.SetDirty(el.destFontInfo); } } // make the src texture readable if ( exTextureHelper.IsValidForAtlas (srcTexture) == false ) { if ( _noImport ) { Debug.LogError( "The texture import settings of [" + AssetDatabase.GetAssetPath(srcTexture) + "] is invalid for atlas build" ); continue; } else { exTextureHelper.ImportTextureForAtlas(srcTexture); } } // apply contour bleed if ( _atlasInfo.useContourBleed ) { srcTexture = exTextureHelper.ApplyContourBleed( srcTexture ); } // copy element's texture into atlas texture int destY = _tex.height - el.coord[1] - el.Height(); exTextureHelper.Fill( _tex, new Vector2 ( destX, destY ), srcTexture, el.trimRect, el.rotated ? exTextureHelper.RotateDirection.RotRight : exTextureHelper.RotateDirection.None, _atlasInfo.useBuildColor, _atlasInfo.buildColor ); // apply padding bleed if ( _atlasInfo.usePaddingBleed ) { exTextureHelper.ApplyPaddingBleed( _tex, new Rect( destX, destY, el.trimRect.width, el.trimRect.height ) ); } // TODO { // Color32[] colors = srcTexture.GetPixels32(); // Color32[] colors_d = new Color32[_tex.width * _tex.height]; // for ( int r = 0; r < srcTexture.width; ++r ) { // for ( int c = 0; c < srcTexture.height; ++c ) { // colors_d[r+c*_tex.width] = colors[r+c*srcTexture.width]; // } // } // _tex.SetPixels32( colors_d ); // } TODO end } #if EX2D_EVALUATE // ======================================================== // Add water mark // ======================================================== // NOTE: onlly open it in evaluate version { // Make Water Make { // Texture2D texWaterMark = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/ex2D/Editor/Resource/water_mark.png", typeof(Texture2D)); // exTextureHelper.ImportTextureForAtlas(texWaterMark); // Color[] colors = texWaterMark.GetPixels(); // StreamWriter sw = new StreamWriter("Assets/TestFile.txt"); // Color32[] colors32 = texWaterMark.GetPixels32(); // for ( int r = 0; r < texWaterMark.height; ++r ) { // for ( int c = 0; c < texWaterMark.width; ++c ) { // Color32 cc = colors32[r*texWaterMark.width+c]; // sw.Write( "0x" + cc.r.ToString("X2") // + ", 0x" + cc.g.ToString("X2") // + ", 0x" + cc.b.ToString("X2") // + ", 0x" + cc.a.ToString("X2") // + ", " ); // } // sw.WriteLine(""); // } // sw.Close(); // } Make Water Make end int wa_width = 392; int wa_height = 40; Color[] colors = new Color[wa_width*wa_height]; for ( int r = 0; r < wa_height; ++r ) { for ( int c = 0; c < wa_width; ++c ) { colors[r*wa_width+c] = new Color ( waterMark[(r*wa_width+c)*4]/255.0f, waterMark[(r*wa_width+c)*4+1]/255.0f, waterMark[(r*wa_width+c)*4+2]/255.0f, waterMark[(r*wa_width+c)*4+3]/255.0f ); } } Color[] colors_d = _tex.GetPixels(); for ( int r = 0; r < wa_height; ++r ) { for ( int c = 0; c < wa_width; ++c ) { Color color_d = colors_d[r*_tex.width+c]; Color color = colors[r*wa_width+c]; // colors_d[r*_tex.width+(c+_tex.height-wa_height)] = colors_d[r*_tex.width+c] = color_d * ( 1.0f - color.a ) + color * color.a; } } _tex.SetPixels( colors_d ); // } NOTE end #endif // EX2D_EVALUATE _tex.Apply(false); }
// ------------------------------------------------------------------ /// \param _obj /// Check if the object is valid atlas and open it in atlas editor. // ------------------------------------------------------------------ public void Edit( Object _obj ) { // check if repaint if ( curEdit != _obj ) { // check if we have atlas - editorinfo in the same directory Object obj = _obj; if ( obj is exAtlas || obj is Texture2D || obj is Material ) { string assetPath = AssetDatabase.GetAssetPath(obj); string dirname = Path.GetDirectoryName(assetPath); string filename = Path.GetFileNameWithoutExtension(assetPath); obj = (exAtlasInfo)AssetDatabase.LoadAssetAtPath( Path.Combine( dirname, filename + " - EditorInfo.asset" ), typeof(exAtlasInfo) ); if ( obj == null ) { obj = _obj; } } // if this is another atlas, swtich to it. if ( obj is exAtlasInfo && obj != curEdit ) { curEdit = obj as exAtlasInfo; Init(); Repaint (); return; } } }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void AtlasElementField( Rect _atlasRect, exAtlasInfo _atlasInfo, exAtlasInfo.Element _el ) { Color oldBGColor = GUI.backgroundColor; Rect srcRect; Rect rect = new Rect( _el.coord[0] * _atlasInfo.scale, _el.coord[1] * _atlasInfo.scale, _el.Width() * _atlasInfo.scale, _el.Height() * _atlasInfo.scale ); bool selected = selectedElements.IndexOf(_el) != -1; // ======================================================== // draw the sprite background // ======================================================== GUI.BeginGroup(_atlasRect); GUI.color = _el.atlasInfo.elementBgColor; GUI.DrawTexture( rect, exEditorHelper.WhiteTexture() ); GUI.color = oldBGColor; GUI.EndGroup(); // ======================================================== // draw the texture // ======================================================== // process rotate Matrix4x4 oldMat = GUI.matrix; if ( _el.rotated ) { GUIUtility.RotateAroundPivot( 90.0f, new Vector2 ( _atlasRect.x, _atlasRect.y) ); GUI.matrix = GUI.matrix * Matrix4x4.TRS ( new Vector3( 0.0f, -_atlasRect.width, 0.0f), Quaternion.identity, Vector3.one ); // NOTE: clipping is done before rotating, if we rotate, we have to change the clip GUI.BeginGroup( _atlasRect ); srcRect = new Rect( _el.coord[1], _atlasRect.width - _el.coord[0] - _el.trimRect.height, _el.trimRect.width, _el.trimRect.height ); } else { GUI.BeginGroup( _atlasRect ); srcRect = new Rect( _el.coord[0], _el.coord[1], _el.trimRect.width, _el.trimRect.height ); } srcRect = new Rect ( srcRect.x * _atlasInfo.scale, srcRect.y * _atlasInfo.scale, srcRect.width * _atlasInfo.scale, srcRect.height * _atlasInfo.scale ); // draw texture if ( _el.trim ) { Rect rect2 = new Rect( -_el.trimRect.x * _atlasInfo.scale, -_el.trimRect.y * _atlasInfo.scale, _el.texture.width * _atlasInfo.scale, _el.texture.height * _atlasInfo.scale ); GUI.BeginGroup( srcRect ); GUI.DrawTexture( rect2, _el.texture ); GUI.EndGroup(); } else { GUI.DrawTexture( srcRect, _el.texture ); } // recover from rotate if ( _el.rotated ) GUI.matrix = oldMat; GUI.EndGroup(); // ======================================================== // draw selected border // ======================================================== GUI.BeginGroup(_atlasRect); if ( selected ) { GUI.backgroundColor = _el.atlasInfo.elementSelectColor; GUI.Box ( rect, GUIContent.none, exEditorHelper.RectBorderStyle() ); GUI.backgroundColor = oldBGColor; } GUI.EndGroup(); // ======================================================== // process mouse event Event e = Event.current; // ======================================================== GUI.BeginGroup(_atlasRect); if ( e.type == EventType.MouseDown && e.button == 0 && e.clickCount == 1 ) { if ( rect.Contains( e.mousePosition ) ) { GUIUtility.keyboardControl = -1; // remove any keyboard control if ( e.command || e.control ) { ToggleSelected(_el); } else { inDraggingElementState = true; if ( selected == false ) { if ( e.command == false && e.control == false ) { selectedElements.Clear(); AddSelected(_el); } } } e.Use(); Repaint(); } } GUI.EndGroup(); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void AtlasElementField(Rect _atlasRect, exAtlasInfo _atlasInfo, exAtlasInfo.Element _el) { Color oldBGColor = GUI.backgroundColor; Rect srcRect; Rect rect = new Rect(_el.coord[0] * _atlasInfo.scale, _el.coord[1] * _atlasInfo.scale, _el.Width() * _atlasInfo.scale, _el.Height() * _atlasInfo.scale); bool selected = selectedElements.IndexOf(_el) != -1; // ======================================================== // draw the sprite background // ======================================================== GUI.BeginGroup(_atlasRect); GUI.color = _el.atlasInfo.elementBgColor; GUI.DrawTexture(rect, exEditorHelper.WhiteTexture()); GUI.color = oldBGColor; GUI.EndGroup(); // ======================================================== // draw the texture // ======================================================== // process rotate Matrix4x4 oldMat = GUI.matrix; if (_el.rotated) { GUIUtility.RotateAroundPivot(90.0f, new Vector2(_atlasRect.x, _atlasRect.y)); GUI.matrix = GUI.matrix * Matrix4x4.TRS(new Vector3(0.0f, -_atlasRect.width, 0.0f), Quaternion.identity, Vector3.one); // NOTE: clipping is done before rotating, if we rotate, we have to change the clip GUI.BeginGroup(_atlasRect); srcRect = new Rect(_el.coord[1], _atlasRect.width - _el.coord[0] - _el.trimRect.height, _el.trimRect.width, _el.trimRect.height); } else { GUI.BeginGroup(_atlasRect); srcRect = new Rect(_el.coord[0], _el.coord[1], _el.trimRect.width, _el.trimRect.height); } srcRect = new Rect(srcRect.x * _atlasInfo.scale, srcRect.y * _atlasInfo.scale, srcRect.width * _atlasInfo.scale, srcRect.height * _atlasInfo.scale); // draw texture if (_el.trim) { Rect rect2 = new Rect(-_el.trimRect.x * _atlasInfo.scale, -_el.trimRect.y * _atlasInfo.scale, _el.texture.width * _atlasInfo.scale, _el.texture.height * _atlasInfo.scale); GUI.BeginGroup(srcRect); GUI.DrawTexture(rect2, _el.texture); GUI.EndGroup(); } else { GUI.DrawTexture(srcRect, _el.texture); } // recover from rotate if (_el.rotated) { GUI.matrix = oldMat; } GUI.EndGroup(); // ======================================================== // draw selected border // ======================================================== GUI.BeginGroup(_atlasRect); if (selected) { GUI.backgroundColor = _el.atlasInfo.elementSelectColor; GUI.Box(rect, GUIContent.none, exEditorHelper.RectBorderStyle()); GUI.backgroundColor = oldBGColor; } GUI.EndGroup(); // ======================================================== // process mouse event Event e = Event.current; // ======================================================== GUI.BeginGroup(_atlasRect); if (e.type == EventType.MouseDown && e.button == 0 && e.clickCount == 1) { if (rect.Contains(e.mousePosition)) { GUIUtility.keyboardControl = -1; // remove any keyboard control if (e.command || e.control) { ToggleSelected(_el); } else { inDraggingElementState = true; if (selected == false) { if (e.command == false && e.control == false) { selectedElements.Clear(); AddSelected(_el); } } } e.Use(); Repaint(); } } GUI.EndGroup(); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ void ToggleSelected( exAtlasInfo.Element _el ) { int i = selectedElements.IndexOf(_el); if ( i != -1 ) { selectedElements.RemoveAt(i); } else { selectedElements.Add(_el); } }
// ------------------------------------------------------------------ /// \param _atlasInfo the atlas info /// \param _noImport if true, ex2D will not import the texture to fit for atlas /// build the atlas info to atlas // ------------------------------------------------------------------ public static void Build(exAtlasInfo _atlasInfo, bool _noImport = false) { exAtlas atlas = _atlasInfo.atlas; Texture2D texture = _atlasInfo.texture; Material material = _atlasInfo.material; // check if the atlas info is valid for build if (atlas == null) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the atlas is missing!"); return; } if (texture == null) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the texture is missing!"); return; } if (material == null) { Debug.LogError("Failed to build atlas info " + _atlasInfo.name + ", the material is missing!"); return; } // if (_atlasInfo.needLayout) { _atlasInfo.LayoutElements(); _atlasInfo.needLayout = false; } // create temp texture Color32 buildColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); if (_atlasInfo.useBuildColor) { buildColor = new Color(_atlasInfo.buildColor.r, _atlasInfo.buildColor.g, _atlasInfo.buildColor.b, 0.0f); } string path = AssetDatabase.GetAssetPath(texture); TextureImporter importer = TextureImporter.GetAtPath(path) as TextureImporter; // TextureImporterSettings textureImporterSettings = new TextureImporterSettings(); // importer.ReadTextureSettings(textureImporterSettings); // textureImporterSettings.readable = true; // importer.SetTextureSettings(textureImporterSettings); importer.wrapMode = TextureWrapMode.Clamp; importer.isReadable = true; AssetDatabase.ImportAsset(path); Color32[] colors = new Color32[_atlasInfo.width * _atlasInfo.height]; for (int i = 0; i < _atlasInfo.width * _atlasInfo.height; ++i) { colors[i] = buildColor; } texture.SetPixels32(colors); try { EditorUtility.DisplayProgressBar("Building Atlas " + _atlasInfo.name, "Building Atlas...", 0.1f); // build atlas texture _atlasInfo.elements.Sort(exAtlasInfo.CompareByName); FillAtlasTexture(texture, _atlasInfo, _noImport); EditorUtility.DisplayProgressBar("Building Atlas " + _atlasInfo.name, "Import Atlas", 0.9f); // write to disk byte[] pngData = texture.EncodeToPNG(); if (pngData != null) { File.WriteAllBytes(path, pngData); } // now we finish atlas texture filling, we should turn off Read/Write settings, that will save memory a lot! TextureImporter importSettings = TextureImporter.GetAtPath(path) as TextureImporter; importSettings.wrapMode = TextureWrapMode.Clamp; importSettings.isReadable = _atlasInfo.readable; AssetDatabase.ImportAsset(path); // atlas.elements = new exAtlas.Element[_atlasInfo.elements.Count]; for (int i = 0; i < _atlasInfo.elements.Count; ++i) { exAtlasInfo.Element el = _atlasInfo.elements[i]; exAtlas.Element el2 = new exAtlas.Element(); int coord_x = el.coord[0]; int coord_y = el.atlasInfo.height - el.coord[1] - (int)el.Height(); float xStart = (float)coord_x / (float)el.atlasInfo.width; float yStart = (float)coord_y / (float)el.atlasInfo.height; float xEnd = (float)(coord_x + el.Width()) / (float)el.atlasInfo.width; float yEnd = (float)(coord_y + el.Height()) / (float)el.atlasInfo.height; el2.name = el.texture.name; el2.coords = new Rect(xStart, yStart, xEnd - xStart, yEnd - yStart); el2.rotated = el.rotated; el2.originalWidth = el.texture.width; el2.originalHeight = el.texture.height; el2.trimRect = el.trimRect; atlas.elements[i] = el2; // update the index in exAtlasDB if (el.isFontElement == false) { exAtlasDB.UpdateElementInfo(el, i); } } atlas.texture = texture; atlas.material = material; EditorUtility.SetDirty(atlas); EditorUtility.ClearProgressBar(); } catch (System.Exception) { EditorUtility.ClearProgressBar(); throw; } // save the needRebuild setting _atlasInfo.needRebuild = false; EditorUtility.SetDirty(_atlasInfo); }
// ------------------------------------------------------------------ /// \param _atlasInfo the atlas info /// build sprite animation clips from the exAtlasInfo.rebuildAnimClipGUIDs // ------------------------------------------------------------------ public static void BuildSpAnimClipsFromRebuildList( exAtlasInfo _atlasInfo ) { try { EditorUtility.DisplayProgressBar( "Building Sprite Animation Clips...", "Building Sprite Animation Clips...", 0.5f ); for ( int i = 0; i < _atlasInfo.rebuildAnimClipGUIDs.Count; ++i ) { string guidAnimClip = _atlasInfo.rebuildAnimClipGUIDs[i]; exSpriteAnimClip sp = exEditorHelper.LoadAssetFromGUID<exSpriteAnimClip>(guidAnimClip); if ( sp ) { sp.editorNeedRebuild = true; sp.Build(); } } _atlasInfo.rebuildAnimClipGUIDs.Clear(); EditorUtility.ClearProgressBar(); } catch ( System.Exception ) { EditorUtility.ClearProgressBar(); throw; } }