public override bool ImportModel(string path, ref Model model)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                string magicStr = fs.ReadString();
                if (magicStr != "DMW")
                {
                    MessageBox.Show("Error: Model is not of the DMW format", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }
                int version = fs.ReadInt32();
                if (version < DMW_LOWEST_SUPPORTED_VERSION || version > DMW_CURRENT_VERSION)
                {
                    MessageBox.Show("Error: Model is of unsupported version " + version + "\n\nThis version of the DMW Suite only supports DMW models between versions " + DMW_LOWEST_SUPPORTED_VERSION + " and " + DMW_CURRENT_VERSION, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }

                string readString;
                while ((readString = fs.ReadString()) != null)
                {
                    string[] splString = readString.Split(new char[] { ':' }, 2);
                    model.Metadata[splString[0]] = splString[1];
                }

                short encryptionTypeShrt = fs.ReadInt16();
                if (!Enum.IsDefined(typeof(DMW_DATAENC), encryptionTypeShrt))
                {
                    MessageBox.Show("Error: Model uses unsupported encryption method", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }
                DMW_DATAENC encryptionType = (DMW_DATAENC)encryptionTypeShrt;

                MemoryStream modelData = new MemoryStream();

                if (encryptionType != DMW_DATAENC.None)
                {
                    string encryptionKey = Prompt.Show("The model is encrypted. Enter the file's encryption key:");

                    if (encryptionKey.Trim().Length == 0)
                    {
                        MessageBox.Show("No encryption key entered. Model decryption cancelled.", "Encryption", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return(false);
                    }

                    MemoryStream encryptedData = new MemoryStream();
                    fs.CopyTo(encryptedData);

                    MemoryStream decryptedData = new MemoryStream();
                    if (!Decryptors[encryptionType](encryptedData.ToArray(), encryptionKey, decryptedData))
                    {
                        MessageBox.Show("Invalid encrypt key. Model decryption cancelled.", "Encryption", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return(false);
                    }

                    magicStr = decryptedData.ReadString();
                    if (magicStr != "DMW")
                    {
                        MessageBox.Show("Error: Decrypted data is corrupted. Model cannot be loaded", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return(false);
                    }

                    int decVersion = decryptedData.ReadInt32();
                    if (decVersion != version)
                    {
                        MessageBox.Show("Error: Decrypted data has been modified or is corrupted. Model cannot be loaded.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return(false);
                    }

                    while ((readString = decryptedData.ReadString()) != null)
                    {
                        string[] splString = readString.Split(new char[] { ':' }, 2);

                        if (!model.Metadata.ContainsKey(splString[0])) //Hidden metadata
                        {
                            model.Metadata[splString[0]] = splString[1];
                        }
                        else if (model.Metadata[splString[0]] != splString[1])
                        {
                            MessageBox.Show("Error: Decrypted data has been modified or is corrupted. Model cannot be loaded.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return(false);
                        }
                    }

                    decryptedData.CopyTo(modelData);
                }
                else
                {
                    fs.CopyTo(modelData);
                }

                model.Metadata["ComputedHash"] = Hash.Calculate(modelData.ToArray());

                modelData.Position = 0;
                while (modelData.Position < modelData.Length)
                {
                    byte mode    = (byte)modelData.ReadByte();
                    int  dataLen = modelData.ReadInt32();
                    long end     = modelData.Position + dataLen;

                    while (modelData.Position < end)
                    {
                        switch (mode)
                        {
                        default:     //Unsupported type. Just burn though it
                            modelData.ReadByte();
                            break;

                        case MARKER_VERT:
                            model.Vertices.Add(new Vertex(modelData.ReadFloat(), modelData.ReadFloat(), modelData.ReadFloat()));
                            break;

                        case MARKER_INDEX:
                            model.Faces.Add(new Face(modelData.ReadInt32(), modelData.ReadInt32(), modelData.ReadInt32()));
                            break;
                        }
                    }
                }
            }

            return(true);
        }
        public override bool SaveModel(ref string path, ref Model model)
        {
            bool   encrypted     = false;
            string encryptionKey = "";

            if (MessageBox.Show("Encrypt content?", "Encrypt", MessageBoxButtons.YesNo, MessageBoxIcon.None, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
            {
                encrypted     = true;
                encryptionKey = Prompt.Show("Enter an encryption key:");

                if (encryptionKey.Trim().Length == 0)
                {
                    MessageBox.Show("No encryption key entered. Encryption cancelled.", "Encryption", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return(false);
                }

                if (!path.EndsWith(".enc.dmw"))
                {
                    path = path.Substring(0, path.LastIndexOf('.')) + ".enc" + path.Substring(path.LastIndexOf('.'));
                }
            }
            else
            {
                if (path.EndsWith(".enc.dmw"))
                {
                    path = path.Substring(0, path.LastIndexOf(".enc")) + path.Substring(path.LastIndexOf('.'));
                }
            }

            MemoryStream data = new MemoryStream(), vertStream = new MemoryStream(), indexStream = new MemoryStream();

            foreach (Vertex vert in model.Vertices)
            {
                vertStream.WriteFloat(vert.Position.X);
                vertStream.WriteFloat(vert.Position.Y);
                vertStream.WriteFloat(vert.Position.Z);
            }

            for (int i = 0; i < model.Faces.Count; ++i)
            {
                indexStream.WriteInt32(model.Faces[i].Vertex1);
                indexStream.WriteInt32(model.Faces[i].Vertex2);
                indexStream.WriteInt32(model.Faces[i].Vertex3);
            }

            data.WriteByte(MARKER_VERT);
            data.WriteInt32((int)vertStream.Length);
            vertStream.Position = 0; vertStream.CopyTo(data);

            data.WriteByte(MARKER_INDEX);
            data.WriteInt32((int)indexStream.Length);
            indexStream.Position = 0; indexStream.CopyTo(data);

            model.Metadata["DataHash"] = Hash.Calculate(data.ToArray());

            MemoryStream metadata = new MemoryStream();

            metadata.WriteString("DMW");
            metadata.WriteInt32(DMW_CURRENT_VERSION);

            foreach (KeyValuePair <StringKey, string> kvp in model.Metadata)
            {
                if (kvp.Key.Save)
                {
                    metadata.WriteString(kvp.Key.KeyText + ":" + kvp.Value);
                }
            }

            metadata.WriteInt16(0); //End of metadata notifier

            MemoryStream finalFile = new MemoryStream();

            metadata.Position = 0; metadata.CopyTo(finalFile);

            if (encrypted)
            {
                finalFile.WriteInt16((short)DefaultEncoder);
                MemoryStream toEncrypt = new MemoryStream();
                metadata.Position = 0; metadata.CopyTo(toEncrypt);
                data.Position     = 0; data.CopyTo(toEncrypt);
                Encryptors[DefaultEncoder](toEncrypt.ToArray(), encryptionKey, finalFile);
            }
            else
            {
                finalFile.WriteInt16((short)DMW_DATAENC.None);
                data.Position = 0; data.CopyTo(finalFile);
            }

            File.WriteAllBytes(path, finalFile.ToArray());

            return(true);
        }