From ad1fa8cd4e6936e91d5a94ec53b622be5a47d837 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 23 Aug 2016 19:27:15 +0700 Subject: [PATCH] swf postprocessors refactor --- .../Resources/SwfConverterSettings.asset | 4 +- .../Resources/SwfConverterSettings.asset.meta | 4 +- .../Editor/SwfAnimationAssetEditor.cs | 25 +++- .../Editor/SwfAnimationAssetPostprocessor.cs | 81 ++++++++--- .../Internal/Editor/SwfPostprocessor.cs | 130 +++++++++++------- .../Editor/SwfTools/SwfContextExecuter.cs | 2 +- .../FlashTools/Scripts/SwfAnimationAsset.cs | 2 + .../Scripts/SwfConverterSettings.cs | 85 +++++++----- 8 files changed, 219 insertions(+), 114 deletions(-) diff --git a/Assets/FlashTools/Resources/SwfConverterSettings.asset b/Assets/FlashTools/Resources/SwfConverterSettings.asset index ed8c61a..df7ce67 100644 --- a/Assets/FlashTools/Resources/SwfConverterSettings.asset +++ b/Assets/FlashTools/Resources/SwfConverterSettings.asset @@ -18,5 +18,5 @@ MonoBehaviour: GenerateMipMaps: 1 AtlasPowerOfTwo: 1 AtlasForceSquare: 0 - AtlasFilterMode: 1 - AtlasImporterFormat: -3 + AtlasTextureFilter: 1 + AtlasTextureFormat: 2 diff --git a/Assets/FlashTools/Resources/SwfConverterSettings.asset.meta b/Assets/FlashTools/Resources/SwfConverterSettings.asset.meta index ccf92cf..0d539a2 100644 --- a/Assets/FlashTools/Resources/SwfConverterSettings.asset.meta +++ b/Assets/FlashTools/Resources/SwfConverterSettings.asset.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: cda4fb87dc8624946bdaed871b60f0b8 -timeCreated: 1471880348 +guid: ea1dd488b8903439b90ce209ff82574c +timeCreated: 1471954996 licenseType: Free NativeFormatImporter: userData: diff --git a/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetEditor.cs b/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetEditor.cs index 025eb9e..e356112 100644 --- a/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetEditor.cs +++ b/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetEditor.cs @@ -1,6 +1,7 @@ using UnityEngine; using UnityEditor; using System.IO; +using System.Linq; namespace FlashTools.Internal { [CustomEditor(typeof(SwfAnimationAsset))] @@ -122,7 +123,17 @@ namespace FlashTools.Internal { if ( _settingsFoldout ) { var it = serializedObject.FindProperty("Overridden"); while ( it.NextVisible(true) ) { - EditorGUILayout.PropertyField(it); + if ( it.name == "MaxAtlasSize" && _asset.Overridden.AtlasPowerOfTwo ) { + if ( !Mathf.IsPowerOfTwo(it.intValue) ) { + it.intValue = Mathf.ClosestPowerOfTwo(it.intValue); + serializedObject.ApplyModifiedProperties(); + } + var values = new int[] {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}; + var names = values.Select(p => new GUIContent(p.ToString())).ToArray(); + EditorGUILayout.IntPopup(it, names, values); + } else { + EditorGUILayout.PropertyField(it); + } } DrawGUISettingsControls(); } @@ -131,15 +142,16 @@ namespace FlashTools.Internal { void DrawGUISettingsControls() { GUILayout.BeginHorizontal(); { - GUI.enabled = !_asset.Overridden.Equal(SwfConverterSettings.GetDefaultSettings()); + var default_settings = SwfConverterSettings.GetDefaultSettings(); + GUI.enabled = !_asset.Overridden.CheckEquals(default_settings); if ( GUILayout.Button("Default") ) { OverriddenSettingsToDefault(); } - GUI.enabled = !_asset.Overridden.Equal(_asset.Settings); + GUI.enabled = !_asset.Overridden.CheckEquals(_asset.Settings); if ( GUILayout.Button("Revert") ) { RevertOverriddenSettings(); } - GUI.enabled = !_asset.Overridden.Equal(_asset.Settings); + GUI.enabled = !_asset.Overridden.CheckEquals(_asset.Settings); if ( GUILayout.Button("Apply") ) { ApplyOverriddenSettings(); } @@ -169,11 +181,12 @@ namespace FlashTools.Internal { void OnEnable() { _asset = target as SwfAnimationAsset; - _settingsFoldout = _asset && !_asset.Settings.Equal(SwfConverterSettings.GetDefaultSettings()); + _settingsFoldout = _asset && !_asset.Settings.CheckEquals( + SwfConverterSettings.GetDefaultSettings()); } void OnDisable() { - if ( _asset && !_asset.Settings.Equal(_asset.Overridden) ) { + if ( _asset && !_asset.Settings.CheckEquals(_asset.Overridden) ) { ShowUnappliedDialog(); } } diff --git a/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetPostprocessor.cs b/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetPostprocessor.cs index 7ca60c5..e372b7a 100644 --- a/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetPostprocessor.cs +++ b/Assets/FlashTools/Scripts/Internal/Editor/SwfAnimationAssetPostprocessor.cs @@ -8,8 +8,10 @@ using System.Reflection; namespace FlashTools.Internal { public class SwfAnimationAssetPostprocessor : AssetPostprocessor { static void OnPostprocessAllAssets( - string[] imported_assets, string[] deleted_assets, - string[] moved_assets, string[] moved_from_asset_paths) + string[] imported_assets, + string[] deleted_assets, + string[] moved_assets, + string[] moved_from_asset_paths) { var asset_paths = imported_assets .Where(p => Path.GetExtension(p).ToLower().Equals(".asset")); @@ -23,9 +25,9 @@ namespace FlashTools.Internal { static void AssetProcess(string asset_path, SwfAnimationAsset asset) { try { - var new_asset = AssetDatabase.LoadAssetAtPath(GetAtlasPath(asset_path)); - if ( new_asset != asset.Atlas ) { - asset.Atlas = new_asset; + var atlas_asset = LoadAtlasAsset(asset_path); + if ( atlas_asset != asset.Atlas ) { + asset.Atlas = atlas_asset; ConfigureAtlas(asset_path, asset); EditorUtility.SetDirty(asset); AssetDatabase.SaveAssets(); @@ -37,38 +39,47 @@ namespace FlashTools.Internal { } } + static Texture2D LoadAtlasAsset(string asset_path) { + return AssetDatabase.LoadAssetAtPath( + GetAtlasPath(asset_path)); + } + + static string GetAtlasPath(string asset_path) { + return Path.ChangeExtension(asset_path, ".png"); + } + static void ConfigureAtlas(string asset_path, SwfAnimationAsset asset) { - var atlas_importer = GetBitmapsAtlasImporter(asset_path); - var atlas_size = GetSizeFromTextureImporter(atlas_importer); + var atlas_importer = GetBitmapsAtlasImporter(asset_path); + var atlas_importer_size = GetSizeFromTextureImporter(atlas_importer); atlas_importer.spritesheet = asset.Data.Bitmaps .Select(bitmap => new SpriteMetaData{ name = bitmap.Id.ToString(), rect = new Rect( - bitmap.SourceRect.xMin * atlas_size.x, - bitmap.SourceRect.yMin * atlas_size.y, - bitmap.SourceRect.width * atlas_size.x, - bitmap.SourceRect.height * atlas_size.y)}) + bitmap.SourceRect.xMin * atlas_importer_size.x, + bitmap.SourceRect.yMin * atlas_importer_size.y, + bitmap.SourceRect.width * atlas_importer_size.x, + bitmap.SourceRect.height * atlas_importer_size.y)}) .ToArray(); atlas_importer.textureType = TextureImporterType.Sprite; atlas_importer.spriteImportMode = SpriteImportMode.Multiple; atlas_importer.spritePixelsPerUnit = asset.Settings.PixelsPerUnit; atlas_importer.mipmapEnabled = asset.Settings.GenerateMipMaps; - atlas_importer.filterMode = asset.Settings.AtlasFilterMode; - atlas_importer.textureFormat = asset.Settings.AtlasImporterFormat; + atlas_importer.filterMode = SwfAtlasFilterToImporterFilter(asset.Settings.AtlasTextureFilter); + atlas_importer.textureFormat = SwfAtlasFormatToImporterFormat(asset.Settings.AtlasTextureFormat); AssetDatabase.ImportAsset( GetAtlasPath(asset_path), ImportAssetOptions.ForceUpdate); } static TextureImporter GetBitmapsAtlasImporter(string asset_path) { - var atlas_path = GetAtlasPath(asset_path); - var importer = AssetImporter.GetAtPath(atlas_path) as TextureImporter; - if ( !importer ) { + var atlas_path = GetAtlasPath(asset_path); + var atlas_importer = AssetImporter.GetAtPath(atlas_path) as TextureImporter; + if ( !atlas_importer ) { throw new UnityException(string.Format( "atlas texture importer not found ({0})", atlas_path)); } - return importer; + return atlas_importer; } static Vector2 GetSizeFromTextureImporter(TextureImporter importer) { @@ -79,8 +90,40 @@ namespace FlashTools.Internal { return new Vector2((int)method_args[0], (int)method_args[1]); } - static string GetAtlasPath(string asset_path) { - return Path.ChangeExtension(asset_path, ".png"); + static FilterMode SwfAtlasFilterToImporterFilter( + SwfConverterSettings.SwfAtlasFilter filter) + { + switch ( filter ) { + case SwfConverterSettings.SwfAtlasFilter.Point: + return FilterMode.Point; + case SwfConverterSettings.SwfAtlasFilter.Bilinear: + return FilterMode.Bilinear; + case SwfConverterSettings.SwfAtlasFilter.Trilinear: + return FilterMode.Trilinear; + default: + throw new UnityException(string.Format( + "incorrect swf atlas filter ({0})", + filter)); + } + } + + static TextureImporterFormat SwfAtlasFormatToImporterFormat( + SwfConverterSettings.SwfAtlasFormat format) + { + switch ( format ) { + case SwfConverterSettings.SwfAtlasFormat.AutomaticCompressed: + return TextureImporterFormat.AutomaticCompressed; + case SwfConverterSettings.SwfAtlasFormat.Automatic16bit: + return TextureImporterFormat.Automatic16bit; + case SwfConverterSettings.SwfAtlasFormat.AutomaticTruecolor: + return TextureImporterFormat.AutomaticTruecolor; + case SwfConverterSettings.SwfAtlasFormat.AutomaticCrunched: + return TextureImporterFormat.AutomaticCrunched; + default: + throw new UnityException(string.Format( + "incorrect swf atlas format ({0})", + format)); + } } } } \ No newline at end of file diff --git a/Assets/FlashTools/Scripts/Internal/Editor/SwfPostprocessor.cs b/Assets/FlashTools/Scripts/Internal/Editor/SwfPostprocessor.cs index 8007582..0b8182a 100644 --- a/Assets/FlashTools/Scripts/Internal/Editor/SwfPostprocessor.cs +++ b/Assets/FlashTools/Scripts/Internal/Editor/SwfPostprocessor.cs @@ -12,8 +12,10 @@ using FlashTools.Internal.SwfTools.SwfTypes; namespace FlashTools.Internal { public class SwfPostprocessor : AssetPostprocessor { static void OnPostprocessAllAssets( - string[] imported_assets, string[] deleted_assets, - string[] moved_assets, string[] moved_from_asset_paths) + string[] imported_assets, + string[] deleted_assets, + string[] moved_assets, + string[] moved_from_asset_paths) { var swf_asset_paths = imported_assets .Where(p => Path.GetExtension(p).ToLower().Equals(".swf")); @@ -33,7 +35,7 @@ namespace FlashTools.Internal { EditorUtility.SetDirty(new_asset); AssetDatabase.SaveAssets(); } else { - AssetDatabase.DeleteAsset(new_asset_path); + DeleteSwfAnimationAsset(new_asset); } } @@ -184,57 +186,18 @@ namespace FlashTools.Internal { .Select (p => LoadTextureFromBitmapDefine(p.Value)) .ToArray(); - var atlas_padding = Mathf.Max(0, asset.Settings.AtlasPadding); - var max_atlas_size = (asset.Settings.AtlasPowerOfTwo && !Mathf.IsPowerOfTwo(asset.Settings.MaxAtlasSize)) - ? Mathf.NextPowerOfTwo(asset.Settings.MaxAtlasSize) - : asset.Settings.MaxAtlasSize; - - var atlas = new Texture2D(0, 0); - var atlas_rects = atlas.PackTextures( + var rects = PackAndSaveBitmapsAtlas( + swf_asset, textures, - atlas_padding, - Mathf.Max(32, max_atlas_size)); + asset.Settings); - if ( asset.Settings.AtlasForceSquare && atlas.width != atlas.height ) { - var atlas_size = Mathf.Max(atlas.width, atlas.height); - var new_atlas = new Texture2D(atlas_size, atlas_size, TextureFormat.ARGB32, false); - for ( var i = 0; i < atlas_rects.Length; ++i ) { - var new_position = atlas_rects[i].position; - new_position.x *= (float)(atlas.width )/atlas_size; - new_position.y *= (float)(atlas.height)/atlas_size; - - var new_size = atlas_rects[i].size; - new_size.x *= (float)(atlas.width )/atlas_size; - new_size.y *= (float)(atlas.height)/atlas_size; - - atlas_rects[i] = new Rect(new_position, new_size); - } - var empty_pixels = new Color32[atlas_size * atlas_size]; - for ( var i = 0; i < atlas_size * atlas_size; ++i ) { - empty_pixels[i] = new Color(1,1,1,0); - } - new_atlas.SetPixels32(empty_pixels); - new_atlas.SetPixels32(0, 0, atlas.width, atlas.height, atlas.GetPixels32()); - new_atlas.Apply(); - GameObject.DestroyImmediate(atlas, true); - atlas = new_atlas; - } - - File.WriteAllBytes( - GetAtlasPath(swf_asset), - atlas.EncodeToPNG()); - GameObject.DestroyImmediate(atlas, true); - AssetDatabase.ImportAsset( - GetAtlasPath(swf_asset), - ImportAssetOptions.ForceUpdate); - - var bitmaps = new List(); + var bitmaps = new List(bitmap_defines.Length); for ( var i = 0; i < bitmap_defines.Length; ++i ) { var bitmap_define = bitmap_defines[i]; var bitmap_data = new SwfAnimationBitmapData{ Id = bitmap_define.Key, RealSize = new Vector2(bitmap_define.Value.Width, bitmap_define.Value.Height), - SourceRect = atlas_rects[i] + SourceRect = rects[i] }; bitmaps.Add(bitmap_data); } @@ -251,8 +214,8 @@ namespace FlashTools.Internal { } static void RevertTexturePremultipliedAlpha(Texture2D texture) { - for (int y = 0; y < texture.height; ++y) { - for (int x = 0; x < texture.width; ++x) { + for ( int y = 0; y < texture.height; ++y ) { + for ( int x = 0; x < texture.width; ++x ) { var c = texture.GetPixel(x, y); if ( c.a > 0 ) { c.r /= c.a; @@ -265,8 +228,77 @@ namespace FlashTools.Internal { texture.Apply(); } + struct BitmapsAtlasInfo { + public Texture2D Atlas; + public Rect[] Rects; + } + static string GetAtlasPath(string swf_asset) { return Path.ChangeExtension(swf_asset, ".png"); } + + static Rect[] PackAndSaveBitmapsAtlas( + string swf_asset, + Texture2D[] textures, + SwfConverterSettings.Settings settings) + { + var atlas_info = PackBitmapsAtlas(textures, settings); + File.WriteAllBytes( + GetAtlasPath(swf_asset), + atlas_info.Atlas.EncodeToPNG()); + GameObject.DestroyImmediate(atlas_info.Atlas, true); + AssetDatabase.ImportAsset( + GetAtlasPath(swf_asset), + ImportAssetOptions.ForceUpdate); + return atlas_info.Rects; + } + + static BitmapsAtlasInfo PackBitmapsAtlas( + Texture2D[] textures, + SwfConverterSettings.Settings settings) + { + var atlas_padding = Mathf.Max(0, settings.AtlasPadding); + var max_atlas_size = Mathf.Max(32, settings.AtlasPowerOfTwo + ? Mathf.ClosestPowerOfTwo(settings.MaxAtlasSize) + : settings.MaxAtlasSize); + var atlas = new Texture2D(0, 0); + var rects = atlas.PackTextures(textures, atlas_padding, max_atlas_size); + return settings.AtlasForceSquare && atlas.width != atlas.height + ? BitmapsAtlasToSquare(atlas, rects) + : new BitmapsAtlasInfo{Atlas = atlas, Rects = rects}; + } + + static BitmapsAtlasInfo BitmapsAtlasToSquare(Texture2D atlas, Rect[] rects) { + var atlas_size = Mathf.Max(atlas.width, atlas.height); + var atlas_scale = new Vector2(atlas.width, atlas.height) / atlas_size; + var new_atlas = new Texture2D(atlas_size, atlas_size, TextureFormat.ARGB32, false); + for ( var i = 0; i < rects.Length; ++i ) { + var new_position = rects[i].position; + new_position.Scale(atlas_scale); + var new_size = rects[i].size; + new_size.Scale(atlas_scale); + rects[i] = new Rect(new_position, new_size); + } + var fill_pixels = new Color32[atlas_size * atlas_size]; + for ( var i = 0; i < atlas_size * atlas_size; ++i ) { + fill_pixels[i] = new Color(1,1,1,0); + } + new_atlas.SetPixels32(fill_pixels); + new_atlas.SetPixels32(0, 0, atlas.width, atlas.height, atlas.GetPixels32()); + new_atlas.Apply(); + GameObject.DestroyImmediate(atlas, true); + return new BitmapsAtlasInfo{Atlas = new_atlas, Rects = rects}; + } + + static void DeleteSwfAnimationAsset(SwfAnimationAsset asset) { + if ( asset ) { + if ( asset.Atlas ) { + AssetDatabase.DeleteAsset( + AssetDatabase.GetAssetPath(asset.Atlas)); + } + AssetDatabase.DeleteAsset( + AssetDatabase.GetAssetPath(asset)); + } + } } } \ No newline at end of file diff --git a/Assets/FlashTools/Scripts/Internal/Editor/SwfTools/SwfContextExecuter.cs b/Assets/FlashTools/Scripts/Internal/Editor/SwfTools/SwfContextExecuter.cs index ecd8efc..cda7085 100644 --- a/Assets/FlashTools/Scripts/Internal/Editor/SwfTools/SwfContextExecuter.cs +++ b/Assets/FlashTools/Scripts/Internal/Editor/SwfTools/SwfContextExecuter.cs @@ -18,7 +18,7 @@ namespace FlashTools.Internal.SwfTools { dl.FrameName = string.Empty; while ( CurrentTag < tags.Count ) { var tag = tags[CurrentTag++]; - TagToDebugLog(tag); + //TagToDebugLog(tag); tag.AcceptVistor(this, dl); if ( tag.TagType == SwfTagType.ShowFrame ) { ChildrenNextFrameLooped(dl); diff --git a/Assets/FlashTools/Scripts/SwfAnimationAsset.cs b/Assets/FlashTools/Scripts/SwfAnimationAsset.cs index 8dc7d69..0e73917 100644 --- a/Assets/FlashTools/Scripts/SwfAnimationAsset.cs +++ b/Assets/FlashTools/Scripts/SwfAnimationAsset.cs @@ -71,8 +71,10 @@ namespace FlashTools { public class SwfAnimationAsset : ScriptableObject { public SwfAnimationData Data; public Texture2D Atlas; + #if UNITY_EDITOR public SwfConverterSettings.Settings Settings; public SwfConverterSettings.Settings Overridden; + #endif #if UNITY_EDITOR void Reset() { diff --git a/Assets/FlashTools/Scripts/SwfConverterSettings.cs b/Assets/FlashTools/Scripts/SwfConverterSettings.cs index b67ffce..2f4bb32 100644 --- a/Assets/FlashTools/Scripts/SwfConverterSettings.cs +++ b/Assets/FlashTools/Scripts/SwfConverterSettings.cs @@ -1,48 +1,61 @@ using UnityEngine; #if UNITY_EDITOR -using System.IO; using UnityEditor; +using System.IO; #endif namespace FlashTools { public class SwfConverterSettings : ScriptableObject { + public enum SwfAtlasFilter { + Point, + Bilinear, + Trilinear + } + + public enum SwfAtlasFormat { + AutomaticCompressed, + Automatic16bit, + AutomaticTruecolor, + AutomaticCrunched + } + [System.Serializable] public struct Settings { - public int MaxAtlasSize; - public int AtlasPadding; - public int PixelsPerUnit; - public bool GenerateMipMaps; - public bool AtlasPowerOfTwo; - public bool AtlasForceSquare; //TODO: implme - public FilterMode AtlasFilterMode; - public TextureImporterFormat AtlasImporterFormat; - - public bool Equal(Settings other) { - return - MaxAtlasSize == other.MaxAtlasSize && - AtlasPadding == other.AtlasPadding && - PixelsPerUnit == other.PixelsPerUnit && - GenerateMipMaps == other.GenerateMipMaps && - AtlasPowerOfTwo == other.AtlasPowerOfTwo && - AtlasForceSquare == other.AtlasForceSquare && - AtlasFilterMode == other.AtlasFilterMode && - AtlasImporterFormat == other.AtlasImporterFormat; - } + public int MaxAtlasSize; + public int AtlasPadding; + public int PixelsPerUnit; + public bool GenerateMipMaps; + public bool AtlasPowerOfTwo; + public bool AtlasForceSquare; + public SwfAtlasFilter AtlasTextureFilter; + public SwfAtlasFormat AtlasTextureFormat; public static Settings identity { get { return new Settings{ - MaxAtlasSize = 1024, - AtlasPadding = 1, - PixelsPerUnit = 100, - GenerateMipMaps = true, - AtlasPowerOfTwo = true, - AtlasForceSquare = false, - AtlasFilterMode = FilterMode.Bilinear, - AtlasImporterFormat = TextureImporterFormat.AutomaticTruecolor}; + MaxAtlasSize = 1024, + AtlasPadding = 1, + PixelsPerUnit = 100, + GenerateMipMaps = true, + AtlasPowerOfTwo = true, + AtlasForceSquare = false, + AtlasTextureFilter = SwfAtlasFilter.Bilinear, + AtlasTextureFormat = SwfAtlasFormat.AutomaticTruecolor}; } } + + public bool CheckEquals(Settings other) { + return + MaxAtlasSize == other.MaxAtlasSize && + AtlasPadding == other.AtlasPadding && + PixelsPerUnit == other.PixelsPerUnit && + GenerateMipMaps == other.GenerateMipMaps && + AtlasPowerOfTwo == other.AtlasPowerOfTwo && + AtlasForceSquare == other.AtlasForceSquare && + AtlasTextureFilter == other.AtlasTextureFilter && + AtlasTextureFormat == other.AtlasTextureFormat; + } } public Settings DefaultSettings; @@ -51,8 +64,8 @@ namespace FlashTools { DefaultSettings = Settings.identity; } - public static SwfConverterSettings.Settings GetDefaultSettings() { - var settings_path = GetSettingsPath(); + public static Settings GetDefaultSettings() { + var settings_path = DefaultSettingsPath; var settings = AssetDatabase.LoadAssetAtPath(settings_path); if ( !settings ) { settings = ScriptableObject.CreateInstance(); @@ -63,6 +76,12 @@ namespace FlashTools { return settings.DefaultSettings; } + static string DefaultSettingsPath { + get { + return "Assets/FlashTools/Resources/SwfConverterSettings.asset"; + } + } + static void CreateAssetDatabaseFolders(string path) { if ( !AssetDatabase.IsValidFolder(path) ) { var parent = Path.GetDirectoryName(path); @@ -72,10 +91,6 @@ namespace FlashTools { AssetDatabase.CreateFolder(parent, Path.GetFileName(path)); } } - - static string GetSettingsPath() { - return "Assets/FlashTools/Resources/SwfConverterSettings.asset"; - } #endif } } \ No newline at end of file