A class reference trait on an object
Inheritance: Trait, IHasSlotID
Esempio n. 1
0
        /// <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;
        }
Esempio n. 2
0
        /// <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. */
        }