package CharacterExport
{
import Defs.*;
import flash.display.*;
import djarts.display.*;
import flash.geom.Rectangle;
import djarts.core.*;
import djarts.utils.CountWaiter;
import flash.geom.Matrix;
import flash.geom.Point;
import HeroUI.HeroSprite;
import flash.utils.ByteArray;
import GraphicExport.*;
import djarts.utils.SimpleTimer;
import org.aszip.zip.ASZip;
import org.aszip.compression.CompressionMethod;
import org.aszip.saving.Method;
import flash.net.FileReference;
import com.adobe.images.PNGEncoder;
import flash.utils.getQualifiedClassName;
import flash.net.*;
import flash.events.*;
public class CharacterExporter
{
protected var loaded = false;
// the graphic we are working on
protected var heroDef:HeroDef;
protected var baseGraphicId;
protected var graphicDef:GraphicDef;
protected var graphicId;
protected var graphic:MovieClip;
protected var graphicClass:Class;
protected var graphicName:String = "";
public function set GraphicName(val:String) { graphicName = val;}
public function get GraphicName():String { return (graphicName == "") ? getQualifiedClassName(graphic) : graphicName; }
protected var characterDef:CharacterDef;
protected var externalAnimationData:ExternalAnimationInfo;
protected var force;
public function get BaseGraphicId() { return baseGraphicId; }
public function get GraphicId() { return graphicId; }
public function get GraphicClass():Class { return graphicClass; }
protected var isLocalLibrary = false;
protected var library:PieceLibrary;
public function get Library():PieceLibrary { return library; }
protected var loadWaiter:CountWaiter;
public var Upscale = 1.0;
protected var exportSequences:Array;
protected var fullSequence:Array;
// formatType
public static const NORMAL = 0;
public static const OLDMONSTER = 1;
protected var formatType;
protected var holder:MovieClip;
public function CharacterExporter(holder:MovieClip = null)
{
this.holder = holder;
}
public function GetNewSequence(sequence):MovieClip
{
if (!loaded) return null;
var className = flash.utils.getQualifiedClassName(graphic);
if (className == "flash.display::MovieClip")
{
graphic.transform.matrix = new Matrix();
return GetSequenceClip(graphic, sequence);
}
if (SingleSequenceClip)
{
graphic.transform.matrix = new Matrix();
return graphic;
}
if (characterDef)
{
return new CharacterTypeGraphic(graphicId, characterDef, force, sequence, externalAnimationData);
}
var base:MovieClip = new (graphicClass)();
return GetSequenceClip(base, sequence);
}
public function GetSequenceName(sequence):String
{
var base:MovieClip = new (graphicClass)();
return CharacterExporter.GetSequenceName(base, sequence);
}
protected var sequences:Array = [];
public function get Sequences():Array { return sequences; }
protected var doneCallback;
public function ProcessFromClip(graphic:MovieClip, callback, library:PieceLibrary = null)
{
this.doneCallback = callback;
Reset();
this.baseGraphicId = -1;
this.graphicId = -1;
//this.graphicDef = null;
this.graphic = graphic;
if (!library)
{
isLocalLibrary = true;
library = new PieceLibrary();
}
this.library = library;
if (SingleSequenceClip)
{
exportSequences = [1];
fullSequence = [true];
}
else
{
//exportSequences = [1];
//fullSequence = [false];
exportSequences = [];
fullSequence = [];
for (var i = 0; i < graphic.totalFrames; i++){
exportSequences[i] = i+1;
fullSequence[i] = true;
}
}
loaded = true;
graphicClass = Object(graphic).constructor;
GenerateSequences();
}
var defaultExportType = null;
public function Process(baseGraphicId, callback, library:PieceLibrary = null, defaultExportType = null, scale = 1)
{
this.baseGraphicId = baseGraphicId;
this.defaultExportType = defaultExportType;
this.Upscale = scale;
if (!library)
{
isLocalLibrary = true;
library = new PieceLibrary();
}
this.library = library;
this.doneCallback = callback;
Reset();
this.graphicDef = GameData.Instance().GetGraphicDefByID(baseGraphicId);
if (graphicDef.ExportParams.hasOwnProperty("from_hero_id"))
{
this.heroDef = GameData.Instance().GetHeroDefByID(graphicDef.ExportParams.from_hero_id);
if (heroDef.UseCharacterGraphics)
{
this.characterDef = heroDef.characterDef;
this.force = characterDef.GenerateForce();
graphicId = GraphicFactory.Instance().ReverseLookup(characterDef.Body);
} else {
graphicId = heroDef.AnimalGraphicID;
}
} else {
graphicId = baseGraphicId;
}
this.loadWaiter.Wait();
var g = GraphicFactory.Instance().GetGraphicByID(graphicId, null, loadWaiter.WaitDone);
if (GraphicFactory.Instance().LoadedOK(g))
{
loadWaiter.WaitDone();
}
if (characterDef)
{
for (var i in force)
{
var info = force[i];
if (info.hasOwnProperty("frame"))
{
var partGraphicId = GraphicFactory.Instance().ReverseLookup(info.frame);
if (partGraphicId > 0)
{
loadWaiter.Wait();
var g = GraphicFactory.Instance().GetGraphicByID(partGraphicId, null, loadWaiter.WaitDone);
if (GraphicFactory.Instance().LoadedOK(g))
{
loadWaiter.WaitDone();
}
}
}
}
}
this.loadWaiter.Go();
}
public function Reset()
{
loaded = false;
heroDef = null;
graphicDef = null;
graphicId = null;
graphic = null;
graphicClass = null;
characterDef = null;
sequences.splice(0);
if (isLocalLibrary)
{
library.Reset();
}
this.loadWaiter = new CountWaiter(GraphicsLoaded);
}
protected function GraphicsLoaded(w:CountWaiter)
{
if (!loaded && w == this.loadWaiter)
{
loaded = true;
graphic = GraphicFactory.Instance().GetGraphicByID(this.graphicId);
graphicClass = Object(graphic).constructor;
if (characterDef)
{
externalAnimationData = CacheManager.Instance().GetExternalData(graphic);
}
GenerateSequences();
}
}
protected function GenerateSequences()
{
var exportType = defaultExportType == null ? "monster" : defaultExportType;
if (graphicDef != null && graphicDef.ExportParams.hasOwnProperty("export_type"))
{
exportType = graphicDef.ExportParams.export_type;
}
switch (exportType)
{
case "character":
exportSequences = [1,4,16];
fullSequence = [true,false,true];
break;
case "escort":
exportSequences = [1];
fullSequence = [true];
break;
case "monster":
default:
exportSequences = [];
fullSequence = [];
for (var i = 0; i < graphic.totalFrames; i++)
{
exportSequences[i] = i+1;
fullSequence[i] = true;
}
break;
}
formatType = NORMAL;
if (this.characterDef == null && this.graphic.numChildren > 1 && !this.SingleSequenceClip)
{
var hasSingleLengthClip = true;
var lengthClip = null;
for (var i = 0; i < graphic.numChildren; i++)
{
var child = graphic.getChildAt(i);
if (child is MovieClip)
{
if (child.totalFrames > 1)
{
if (lengthClip)
{
hasSingleLengthClip = false;
break;
} else {
lengthClip = child;
}
}
}
}
if (hasSingleLengthClip)
{
formatType = OLDMONSTER;
}
}
NextSequence();
}
var nextX = 50;
var nextY = 200;
var sequenceIndex = 0;
public function NextSequence()
{
var i = sequenceIndex;
sequenceIndex++;
var sequence:CharacterSequence = new CharacterSequence(this, exportSequences[i] - 1, fullSequence[i], formatType);
sequence.ProducePieces();
//sequence.DebugPieces(i * 150);
sequences.push(sequence);
var includeOriginal = true;
if (holder)
{
/*
if (includeOriginal)
{
if (characterDef != null)
{
var char:CharacterGenerator = new CharacterGenerator();
char.Generate(characterDef, false, false, 1.0, false);
var clip:CacheByFrame = char.GetData();
holder.addChild(clip);
clip.gotoAndStop(exportSequences[i]);
clip.Frame.gotoAndPlay(1);
clip.x = nextX;
clip.y = nextY;
}
else
{
var original:CacheByFrame = GraphicFactory.Instance().GetCachedClip(GraphicFactory.Instance().GetGraphicName(graphicId), true);
holder.addChild(original);
original.gotoAndStop(exportSequences[i]);
original.Frame.gotoAndPlay(1);
original.x = nextX;
original.y = nextY;
}
}
*/
var c:CachedMovieClip = sequence.GetDebugClip();
holder.addChild(c);
c.gotoAndPlay(1);
c.x = nextX + 75;
c.y = nextY;
nextX += includeOriginal ? 150 : 75;
if (nextX > 2400)
{
nextX = 50;
nextY += 150;
}
}
if (sequenceIndex == exportSequences.length)
{
SequencesComplete();
} else {
var t:SimpleTimer = new SimpleTimer(0.01, function(){ NextSequence(); } );
}
}
public function SequencesComplete()
{
var pieces:Array = GetAllPieces();
if (holder)
{
var startX = 800;
var startY = 100;
var count = 0;
var max = 0;
for (var i in pieces)
{
var p:Piece = pieces[i];
var b:Bitmap = new Bitmap(p.FullData);
holder.addChild(b);
b.x = startX;
b.y = startY;
startY += b.height + 5;
max = Math.max(max, b.width);
if (count == 20)
{
count = 0;
startX += max + 5;
startY = 100;
max = 0;
}
count++;
}
}
for (var i in pieces)
{
for (var j in pieces)
{
if (i != j)
{
if (pieces[i].Matches(pieces[j].FullData, null))
{
_strace("MATCHING PIECES: " + i + " " + j);
}
}
}
}
if (this.isLocalLibrary)
{
this.library.EnsureAllUsedPiecesHaveNames();
}
if (doneCallback) doneCallback();
}
public function GetAllPieces():Array
{
return library.GetAllUsedPieces();
}
protected var templateCallback;
public function ProduceTemplate(callback)
{
this.templateCallback = callback;
var output:ASZip = new ASZip(CompressionMethod.GZIP);
var allPieces:Array = GetAllPieces();
for (var i = 0; i < allPieces.length; i++)
{
var imgBytes:ByteArray = PNGEncoder.encode(allPieces[i].FullData);
output.addFile(imgBytes, allPieces[i].Name + ".png");
}
var allPiecesUsed = false;
var frame = 1;
var piecesOutput:Array = [];
var templateText = getQualifiedClassName(graphic) + "\n";
while (!allPiecesUsed)
{
for (var i = 0; i < exportSequences.length; i++)
{
var newPiece = false;
var pieces:Array = sequences[i].PieceSequences
for (var j in pieces)
{
var pieceSeq:PieceSequence = pieces[j];
var pieceIndex = allPieces.indexOf(pieceSeq.GetPiece());
if (pieceSeq.GetFrame(frame).Present && !piecesOutput[pieceIndex])
{
newPiece = true;
break;
}
}
if (newPiece)
{
var sortOrder =
pieces = pieces.concat();
pieces.sort(function(a:PieceSequence,b:PieceSequence)
{
return a.GetFrame(frame).Depth - b.GetFrame(frame).Depth;
}
);
for (var j = 0; j < pieces.length; j++)
{
var pieceSeq:PieceSequence = pieces[j];
var piece:Piece = pieceSeq.GetPiece();
var pieceIndex = allPieces.indexOf(piece);
var pieceFrame:PieceFrameInfo = pieceSeq.GetFrame(frame);
if (pieceFrame.Present)
{
templateText += "piece" + pieceIndex + " " + piece.Name + " " +
piece.CenterPoint.x + " " +
piece.CenterPoint.y + " " +
pieceFrame.Transform.a + " " +
pieceFrame.Transform.b + " " +
pieceFrame.Transform.c + " " +
pieceFrame.Transform.d + " " +
pieceFrame.Transform.tx + " " +
pieceFrame.Transform.ty + "\n";
piecesOutput[pieceIndex] = true;
}
}
templateText += "end frame\n";
var usedCount = 0;
for (var j in piecesOutput)
{
if (piecesOutput[j]) usedCount++;
}
if (usedCount >= allPieces.length) allPiecesUsed = true;
}
if (allPiecesUsed) break;
}
frame++;
}
var b:ByteArray = new ByteArray();
b.writeUTFBytes(templateText);
output.addFile(b, "template.txt");
var loader:URLLoader = new URLLoader(new URLRequest("loadTemplate.jsfl"));
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function(e) {TemplateLoadComplete(loader, output);});
}
public function ProduceTemplateType2(clipName, excludeNames:Array, sampleAnimationIndices:Array, callback)
{
this.templateCallback = callback;
var output:ASZip = new ASZip(CompressionMethod.GZIP);
var templateText = clipName + "\n\n";
var allPieces:Array = GetAllPieces();
for (var i = 0; i < allPieces.length; i++)
{
var imgBytes:ByteArray = PNGEncoder.encode(allPieces[i].FullData);
output.addFile(imgBytes, allPieces[i].Name + ".png");
templateText += allPieces[i].Name + " " + allPieces[i].CenterPoint.x + " " + allPieces[i].CenterPoint.y + "\n";
}
templateText += "\n";
var allPiecesUsed = false;
var frame = 1;
var piecesOutput:Array = [];
while (!allPiecesUsed)
{
for (var i = 0; i < exportSequences.length; i++)
{
var newPiece = false;
var pieces:Array = sequences[i].PieceSequences
for (var j in pieces)
{
var pieceSeq:PieceSequence = pieces[j];
var pieceIndex = allPieces.indexOf(pieceSeq.GetPiece());
if (excludeNames.indexOf(pieceSeq.GetPiece().Name) == -1 && pieceSeq.GetFrame(frame).Present && !piecesOutput[pieceIndex])
{
newPiece = true;
break;
}
}
if (newPiece)
{
var sortOrder =
pieces = pieces.concat();
pieces.sort(function(a:PieceSequence,b:PieceSequence)
{
return a.GetFrame(frame).Depth - b.GetFrame(frame).Depth;
}
);
for (var j = 0; j < pieces.length; j++)
{
var pieceSeq:PieceSequence = pieces[j];
var piece:Piece = pieceSeq.GetPiece();
var pieceIndex = allPieces.indexOf(piece);
var pieceFrame:PieceFrameInfo = pieceSeq.GetFrame(frame);
if (pieceFrame.Present && excludeNames.indexOf(piece.Name) == -1)
{
templateText += "piece" + pieceIndex + " " + piece.Name + " " +
//piece.CenterPoint.x + " " +
//piece.CenterPoint.y + " " +
pieceFrame.Transform.a + " " +
pieceFrame.Transform.b + " " +
pieceFrame.Transform.c + " " +
pieceFrame.Transform.d + " " +
pieceFrame.Transform.tx + " " +
pieceFrame.Transform.ty + "\n";
piecesOutput[pieceIndex] = true;
}
}
templateText += "\n";
var usedCount = 0;
for (var j in piecesOutput)
{
if (piecesOutput[j]) usedCount++;
}
if (usedCount >= allPieces.length - excludeNames.length) allPiecesUsed = true;
}
if (allPiecesUsed) break;
}
frame++;
}
templateText += "end clip\n";
for (var i in sampleAnimationIndices)
{
var index = sampleAnimationIndices[i];
var seq:CharacterSequence = Sequences[index];
templateText += "\n" + seq.AnimationName + " " + seq.Length + " " + seq.PieceSequences.length + "\n";
for (var j = 0; j < seq.PieceSequences.length; j++)
{
var ps:PieceSequence = seq.PieceSequences[j];
templateText += ps.GetPiece().Name + "\n";
for (var k = 0; k < seq.Length; k++)
{
var info:PieceFrameInfo = ps.GetFrame(k + 1);
templateText += info.Present ? "1" : "0";
if (info.Present)
{
templateText += " " + info.Depth + " " + info.Transform.a + " " + info.Transform.b + " " + info.Transform.c + " " + info.Transform.d + " " + info.Transform.tx + " " + info.Transform.ty;
}
templateText += "\n";
}
}
}
var b:ByteArray = new ByteArray();
b.writeUTFBytes(templateText);
output.addFile(b, "template.txt");
/*
var loader:URLLoader = new URLLoader(new URLRequest("loadTemplate2.jsfl"));
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function(e) {TemplateLoadComplete2(loader, output, clipName);});
*/
var loaderBytes:ByteArray = new ByteArray();
loaderBytes.writeUTFBytes(TEMPLATE2);
output.addFile(loaderBytes, clipName + "_Load.jsfl");
OutputProjectZip(output, clipName);
}
private function TemplateLoadComplete(loader:URLLoader, output:ASZip)
{
output.addFile(loader.data, "loadTemplate.jsfl");
loader = new URLLoader(new URLRequest("empty.fla"));
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function(e) {EmptyFLALoadComplete(loader, output);});
}
private function TemplateLoadComplete2(loader:URLLoader, output:ASZip, fileName)
{
output.addFile(loader.data, fileName + "_Load.jsfl");
OutputProjectZip(output, fileName);
}
private function EmptyFLALoadComplete(loader:URLLoader, output:ASZip)
{
output.addFile(loader.data, getQualifiedClassName(graphic) + ".fla");
OutputProjectZip(output, getQualifiedClassName(graphic));
}
private function OutputProjectZip(output:ASZip, fileName)
{
var outputBytes:ByteArray = output.saveZIP(Method.LOCAL);
var fr:FileReference = new FileReference();
fr.addEventListener(Event.COMPLETE, SaveTemplateComplete);
fr.addEventListener(Event.CANCEL, SaveTemplateComplete);
fr.save(outputBytes, fileName + ".zip");
}
protected function SaveTemplateComplete(e:Event)
{
if (templateCallback != null) templateCallback();
}
// ====================
// Utils
// ====================
static var maxDepth = 99;
public static function SafeGotoFrame2(clip:MovieClip, frame)
{
if (clip is CharacterTypeGraphic)
{
(clip as CharacterTypeGraphic).SetFrame(frame);
return;
}
if (clip.currentFrame == 0) return;
frame = Math.max(1, frame);
if (clip.currentFrame == frame) return;
var diff = frame - clip.currentFrame;
AdvanceChildFrames(clip, diff, 0);
frame = ((frame - 1) % clip.totalFrames) + 1;
while (clip.currentFrame != frame)
{
if (frame > clip.currentFrame)
{
clip.nextFrame();
} else {
clip.prevFrame();
}
}
}
protected static function AdvanceChildFrames(clip:MovieClip, diff, depth)
{
if (depth > maxDepth) return;
for (var i = 0; i < clip.numChildren; i++)
{
var c = clip.getChildAt(i);
if (c is MovieClip)
{
AdvanceChildFrames(c, diff, depth+1);
}
}
if (clip.currentFrame == 0) return;
var newFrame = clip.currentFrame + diff;
newFrame = ((newFrame - 1) % clip.totalFrames) + 1;
while (clip.currentFrame != newFrame)
{
if (newFrame > clip.currentFrame)
{
clip.nextFrame();
} else {
clip.prevFrame();
}
}
}
public static function SafeGotoFrame(clip:MovieClip, frame)
{
if (clip is CharacterTypeGraphic)
{
(clip as CharacterTypeGraphic).SetFrame(frame);
} else {
frame = Math.max(1, Math.min(clip.totalFrames, frame));
if (frame == clip.currentFrame || clip.currentFrame == 0) return;
var dir = frame > clip.currentFrame ? 1 : -1;
while (clip.currentFrame != frame)
{
RecurseDir(clip, dir);
}
}
}
protected static function RecurseDir(clip:MovieClip, dir)
{
for (var i = 0; i < clip.numChildren; i++)
{
var child = clip.getChildAt(i);
if (child is MovieClip)
{
RecurseDir(child, dir);
}
}
if (clip.currentFrame != 0)
{
if (dir == 1)
{
clip.nextFrame();
} else {
clip.prevFrame();
}
}
}
public static function GetChildren(clip:MovieClip):Array
{
if (clip is CharacterTypeGraphic)
{
return (clip as CharacterTypeGraphic).GetGraphicChildren();
}
var ret:Array = [];
for (var i = 0; i < clip.numChildren; i++)
{
ret.push(clip.getChildAt(i));
}
return ret;
}
public static function RoundRect(r:Rectangle)
{
r.left = Math.floor(r.left);
r.top = Math.floor(r.top);
r.right = Math.ceil(r.right);
r.bottom = Math.ceil(r.bottom);
}
public static function ScaleRect(r:Rectangle, s)
{
r.left *= s;
r.top *= s;
r.right *= s;
r.bottom *= s;
}
public static function GetSequenceName(base:MovieClip, sequence):String
{
Utils.RecursivelyStop(base, sequence + 1);
if (base.currentLabel == null) return "UnknownAnimation";
return base.currentLabel;
}
public var SingleSequenceClip = false;
public static function GetSequenceClip(base:MovieClip, sequence):MovieClip
{
Utils.RecursivelyStop(base, sequence + 1);
if (base.numChildren == 1 && base.getChildAt(0) is MovieClip)
{
return base.getChildAt(0) as MovieClip;
}
var ret:MovieClip = new MovieClip();
while (base.numChildren > 0)
{
ret.addChild(base.getChildAt(0));
}
return ret;
}
public static function TransformRect(r:Rectangle, m:Matrix)
{
var p1:Point = new Point(r.left, r.top);
var p2:Point = new Point(r.right, r.top);
var p3:Point = new Point(r.left, r.bottom);
var p4:Point = new Point(r.right, r.bottom);
p1 = m.transformPoint(p1);
p2 = m.transformPoint(p2);
p3 = m.transformPoint(p3);
p4 = m.transformPoint(p4);
r.left = Math.min(p1.x, p2.x, p3.x, p4.x);
r.top = Math.min(p1.y, p2.y, p3.y, p4.y);
r.right = Math.max(p1.x, p2.x, p3.x, p4.x);
r.bottom = Math.max(p1.y, p2.y, p3.y, p4.y);
}
private static function HasAnyNamedChildren(m)
{
if (m is MovieClip)
{
for (var i = 0; i < m.numChildren; i++)
{
var c = m.getChildAt(i);
if (c is MovieClip)
{
if (!c.name.match("^instance\\d+$")) return true;
if (HasAnyNamedChildren(c as MovieClip)) return true;
}
}
}
return false;
}
public static function IsFullPiece(baseClip:DisplayObject, parentClip:MovieClip, clip:DisplayObject)
{
if (baseClip is CharacterTypeGraphic && baseClip == parentClip) return false;
if (clip is MovieClip && baseClip is CharacterTypeGraphic)
{
var ctg:CharacterTypeGraphic = baseClip as CharacterTypeGraphic;
if (ctg.IsForcedPiece(clip)) return true;
}
//if (HasAnyNamedChildren(clip)) return false;
//if (!clip.name.match("^instance\\d+$")) return true;
if (parentClip.totalFrames != 1) return false;
//if (clip == baseClip || (clip.parent && clip.parent == baseClip)) return false;
if (clip is MovieClip)
{
var m:MovieClip = clip as MovieClip;
if (m.totalFrames > 1) return false;
if (!m.name.match("^instance\\d+$")) return false;
for (var i = 0; i < m.numChildren; i++)
{
var c = m.getChildAt(i);
if (!IsFullPiece(baseClip, m, c)) return false;
}
}
return true;
}
public static function Decompose(m:Matrix)
{
var s:Point = ScaleFromMat(m);
m = m.clone();
var sxUnit = s.x >= 0 ? 1 : -1;
var syUnit = s.y >= 0 ? 1 : -1;
m.scale(sxUnit, syUnit);
//m.a /= sxUnit;
//m.d /= syUnit;
var rot = RotFromMat(m);
return {sx:s.x, sy:s.y, rot:rot};
}
public static function RotFromMat(m:Matrix)
{
return Math.atan2(-m.c, m.a);
}
public static function ScaleFromMat(m:Matrix):Point
{
var xAxisX = m.a;
var xAxisY = m.c;
var yAxisX = m.b;
var yAxisY = m.d;
var sx = Math.sqrt(xAxisX * xAxisX + xAxisY * xAxisY);
if (m.a < 0) sx *= -1;
var sy = Math.sqrt(yAxisX * yAxisX + yAxisY * yAxisY);
if (m.d < 0) sy *= -1;
return new Point(sx, sy);
}
/*
* angle difference
* (range -Math.PI to Math.PI)
*/
public static function GetAngleDiff(a, b)
{
var angleDiff = b - a;
while (angleDiff > Math.PI)
{
angleDiff -= Math.PI * 2;
}
while (angleDiff < -Math.PI)
{
angleDiff += Math.PI * 2;
}
return angleDiff;
}
/*
* angle difference
* (range 0 to Math.PI)
*/
public static function GetAngleDiffAbs(a, b)
{
var angleDiff = GetAngleDiff(a, b);
while (angleDiff < 0)
{
angleDiff += Math.PI * 2;
}
if (angleDiff > Math.PI)
{
angleDiff = Math.PI * 2 - angleDiff;
}
return angleDiff;
}
public static function GetTransform(from:Matrix, to:Matrix)
{
var i:Matrix = from.clone();
i.invert();
var m:Matrix = to.clone();
m.concat(i);
return m;
}
public static function MatricesMatch(a:Matrix, b:Matrix)
{
if (Math.abs(a.a - b.a) > 0.001) return false;
if (Math.abs(a.b - b.b) > 0.001) return false;
if (Math.abs(a.c - b.c) > 0.001) return false;
if (Math.abs(a.d - b.d) > 0.001) return false;
if (Math.abs(a.tx - b.tx) > 0.001) return false;
if (Math.abs(a.ty - b.ty) > 0.001) return false;
return true;
}
/*
* START IMPORT PROGRAM (jsfl)
*/
private static const TEMPLATE2:String = ( <![CDATA[
function _trace(str)
{
fl.outputPanel.trace(str);
}
var templateFolder = "OriginalTemplatePieces";
var sampleAnimationsFolder = "SampleAnimations";
(function()
{
var scriptPath = fl.scriptURI;
var folderIndex = scriptPath.lastIndexOf("/");
var scriptFolder = scriptPath.substr(0, folderIndex + 1);
_strace(scriptFolder);
var templatePath = scriptFolder + "template.txt";
var template = FLfile.read(templatePath);
var lines = template.split("\n");
var name = lines.shift();
lines.shift();
var flaPath = scriptFolder + name + ".fla";
if (FLfile.exists(flaPath))
{
alert("The file '" + name + ".fla' already exists. Did you already run the script? If you want to re-generate this project, delete '" + name + ".fla' and run this script again.");
return;
}
var doc = fl.createDocument();
var lib = doc.library;
fl.saveDocument(doc, flaPath);
lib.newFolder(templateFolder);
var clipFolder = name + "Clips";
var clipFolderNotExported = name + "Clips_NotExported";
var exportedNames = {};
var pieceNames = [];
var line;
while ((line = lines.shift()) != "")
{
var parts = line.split(" ");
var pieceName = parts[0];
pieceNames.push(pieceName);
doc.importFile(scriptFolder + pieceName + ".png", true, false, false);
lib.moveToFolder(templateFolder, pieceName + ".png", true);
var clipName = "piece_" + pieceName + "_clip";
var cx = Number(parts[1]);
var cy = Number(parts[2]);
var clipItem;
if (!lib.itemExists(clipFolderNotExported + "/" + clipName))
{
if (!lib.itemExists(clipFolderNotExported))
{
lib.newFolder(clipFolderNotExported);
}
lib.addNewItem("movie clip", clipName);
lib.editItem(clipName);
var clipFile = pieceName + ".png";
var index = lib.findItemIndex(templateFolder + "/" + clipFile);
var clipPNGItem = lib.items[index];
doc.addItem({x:0, y:0}, clipPNGItem);
doc.selection[0].x = -cx;
doc.selection[0].y = -cy;
var tl = doc.getTimeline();
tl.layers[0].name = "Template Piece";
tl.layers[0].locked = true;
tl.addNewLayer(pieceName, "normal", true);
doc.exitEditMode();
lib.moveToFolder(clipFolderNotExported, clipName, true);
}
}
lib.addNewItem("movie clip", name);
var index = lib.findItemIndex(name);
var animationItem = lib.items[index];
animationItem.linkageExportForAS = true;
animationItem.linkageExportInFirstFrame = true;
animationItem.linkageClassName = name;
lib.editItem(name);
var inNewClip = true;
var offsetX = 0;
var offsetY = 0;
while (inNewClip)
{
while ((line = lines.shift()) != "")
{
if (line == "end clip")
{
inNewClip = false;
lines.shift();
break;
}
var parts = line.split(" ");
var pieceName = parts[1];
//var cx = Number(parts[2]);
//var cy = Number(parts[3]);
var a = Number(parts[2]);
var b = Number(parts[3]);
var c = Number(parts[4]);
var d = Number(parts[5]);
var tx = Number(parts[6]);
var ty = Number(parts[7]);
var clipName = "piece_" + pieceName + "_clip";
lib.editItem(name);
if (!lib.itemExists(clipFolder + "/" + clipName))
{
if (lib.itemExists(clipFolderNotExported + "/" + clipName))
{
exportedNames[clipName] = true;
if (!lib.itemExists(clipFolder))
{
lib.newFolder(clipFolder);
}
lib.moveToFolder(clipFolder, clipFolderNotExported + "/" + clipName);
}
}
if (lib.itemExists(clipFolder + "/" + clipName))
{
var index = lib.findItemIndex(clipFolder + "/" + clipName);
clipItem = lib.items[index];
doc.addItem({x:0, y:0}, clipItem);
doc.selection[0].matrix =
//fl.Math.concatMatrix(
// {a:1, b:0, c:0, d:1, tx:-cx, ty:-cy},
{a:a, b:b, c:c, d:d, tx:tx + offsetX, ty:ty};
//);
doc.selection[0].name = "piece_" + pieceName + "_clip";
}
else
{
_strace("Missing Piece " + clipName);
}
}
offsetX += 200;
}
doc.exitEditMode();
lib.newFolder(sampleAnimationsFolder);
//alert("Clips Imported");
while (lines.length > 0)
{
var animDesc = lines.shift();
var parts = animDesc.split(" ");
if (parts.length != 3) break;
var animName = parts[0];
var animLength = parts[1];
var animParts = parts[2];
lib.addNewItem("movie clip", name + animName);
lib.editItem(name + animName);
var timeline = doc.getTimeline();
timeline.layers[0].name = "depth" + 0;
while (timeline.layerCount < animParts)
{
timeline.addNewLayer("depth" + timeline.layerCount, "normal", false);
}
var parts = [];
var partFrames = [];
for (var i = 0; i < animParts; i++)
{
var partName = lines.shift();
var clipName = "piece_" + partName + "_clip";
var clipLoc = clipFolderNotExported + "/" + clipName;
if (exportedNames[clipName])
{
clipLoc = clipFolder + "/" + clipName;
}
var index = lib.findItemIndex(clipLoc);
var item = lib.items[index];
parts.push(item);
var frames = [];
for (var k = 0; k < animLength; k++)
{
var frameInfo = lines.shift();
var lineParts = frameInfo.split(" ");
var info = {present:lineParts[0] == "1"};
if (info.present)
{
info.index = i;
info.depth = Number(lineParts[1]);
info.transform = {
a:Number(lineParts[2]),
b:Number(lineParts[3]),
c:Number(lineParts[4]),
d:Number(lineParts[5]),
tx:Number(lineParts[6]),
ty:Number(lineParts[7]),
};
}
frames.push(info);
}
partFrames.push(frames);
}
var lastOrder = "";
for (var i = 0; i < animLength; i++)
{
var order = "";
var usedParts = [];
for (var k = 0; k < animParts; k++)
{
if (partFrames[k][i].present)
{
usedParts.push(partFrames[k][i]);
}
}
usedParts.sort(function(a, b) { return a.depth - b.depth; });
for (var j = 0; j < usedParts.length; j++)
{
order += usedParts[j].index + "|";
}
if (order != lastOrder)
{
if (i != 0)
{
for (var j = 0; j < animParts; j++)
{
timeline.currentLayer = j;
timeline.insertBlankKeyframe(i);
}
}
timeline.currentFrame = i;
for (var j = 0; j < usedParts.length; j++)
{
timeline.setSelectedLayers(animParts - j - 1, true);
doc.addItem({x:0, y:0}, parts[usedParts[j].index]);
}
lastOrder = order;
}
else
{
for (var j = 0; j < animParts; j++)
{
timeline.currentLayer = j;
timeline.insertKeyframe(i);
}
}
for (var j = 0; j < usedParts.length; j++)
{
if (timeline.layers[animParts - j - 1].frames[i].elements.length == 0)
{
_strace("UHOH" + animParts + " " + i + " " + j + " " + usedParts.length);
}
timeline.layers[animParts - j - 1].frames[i].elements[0].matrix = usedParts[j].transform;
}
//break;
}
lines.shift();
timeline.currentFrame = 1;
doc.exitEditMode();
lib.moveToFolder(sampleAnimationsFolder, name + animName, true);
}
doc.save(true);
})();
]]> ).toString();
/*
* END PROGRAM
*/
}
}