Есть задача: создание swf средствами as3, в котором находятся embed-ресурсы.
Я использовал для этого библиотеку as3swf и всё бы хорошо, кроме отсутствия переменных embed-данных в конструкторе. Видимо, я неверно использую
Opcode.initproperty
Код AS3:
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// создание двух массивов данных(для примера - просто строки)
var ba:ByteArray = new ByteArray();
ba.writeMultiByte("first text for embeddeng as ByteArray", "utf-8");
var ba2:ByteArray = new ByteArray();
ba2.writeMultiByte("second text for embeddeng as ByteArray", "utf-8");
// создание словаря ресурсов для записи
var dict:Dictionary = new Dictionary();
dict["text1"] = ba;
dict["text2"] = ba2;
// создание swf из словаря массивов данных
var swfdata:SWFData = compileResourcesSwf("somePackage", "someClass", dict);
var fr:FileReference = new FileReference();
fr.save(swfdata, "data.swf");
}
Код AS3:
/**
* Компилировать swf-файл с embed ByteArray, которые переданы в аргументах.
* @param packageName Имя пакета, которому принадлежит скомпилированный swf.
* @param className Имя класса swf.
* @param resources Dictionary с ключами - именами embed-ресурсов и значениями - массивами байтов.
* @return SWFData
*/
public function compileResourcesSwf(packageName:String, className:String, resources:Dictionary):SWFData
{
var qulifiedName:String = packageName + "." + className;
var resourceName:String;
var swf:SWF = new SWF();
var swfTags:Vector.<ITag> = swf.tags;
swfTags.push(new TagFileAttributes());
var embedBinaryTag:TagDefineBinaryData;
var customMetaTag:TagCustom;
var abcBuilder:IAbcBuilder = new AbcBuilder();
var packageBuilder:IPackageBuilder = abcBuilder.definePackage(packageName);
var classBuilder:IClassBuilder = packageBuilder.defineClass(className, "flash.display.Sprite");
// нужно импортировать класс mx.core.ByteArrayAsset, от которого наследуются emded-массивы данных
packageBuilder.defineClass("mx.core.ByteArrayAsset");
var ctorBuilder:ICtorBuilder = classBuilder.defineConstructor();
for (resourceName in resources)
{
// создание тега TagDefineBinaryData
embedBinaryTag = new TagDefineBinaryData();
var bytearray:ByteArray = resources[resourceName];
embedBinaryTag.binaryData.writeBytes(bytearray, 0, bytearray.length);
swfTags.push(embedBinaryTag);
// создание класса embed-ресурса, наследующегося от "mx.core.ByteArrayAsset"
packageBuilder.defineClass(className + "_" + resourceName, "mx.core.ByteArrayAsset");
// добавление переменных embed-ресурсов
var pb:IPropertyBuilder = classBuilder.defineProperty(resourceName, "Class", null);
pb.visibility = MemberVisibility.PUBLIC;
var bm2:QualifiedName = new QualifiedName(className + "_" + resourceName, LNamespace.PUBLIC);
ctorBuilder.addOpcode(Opcode.findpropstrict, [bm2]);
ctorBuilder.addOpcode(Opcode.getproperty, [bm2]);
ctorBuilder.addOpcode(Opcode.initproperty, [new QualifiedName(className + "::" + resourceName, LNamespace.BUILTIN, MultinameKind.QNAME)]);
}
var abcFile:AbcFile = abcBuilder.build();
var abcSerializer:AbcSerializer = new AbcSerializer();
var abcBytes:ByteArray = abcSerializer.serializeAbcFile(abcFile);
swfTags.push(TagDoABC.create(abcBytes));
var symbolClass:TagSymbolClass = new TagSymbolClass();
symbolClass.symbols.push(SWFSymbol.create(0, qulifiedName));
var sym:SWFSymbol;
var i:uint = 1;
for (resourceName in resources)
{
sym = SWFSymbol.create(i, qulifiedName + "_" + resourceName);
symbolClass.symbols.push(sym);
i++;
}
swfTags.push(symbolClass);
swfTags.push(new TagShowFrame);
swfTags.push(new TagEnd);
var data:SWFData = new SWFData();
try
{
swf.publish(data);
}
catch (e:Error)
{
trace(e);
}
return data;
}
На выходе конструктор неправильно оформлен, как это видно из скрина.
Должно получиться так:
Код AS3:
package somePackage
{
import flash.display.*;
public class someClass extends Sprite
{
private var text1:Class;
private var text2:Class;
public function someClass()
{
this.text1 = someClass_text1;
this.text2 = someClass_text2;
}
}
}