diff --git a/Assembly-CSharp-Editor.csproj b/Assembly-CSharp-Editor.csproj index 843a48e..974f414 100644 --- a/Assembly-CSharp-Editor.csproj +++ b/Assembly-CSharp-Editor.csproj @@ -49,6 +49,9 @@ + + + /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Advertisements/Editor/UnityEditor.Advertisements.dll @@ -103,6 +106,9 @@ /Applications/Unity/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll + + + /Users/matov/Programming/Projects/unityflash/Assets/Plugins/Ionic.Zip.Unity.dll diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index b0d445b..eac836c 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -53,6 +53,9 @@ /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll + + + /Users/matov/Programming/Projects/unityflash/Assets/Plugins/Ionic.Zip.Unity.dll diff --git a/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla b/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla new file mode 100644 index 0000000..603f662 Binary files /dev/null and b/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla differ diff --git a/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla.meta b/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla.meta new file mode 100644 index 0000000..93ffef8 --- /dev/null +++ b/Assets/FlashTools/Examples/Animations/Tests/swf_test.fla.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c317ff8ea48c428da50f57544fe49bd +timeCreated: 1457365163 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs new file mode 100644 index 0000000..f63abe3 --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs @@ -0,0 +1,35 @@ +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Linq; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using Ionic.Zlib; + +namespace FlashTools.Internal { + public class FlashAnimSwfPostprocessor : AssetPostprocessor { + static void OnPostprocessAllAssets( + 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")); + foreach ( var swf_asset_path in swf_asset_paths ) { + SwfAssetProcess(swf_asset_path); + } + } + + static void SwfAssetProcess(string swf_asset) { + Debug.LogFormat("SwfAssetProcess: {0}", swf_asset); + var reader = new SwfStreamReader(swf_asset); + var header = SwfHeader.Read(reader); + Debug.LogFormat("Header: {0}", header); + while ( !reader.IsEOF ) { + var tag_data = SwfTagData.Read(reader); + var tag = SwfTagBase.Create(tag_data); + Debug.LogFormat("Tag: {0} - {1}", tag.TagType.ToString(), tag.ToString()); + } + } + } +} diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs.meta b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs.meta new file mode 100644 index 0000000..cbe9645 --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfPostprocessor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 27c44c175a74f4707bafa0bb1a8d47f7 +timeCreated: 1457365970 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs new file mode 100644 index 0000000..f5e834e --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs @@ -0,0 +1,758 @@ +using System.IO; +using System.Collections.Generic; +using Ionic.Zlib; + +namespace FlashTools.Internal { + enum SwfTagType : ushort { + // + // Display list + // + PlaceObject = 4, + PlaceObject2 = 26, + PlaceObject3 = 70, + RemoveObject = 5, + RemoveObject2 = 28, + ShowFrame = 1, + + // + // Control + // + SetBackgroundColor = 9, + FrameLabel = 43, + //Protect = 24, + End = 0, + //ExportAssets = 56, + //ImportAssets = 57, + //EnableDebugger = 58, + //EnableDebugger2 = 64, + //ScriptLimits = 65, + SetTabIndex = 66, + //ImportAssets2 = 71, + //SymbolClass = 76, + //Metadata = 77, + DefineScalingGrid = 78, + DefineSceneAndFrameLabelData = 86, + + // + // Actions + // + //DoAction = 12, + //DoInitAction = 59, + //DoABC = 82, + + // + // Shape + // + DefineShape = 2, + DefineShape2 = 22, + DefineShape3 = 32, + DefineShape4 = 83, + + // + // Bitmaps + // + DefineBits = 6, + JPEGTables = 8, + DefineBitsJPEG2 = 21, + DefineBitsJPEG3 = 35, + DefineBitsLossless = 20, + DefineBitsLossless2 = 36, + DefineBitsJPEG4 = 90, + + // + // Shape Morphing + // + //DefineMorphShape = 46, + //DefineMorphShape2 = 84, + + // + // Fonts and Text + // + //DefineFont = 10, + //DefineFontInfo = 13, + //DefineFontInfo2 = 62, + //DefineFont2 = 48, + //DefineFont3 = 75, + //DefineFontAlignZones = 73, + //DefineFontName = 88, + //DefineText = 11, + //DefineText2 = 33, + //DefineEditText = 37, + //CSMTextSettings = 74, + //DefineFont4 = 91, + + // + // Sounds + // + //DefineSound = 14, + //StartSound = 15, + //StartSound2 = 89, + //SoundStreamHead = 18, + //SoundStreamHead2 = 45, + //SoundStreamBlock = 19, + + // + // Buttons + // + //DefineButton = 7, + //DefineButton2 = 34, + //DefineButtonCxform = 23, + //DefineButtonSound = 17, + + // + // Sprites and Movie Clips + // + DefineSprite = 39, + + // + // Video + // + //DefineVideoStream = 60, + //VideoFrame = 61, + + // + // Metadata + // + FileAttributes = 69, + //EnableTelemetry = 93, + //DefineBinaryData = 87, + } + + struct SwfTagData { + public SwfTagType Type; + public byte[] Data; + + public static SwfTagData Read(SwfStreamReader reader) { + var type_and_size = reader.Reader.ReadUInt16(); + var type = (SwfTagType)(type_and_size >> 6); + var short_size = type_and_size & 0x3f; + var size = short_size < 0x3f ? short_size : reader.Reader.ReadInt32(); + var tag_data = reader.Reader.ReadBytes(size); + return new SwfTagData{Type = type, Data = tag_data}; + } + } + + abstract class SwfTagBase { + public abstract SwfTagType TagType { get; } + public static SwfTagBase Create(SwfTagData tag_data) { + var stream = new MemoryStream(tag_data.Data); + var reader = new SwfStreamReader(stream); + switch ( tag_data.Type ) { + case SwfTagType.PlaceObject: return PlaceObjectTag.Create(reader); + case SwfTagType.PlaceObject2: return PlaceObject2Tag.Create(reader); + case SwfTagType.PlaceObject3: return PlaceObject3Tag.Create(reader); + case SwfTagType.RemoveObject: return RemoveObjectTag.Create(reader); + case SwfTagType.RemoveObject2: return RemoveObject2Tag.Create(reader); + case SwfTagType.ShowFrame: return ShowFrameTag.Create(reader); + case SwfTagType.SetBackgroundColor: return SetBackgroundColorTag.Create(reader); + case SwfTagType.FrameLabel: return FrameLabelTag.Create(reader); + case SwfTagType.End: return EndTag.Create(reader); + case SwfTagType.SetTabIndex: return SetTabIndexTag.Create(reader); + case SwfTagType.DefineScalingGrid: return DefineScalingGridTag.Create(reader); + case SwfTagType.DefineSceneAndFrameLabelData: return DefineSceneAndFrameLabelDataTag.Create(reader); + case SwfTagType.DefineShape: return DefineShapeTag.Create(reader); + case SwfTagType.DefineShape2: return DefineShape2Tag.Create(reader); + case SwfTagType.DefineShape3: return DefineShape3Tag.Create(reader); + case SwfTagType.DefineShape4: return DefineShape4Tag.Create(reader); + //case DefineBits: + //case JPEGTables: + //case DefineBitsJPEG2: + //case DefineBitsJPEG3: + case SwfTagType.DefineBitsLossless: return DefineBitsLosslessTag.Create(reader); + case SwfTagType.DefineBitsLossless2: return DefineBitsLossless2Tag.Create(reader); + //case DefineBitsJPEG4: + case SwfTagType.DefineSprite: return DefineSpriteTag.Create(reader); + case SwfTagType.FileAttributes: return FileAttributesTag.Create(reader); + default: return UnknownTag.Create(tag_data.Type); + } + } + } + + class PlaceObjectTag : SwfTagBase { + public ushort CharacterId; + public ushort Depth; + public SwfMatrix Matrix; + public SwfColorTransformRGB ColorTransform; + + public override string ToString() { + return string.Format( + "CharacterId: {0}, Depth: {1}, Matrix: {2}, ColorTransform: {3}", + CharacterId, Depth, Matrix, ColorTransform); + } + + public override SwfTagType TagType { + get { return SwfTagType.PlaceObject; } + } + + public static PlaceObjectTag Create(SwfStreamReader reader) { + var tag = new PlaceObjectTag(); + tag.CharacterId = reader.Reader.ReadUInt16(); + tag.Depth = reader.Reader.ReadUInt16(); + tag.Matrix = SwfMatrix.Read(reader); + if ( !reader.IsEOF ) { + tag.ColorTransform = SwfColorTransformRGB.Read(reader); + } + return tag; + } + } + + class PlaceObject2Tag : SwfTagBase { + public bool HasClipActions; + public bool HasClipDepth; + public bool HasName; + public bool HasRatio; + public bool HasColorTransform; + public bool HasMatrix; + public bool HasCharacter; + public bool Move; + public ushort Depth; + public ushort CharacterId; + public SwfMatrix Matrix; + public SwfColorTransformRGBA ColorTransform; + public ushort Ratio; + public string Name; + public ushort ClipDepth; + public SwfClipActions ClipActions; + + public override string ToString() { + return string.Format( + "CharacterId: {0}, Depth: {1}, Matrix: {2}, ColorTransform: {3}", + CharacterId, Depth, Matrix, ColorTransform); + } + + public override SwfTagType TagType { + get { return SwfTagType.PlaceObject2; } + } + + public static PlaceObject2Tag Create(SwfStreamReader reader) { + var tag = new PlaceObject2Tag(); + tag.HasClipActions = reader.ReadBit(); + tag.HasClipDepth = reader.ReadBit(); + tag.HasName = reader.ReadBit(); + tag.HasRatio = reader.ReadBit(); + tag.HasColorTransform = reader.ReadBit(); + tag.HasMatrix = reader.ReadBit(); + tag.HasCharacter = reader.ReadBit(); + tag.Move = reader.ReadBit(); + tag.Depth = reader.Reader.ReadUInt16(); + if ( tag.HasCharacter ) { + tag.CharacterId = reader.Reader.ReadUInt16(); + } + if ( tag.HasMatrix ) { + tag.Matrix = SwfMatrix.Read(reader); + } + if ( tag.HasColorTransform ) { + tag.ColorTransform = SwfColorTransformRGBA.Read(reader); + } + if ( tag.HasRatio ) { + tag.Ratio = reader.Reader.ReadUInt16(); + } + if ( tag.HasName ) { + tag.Name = reader.ReadString(); + } + if ( tag.HasClipDepth ) { + tag.ClipDepth = reader.Reader.ReadUInt16(); + } + if ( tag.HasClipActions ) { + tag.ClipActions = SwfClipActions.Read(reader); + } + return tag; + } + } + + class PlaceObject3Tag : SwfTagBase { + public bool HasClipActions; + public bool HasClipDepth; + public bool HasName; + public bool HasRatio; + public bool HasColorTransform; + public bool HasMatrix; + public bool HasCharacter; + public bool Move; + public bool OpaqueBackground; + public bool HasVisible; + public bool HasImage; + public bool HasClassName; + public bool HasCacheAsBitmap; + public bool HasBlendMode; + public bool HasFilterList; + public ushort Depth; + public string ClassName; + public ushort CharacterId; + public SwfMatrix Matrix; + public SwfColorTransformRGBA ColorTransform; + public ushort Ratio; + public string Name; + public ushort ClipDepth; + public SwfSurfaceFilters SurfaceFilters; + public SwfBlendMode BlendMode; + public byte BitmapCache; + public byte Visible; + public SwfRGBA BackgroundColor; + public SwfClipActions ClipActions; + + public override string ToString() { + return string.Format( + "CharacterId: {0}, Depth: {1}, Matrix: {2}, ColorTransform: {3}", + CharacterId, Depth, Matrix, ColorTransform); + } + + public override SwfTagType TagType { + get { return SwfTagType.PlaceObject3; } + } + + public static PlaceObject3Tag Create(SwfStreamReader reader) { + var tag = new PlaceObject3Tag(); + tag.HasClipActions = reader.ReadBit(); + tag.HasClipDepth = reader.ReadBit(); + tag.HasName = reader.ReadBit(); + tag.HasRatio = reader.ReadBit(); + tag.HasColorTransform = reader.ReadBit(); + tag.HasMatrix = reader.ReadBit(); + tag.HasCharacter = reader.ReadBit(); + tag.Move = reader.ReadBit(); + reader.ReadBit(); // reserved + tag.OpaqueBackground = reader.ReadBit(); + tag.HasVisible = reader.ReadBit(); + tag.HasImage = reader.ReadBit(); + tag.HasClassName = reader.ReadBit(); + tag.HasCacheAsBitmap = reader.ReadBit(); + tag.HasBlendMode = reader.ReadBit(); + tag.HasFilterList = reader.ReadBit(); + tag.Depth = reader.Reader.ReadUInt16(); + if ( tag.HasCharacter || (tag.HasImage && tag.HasCharacter) ) { + tag.ClassName = reader.ReadString(); + } + if ( tag.HasCharacter ) { + tag.CharacterId = reader.Reader.ReadUInt16(); + } + if ( tag.HasMatrix ) { + tag.Matrix = SwfMatrix.Read(reader); + } + if ( tag.HasColorTransform ) { + tag.ColorTransform = SwfColorTransformRGBA.Read(reader); + } + if ( tag.HasRatio ) { + tag.Ratio = reader.Reader.ReadUInt16(); + } + if ( tag.HasName ) { + tag.Name = reader.ReadString(); + } + if ( tag.HasClipDepth ) { + tag.ClipDepth = reader.Reader.ReadUInt16(); + } + if ( tag.HasFilterList ) { + tag.SurfaceFilters = SwfSurfaceFilters.Read(reader); + } + if ( tag.HasBlendMode ) { + tag.BlendMode = (SwfBlendMode)reader.Reader.ReadByte(); + } + if ( tag.HasCacheAsBitmap ) { + tag.BitmapCache = reader.Reader.ReadByte(); + } + if ( tag.HasVisible ) { + tag.Visible = reader.Reader.ReadByte(); + tag.BackgroundColor = SwfRGBA.Read(reader); + } + if ( tag.HasClipActions ) { + tag.ClipActions = SwfClipActions.Read(reader); + } + return tag; + } + } + + class RemoveObjectTag : SwfTagBase { + public ushort CharacterId; + public ushort Depth; + + public override string ToString() { + return string.Format("CharacterId: {0}, Depth: {1}", CharacterId, Depth); + } + + public override SwfTagType TagType { + get { return SwfTagType.RemoveObject; } + } + + public static RemoveObjectTag Create(SwfStreamReader reader) { + var tag = new RemoveObjectTag(); + tag.CharacterId = reader.Reader.ReadUInt16(); + tag.Depth = reader.Reader.ReadUInt16(); + return tag; + } + } + + class RemoveObject2Tag : SwfTagBase { + public ushort Depth; + + public override string ToString() { + return string.Format("Depth: {0}", Depth); + } + + public override SwfTagType TagType { + get { return SwfTagType.RemoveObject2; } + } + + public static RemoveObject2Tag Create(SwfStreamReader reader) { + var tag = new RemoveObject2Tag(); + tag.Depth = reader.Reader.ReadUInt16(); + return tag; + } + } + + class ShowFrameTag : SwfTagBase { + public override string ToString() { + return "ShowFrameTag"; + } + + public override SwfTagType TagType { + get { return SwfTagType.ShowFrame; } + } + + public static ShowFrameTag Create(SwfStreamReader reader) { + return new ShowFrameTag(); + } + } + + class SetBackgroundColorTag : SwfTagBase { + public SwfRGB BackgroundColor; + + public override string ToString() { + return string.Format("BackgroundColor: {0}", BackgroundColor); + } + + public override SwfTagType TagType { + get { return SwfTagType.SetBackgroundColor; } + } + + public static SetBackgroundColorTag Create(SwfStreamReader reader) { + var tag = new SetBackgroundColorTag(); + tag.BackgroundColor = SwfRGB.Read(reader); + return tag; + } + } + + class FrameLabelTag : SwfTagBase { + public string Name; + public byte AnchorFlag; + + public override string ToString() { + return string.Format("Name: {0}, AnchorFlag: {1}", Name, AnchorFlag); + } + + public override SwfTagType TagType { + get { return SwfTagType.FrameLabel; } + } + + public static FrameLabelTag Create(SwfStreamReader reader) { + var tag = new FrameLabelTag(); + tag.Name = reader.ReadString(); + if ( !reader.IsEOF ) { + tag.AnchorFlag = reader.Reader.ReadByte(); + } + return tag; + } + } + + class EndTag : SwfTagBase { + public override string ToString() { + return "EndTag"; + } + + public override SwfTagType TagType { + get { return SwfTagType.End; } + } + + public static EndTag Create(SwfStreamReader reader) { + return new EndTag(); + } + } + + class SetTabIndexTag : SwfTagBase { + public ushort Depth; + public ushort TabIndex; + + public override string ToString() { + return string.Format("Depth: {0}, TabIndex: {1}", Depth, TabIndex); + } + + public override SwfTagType TagType { + get { return SwfTagType.SetTabIndex; } + } + + public static SetTabIndexTag Create(SwfStreamReader reader) { + var tag = new SetTabIndexTag(); + tag.Depth = reader.Reader.ReadUInt16(); + tag.TabIndex = reader.Reader.ReadUInt16(); + return tag; + } + } + + class DefineScalingGridTag : SwfTagBase { + public ushort CharacterId; + public SwfRect Splitter; + + public override string ToString() { + return string.Format("CharacterId: {0}, Splitter: {1}", CharacterId, Splitter); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineScalingGrid; } + } + + public static DefineScalingGridTag Create(SwfStreamReader reader) { + var tag = new DefineScalingGridTag(); + tag.CharacterId = reader.Reader.ReadUInt16(); + tag.Splitter = SwfRect.Read(reader); + return tag; + } + } + + class DefineSceneAndFrameLabelDataTag : SwfTagBase { + public List Scenes = new List(); + public List Frames = new List(); + + public override string ToString() { + return string.Format("Scenes: {0}, Frames: {1}", Scenes.Count, Frames.Count); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineSceneAndFrameLabelData; } + } + + public static DefineSceneAndFrameLabelDataTag Create(SwfStreamReader reader) { + var tag = new DefineSceneAndFrameLabelDataTag(); + var scenes = reader.ReadEncodedU32(); + for ( var i = 0; i < scenes; ++i ) { + tag.Scenes.Add(new SceneOffsetData { + Offset = reader.ReadEncodedU32(), + Name = reader.ReadString() + }); + } + var frames = reader.ReadEncodedU32(); + for ( var i = 0; i < frames; ++i ) { + tag.Frames.Add(new FrameLabelData { + Number = reader.ReadEncodedU32(), + Label = reader.ReadString() + }); + } + return tag; + } + } + + class DefineShapeTag : SwfTagBase { + public ushort ShapeID; + public SwfRect ShapeBounds; + + public override string ToString() { + return string.Format("ShapeID: {0}, ShapeBounds: {1}", ShapeID, ShapeBounds); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineShape; } + } + + public static DefineShapeTag Create(SwfStreamReader reader) { + var tag = new DefineShapeTag(); + tag.ShapeID = reader.Reader.ReadUInt16(); + tag.ShapeBounds = SwfRect.Read(reader); + //tag.Shapes = SwfShapes.Read(reader); + return tag; + } + } + + class DefineShape2Tag : SwfTagBase { + public ushort ShapeID; + public SwfRect ShapeBounds; + + public override string ToString() { + return string.Format("ShapeID: {0}, ShapeBounds: {1}", ShapeID, ShapeBounds); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineShape2; } + } + + public static DefineShape2Tag Create(SwfStreamReader reader) { + var tag = new DefineShape2Tag(); + tag.ShapeID = reader.Reader.ReadUInt16(); + tag.ShapeBounds = SwfRect.Read(reader); + //tag.Shapes = SwfShapes.Read(reader); + return tag; + } + } + + class DefineShape3Tag : SwfTagBase { + public ushort ShapeID; + public SwfRect ShapeBounds; + + public override string ToString() { + return string.Format("ShapeID: {0}, ShapeBounds: {1}", ShapeID, ShapeBounds); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineShape3; } + } + + public static DefineShape3Tag Create(SwfStreamReader reader) { + var tag = new DefineShape3Tag(); + tag.ShapeID = reader.Reader.ReadUInt16(); + tag.ShapeBounds = SwfRect.Read(reader); + //tag.Shapes = SwfShapes.Read(reader); + return tag; + } + } + + class DefineShape4Tag : SwfTagBase { + public ushort ShapeID; + public SwfRect ShapeBounds; + public SwfRect EdgeBounds; + + public override string ToString() { + return string.Format( + "ShapeID: {0}, ShapeBounds: {1}, EdgeBounds: {2}", + ShapeID, ShapeBounds, EdgeBounds); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineShape4; } + } + + public static DefineShape4Tag Create(SwfStreamReader reader) { + var tag = new DefineShape4Tag(); + tag.ShapeID = reader.Reader.ReadUInt16(); + tag.ShapeBounds = SwfRect.Read(reader); + tag.EdgeBounds = SwfRect.Read(reader); + //tag.Flags = reader.Reader.ReadByte(); + //tag.Shapes = SwfShapes.Read(reader); + return tag; + } + } + + class DefineBitsLosslessTag : SwfTagBase { + public ushort CharacterId; + public byte BitmapFormat; + public ushort BitmapWidth; + public ushort BitmapHeight; + public byte BitmapColorTableSize; + public byte[] ZlibBitmapData; + + public override SwfTagType TagType { + get { return SwfTagType.DefineBitsLossless; } + } + + public override string ToString() { + return string.Format( + "CharacterId: {0}, BitmapFormat: {1}, Width: {2}, Height: {3}", + CharacterId, BitmapFormat, BitmapWidth, BitmapHeight); + } + + public static DefineBitsLosslessTag Create(SwfStreamReader reader) { + var tag = new DefineBitsLosslessTag(); + tag.CharacterId = reader.Reader.ReadUInt16(); + tag.BitmapFormat = reader.Reader.ReadByte(); + tag.BitmapWidth = reader.Reader.ReadUInt16(); + tag.BitmapHeight = reader.Reader.ReadUInt16(); + if ( tag.BitmapFormat == 3 ) { + tag.BitmapColorTableSize = reader.Reader.ReadByte(); + } + tag.ZlibBitmapData = reader.ReadRest(); + return tag; + } + } + + class DefineBitsLossless2Tag : SwfTagBase { + public ushort CharacterId; + public byte BitmapFormat; + public ushort BitmapWidth; + public ushort BitmapHeight; + public byte BitmapColorTableSize; + public byte[] ZlibBitmapData; + + public override SwfTagType TagType { + get { return SwfTagType.DefineBitsLossless2; } + } + + public override string ToString() { + return string.Format( + "CharacterId: {0}, BitmapFormat: {1}, Width: {2}, Height: {3}", + CharacterId, BitmapFormat, BitmapWidth, BitmapHeight); + } + + public static DefineBitsLossless2Tag Create(SwfStreamReader reader) { + var tag = new DefineBitsLossless2Tag(); + tag.CharacterId = reader.Reader.ReadUInt16(); + tag.BitmapFormat = reader.Reader.ReadByte(); + tag.BitmapWidth = reader.Reader.ReadUInt16(); + tag.BitmapHeight = reader.Reader.ReadUInt16(); + if ( tag.BitmapFormat == 3 ) { + tag.BitmapColorTableSize = reader.Reader.ReadByte(); + } + tag.ZlibBitmapData = reader.ReadRest(); + return tag; + } + } + + class DefineSpriteTag : SwfTagBase { + public ushort SpriteId; + public ushort FrameCount; + public List ControlTags; + + public override string ToString() { + return string.Format( + "SpriteId: {0}, FrameCount: {1}, ControlTags: {2}", + SpriteId, FrameCount, ControlTags.Count); + } + + public override SwfTagType TagType { + get { return SwfTagType.DefineSprite; } + } + + public static DefineSpriteTag Create(SwfStreamReader reader) { + var tag = new DefineSpriteTag(); + tag.SpriteId = reader.Reader.ReadUInt16(); + tag.FrameCount = reader.Reader.ReadUInt16(); + tag.ControlTags = new List(); + SwfTagBase sub_tag; + do { + var sub_tag_data = SwfTagData.Read(reader); + sub_tag = SwfTagBase.Create(sub_tag_data); + if ( sub_tag != null ) { + tag.ControlTags.Add(sub_tag); + } + } while ( sub_tag != null && sub_tag.TagType != SwfTagType.End ); + return tag; + } + } + + class FileAttributesTag : SwfTagBase { + public override string ToString() { + return "FileAttributesTag"; + } + + public override SwfTagType TagType { + get { return SwfTagType.FileAttributes; } + } + + public static FileAttributesTag Create(SwfStreamReader reader) { + return new FileAttributesTag(); + } + } + + class UnknownTag : SwfTagBase { + SwfTagType Type; + + public override string ToString() { + return "UnknownTag"; + } + + public override SwfTagType TagType { + get { return Type; } + } + + public static UnknownTag Create(SwfTagType type) { + var tag = new UnknownTag(); + tag.Type = type; + return tag; + } + } +} \ No newline at end of file diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs.meta b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs.meta new file mode 100644 index 0000000..e218311 --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfTags.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a6fd42db76e554f85abc15861c15e758 +timeCreated: 1457387815 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs new file mode 100644 index 0000000..062f3d8 --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs @@ -0,0 +1,400 @@ +using UnityEngine; +using System.IO; +using System.Text; + +namespace FlashTools.Internal { + class SwfStreamReader { + struct BitContext { + public byte CachedByte; + public byte BitIndex; + } + BitContext _bitContext; + BinaryReader _reader; + + long Length { + get { return _reader.BaseStream.Length; } + } + + long Position { + get { return _reader.BaseStream.Position; } + } + + long BytesLeft { + get { return Length - Position; } + } + + public SwfStreamReader(string path) { + _reader = new BinaryReader(File.OpenRead(path)); + } + + public SwfStreamReader(Stream stream) { + _reader = new BinaryReader(stream); + } + + public BinaryReader Reader { + get { return _reader; } + } + + public bool ReadBit() { + var bitIndex = _bitContext.BitIndex & 0x07; + if ( bitIndex == 0 ) { + _bitContext.CachedByte = Reader.ReadByte(); + } + ++_bitContext.BitIndex; + return ((_bitContext.CachedByte << bitIndex) & 0x80) != 0; + } + + public int ReadSignedBits(uint count) { + if ( count == 0 ) { + return 0; + } + bool sign = ReadBit(); + var res = sign ? uint.MaxValue : 0; + --count; + for ( var i = 0; i < count; ++i ) { + var bit = ReadBit(); + res = (res << 1 | (bit ? 1u : 0u)); + } + return (int)res; + } + + public uint ReadUnsignedBits(uint count) { + if ( count == 0 ) { + return 0; + } + uint res = 0; + for ( var i = 0; i < count; ++i ) { + var bit = ReadBit(); + res = (res << 1 | (bit ? 1u : 0u)); + } + return res; + } + + public void AlignToByte() { + _bitContext.BitIndex = 0; + _bitContext.CachedByte = 0; + } + + public string ReadString() { + var data_stream = new MemoryStream(); + byte bt = 1; + while ( bt > 0 ) { + bt = _reader.ReadByte(); + if ( bt > 0 ) { + data_stream.WriteByte(bt); + } + } + return Encoding.UTF8.GetString(data_stream.ToArray()); + } + + public float ReadFixedPoint8() { + return Reader.ReadInt16() / 256.0f; + } + + public float ReadFixedPoint16(uint bits) { + var value = ReadSignedBits(bits); + return value / 65536.0f; + } + + public uint ReadEncodedU32() { + AlignToByte(); + uint val = 0; + var bt = _reader.ReadByte(); + val |= bt & 0x7fu; + if ((bt & 0x80) == 0) return val; + + bt = _reader.ReadByte(); + val |= (bt & 0x7fu) << 7; + if ((bt & 0x80) == 0) return val; + + bt = _reader.ReadByte(); + val |= (bt & 0x7fu) << 14; + if ((bt & 0x80) == 0) return val; + + bt = _reader.ReadByte(); + val |= (bt & 0x7fu) << 21; + if ((bt & 0x80) == 0) return val; + + bt = _reader.ReadByte(); + val |= (bt & 0x7fu) << 28; + return val; + } + + public byte[] ReadRest() { + return Reader.ReadBytes((int)BytesLeft); + } + + public bool IsEOF { + get { return Position == Length; } + } + } + + enum SwfBlendMode : byte { + Normal = 0, + Normal1 = 1, + Layer = 2, + Multiply = 3, + Screen = 4, + Lighten = 5, + Darken = 6, + Difference = 7, + Add = 8, + Subtract = 9, + Invert = 10, + Alpha = 11, + Erase = 12, + Overlay = 13, + Hardlight = 14 + } + + struct SwfHeader { + public string Format; + public byte Version; + public uint FileLength; + public SwfRect FrameSize; + public float FrameRate; + public ushort FrameCount; + + public static SwfHeader Read(SwfStreamReader reader) { + var header = new SwfHeader(); + header.Format = new string(reader.Reader.ReadChars(3)); + header.Version = reader.Reader.ReadByte(); + header.FileLength = reader.Reader.ReadUInt32(); + header.FrameSize = SwfRect.Read(reader); + header.FrameRate = reader.ReadFixedPoint8(); + header.FrameCount = reader.Reader.ReadUInt16(); + return header; + } + + public override string ToString() { + return string.Format( + "Format: {0}, Version: {1}, FileLength: {2}, FrameSize: {3}, FrameRate: {4}, FrameCount: {5}", + Format, Version, FileLength, FrameSize, FrameRate, FrameCount); + } + } + + struct SceneOffsetData { + public uint Offset; + public string Name; + } + + struct FrameLabelData { + public uint Number; + public string Label; + } + + struct SwfRGB { + public byte Red; + public byte Green; + public byte Blue; + + public static SwfRGB Read(SwfStreamReader reader) { + var rgb = new SwfRGB(); + rgb.Red = reader.Reader.ReadByte(); + rgb.Green = reader.Reader.ReadByte(); + rgb.Blue = reader.Reader.ReadByte(); + return rgb; + } + + public override string ToString() { + return string.Format( + "R: {0}, G: {1}, B: {2}", + Red, Green, Blue); + } + } + + struct SwfRGBA { + public byte Red; + public byte Green; + public byte Blue; + public byte Alpha; + + public static SwfRGBA Read(SwfStreamReader reader) { + var rgba = new SwfRGBA(); + rgba.Red = reader.Reader.ReadByte(); + rgba.Green = reader.Reader.ReadByte(); + rgba.Blue = reader.Reader.ReadByte(); + rgba.Alpha = reader.Reader.ReadByte(); + return rgba; + } + + public override string ToString() { + return string.Format( + "R: {0}, G: {1}, B: {2}, A: {3}", + Red, Green, Blue, Alpha); + } + } + + struct SwfRect { + public float XMin; + public float XMax; + public float YMin; + public float YMax; + + public static SwfRect Read(SwfStreamReader reader) { + var rect = new SwfRect(); + var bits = reader.ReadUnsignedBits(5); + rect.XMin = reader.ReadSignedBits(bits) / 20.0f; + rect.XMax = reader.ReadSignedBits(bits) / 20.0f; + rect.YMin = reader.ReadSignedBits(bits) / 20.0f; + rect.YMax = reader.ReadSignedBits(bits) / 20.0f; + reader.AlignToByte(); + return rect; + } + + public override string ToString() { + return string.Format( + "XMin: {0}, XMax: {1}, YMin: {2}, YMax: {3}", + XMin, XMax, YMin, YMax); + } + } + + struct SwfMatrix { + public float ScaleX; + public float ScaleY; + public float RotateSkew0; + public float RotateSkew1; + public int TranslateX; + public int TranslateY; + + public static SwfMatrix Identity { + get { + return new SwfMatrix { + ScaleX = 1, + ScaleY = 1, + RotateSkew0 = 0, + RotateSkew1 = 0, + TranslateX = 0, + TranslateY = 0 + }; + } + } + + public static SwfMatrix Read(SwfStreamReader reader) { + var matrix = SwfMatrix.Identity; + var has_scale = reader.ReadBit(); + if ( has_scale ) { + var bits = (byte)reader.ReadUnsignedBits(5); + matrix.ScaleX = reader.ReadFixedPoint16(bits); + matrix.ScaleY = reader.ReadFixedPoint16(bits); + } + var has_rotate = reader.ReadBit(); + if ( has_rotate ) { + var bits = (byte)reader.ReadUnsignedBits(5); + matrix.RotateSkew0 = reader.ReadFixedPoint16(bits); + matrix.RotateSkew1 = reader.ReadFixedPoint16(bits); + } + var translate_bits = (byte)reader.ReadUnsignedBits(5); + matrix.TranslateX = reader.ReadSignedBits(translate_bits); + matrix.TranslateY = reader.ReadSignedBits(translate_bits); + reader.AlignToByte(); + return matrix; + } + + public override string ToString() { + return string.Format( + "ScaleX: {0}, ScaleY: {1}, RotateSkew0: {2}, RotateSkew1: {3}, TranslateX: {4}, TranslateY: {5}", + ScaleX, ScaleY, RotateSkew0, RotateSkew1, TranslateX, TranslateY); + } + } + + struct SwfColorTransformRGB { + public short RMul; + public short GMul; + public short BMul; + public bool HasMul; + public short RAdd; + public short GAdd; + public short BAdd; + public bool HasAdd; + public static SwfColorTransformRGB Read(SwfStreamReader reader) { + SwfColorTransformRGB transform; + var has_add = reader.ReadBit(); + var has_mul = reader.ReadBit(); + var bits = reader.ReadUnsignedBits(4); + if ( has_mul ) { + transform.RMul = (short)reader.ReadSignedBits(bits); + transform.GMul = (short)reader.ReadSignedBits(bits); + transform.BMul = (short)reader.ReadSignedBits(bits); + transform.HasMul = true; + } else { + transform.RMul = 1; + transform.GMul = 1; + transform.BMul = 1; + transform.HasMul = false; + } + if ( has_add ) { + transform.RAdd = (short)reader.ReadSignedBits(bits); + transform.GAdd = (short)reader.ReadSignedBits(bits); + transform.BAdd = (short)reader.ReadSignedBits(bits); + transform.HasAdd = true; + } else { + transform.RAdd = 0; + transform.GAdd = 0; + transform.BAdd = 0; + transform.HasAdd = false; + } + reader.AlignToByte(); + return transform; + } + } + + struct SwfColorTransformRGBA { + public short RMul; + public short GMul; + public short BMul; + public short AMul; + public bool HasMul; + public short RAdd; + public short GAdd; + public short BAdd; + public short AAdd; + public bool HasAdd; + public static SwfColorTransformRGBA Read(SwfStreamReader reader) { + SwfColorTransformRGBA transform; + var has_add = reader.ReadBit(); + var has_mul = reader.ReadBit(); + var bits = reader.ReadUnsignedBits(4); + if ( has_mul ) { + transform.RMul = (short)reader.ReadSignedBits(bits); + transform.GMul = (short)reader.ReadSignedBits(bits); + transform.BMul = (short)reader.ReadSignedBits(bits); + transform.AMul = (short)reader.ReadSignedBits(bits); + transform.HasMul = true; + } else { + transform.RMul = 1; + transform.GMul = 1; + transform.BMul = 1; + transform.AMul = 1; + transform.HasMul = false; + } + if ( has_add ) { + transform.RAdd = (short)reader.ReadSignedBits(bits); + transform.GAdd = (short)reader.ReadSignedBits(bits); + transform.BAdd = (short)reader.ReadSignedBits(bits); + transform.AAdd = (short)reader.ReadSignedBits(bits); + transform.HasAdd = true; + } else { + transform.RAdd = 0; + transform.GAdd = 0; + transform.BAdd = 0; + transform.AAdd = 0; + transform.HasAdd = false; + } + reader.AlignToByte(); + return transform; + } + } + + struct SwfClipActions { + public static SwfClipActions Read(SwfStreamReader reader) { + throw new UnityException("implme!"); + } + } + + struct SwfSurfaceFilters { + public static SwfSurfaceFilters Read(SwfStreamReader reader) { + throw new UnityException("implme!"); + } + } +} \ No newline at end of file diff --git a/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs.meta b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs.meta new file mode 100644 index 0000000..f2e6ce0 --- /dev/null +++ b/Assets/FlashTools/Scripts/Internal/Editor/FlashAnimSwfUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3cbe133e688394de3a3ccafde9ac5942 +timeCreated: 1457387827 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta new file mode 100644 index 0000000..22696b5 --- /dev/null +++ b/Assets/Plugins.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: df75e9c9573ce4e98b7b825da1804c9c +folderAsset: yes +timeCreated: 1457386400 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Ionic.Zip.Unity.dll b/Assets/Plugins/Ionic.Zip.Unity.dll new file mode 100644 index 0000000..71ae13b Binary files /dev/null and b/Assets/Plugins/Ionic.Zip.Unity.dll differ diff --git a/Assets/Plugins/Ionic.Zip.Unity.dll.meta b/Assets/Plugins/Ionic.Zip.Unity.dll.meta new file mode 100644 index 0000000..fd62e55 --- /dev/null +++ b/Assets/Plugins/Ionic.Zip.Unity.dll.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: 55da4d34bbe6e475a9a18082a820d3fb +timeCreated: 1457386519 +licenseType: Free +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 1 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/FlashExport.jsfl b/Tools/FlashExport.jsfl new file mode 100644 index 0000000..83c5d01 --- /dev/null +++ b/Tools/FlashExport.jsfl @@ -0,0 +1,213 @@ +(function () { + + "use strict"; + + // ---------------------------------------------------------------------------- + // + // ft + // + // ---------------------------------------------------------------------------- + + var ft = {}; + + ft.trace = function () { + fl.outputPanel.trace( + Array.prototype.join.call(arguments, " ")); + }; + + ft.trace_fmt = function (format) { + var args = Array.prototype.slice.call(arguments, 1); + ft.trace(format.format.apply(format, args)); + }; + + ft.clear_output = function () { + fl.outputPanel.clear(); + }; + + ft.assert = function (expr, format) { + if (!expr) { + if (format === undefined) { + throw "!!!Assert!!!"; + } else { + var args = Array.prototype.slice.call(arguments, 2); + throw "!!!Assert!!! " + format.format.apply(format, args); + } + } + }; + + ft.type_assert = function (item, type) { + var type_is_string = (typeof type === 'string'); + ft.assert( + (type_is_string && typeof item === type) || + (!type_is_string && item instanceof type), + "Type error: {0} != {1}", + typeof item, + type_is_string ? type : type.constructor.name); + }; + + ft.type_assert_if_defined = function (item, type) { + if (item !== undefined) { + ft.type_assert(item, type); + } + }; + + ft.escape_path = function (path) { + ft.type_assert(path, 'string'); + return path.replace(/ /g, '%20'); + }; + + ft.escape_string = function (str) { + ft.type_assert(str, 'string'); + return str + .replace(/\&/g, '&') + .replace(/\"/g, '"') + .replace(/\'/g, ''') + .replace(//g, '>'); + }; + + ft.combine_path = function (lhs, rhs) { + ft.type_assert(lhs, 'string'); + ft.type_assert(rhs, 'string'); + return ft.escape_path(lhs) + ft.escape_path(rhs); + }; + + ft.hex_str_to_color32 = function (hstr) { + ft.type_assert(hstr, 'string'); + ft.assert(hstr.length == 7, "incorrect hex_str"); + var result = []; + var hex_digit = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']; + for (var i = 1; i < hstr.length; i += 2) { + result.push( + hex_digit.indexOf(hstr[i + 0].toUpperCase()) * 16.0 + + hex_digit.indexOf(hstr[i + 1].toUpperCase()) + ); + } + return result; + }; + + ft.array_filter = function (arr, filter) { + ft.type_assert(arr, Array); + ft.type_assert(filter, Function); + var new_arr = []; + for (var index = 0; index < arr.length; ++index) { + var value = arr[index]; + if ( filter(value, index) ) { + new_arr.push(value); + } + } + return new_arr; + }; + + ft.array_foreach = function (arr, func, filter) { + ft.type_assert(arr, Array); + ft.type_assert(func, Function); + ft.type_assert_if_defined(filter, Function); + for (var index = 0; index < arr.length; ++index) { + var value = arr[index]; + if (filter === undefined || filter(value, index)) { + func(value, index); + } + } + }; + + ft.array_reverse_foreach = function (arr, func, filter) { + ft.type_assert(arr, Array); + ft.type_assert(func, Function); + ft.type_assert_if_defined(filter, Function); + for (var index = arr.length - 1; index >= 0; --index) { + var value = arr[index]; + if (filter === undefined || filter(value, index)) { + func(value, index); + } + } + }; + + ft.object_foreach = function (obj, func, filter) { + ft.type_assert(obj, 'object'); + ft.type_assert(func, Function); + ft.type_assert_if_defined(filter, Function); + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var value = obj[key]; + if (filter === undefined || filter(key, value)) { + func(key, value); + } + } + } + }; + + // ------------------------------------ + // Document + // ------------------------------------ + + var ftd = {}; + + ftd.prepare_folders = function (document) { + ft.type_assert(document, Document); + var export_folder = ftd.get_export_folder(document); + if (FLfile.exists(export_folder)) { + if (!FLfile.remove(export_folder)) { + throw "Can't remove document export folder ({0})!" + .format(export_folder); + } + } + if (!FLfile.createFolder(export_folder)) { + throw "Can't create document export folder ({0})!" + .format(export_folder); + } + }; + + ftd.prepare_bitmaps = function (document) { + ft.type_assert(document, Document); + ft.array_foreach(document.library.items, function(item) { + ft.trace_fmt("-Item: {0}", item.name); + if ( item.itemType == "bitmap" ) { + item.compressionType = "lossless"; + } + }); + }; + + ftd.export_swf = function (document) { + ft.type_assert(document, Document); + document.exportSWF(ftd.get_swf_export_path(document)); + }; + + ftd.get_document_name = function (document) { + ft.type_assert(document, Document); + return document.name; + }; + + ftd.get_document_path = function (document) { + ft.type_assert(document, Document); + return ft.escape_path(document.pathURI); + }; + + ftd.get_export_folder = function (document) { + ft.type_assert(document, Document); + return ft.combine_path( + ftd.get_document_path(document), + "_export/"); + }; + + ftd.get_swf_export_path = function (document) { + ft.type_assert(document, Document); + return ft.combine_path( + ftd.get_export_folder(document), + ftd.get_document_name(document) + ".swf"); + }; + + // ------------------------------------ + // Main + // ------------------------------------ + + (function () { + ft.clear_output(); + ft.array_foreach(fl.documents, function (document) { + ft.trace_fmt("Doc: {0}", document.name); + ftd.prepare_folders(document); + ftd.prepare_bitmaps(document); + ftd.export_swf(document); + }); + })(); +})(); \ No newline at end of file