/// <summary>
        /// Creates a Structure filled with data.
        /// </summary>
        /// <param name="data">Bytestream representing the data to be filled.</param>
        /// <param name="template">Structure prototype that matches the bytestream.</param>
        /// <param name="file">Source file object.</param>
        protected Structure(byte[] data, StructureDefinition template, BlenderFile file)
        {
            // since this is a root structure, set its name to the type name (as an identification) and
            // Value to the type name (as expected by IField)
            Name = Value = TypeName = template.StructureTypeName;
            // roots have no parents
            Parent = null;
            Size   = template.StructureTypeSize;

            List <IField> fields = new List <IField>();
            int           pos    = 0;

            this.ContainingFile = file;
            parseStructureFields(this, template, data, ref fields, ref pos); // begin recursive parsing
            Fields = fields.ToArray();
        }
        /// <summary>
        /// Parses a file block. If the file block is SDNA or another block with block.count == 0, it will return null.
        /// </summary>
        /// <param name="block">The block to parse.</param>
        /// <param name="blocksParsed">Number of blocks parsed so far.</param>
        /// <param name="file">Source file for the structures.</param>
        /// <returns>An array of PopulatedStructures, or { null } if no structures are defined.</returns>
        public static Structure[] ParseFileBlock(FileBlock block, int blocksParsed, BlenderFile file)
        {
            if (block.Count == 0 || block.Code == "DNA1")
            {
                return(null);
            }

            StructureDNA sdna = file.StructureDNA;

            if (block.Data.Length != sdna.StructureList[block.SDNAIndex].StructureTypeSize * block.Count)
            {
                // generally, these are things like raw data; packed files, preview images, and arrays of pointers that are themselves pointed to.
                // I have no idea what TEST and REND do.
                file.RawBlockMessages.Add(blocksParsed + " " + block.OldMemoryAddress.ToString("X" + (file.PointerSize * 2)) + " " + block.Code + " " + block.SDNAIndex + " " + sdna.StructureList[block.SDNAIndex].StructureTypeSize * block.Count + " " + block.Data.Length);
                return(null);
            }

            Structure[] output = new Structure[block.Count];

            if (block.Count > 1)
            {
                for (int i = 0; i < block.Count; i++)
                {
                    byte[] data = new byte[block.Size / block.Count];
                    for (int j = 0; j < block.Size / block.Count; j++)
                    {
                        data[j] = block.Data[i * (block.Size / block.Count) + j];
                    }
                    output[i]                 = new Structure(data, sdna.StructureList[block.SDNAIndex], file);
                    output[i].Size            = sdna.StructureList[block.SDNAIndex].StructureTypeSize;
                    output[i].TypeName        = sdna.StructureList[block.SDNAIndex].StructureTypeName;
                    output[i].ContainingBlock = block;
                }
            }
            else
            {
                output[0]                 = new Structure(block.Data, sdna.StructureList[block.SDNAIndex], file);
                output[0].Size            = sdna.StructureList[block.SDNAIndex].StructureTypeSize;
                output[0].TypeName        = sdna.StructureList[block.SDNAIndex].StructureTypeName;
                output[0].ContainingBlock = block;
            }

            return(output);
        }