public Script(IntermediateNode root, ConstructCollection constructs)
 {
     ObjectMaps = new List <ObjectMap>();
     JointMaps  = new List <JointMap>();
     foreach (Node node in root)
     {
         if (node.Name.Equals("root height", StringComparison.OrdinalIgnoreCase))
         {
             HasRootHeight = true;
             RootHeight    = (node as LeafNode).SingleData.Value;
         }
         else if (node.Name.StartsWith("object map", StringComparison.OrdinalIgnoreCase))
         {
             ObjectMaps.Add(new ObjectMap(node as IntermediateNode));
         }
         else if (node.Name.StartsWith("joint map", StringComparison.OrdinalIgnoreCase))
         {
             JointMaps.Add(new JointMap(node as IntermediateNode));
         }
         else
         {
             throw new Exception("Invalid Node in script root: " + node.Name);
         }
     }
 }
Beispiel #2
0
        public override void Update(TimeSpan time)
        {
            if (constructs == null)
            {
                constructs = Parent.CmpConstructs;
            }
            totalTime += time.TotalSeconds;
            int c = animations.Count;

            for (int i = animations.Count - 1; i >= 0; i--)
            {
                if (ProcessAnimation(animations[i]))
                {
                    if (AnimationCompleted != null)
                    {
                        AnimationCompleted(animations[i].Name);
                    }
                    animations.RemoveAt(i);
                }
            }
            if (c > 0 && Parent != null)
            {
                Parent.UpdateCollision();
            }
        }
Beispiel #3
0
 public Script(IntermediateNode root, ConstructCollection constructs)
 {
     Name       = root.Name;
     ObjectMaps = new List <ObjectMap>();
     JointMaps  = new List <JointMap>();
     foreach (Node node in root)
     {
         if (node.Name.Equals("root height", StringComparison.OrdinalIgnoreCase))
         {
             HasRootHeight = true;
             RootHeight    = (node as LeafNode).SingleData.Value;
         }
         else if (node.Name.StartsWith("object map", StringComparison.OrdinalIgnoreCase))
         {
             ObjectMaps.Add(new ObjectMap(node as IntermediateNode));
         }
         else if (node.Name.StartsWith("joint map", StringComparison.OrdinalIgnoreCase))
         {
             JointMaps.Add(new JointMap(node as IntermediateNode));
         }
         else
         {
             FLLog.Warning("Anm", $"{root.Name}: invalid node {node.Name}, possible broken animation?");
         }
     }
 }
Beispiel #4
0
 public DfmPart(string objectName, string fileName, Dictionary <string, Bone> models, ConstructCollection constructs)
 {
     this.bones      = models;
     this.constructs = constructs;
     this.objectName = objectName;
     this.fileName   = fileName;
 }
Beispiel #5
0
 public Part(string objectName, string fileName, Dictionary <string, ModelFile> models, ConstructCollection constructs)
 {
     this.models     = models;
     this.constructs = constructs;
     this.objectName = objectName;
     this.fileName   = fileName;
 }
Beispiel #6
0
 void Load(IntermediateNode root, ConstructCollection constructs)
 {
     if (Scripts == null)
     {
         Scripts = new Dictionary <string, Script>(root.Count, StringComparer.OrdinalIgnoreCase);
     }
     foreach (Node node in root)
     {
         if (node.Name.Equals("script", StringComparison.OrdinalIgnoreCase))
         {
             foreach (IntermediateNode scNode in (IntermediateNode)node)
             {
                 Scripts[scNode.Name] = new Script(scNode, constructs);
             }
         }
     }
 }
Beispiel #7
0
        private void load(IntermediateNode root, ConstructCollection constructs)
        {
            Scripts = new Dictionary <string, Script>();

            foreach (Node node in root)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "script":
                    foreach (IntermediateNode scNode in (IntermediateNode)node)
                    {
                        Scripts.Add(scNode.Name, new Script(scNode, constructs));
                    }
                    break;

                case "anim_credits":
                    //TODO: What is this?
                    break;

                default: throw new Exception("Invalid node in " + root.Name + ": " + node.Name);
                }
            }
        }
        public VisitStatus VisitCollectionProperty <TSrcProperty, TSrcContainer, TSrcValue>(
            TSrcProperty srcProperty,
            ref TSrcContainer srcContainer,
            ref ChangeTracker changeTracker)
            where TSrcProperty : ICollectionProperty <TSrcContainer, TSrcValue>
        {
            var action = new ConstructCollection <TSrcProperty, TSrcContainer, TSrcValue>
            {
                Options      = m_Options,
                Result       = Result,
                SrcProperty  = srcProperty,
                SrcContainer = srcContainer,
                SrcValue     = srcProperty.GetValue(ref srcContainer)
            };

            m_DstPropertyBag.FindProperty(
                srcProperty.GetName(),
                ref m_DstContainer,
                ref changeTracker,
                ref action);

            return(VisitStatus.Handled);
        }
Beispiel #9
0
        void InitWithDrawable(IDrawable drawable, ResourceManager res, bool staticpos, bool havePhys = true)
        {
            Resources = res;
            dr        = drawable;
            PhysicsComponent phys  = null;
            bool             isCmp = false;
            string           name  = "";

            if (dr is SphFile)
            {
                var radius = ((SphFile)dr).Radius;
                phys = new PhysicsComponent(this)
                {
                    SphereRadius = radius
                };
                name = ((SphFile)dr).SideMaterialNames[0];
            }
            else if (dr is ModelFile)
            {
                var mdl  = dr as ModelFile;
                var path = Path.ChangeExtension(mdl.Path, "sur");
                name = Path.GetFileNameWithoutExtension(mdl.Path);
                if (File.Exists(path))
                {
                    phys = new PhysicsComponent(this)
                    {
                        SurPath = path
                    }
                }
                ;
            }
            else if (dr is CmpFile)
            {
                isCmp = true;
                var cmp = dr as CmpFile;
                CmpParts      = new List <Part>();
                CmpConstructs = cmp.Constructs.CloneAll();
                foreach (var part in cmp.Parts)
                {
                    CmpParts.Add(part.Clone(CmpConstructs));
                }
                if (cmp.Animation != null)
                {
                    AnimationComponent = new AnimationComponent(this, cmp.Animation);
                    Components.Add(AnimationComponent);
                }
                var path = Path.ChangeExtension(cmp.Path, "sur");
                name = Path.GetFileNameWithoutExtension(cmp.Path);
                if (File.Exists(path))
                {
                    phys = new PhysicsComponent(this)
                    {
                        SurPath = path
                    }
                }
                ;

                /*if (File.Exists(path))
                 *              {
                 *                      SurFile sur = res.GetSur(path);
                 *                      var shapes = new List<CompoundSurShape.TransformedShape>();
                 *                      foreach (var part in CmpParts)
                 *                      {
                 *                              var crc = CrcTool.FLModelCrc(part.ObjectName);
                 *                              if (!sur.HasShape(crc))
                 *                              {
                 *                                      FLLog.Warning("Sur", "No hitbox for " + part.ObjectName);
                 *                                      continue;
                 *                              }
                 *                              var colshape = sur.GetShape(crc);
                 *                              if (part.Construct == null)
                 *                              {
                 *                                      foreach (var s in colshape)
                 *                                              shapes.Add(new CompoundSurShape.TransformedShape(s, Matrix3.Identity, Vector3.Zero));						}
                 *                              else
                 *                              {
                 *                                      var tr = part.Construct.Transform;
                 *                                      var pos = tr.ExtractTranslation();
                 *                                      var q = tr.ExtractRotation(true);
                 *                                      var rot = Matrix3.CreateFromQuaternion(q);
                 *                                      foreach (var s in colshape)
                 *                                              shapes.Add(new CompoundSurShape.TransformedShape(s, rot, pos) { Tag = part.Construct });
                 *                              }
                 *                      }
                 *                      collisionShape = new CompoundSurShape(shapes);
                 *              }*/
            }

            if (havePhys && phys != null)
            {
                PhysicsComponent = phys;
                Components.Add(phys);
            }
            PopulateHardpoints(dr);
            if (isCmp)
            {
                RenderComponent = new ModelRenderer(CmpParts, (dr as CmpFile))
                {
                    Name = name
                }
            }
            ;
            else
            {
                RenderComponent = new ModelRenderer(dr)
                {
                    Name = name
                }
            };
        }
Beispiel #10
0
 public AnimationComponent(ConstructCollection constructs, AnmFile animation) : base(null)
 {
     anm             = animation;
     this.constructs = constructs;
 }
Beispiel #11
0
        void InitWithDrawable(IDrawable drawable, ResourceManager res, bool draw, bool staticpos, bool havePhys = true)
        {
            Resources = res;
            dr        = drawable;
            PhysicsComponent phys  = null;
            bool             isCmp = false;
            string           name  = "";

            if (dr is SphFile)
            {
                var radius = ((SphFile)dr).Radius;
                phys = new PhysicsComponent(this)
                {
                    SphereRadius = radius
                };
                name = ((SphFile)dr).SideMaterialNames[0];
            }
            else if (dr is ModelFile)
            {
                var mdl  = dr as ModelFile;
                var path = Path.ChangeExtension(mdl.Path, "sur");
                name = Path.GetFileNameWithoutExtension(mdl.Path);
                if (File.Exists(path))
                {
                    phys = new PhysicsComponent(this)
                    {
                        SurPath = path
                    }
                }
                ;
            }
            else if (dr is CmpFile)
            {
                isCmp = true;
                var cmp = dr as CmpFile;
                CmpParts      = new List <Part>();
                CmpConstructs = cmp.Constructs.CloneAll();
                foreach (var part in cmp.Parts)
                {
                    CmpParts.Add(part.Clone(CmpConstructs));
                }
                if (cmp.Animation != null)
                {
                    AnimationComponent = new AnimationComponent(this, cmp.Animation);
                    Components.Add(AnimationComponent);
                }
                var path = Path.ChangeExtension(cmp.Path, "sur");
                name = Path.GetFileNameWithoutExtension(cmp.Path);
                if (File.Exists(path))
                {
                    phys = new PhysicsComponent(this)
                    {
                        SurPath = path
                    }
                }
                ;
            }

            if (havePhys && phys != null)
            {
                PhysicsComponent = phys;
                Components.Add(phys);
            }
            PopulateHardpoints(dr);
            if (draw)
            {
                if (isCmp)
                {
                    RenderComponent = new ModelRenderer(CmpParts, (dr as CmpFile))
                    {
                        Name = name
                    }
                }
                ;
                else
                {
                    RenderComponent = new ModelRenderer(dr)
                    {
                        Name = name
                    }
                };
            }
        }
Beispiel #12
0
        public CmpFile(IntermediateNode rootnode, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;

            Models     = new Dictionary <string, ModelFile>();
            Constructs = new ConstructCollection();
            Parts      = new Dictionary <int, Part>();

            foreach (Node node in rootnode)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "vmeshlibrary":
                    IntermediateNode vMeshLibraryNode = node as IntermediateNode;
                    if (VMeshLibrary == null)
                    {
                        VMeshLibrary = new VmsFile(vMeshLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple vmeshlibrary nodes in cmp root");
                    }
                    break;

                case "animation":
                    IntermediateNode animationNode = node as IntermediateNode;
                    if (Animation == null)
                    {
                        Animation = new AnmFile(animationNode, Constructs);
                    }
                    else
                    {
                        throw new Exception("Multiple animation nodes in cmp root");
                    }
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in cmp root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in cmp root");
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    int maxIndices             = int.MaxValue;
                    foreach (Node SubNode in cmpndNode)
                    {
                        if (SubNode is LeafNode)
                        {
                            continue;
                        }
                        var cmpndSubNode = (IntermediateNode)SubNode;
                        if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            Constructs.AddNode(cmpndSubNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            string objectName = string.Empty, fileName = string.Empty;
                            int    index = -1;

                            foreach (LeafNode partNode in cmpndSubNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    if (partNode.Int32Data != null)
                                    {
                                        index = partNode.Int32Data.Value;
                                    }
                                    else
                                    {
                                        index = partNode.Int32ArrayData [0];
                                    }
                                    break;

                                default: throw new Exception("Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                }
                            }
                            if (Parts.ContainsKey(index))
                            {
                                FLLog.Error("Cmp", "Duplicate index");
                                Parts.Add(maxIndices--, new Part(objectName, fileName, Models, Constructs));
                            }
                            else
                            {
                                Parts.Add(index, new Part(objectName, fileName, Models, Constructs));
                            }
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + cmpndNode.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                case "materialanim":
                    MaterialAnim = new MaterialAnimCollection((IntermediateNode)node);
                    break;

                default:
                    if (node.Name.EndsWith(".3db", StringComparison.OrdinalIgnoreCase))
                    {
                        ModelFile m = new ModelFile(node as IntermediateNode, this);
                        Models.Add(node.Name, m);
                    }
                    else
                    {
                        FLLog.Error("Cmp", Path ?? "Utf" + ": Invalid Node in cmp root: " + node.Name);
                    }
                    break;
                }
            }
        }
Beispiel #13
0
 public AnmFile(IntermediateNode root, ConstructCollection constructs)
 {
     load(root, constructs);
 }
Beispiel #14
0
        public DfmFile(IntermediateNode root, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;
            Levels = new Dictionary <int, DfmMesh>();

            Bones      = new Dictionary <string, Bone>();
            Parts      = new Dictionary <int, DfmPart>();
            Constructs = new ConstructCollection();

            foreach (Node node in root)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in dfm root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in dfm root");
                    }
                    break;

                case "multilevel":
                    IntermediateNode multiLevelNode = node as IntermediateNode;
                    foreach (Node multiLevelSubNode in multiLevelNode)
                    {
                        if (multiLevelSubNode.Name.StartsWith("mesh", StringComparison.OrdinalIgnoreCase))
                        {
                            IntermediateNode meshNode = multiLevelSubNode as IntermediateNode;

                            int level = 0;
                            if (!int.TryParse(meshNode.Name.Substring(4), out level))
                            {
                                throw new Exception("");
                            }
                            Levels.Add(level, new DfmMesh(meshNode, this, Parts));
                        }
                        else if (multiLevelSubNode.Name.Equals("fractions", StringComparison.OrdinalIgnoreCase))
                        {
                            LeafNode fractionsNode = multiLevelSubNode as LeafNode;
                            if (Fractions == null)
                            {
                                Fractions = fractionsNode.SingleArrayData;
                            }
                            else
                            {
                                throw new Exception("Multiple fractions nodes in multilevel node");
                            }
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + multiLevelNode.Name + ": " + multiLevelSubNode.Name);
                        }
                    }
                    break;

                case "skeleton":
                    IntermediateNode skeletonNode = node as IntermediateNode;
                    foreach (LeafNode skeletonSubNode in skeletonNode)
                    {
                        switch (skeletonSubNode.Name.ToLowerInvariant())
                        {
                        case "name":
                            if (Skeleton == null)
                            {
                                Skeleton = skeletonSubNode.StringData;
                            }
                            else
                            {
                                throw new Exception("Multiple name nodes in skeleton node");
                            }
                            break;

                        default: throw new Exception("Invalid node in " + skeletonSubNode.Name + ": " + skeletonSubNode.Name);
                        }
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    foreach (Node cmpndSubNode in cmpndNode)
                    {
                        if (cmpndSubNode.Name.Equals("scale", StringComparison.OrdinalIgnoreCase))
                        {
                            if (Scale == null)
                            {
                                Scale = (cmpndSubNode as LeafNode).SingleData;
                            }
                            else
                            {
                                throw new Exception("Multiple scale nodes in cmpnd node");
                            }
                        }
                        else if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            IntermediateNode consNode = cmpndSubNode as IntermediateNode;
                            Constructs.AddNode(consNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            IntermediateNode partsNode = cmpndSubNode as IntermediateNode;
                            string           objectName = string.Empty, fileName = string.Empty;
                            int index = -1;

                            foreach (LeafNode partNode in partsNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    index = partNode.Int32Data.Value;
                                    break;

                                default: throw new Exception("Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                }
                            }

                            Parts.Add(index, new DfmPart(objectName, fileName, Bones, Constructs));
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + node.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                default:
                    if (node.Name.EndsWith(".3db", StringComparison.OrdinalIgnoreCase))
                    {
                        Bone b = new Bone(node as IntermediateNode);
                        Bones.Add(node.Name, b);
                    }
                    else
                    {
                        throw new Exception("Invalid Node in dfm root: " + node.Name);
                    }
                    break;
                }
            }
            foreach (var bone in Bones)
            {
                foreach (var construct in Constructs)
                {
                    if (bone.Key.StartsWith(construct.ChildName, StringComparison.OrdinalIgnoreCase))
                    {
                        bone.Value.Construct = construct;
                        break;
                    }
                }
            }
        }
Beispiel #15
0
        void InitWithDrawable(IDrawable drawable, ResourceManager res, bool staticpos)
        {
            Resources = res;
            dr        = drawable;
            Shape collisionShape = null;
            bool  isCmp          = false;

            if (dr is SphFile)
            {
                var radius = ((SphFile)dr).Radius;
                collisionShape = new SphereShape(radius);
            }
            else if (dr is ModelFile)
            {
                var mdl  = dr as ModelFile;
                var path = Path.ChangeExtension(mdl.Path, "sur");
                if (File.Exists(path))
                {
                    SurFile sur = res.GetSur(path);
                    var     shs = new List <CompoundSurShape.TransformedShape>();
                    foreach (var s in sur.GetShape(0))
                    {
                        shs.Add(new CompoundSurShape.TransformedShape(s, Matrix3.Identity, Vector3.Zero));
                    }
                    collisionShape = new CompoundSurShape(shs);
                }
            }
            else if (dr is CmpFile)
            {
                isCmp = true;
                var cmp = dr as CmpFile;
                CmpParts      = new List <Part>();
                CmpConstructs = cmp.Constructs.CloneAll();
                foreach (var part in cmp.Parts.Values)
                {
                    CmpParts.Add(part.Clone(CmpConstructs));
                }
                if (cmp.Animation != null)
                {
                    AnimationComponent = new AnimationComponent(this, cmp.Animation);
                    Components.Add(AnimationComponent);
                }
                var path = Path.ChangeExtension(cmp.Path, "sur");
                if (File.Exists(path))
                {
                    SurFile sur    = res.GetSur(path);
                    var     shapes = new List <CompoundSurShape.TransformedShape>();
                    foreach (var part in CmpParts)
                    {
                        var crc = CrcTool.FLModelCrc(part.ObjectName);
                        if (!sur.HasShape(crc))
                        {
                            FLLog.Warning("Sur", "No hitbox for " + part.ObjectName);
                            continue;
                        }
                        var colshape = sur.GetShape(crc);
                        if (part.Construct == null)
                        {
                            foreach (var s in colshape)
                            {
                                shapes.Add(new CompoundSurShape.TransformedShape(s, Matrix3.Identity, Vector3.Zero));
                            }
                        }
                        else
                        {
                            var tr  = part.Construct.Transform;
                            var pos = tr.ExtractTranslation();
                            var q   = tr.ExtractRotation(true);
                            var rot = Matrix3.CreateFromQuaternion(q);
                            foreach (var s in colshape)
                            {
                                shapes.Add(new CompoundSurShape.TransformedShape(s, rot, pos)
                                {
                                    Tag = part.Construct
                                });
                            }
                        }
                    }
                    collisionShape = new CompoundSurShape(shapes);
                }
            }
            if (collisionShape != null)
            {
                PhysicsComponent          = new RigidBody(collisionShape);
                PhysicsComponent.Tag      = this;
                PhysicsComponent.IsStatic = staticpos;
                if (staticpos)
                {
                    PhysicsComponent.Material.Restitution = 1;
                }
            }
            PopulateHardpoints(dr);
            if (isCmp)
            {
                RenderComponent = new ModelRenderer(CmpParts, (dr as CmpFile));
            }
            else
            {
                RenderComponent = new ModelRenderer(dr);
            }
        }
Beispiel #16
0
 public Part Clone(ConstructCollection newcol)
 {
     return(new Part(ObjectName, fileName, models, newcol));
 }
Beispiel #17
0
        public CmpFile(IntermediateNode rootnode, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;

            Models     = new Dictionary <string, ModelFile>();
            Cameras    = new Dictionary <string, CmpCameraInfo>();
            Constructs = new ConstructCollection();
            Parts      = new List <Part>();
            List <string> modelNames = new List <string>();

            foreach (Node node in rootnode)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "vmeshlibrary":
                    IntermediateNode vMeshLibraryNode = node as IntermediateNode;
                    if (VMeshLibrary == null)
                    {
                        VMeshLibrary = new VmsFile(vMeshLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple vmeshlibrary nodes in cmp root");
                    }
                    break;

                case "animation":
                    IntermediateNode animationNode = node as IntermediateNode;
                    if (Animation == null)
                    {
                        Animation = new AnmFile(animationNode, Constructs);
                    }
                    else
                    {
                        throw new Exception("Multiple animation nodes in cmp root");
                    }
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in cmp root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in cmp root");
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    foreach (Node SubNode in cmpndNode)
                    {
                        if (SubNode is LeafNode)
                        {
                            continue;
                        }
                        var cmpndSubNode = (IntermediateNode)SubNode;
                        if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            Constructs.AddNode(cmpndSubNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            string objectName = string.Empty, fileName = string.Empty;

                            foreach (LeafNode partNode in cmpndSubNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    break;

                                default:
                                    FLLog.Error("Cmp", "Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                    break;
                                }
                            }
                            Parts.Add(new Part(objectName, fileName, Models, Cameras, Constructs));
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + cmpndNode.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                case "materialanim":
                    MaterialAnim = new MaterialAnimCollection((IntermediateNode)node);
                    break;

                default:
                    if (node is IntermediateNode)
                    {
                        var im = (IntermediateNode)node;
                        if (im.Any(x => x.Name.Equals("vmeshpart", StringComparison.OrdinalIgnoreCase) ||
                                   x.Name.Equals("multilevel", StringComparison.OrdinalIgnoreCase)))
                        {
                            ModelFile m = new ModelFile(im, this);
                            m.Path = node.Name;
                            Models.Add(node.Name, m);
                            modelNames.Add(node.Name);
                            break;
                        }
                        else if (im.Any(x => x.Name.Equals("camera", StringComparison.OrdinalIgnoreCase)))
                        {
                            var cam = new CmpCameraInfo(im);
                            Cameras.Add(im.Name, cam);
                            break;
                        }
                    }
                    FLLog.Error("Cmp", Path ?? "Utf" + ": Invalid Node in cmp root: " + node.Name);
                    break;
                }
            }
            //FL handles cmpnd nodes that point to non-existant models: fix up here
            List <Part> broken = new List <Part>();

            for (int i = 0; i < Parts.Count; i++)
            {
                if (Parts[i].IsBroken())
                {
                    broken.Add(Parts[i]);
                }
            }
            foreach (var b in broken)
            {
                Parts.Remove(b);
            }
        }