/// <summary> /// Process an instantiation tag in the job XML /// </summary> /// <param name="insTag">A pointer to the instantiation node</param> /// <param name="currentSwfTag">A pointer to the current SWF node that contains /// the instance node.</param> /// <param name="swf">The SWF within which to instantiate something.</param> private void CreateInstance(XPathNavigator insTag, XPathNavigator currentSwfTag, SWF swf) { string type = insTag.GetAttribute(XMLHelper.AttrType, string.Empty); string src = insTag.GetAttribute(XMLHelper.AttrSrc, string.Empty); string className = insTag.GetAttribute(XMLHelper.AttrClass, string.Empty); /* ISSUE 58: If the instance name (id) is the same as the class name, it can * cause problems in files generated and decompiled again in sothink. We should * probably detect this and warn against it. */ switch (type) { case XMLHelper.ValSwf: if (className == string.Empty) { throw new SwiffotronException( SwiffotronError.BadInputXML, this.Context, "An instance created from a SWF needs a class name to be defined."); } if (src.StartsWith("store://")) { throw new SwiffotronException(SwiffotronError.BadPathOrID, this.Context, "Unexpected store path. Did you mean for the type to be extern, perhaps?"); } if (!this.processedSWFs.ContainsKey(src)) { throw new SwiffotronException( SwiffotronError.Internal, this.Context, "Internal error. SWF tags were processed out of order (" + currentSwfTag.GetAttribute(XMLHelper.AttrID, string.Empty) + " requres " + src + ")."); } SWF processedSWF = this.processedSWFs[src]; this.CreateInstanceFromSWF(insTag, swf, className, processedSWF); break; case XMLHelper.ValMovieClip: Sprite clip = swf.GetCharacter(src) as Sprite; if (clip == null) { throw new SwiffotronException(SwiffotronError.BadInputXML, this.Context, "MovieClip not defined: " + src); } this.CreateInstanceIn( insTag.GetAttribute(XMLHelper.AttrID, string.Empty), swf, insTag, clip, className); clip.SpriteProc(delegate(Sprite s) { if (s.Class != null && !(s.Class is AdobeClass)) { /* ISSUE 29: Only do this if the class hasn't already been bound. * Note that this will be a problem if one movieclip is used to create * several instances. At the time of writing, there is no unit test for * this case. */ swf.FirstScript.Code.GenerateClipClassBindingScript(s); } }); break; case XMLHelper.ValInstance: if (className != string.Empty) { throw new SwiffotronException( SwiffotronError.BadInputXML, this.Context.Sentinel("ClassNameInClonedInstance"), "An instance cannot be given a new classname if it is a clone of an existing instance (" + className + ")"); } Sprite srcSprite = swfProc.SpritesFromQname(src, swf, false)[0]; if (!srcSprite.HasClass) { srcSprite.Class = AdobeClass.CreateFlashDisplayMovieClip(srcSprite.Root.FirstScript.Code); className = srcSprite.Class.QualifiedName; } this.CreateInstanceIn( insTag.GetAttribute(XMLHelper.AttrID, string.Empty), swf, insTag, srcSprite, className); break; case XMLHelper.ValExtern: SWF importSwf = this.SwfFromStore(src); this.CreateInstanceFromSWF(insTag, swf, className, importSwf); break; default: /* ISSUE 73 */ throw new SwiffotronException( SwiffotronError.UnimplementedFeature, this.Context, "Bad instance type: " + type); } }