swf parsing begin

This commit is contained in:
2016-03-09 03:34:24 +06:00
parent 8785559257
commit 4764fb88c6
14 changed files with 1492 additions and 0 deletions

View File

@@ -49,6 +49,9 @@
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimAssetPostprocessor.cs" /> <Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimAssetPostprocessor.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimEditor.cs" /> <Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimEditor.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimFtaPostprocessor.cs" /> <Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimFtaPostprocessor.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimSwfPostprocessor.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimSwfTags.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\FlashAnimSwfUtils.cs" />
<None Include="Assets\FlashTools\Shaders\FlashAnim.shader" /> <None Include="Assets\FlashTools\Shaders\FlashAnim.shader" />
<Reference Include="UnityEditor.Advertisements"> <Reference Include="UnityEditor.Advertisements">
<HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Advertisements/Editor/UnityEditor.Advertisements.dll</HintPath> <HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Advertisements/Editor/UnityEditor.Advertisements.dll</HintPath>
@@ -103,6 +106,9 @@
</Reference> </Reference>
<Reference Include="UnityEditor.OSXStandalone.Extensions"> <Reference Include="UnityEditor.OSXStandalone.Extensions">
<HintPath>/Applications/Unity/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll</HintPath> <HintPath>/Applications/Unity/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip.Unity">
<HintPath>/Users/matov/Programming/Projects/unityflash/Assets/Plugins/Ionic.Zip.Unity.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -53,6 +53,9 @@
</Reference> </Reference>
<Reference Include="UnityEngine.Networking"> <Reference Include="UnityEngine.Networking">
<HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll</HintPath> <HintPath>/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip.Unity">
<HintPath>/Users/matov/Programming/Projects/unityflash/Assets/Plugins/Ionic.Zip.Unity.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c317ff8ea48c428da50f57544fe49bd
timeCreated: 1457365163
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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());
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 27c44c175a74f4707bafa0bb1a8d47f7
timeCreated: 1457365970
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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<SceneOffsetData> Scenes = new List<SceneOffsetData>();
public List<FrameLabelData> Frames = new List<FrameLabelData>();
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<SwfTagBase> 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>();
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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a6fd42db76e554f85abc15861c15e758
timeCreated: 1457387815
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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!");
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3cbe133e688394de3a3ccafde9ac5942
timeCreated: 1457387827
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Plugins.meta Normal file
View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: df75e9c9573ce4e98b7b825da1804c9c
folderAsset: yes
timeCreated: 1457386400
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -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:

213
Tools/FlashExport.jsfl Normal file
View File

@@ -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, '&amp;')
.replace(/\"/g, '&quot;')
.replace(/\'/g, '&apos;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
};
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);
});
})();
})();