/// <summary> /// Read in a trait, which are like object properties. /// </summary> /// <returns>A trait.</returns> private Trait ReadTrait() { Trait t = null; Multiname traitName = this.code.GetMultiname((int)this.abcdtr.ReadU30()); int traitCode = this.abcdtr.ReadUI8(); TraitKind kind = (TraitKind)(traitCode & 0xF); switch (kind) { case TraitKind.Slot: case TraitKind.Const: SlotTrait st = new SlotTrait(); st.Name = traitName; st.Kind = kind; st.SlotID = this.abcdtr.ReadU30(); st.TypeName = this.code.GetMultiname((int)this.abcdtr.ReadU30()); uint vindex = this.abcdtr.ReadU30(); if (vindex != 0) { st.ValKind = (ConstantKind)this.abcdtr.ReadUI8(); switch (st.ValKind) { case ConstantKind.ConInt: st.Val = this.code.IntConsts[vindex]; break; case ConstantKind.ConUInt: st.Val = this.code.UIntConsts[vindex]; break; case ConstantKind.ConDouble: st.Val = this.code.DoubleConsts[vindex]; break; case ConstantKind.ConUtf8: st.Val = this.code.StringConsts[vindex]; break; case ConstantKind.ConTrue: case ConstantKind.ConFalse: case ConstantKind.ConNull: case ConstantKind.ConUndefined: break; case ConstantKind.ConNamespace: case ConstantKind.ConPackageNamespace: case ConstantKind.ConPackageInternalNs: case ConstantKind.ConProtectedNamespace: case ConstantKind.ConExplicitNamespace: case ConstantKind.ConStaticProtectedNs: case ConstantKind.ConPrivateNs: st.Val = this.code.GetNamespace((int)vindex); break; default: throw new SWFModellerException( SWFModellerError.Internal, "Unsupported constant kind: " + st.ValKind.ToString()); } } t = st; break; case TraitKind.Class: ClassTrait ct = new ClassTrait(); ct.Name = traitName; ct.Kind = kind; ct.SlotID = this.abcdtr.ReadU30(); this.LateResolutions.Add(ct, (int)this.abcdtr.ReadU30()); /* We'll resolve the class ref later. */ t = ct; break; case TraitKind.Function: FunctionTrait ft = new FunctionTrait(); ft.Name = traitName; ft.Kind = kind; ft.SlotID = this.abcdtr.ReadU30(); ft.Fn = this.code.GetMethod((int)this.abcdtr.ReadU30()); t = ft; break; case TraitKind.Method: case TraitKind.Getter: case TraitKind.Setter: default: MethodTrait mt = new MethodTrait(); mt.Name = traitName; mt.Kind = kind; uint dispID = this.abcdtr.ReadU30(); if (dispID != 0) { mt.OverriddenMethod = this.code.GetMethod((int)dispID); } mt.Fn = this.code.GetMethod((int)this.abcdtr.ReadU30()); t = mt; break; } return t; }
/// <summary> /// Generates a script that binds a class to a clip. /// </summary> /// <param name="spr">The sprite to create the class for.</param> public void GenerateClipClassBindingScript(Sprite spr) { Namespace nsEmptyPackage = this.CreateNamespace(Namespace.NamespaceKind.Package, string.Empty); Namespace nsFlashEvents = this.CreateNamespace(Namespace.NamespaceKind.Package, "flash.events"); Namespace nsFlashDisplay = this.CreateNamespace(Namespace.NamespaceKind.Package, "flash.display"); Multiname mnObject = this.CreateMultiname(Multiname.MultinameKind.QName, "Object", nsEmptyPackage, null); Multiname mnEventDispatcher = this.CreateMultiname(Multiname.MultinameKind.QName, "EventDispatcher", nsFlashEvents, null); Multiname mnDisplayObject = this.CreateMultiname(Multiname.MultinameKind.QName, "DisplayObject", nsFlashDisplay, null); Multiname mnInteractiveObject = this.CreateMultiname(Multiname.MultinameKind.QName, "InteractiveObject", nsFlashDisplay, null); Multiname mnDisplayObjectContainer = this.CreateMultiname(Multiname.MultinameKind.QName, "DisplayObjectContainer", nsFlashDisplay, null); Multiname mnSprite = this.CreateMultiname(Multiname.MultinameKind.QName, "Sprite", nsFlashDisplay, null); Multiname mnMovieClip = this.CreateMultiname(Multiname.MultinameKind.QName, "MovieClip", nsFlashDisplay, null); Multiname sprQName = null; Multiname sprMultiname = null; if (spr.Class.Name.Kind == Multiname.MultinameKind.Multiname) { sprMultiname = spr.Class.Name; /* ISSUE 5: Convert a multiname to a QName of the form: * mn QName "MyClassName"; ns Package "com.mypackage"; set * */ throw new SWFModellerException( SWFModellerError.UnimplementedFeature, "Unsupported sprite class name kind in class binding script generation: " + spr.Class.Name.Kind.ToString()); } else if (spr.Class.Name.Kind == Multiname.MultinameKind.QName) { sprQName = spr.Class.Name; /* Convert to form: * mn Multiname "MyClassName"; ns *; set {ns Package "com.mypackage"} */ sprMultiname = this.CreateMultiname( Multiname.MultinameKind.Multiname, sprQName.Name, nsEmptyPackage, this.CreateNamespaceSet(new Namespace[] { sprQName.NS })); } else { /* ISSUE 73 */ throw new SWFModellerException( SWFModellerError.UnimplementedFeature, "Unsupported sprite class name kind in class binding script generation: " + spr.Class.Name.Kind.ToString()); } Method bindingMethod = this.CreateMethod(spr.Class.Name.Name + "BindingScript.abc", 2, 1, 1, 9, /* The above magic numbers come from the numbers generated by IDE versions of this function. * I have no real ideal about how I'd work them out for myself, which would obviously be * more ideal. */ /* Line */ /* 1 */ this.Op(Opcode.Mnemonics.GetLocal0), /* 2 */ this.Op(Opcode.Mnemonics.PushScope), /* 3 */ this.Op(Opcode.Mnemonics.FindPropStrict, sprMultiname), /* 4 */ this.Op(Opcode.Mnemonics.GetLex, mnObject), /* 5 */ this.Op(Opcode.Mnemonics.PushScope), /* 6 */ this.Op(Opcode.Mnemonics.GetLex, mnEventDispatcher), /* 7 */ this.Op(Opcode.Mnemonics.PushScope), /* 8 */ this.Op(Opcode.Mnemonics.GetLex, mnDisplayObject), /* 9 */ this.Op(Opcode.Mnemonics.PushScope), /* 10 */ this.Op(Opcode.Mnemonics.GetLex, mnInteractiveObject), /* 11 */ this.Op(Opcode.Mnemonics.PushScope), /* 12 */ this.Op(Opcode.Mnemonics.GetLex, mnDisplayObjectContainer), /* 13 */ this.Op(Opcode.Mnemonics.PushScope), /* 14 */ this.Op(Opcode.Mnemonics.GetLex, mnSprite), /* 15 */ this.Op(Opcode.Mnemonics.PushScope), /* 16 */ this.Op(Opcode.Mnemonics.GetLex, mnMovieClip), /* 17 */ this.Op(Opcode.Mnemonics.PushScope), /* 18 */ this.Op(Opcode.Mnemonics.GetLex, mnMovieClip), /* 19 */ this.Op(Opcode.Mnemonics.NewClass, spr.Class), /* 20 */ this.Op(Opcode.Mnemonics.PopScope), /* 21 */ this.Op(Opcode.Mnemonics.PopScope), /* 22 */ this.Op(Opcode.Mnemonics.PopScope), /* 23 */ this.Op(Opcode.Mnemonics.PopScope), /* 24 */ this.Op(Opcode.Mnemonics.PopScope), /* 25 */ this.Op(Opcode.Mnemonics.PopScope), /* 26 */ this.Op(Opcode.Mnemonics.PopScope), /* 27 */ this.Op(Opcode.Mnemonics.InitProperty, sprQName), /* 28 */ this.Op(Opcode.Mnemonics.ReturnVoid)); Trait classTrait = new ClassTrait() { As3class = (AS3ClassDef)spr.Class, Kind = TraitKind.Class, Name = sprQName }; bindingMethod.AddTrait(classTrait); Script bindScript = new Script() { Method = bindingMethod, }; bindScript.AddTrait(classTrait); this.scripts.Insert(0, bindScript); /* Insert at the start to make sure any timeline script is last. */ }