Files
unity-flash-tools/FTSources/FTEditor/Sources/Postprocessors/SwfPostprocessor.cs

369 lines
12 KiB
C#

using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using FTSwfTools;
using FTSwfTools.SwfTags;
using FTSwfTools.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)
{
var swf_paths = imported_assets
.Where(p => Path.GetExtension(p).ToLower().Equals(".swf"));
foreach ( var swf_path in swf_paths ) {
SwfFileProcess(swf_path);
}
}
static void SwfFileProcess(string swf_path) {
var swf_asset_path = Path.ChangeExtension(swf_path, ".asset");
SwfEditorUtils.LoadOrCreateAsset<SwfAsset>(swf_asset_path, (swf_asset, created) => {
if ( created ) {
var default_settings = SwfEditorUtils.GetSettingsHolder().Settings;
swf_asset.Settings = default_settings;
swf_asset.Overridden = default_settings;
}
SafeLoadSwfAsset(swf_path, swf_asset);
});
}
static void SafeLoadSwfAsset(string swf_path, SwfAsset swf_asset) {
try {
var new_data = LoadSwfAssetData(swf_path);
swf_asset.Data = SwfEditorUtils.CompressAsset(new_data);
swf_asset.Converting = new SwfAsset.ConvertingState();
} catch ( Exception e ) {
Debug.LogErrorFormat(
"<b>[FlashTools]</b> Parsing swf error: {0}",
e.Message);
}
}
static SwfAssetData LoadSwfAssetData(string swf_path) {
var library = new SwfLibrary();
var decoder = new SwfDecoder(swf_path);
return new SwfAssetData{
FrameRate = decoder.UncompressedHeader.FrameRate,
Symbols = LoadSymbols(library, decoder),
Bitmaps = LoadBitmaps(library)};
}
// ---------------------------------------------------------------------
//
// LoadSymbols
//
// ---------------------------------------------------------------------
static List<SwfSymbolData> LoadSymbols(
SwfLibrary library, SwfDecoder decoder)
{
var symbols = new List<SwfSymbolData>();
symbols.Add(LoadSymbol("_Stage_", library, decoder.Tags));
var sprite_defs = library.Defines.Values
.OfType<SwfLibrarySpriteDefine>()
.Where(p => !string.IsNullOrEmpty(p.ExportName));
foreach ( var sprite_def in sprite_defs ) {
var name = sprite_def.ExportName;
var tags = sprite_def.ControlTags.Tags;
symbols.Add(LoadSymbol(name, library, tags));
}
return symbols;
}
static SwfSymbolData LoadSymbol(
string symbol_name, SwfLibrary library, List<SwfTagBase> tags)
{
var disp_lst = new SwfDisplayList();
var executer = new SwfContextExecuter(library, 0, warning_msg => {
Debug.LogWarningFormat("<b>[FlashTools]</b> {0}", warning_msg);
});
var symbol_frames = new List<SwfFrameData>();
while ( executer.NextFrame(tags, disp_lst) ) {
symbol_frames.Add(LoadSymbolFrameData(library, disp_lst));
}
return new SwfSymbolData{
Name = symbol_name,
Frames = symbol_frames};
}
static SwfFrameData LoadSymbolFrameData(
SwfLibrary library, SwfDisplayList display_list)
{
var frame = new SwfFrameData();
frame.Name = display_list.FrameName;
return AddDisplayListToFrame(
library,
display_list,
Matrix4x4.identity,
SwfBlendModeData.identity,
SwfColorTransData.identity,
0,
0,
null,
frame);
}
static SwfFrameData AddDisplayListToFrame(
SwfLibrary library,
SwfDisplayList display_list,
Matrix4x4 parent_matrix,
SwfBlendModeData parent_blend_mode,
SwfColorTransData parent_color_transform,
ushort parent_masked,
ushort parent_mask,
List<SwfInstanceData> parent_masks,
SwfFrameData frame)
{
var inst_filter_types = display_list.Instances.Values
.Where(p => p.Visible && p.FilterList.Filters.Count > 0)
.SelectMany(p => p.FilterList.Filters)
.Select(p => p.Type)
.Distinct();
foreach ( var filter_type in inst_filter_types ) {
Debug.LogWarningFormat(
"<b>[FlashTools]</b> SwfSurfaceFilters. Unsupported filter type '{0}'",
filter_type);
}
var self_masks = new List<SwfInstanceData>();
foreach ( var inst in display_list.Instances.Values.Where(p => p.Visible) ) {
CheckSelfMasks(self_masks, inst.Depth, frame);
var child_matrix = parent_matrix * inst.Matrix .ToUMatrix();
var child_blend_mode = parent_blend_mode * inst.BlendMode .ToBlendModeData();
var child_color_transform = parent_color_transform * inst.ColorTransform.ToColorTransData();
switch ( inst.Type ) {
case SwfDisplayInstanceType.Shape:
AddShapeInstanceToFrame(
library,
inst as SwfDisplayShapeInstance,
child_matrix,
child_blend_mode,
child_color_transform,
parent_masked,
parent_mask,
parent_masks,
self_masks,
frame);
break;
case SwfDisplayInstanceType.Sprite:
AddSpriteInstanceToFrame(
library,
inst as SwfDisplaySpriteInstance,
child_matrix,
child_blend_mode,
child_color_transform,
parent_masked,
parent_mask,
parent_masks,
self_masks,
frame);
break;
default:
throw new UnityException(string.Format(
"unsupported SwfDisplayInstanceType: {0}", inst.Type));
}
}
CheckSelfMasks(self_masks, ushort.MaxValue, frame);
return frame;
}
static void AddShapeInstanceToFrame(
SwfLibrary library,
SwfDisplayShapeInstance inst,
Matrix4x4 inst_matrix,
SwfBlendModeData inst_blend_mode,
SwfColorTransData inst_color_transform,
ushort parent_masked,
ushort parent_mask,
List<SwfInstanceData> parent_masks,
List<SwfInstanceData> self_masks,
SwfFrameData frame)
{
var shape_def = library.FindDefine<SwfLibraryShapeDefine>(inst.Id);
if ( shape_def != null ) {
for ( var i = 0; i < shape_def.Bitmaps.Length; ++i ) {
var bitmap_id = shape_def.Bitmaps[i];
var bitmap_matrix = i < shape_def.Matrices.Length ? shape_def.Matrices[i] : SwfMatrix.identity;
var bitmap_def = library.FindDefine<SwfLibraryBitmapDefine>(bitmap_id);
if ( bitmap_def != null ) {
var frame_inst_type =
(parent_mask > 0 || inst.ClipDepth > 0)
? SwfInstanceData.Types.Mask
: (parent_masked > 0 || self_masks.Count > 0)
? SwfInstanceData.Types.Masked
: SwfInstanceData.Types.Group;
var frame_inst_clip_depth =
(parent_mask > 0)
? parent_mask
: (inst.ClipDepth > 0)
? inst.ClipDepth
: parent_masked + self_masks.Count;
frame.Instances.Add(new SwfInstanceData{
Type = frame_inst_type,
ClipDepth = (ushort)frame_inst_clip_depth,
Bitmap = bitmap_id,
Matrix = SwfMatrixData.FromUMatrix(inst_matrix * bitmap_matrix.ToUMatrix()),
BlendMode = inst_blend_mode,
ColorTrans = inst_color_transform});
if ( parent_mask > 0 ) {
parent_masks.Add(frame.Instances[frame.Instances.Count - 1]);
} else if ( inst.ClipDepth > 0 ) {
self_masks.Add(frame.Instances[frame.Instances.Count - 1]);
}
}
}
}
}
static void AddSpriteInstanceToFrame(
SwfLibrary library,
SwfDisplaySpriteInstance inst,
Matrix4x4 inst_matrix,
SwfBlendModeData inst_blend_mode,
SwfColorTransData inst_color_transform,
ushort parent_masked,
ushort parent_mask,
List<SwfInstanceData> parent_masks,
List<SwfInstanceData> self_masks,
SwfFrameData frame)
{
var sprite_def = library.FindDefine<SwfLibrarySpriteDefine>(inst.Id);
if ( sprite_def != null ) {
AddDisplayListToFrame(
library,
inst.DisplayList,
inst_matrix,
inst_blend_mode,
inst_color_transform,
(ushort)(parent_masked + self_masks.Count),
(ushort)(parent_mask > 0
? parent_mask
: (inst.ClipDepth > 0
? inst.ClipDepth
: (ushort)0)),
parent_mask > 0
? parent_masks
: (inst.ClipDepth > 0
? self_masks
: null),
frame);
}
}
static void CheckSelfMasks(
List<SwfInstanceData> masks,
ushort depth,
SwfFrameData frame)
{
foreach ( var mask in masks ) {
if ( mask.ClipDepth < depth ) {
frame.Instances.Add(new SwfInstanceData{
Type = SwfInstanceData.Types.MaskReset,
ClipDepth = 0,
Bitmap = mask.Bitmap,
Matrix = mask.Matrix,
BlendMode = mask.BlendMode,
ColorTrans = mask.ColorTrans});
}
}
masks.RemoveAll(p => p.ClipDepth < depth);
}
// ---------------------------------------------------------------------
//
// LoadBitmaps
//
// ---------------------------------------------------------------------
static List<SwfBitmapData> LoadBitmaps(SwfLibrary library) {
return library.Defines
.Where (p => p.Value.Type == SwfLibraryDefineType.Bitmap)
.ToDictionary(p => p.Key, p => p.Value as SwfLibraryBitmapDefine)
.Select (p => new SwfBitmapData{
Id = p.Key,
ARGB32 = p.Value.ARGB32,
Redirect = p.Value.Redirect,
RealWidth = p.Value.Width,
RealHeight = p.Value.Height})
.ToList();
}
}
// ---------------------------------------------------------------------
//
// Extensions
//
// ---------------------------------------------------------------------
static class SwfExtensions {
public static Matrix4x4 ToUMatrix(this SwfMatrix self) {
var mat = Matrix4x4.identity;
mat.m00 = self.ScaleX;
mat.m10 = self.RotateSkew0;
mat.m01 = self.RotateSkew1;
mat.m11 = self.ScaleY;
mat.m03 = self.TranslateX;
mat.m13 = self.TranslateY;
return mat;
}
public static SwfBlendModeData ToBlendModeData(this SwfBlendMode self) {
switch ( self.Value ) {
case SwfBlendMode.Mode.Normal:
return new SwfBlendModeData(SwfBlendModeData.Types.Normal);
case SwfBlendMode.Mode.Layer:
return new SwfBlendModeData(SwfBlendModeData.Types.Layer);
case SwfBlendMode.Mode.Multiply:
return new SwfBlendModeData(SwfBlendModeData.Types.Multiply);
case SwfBlendMode.Mode.Screen:
return new SwfBlendModeData(SwfBlendModeData.Types.Screen);
case SwfBlendMode.Mode.Lighten:
return new SwfBlendModeData(SwfBlendModeData.Types.Lighten);
case SwfBlendMode.Mode.Darken:
return new SwfBlendModeData(SwfBlendModeData.Types.Darken);
case SwfBlendMode.Mode.Difference:
return new SwfBlendModeData(SwfBlendModeData.Types.Difference);
case SwfBlendMode.Mode.Add:
return new SwfBlendModeData(SwfBlendModeData.Types.Add);
case SwfBlendMode.Mode.Subtract:
return new SwfBlendModeData(SwfBlendModeData.Types.Subtract);
case SwfBlendMode.Mode.Invert:
return new SwfBlendModeData(SwfBlendModeData.Types.Invert);
case SwfBlendMode.Mode.Hardlight:
return new SwfBlendModeData(SwfBlendModeData.Types.Hardlight);
default:
Debug.LogWarningFormat(
"<b>[FlashTools]</b> SwfBlendMode. Unsupported blend mode '{0}'",
self.Value);
return new SwfBlendModeData(SwfBlendModeData.Types.Normal);
}
}
public static SwfColorTransData ToColorTransData(this SwfColorTransform self) {
var trans = SwfColorTransData.identity;
if ( self.HasAdd ) {
trans.addColor = new SwfVec4Data(
self.RAdd / 256.0f,
self.GAdd / 256.0f,
self.BAdd / 256.0f,
self.AAdd / 256.0f);
}
if ( self.HasMul ) {
trans.mulColor = new SwfVec4Data(
self.RMul / 256.0f,
self.GMul / 256.0f,
self.BMul / 256.0f,
self.AMul / 256.0f);
}
return trans;
}
}
}