private Stream saveGeom(string filename, ResourceKey bumpMapKey)
        {
            int bumpmapPos = -1;

            SimGeomFile simgeomfile = new SimGeomFile();

            Stream blah = File.Open(filename, FileMode.Open);
            simgeomfile.Load(blah);
            blah.Close();

            if (bumpMapKey.ToString() != "key:00000000:00000000:0000000000000000")
            {
                // Figure out bumpmap location
                // To do this we loop through the MTNF
                for (int i = 0; i < simgeomfile.simgeom.mtnfChunk.entries.Count; i++)
                {
                    if (simgeomfile.simgeom.mtnfChunk.entries[i].fieldTypeHash == (uint)FieldTypes.NormalMap)
                    {
                        bumpmapPos = (int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0];
                        break;
                    }
                }
                if (bumpmapPos > -1)
                {
                    simgeomfile.simgeom.keytable.keys[bumpmapPos] = bumpMapKey;
                }
            }
            return simgeomfile.Save();
        }
        private void showMeshDetails()
        {
            string meshName = "";

            // Translate selection back into af am etc
            switch (cmbSimAge.Text)
            {
                case "Baby":
                    meshName += "b";
                    break;
                case "Toddler":
                    meshName += "p";
                    break;
                case "Child":
                    meshName += "c";
                    break;
                case "Teen":
                    meshName += "t";
                    break;
                case "Young Adult":
                    meshName += "y";
                    break;
                case "Adult":
                    meshName += "a";
                    break;
                case "Elder":
                    meshName += "e";
                    break;
                case "All Ages":
                    meshName += "u";
                    break;
            }

            switch (cmbSimGender.Text)
            {
                case "Female":
                    meshName += "f";
                    break;
                case "Male":
                    meshName += "m";
                    break;
                case "Unisex":
                    meshName += "u";
                    break;
            }

            if (cmbMeshName.Text == "* Custom")
            {

                //if (this.isNew == false)
                //{
                //meshName += casPartSrc.meshName;
                //}
                txtCasPartName.Text = casPartSrc.meshName;
                txtMeshName.Text = casPartSrc.meshName;

                txtCasPartInstance.Text = "0x" + MadScience.StringHelpers.HashFNV64(meshName).ToString("X16");
                picMeshPreview.Image = null;
                picMeshPreview.Invalidate();

            }
            else
            {

                if (cmbPartTypes.Text == "(none)")
                {
                    meshName += cmbMeshName.Text;
                }
                else
                {
                    meshName += cmbPartTypes.Text + cmbMeshName.Text;
                }

                txtCasPartName.Text = meshName;
                txtMeshName.Text = meshName;

                scrollPanelToThumb(meshName);

                for (int i = 0; i < this.lookupList.Items.Length; i++)
                {
                    filesFile f = lookupList.Items[i];
                    if (f.fullCasPartname == meshName)
                    {
                        txtCasPartInstance.Text = f.instanceid;
                        break;
                    }
                }

                picMeshPreview.Image = null;
                picMeshPreview.Invalidate();

                // Find thumbnail
                if (File.Exists(Path.Combine(Application.StartupPath, Path.Combine("cache", meshName + ".png"))))
                {
                    Stream picMeshPreviewStream = File.OpenRead(Path.Combine(Application.StartupPath, Path.Combine("cache", meshName + ".png")));
                    picMeshPreview.Image = Image.FromStream(picMeshPreviewStream);
                    picMeshPreviewStream.Close();
                }
                else
                {
                    extractCASThumbnail(meshName);
                }
            }

            if (this.isNew == true)
            {
                // Attempt to load the existing caspart into memory so we can extract data later.
                Stream casPartFile = File.Open(Path.Combine(Application.StartupPath, Path.Combine("casparts", txtCasPartName.Text + ".caspart")), FileMode.Open, FileAccess.Read, FileShare.Read);
                casPartFile cPartFile = new casPartFile();
                this.casPartSrc = cPartFile.Load(casPartFile);
                casPartFile.Close();
            }

            for (int i = 0; i < checkedListAge.Items.Count; i++)
            {
                checkedListAge.SetItemChecked(i, false);
            }
            for (int i = 0; i < checkedListCategory.Items.Count; i++)
            {
                checkedListCategory.SetItemChecked(i, false);
            }
            for (int i = 0; i < checkedListCategoryExtended.Items.Count; i++)
            {
                checkedListCategoryExtended.SetItemChecked(i, false);
            }
            for (int i = 0; i < checkedListGender.Items.Count; i++)
            {
                checkedListGender.SetItemChecked(i, false);
            }
            for (int i = 0; i < checkedListOther.Items.Count; i++)
            {
                checkedListOther.SetItemChecked(i, false);
            }
            for (int i = 0; i < checkedListType.Items.Count; i++)
            {
                checkedListType.SetItemChecked(i, false);
            }

            // Get the Mesh links for the first LOD
            Stream meshStream = Stream.Null;

            // Use the VPXY to get the mesh lod
            Stream vpxyStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY], 0);

            if (StreamHelpers.isValidStream(vpxyStream))
            {
                VPXYFile vpxyFile = new VPXYFile(vpxyStream);
                // Get the first VPXY internal link
                if (vpxyFile.vpxy.linkEntries.Count >= 1 && vpxyFile.vpxy.linkEntries[0].tgiList.Count >= 1)
                {
                    meshStream = KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[0], 0);
                }
                vpxyStream.Close();
            }

            if (StreamHelpers.isValidStream(meshStream))
            {
                lstMeshTGILinks.Items.Clear();
                SimGeomFile simgeomfile = new SimGeomFile(meshStream);

                // Always put the bumpmap in the first position and get it from the MTNF
                //int bumpmapPos = -1;
                //int tgiAddNo = 0;
                for (int i = 0; i < simgeomfile.simgeom.mtnfChunk.entries.Count; i++)
                {

                    if (simgeomfile.simgeom.mtnfChunk.entries[i].fieldTypeHash == (uint)FieldTypes.NormalMap)
                    {
                        ListViewItem item = new ListViewItem();
                        item.SubItems.Add(Enum.GetName(typeof(FieldTypes), simgeomfile.simgeom.mtnfChunk.entries[i].fieldTypeHash));
                        item.Text = simgeomfile.simgeom.keytable.keys[(int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0]].ToString();
                        if (simgeomfile.simgeom.keytable.keys[(int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0]].typeId == 0x00B2D882)
                        {
                            item.Tag = "texture";
                        }
                        else
                        {
                            item.Tag = "";
                        }
                        //bumpmapPos = (int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0];
                        lstMeshTGILinks.Items.Add(item);
                        break;
                    }

                }

                for (int i = 0; i < simgeomfile.simgeom.mtnfChunk.entries.Count; i++)
                {
                    if (simgeomfile.simgeom.mtnfChunk.entries[i].fieldTypeHash != (uint)FieldTypes.NormalMap)
                    {
                        foreach (uint fieldHash in Enum.GetValues(typeof(FieldTypes)))
                        {
                            if (fieldHash == simgeomfile.simgeom.mtnfChunk.entries[i].fieldTypeHash)
                            {
                                if (simgeomfile.simgeom.mtnfChunk.entries[i].dwords.Count > 0)
                                {
                                    ListViewItem item = new ListViewItem();
                                    item.SubItems.Add(Enum.GetName(typeof(FieldTypes), fieldHash));
                                    item.Text = simgeomfile.simgeom.keytable.keys[(int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0]].ToString();
                                    if (simgeomfile.simgeom.keytable.keys[(int)simgeomfile.simgeom.mtnfChunk.entries[i].dwords[0]].typeId == 0x00B2D882)
                                    {
                                        item.Tag = "texture";
                                    }
                                    else
                                    {
                                        item.Tag = "";
                                    }
                                    lstMeshTGILinks.Items.Add(item);
                                }
                                break;
                            }
                        }
                    }
                }

                /*
                if (bumpmapPos > -1)
                {
                    ListViewItem item = new ListViewItem();
                    item.SubItems.Add("Bump Map");
                    item.Text = simgeomfile.simgeom.keytable.keys[bumpmapPos].ToString();
                    if (simgeomfile.simgeom.keytable.keys[bumpmapPos].typeId == 0x00B2D882)
                    {
                        item.Tag = "texture";
                    }
                    else
                    {
                        item.Tag = "";
                    }
                    lstMeshTGILinks.Items.Add(item);
                    tgiAddNo++;
                }

                for (int i = 0; i < simgeomfile.simgeom.keytable.keys.Count; i++)
                {
                    if (i != bumpmapPos)
                    {
                        ListViewItem item = new ListViewItem();
                        tgiAddNo++;
                        //item.SubItems.Add("TGI #" + tgiAddNo);
                        //item.SubItems.Add("TGI #" + (i + 1));
                        item.Text = simgeomfile.simgeom.keytable.keys[i].ToString();
                        if (simgeomfile.simgeom.keytable.keys[i].typeId == 0x00B2D882)
                        {
                            item.Tag = "texture";
                        }
                        else
                        {
                            item.Tag = "";
                        }
                        lstMeshTGILinks.Items.Add(item);
                    }
                }
                */
            }

            lstCasPartDetails.Items.Clear();
            // Populate the CAS Part Details
            addCasPartItem("Mesh Name", casPartSrc.meshName);
            toolStripStatusLabel2.Text = casPartSrc.meshName;

            addCasPartItem("Clothing Order", casPartSrc.clothingOrder.ToString());
            addCasPartItem("CAS Part Type", casPartSrc.clothingType.ToString() + " (0x" + casPartSrc.clothingType.ToString("X8") + ")");
            addCasPartItem("Type", casPartSrc.typeFlag.ToString() + " (0x" + casPartSrc.typeFlag.ToString("X8") + ")");
            addCasPartItem("Age/Gender", casPartSrc.ageGenderFlag.ToString() + " (0x" + casPartSrc.ageGenderFlag.ToString("X8") + ")");
            addCasPartItem("Clothing Category", casPartSrc.clothingCategory.ToString() + " (0x" + casPartSrc.clothingCategory.ToString("X8") + ")");
            addCasPartItem("Unk String", casPartSrc.unkString);

            addCasPartItem("Unk2", casPartSrc.unk2.ToString());
            addCasPartItem("TGI Index Body Part 1", casPartSrc.tgiIndexBodyPart1.ToString());
            addCasPartItem("TGI Index Body Part 2", casPartSrc.tgiIndexBodyPart2.ToString());
            addCasPartItem("TGI Index Blend Info Fat", casPartSrc.tgiIndexBlendInfoFat.ToString());
            addCasPartItem("TGI Index Blend Info Fit", casPartSrc.tgiIndexBlendInfoFit.ToString());
            addCasPartItem("TGI Index Blend Info Thin", casPartSrc.tgiIndexBlendInfoThin.ToString());
            addCasPartItem("TGI Index Blend Info Special", casPartSrc.tgiIndexBlendInfoSpecial.ToString());
            addCasPartItem("Unk5", casPartSrc.unk5.ToString());
            addCasPartItem("VPXY", casPartSrc.tgiIndexVPXY.ToString());

            //tgi64 tempvpxy = (tgi64)casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY];
            //txtVPXYPrimary.Text = "key:" + tempvpxy.typeid.ToString("X8") + ":" + tempvpxy.groupid.ToString("X8") + ":" + tempvpxy.instanceid.ToString("X16");

            addCasPartItem("Count 2", casPartSrc.count2.ToString());
            for (int i = 0; i < casPartSrc.count2; i++)
            {
                unkRepeat unk = (unkRepeat)casPartSrc.count2repeat[i];
                addCasPartItem("#" + i.ToString() + ": unkNum ", unk.unkNum.ToString());
                addCasPartItem("#" + i.ToString() + ": unk2", unk.unk2.ToString());
                addCasPartItem("#" + i.ToString() + ": unkRepeatInner", unk.unkRepeatInnerCount.ToString());
                for (int j = 0; j < unk.unkRepeatInnerCount; j++)
                {
                    intTriple iT = (intTriple)unk.unkRepeatInnerLoop[j];
                    addCasPartItem("#" + i.ToString() + "." + j.ToString() + ": One", iT.one.ToString());
                    addCasPartItem("#" + i.ToString() + "." + j.ToString() + ": Two", iT.two.ToString());
                    addCasPartItem("#" + i.ToString() + "." + j.ToString() + ": Three", iT.three.ToString());
                }
            }

            addCasPartItem("TGI Index Diffuse", casPartSrc.tgiIndexDiffuse.ToString());
            addCasPartItem("TGI Index Specular", casPartSrc.tgiIndexSpecular.ToString());

            addCasPartItem("Diffuse Links", casPartSrc.count3.ToString());
            for (int i = 0; i < casPartSrc.count3; i++)
            {
                byte cRepeat = (byte)casPartSrc.count3repeat[i];
                addCasPartItem("#" + i.ToString(), cRepeat.ToString());
            }

            addCasPartItem("Specular Links", casPartSrc.count4.ToString());
            for (int i = 0; i < casPartSrc.count4; i++)
            {
                byte cRepeat = (byte)casPartSrc.count4repeat[i];
                addCasPartItem("#" + i.ToString(), cRepeat.ToString());
            }

            addCasPartItem("Count 5", casPartSrc.count5.ToString());
            for (int i = 0; i < casPartSrc.count5; i++)
            {
                byte cRepeat = (byte)casPartSrc.count5repeat[i];
                addCasPartItem("#" + i.ToString(), cRepeat.ToString());
            }

            for (int i = 0; i < chkDesignType.Items.Count; i++)
            {
                chkDesignType.SetItemChecked(i, false);
            }

            for (int i = 0; i < casPartSrc.count6; i++)
            {
                MadScience.Wrappers.ResourceKey tgi = casPartSrc.tgi64list[i];
                string tgiType = MadScience.Helpers.findMetaEntry(tgi.typeId).shortName;
                Console.WriteLine(tgi.typeId.ToString() + " " + tgiType);

                if (tgi.typeId == 0x0333406C)
                {
                    if (tgi.instanceId == 0x52E8BE209C703561)
                    {
                        chkDesignType.SetItemChecked(0, true);
                    }
                    if (tgi.instanceId == 0xE37696463F6B2D6E)
                    {
                        chkDesignType.SetItemChecked(1, true);
                    }
                    if (tgi.instanceId == 0x01625DDC220C08C6)
                    {
                        chkDesignType.SetItemChecked(2, true);
                    }

                }

                addCasPartItem("TGI #" + i.ToString() + " " + tgiType, tgi.ToString());
            }

            // Category flags
            if ((casPartSrc.typeFlag & 0x1) == 0x1) checkedListType.SetItemChecked(0, true); // Hair
            if ((casPartSrc.typeFlag & 0x2) == 0x2) checkedListType.SetItemChecked(1, true); // Scalp
            if ((casPartSrc.typeFlag & 0x4) == 0x4) checkedListType.SetItemChecked(2, true); // Face Overlay
            if ((casPartSrc.typeFlag & 0x8) == 0x8) checkedListType.SetItemChecked(3, true); // Body
            if ((casPartSrc.typeFlag & 0x10) == 0x10) checkedListType.SetItemChecked(4, true); // Accessory

            switch (casPartSrc.clothingType)
            {
                case 1: checkedListClothingType.SetItemChecked(0, true); break;
                case 2: checkedListClothingType.SetItemChecked(1, true); break;
                case 3: checkedListClothingType.SetItemChecked(2, true); break;
                case 4: checkedListClothingType.SetItemChecked(3, true); break;
                case 5: checkedListClothingType.SetItemChecked(4, true); break;
                case 6: checkedListClothingType.SetItemChecked(5, true); break;
                case 7: checkedListClothingType.SetItemChecked(6, true); break;
                case 11: checkedListClothingType.SetItemChecked(7, true); break;
                case 12: checkedListClothingType.SetItemChecked(8, true); break;
                case 13: checkedListClothingType.SetItemChecked(9, true); break;
                case 14: checkedListClothingType.SetItemChecked(10, true); break;
                case 15: checkedListClothingType.SetItemChecked(11, true); break;
                case 16: checkedListClothingType.SetItemChecked(12, true); break;
                case 17: checkedListClothingType.SetItemChecked(13, true); break;
                case 18: checkedListClothingType.SetItemChecked(14, true); break;
                case 19: checkedListClothingType.SetItemChecked(15, true); break;
                case 20: checkedListClothingType.SetItemChecked(16, true); break;
                case 21: checkedListClothingType.SetItemChecked(17, true); break;
                case 22: checkedListClothingType.SetItemChecked(18, true); break;
                case 24: checkedListClothingType.SetItemChecked(19, true); break;
                case 25: checkedListClothingType.SetItemChecked(20, true); break;
                case 26: checkedListClothingType.SetItemChecked(21, true); break;
                case 29: checkedListClothingType.SetItemChecked(22, true); break;
                case 30: checkedListClothingType.SetItemChecked(23, true); break;
                case 31: checkedListClothingType.SetItemChecked(24, true); break;
            }

            if ((casPartSrc.ageGenderFlag & 0x1) == 0x1) checkedListAge.SetItemChecked(0, true); // Baby
            if ((casPartSrc.ageGenderFlag & 0x2) == 0x2) checkedListAge.SetItemChecked(1, true); // Toddler
            if ((casPartSrc.ageGenderFlag & 0x4) == 0x4) checkedListAge.SetItemChecked(2, true); // Child
            if ((casPartSrc.ageGenderFlag & 0x8) == 0x8) checkedListAge.SetItemChecked(3, true); // Teen
            if ((casPartSrc.ageGenderFlag & 0x10) == 0x10) checkedListAge.SetItemChecked(4, true); // YoungAdult
            if ((casPartSrc.ageGenderFlag & 0x20) == 0x20) checkedListAge.SetItemChecked(5, true); // Adult
            if ((casPartSrc.ageGenderFlag & 0x40) == 0x40) checkedListAge.SetItemChecked(6, true); // Elder

            if ((casPartSrc.ageGenderFlag & 0x1000) == 0x1000) checkedListGender.SetItemChecked(0, true); // Male
            if ((casPartSrc.ageGenderFlag & 0x2000) == 0x2000) checkedListGender.SetItemChecked(1, true); // Female

            if ((casPartSrc.ageGenderFlag & 0x100000) == 0x100000) checkedListOther.SetItemChecked(0, true); // LeftHanded
            if ((casPartSrc.ageGenderFlag & 0x200000) == 0x200000) checkedListOther.SetItemChecked(1, true); // RightHanded
            if ((casPartSrc.ageGenderFlag & 0x10000) == 0x10000) checkedListOther.SetItemChecked(2, true); // Human

            if ((casPartSrc.clothingCategory & 0x1) == 0x1) checkedListCategory.SetItemChecked(0, true); // Naked
            if ((casPartSrc.clothingCategory & 0x2) == 0x2) checkedListCategory.SetItemChecked(1, true); // Everyday
            if ((casPartSrc.clothingCategory & 0x4) == 0x4) checkedListCategory.SetItemChecked(2, true); // Formalwear
            if ((casPartSrc.clothingCategory & 0x8) == 0x8) checkedListCategory.SetItemChecked(3, true); // Sleepwear
            if ((casPartSrc.clothingCategory & 0x10) == 0x10) checkedListCategory.SetItemChecked(4, true); // Swimwear
            if ((casPartSrc.clothingCategory & 0x20) == 0x20) checkedListCategory.SetItemChecked(5, true); // Athletic
            if ((casPartSrc.clothingCategory & 0x40) == 0x40) checkedListCategory.SetItemChecked(6, true); // Singed
            if ((casPartSrc.clothingCategory & 0x100) == 0x100) checkedListCategory.SetItemChecked(7, true); // Career
            if ((casPartSrc.clothingCategory & 0xFFFF) == 0xFFFF) checkedListCategory.SetItemChecked(8, true); // All

            if ((casPartSrc.clothingCategory & 0x100000) == 0x100000) checkedListCategoryExtended.SetItemChecked(0, true); // ValidForMaternity
            if ((casPartSrc.clothingCategory & 0x200000) == 0x200000) checkedListCategoryExtended.SetItemChecked(1, true); // ValidForRandom
            if ((casPartSrc.clothingCategory & 0x400000) == 0x400000) checkedListCategoryExtended.SetItemChecked(2, true); // IsHat
            if ((casPartSrc.clothingCategory & 0x800000) == 0x800000) checkedListCategoryExtended.SetItemChecked(3, true); // IsRevealing
            if ((casPartSrc.clothingCategory & 0x1000000) == 0x1000000) checkedListCategoryExtended.SetItemChecked(4, true); // IsHiddenInCas

            saveAsToolStripMenuItem.Enabled = true;
            btnDumpFromFullbuild2.Enabled = true;

            lstStencilPool.Items.Clear();

            // Default all stencil boxes to blank
            for (int i = 1; i <= 15; i++)
            {
                if (stencilPool.Count < i) { stencilPool.Add(new stencilDetails()); }
                //updateStencilBoxes(i, new stencilDetails());
            }

            // Calculate all the stencils so we can build up the stencil pool
            int curStencilNum = 1;
            for (int i = 0; i < casPartSrc.xmlChunk.Count; i++)
            {
                if (debugModeToolStripMenuItem.Checked)
                {
                    Helpers.logMessageToFile(casPartSrc.xmlChunkRaw[i].ToString().Replace("/><", "/>" + Environment.NewLine + "<"));
                }

                xmlChunkDetails chunk = (xmlChunkDetails)casPartSrc.xmlChunk[i];

                if (!inStencilList(chunk.stencil.A))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.A);
                    curStencilNum++;

                }
                if (!inStencilList(chunk.stencil.B))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.B);
                    curStencilNum++;

                }
                if (!inStencilList(chunk.stencil.C))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.C);
                    curStencilNum++;

                }
                if (!inStencilList(chunk.stencil.D))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.D);
                    curStencilNum++;

                }
                if (!inStencilList(chunk.stencil.E))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.E);
                    curStencilNum++;

                }
                if (!inStencilList(chunk.stencil.F))
                {
                    updateStencilBoxes(curStencilNum, chunk.stencil.F);
                    curStencilNum++;
                }

            }

            for (int i = curStencilNum; i <= 15; i++)
            {
                //if (stencilPool.Count < i) { stencilPool.Add(new stencilDetails()); }
                updateStencilBoxes(i, new stencilDetails());
            }

            if (this.casPartSrc.xmlChunkRaw.Count == 0)
            {
                label8.Visible = true;
                listView1.Enabled = false;
                //btnDumpFromFullbuild2.Enabled = false;
                btnAddNewDesign.Enabled = false;
                btnDeleteDesign.Enabled = false;
            }
            else
            {

                label8.Visible = false;
                listView1.Enabled = true;
                //btnDumpFromFullbuild2.Enabled = true;
                btnAddNewDesign.Enabled = true;
                btnDeleteDesign.Enabled = true;

                this.casPartNew = (casPart)OX.Copyable.ObjectExtensions.Copy(casPartSrc);
                //this.casPartNew = (casPart)casPartSrc.Copy();
                if (this.isNew)
                {
                    this.casPartNew.xmlChunk.Clear();
                    this.casPartNew.xmlChunkRaw.Clear();
                    lastSelected = -1;
                    listView1.Items.Clear();
                    lstTextureDetails.Items.Clear();
                    lstOtherDetails.Items.Clear();

                    //btnAddNewDesign_Click(this, null);
                }

            }
        }
        private void loadFile(string filename)
        {
            this.filename = filename;

            this.simgeomfile = new SimGeomFile();

            toolStripStatusLabel1.Text = this.filename;

            // Deals with RAW chunks here...
            Stream input = File.OpenRead(filename);
            this.simgeomfile.Load(input);
            input.Close();

            saveToolStripMenuItem.Enabled = true;

            int num = 0;
            comboBox1.SelectedIndex = num;
            foreach (uint fieldHash in Enum.GetValues(typeof(ShaderType)))
            {
                num++;
                if (fieldHash == simgeomfile.simgeom.embeddedId)
                {
                    comboBox1.SelectedIndex = num;
                    break;
                }
            }

            showEntries();

            importMTNFToolStripMenuItem.Enabled = true;
            exportMTNFToolStripMenuItem.Enabled = true;
        }
        private void button8_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "Sim GEOM File|*.simgeom";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Stream input = File.OpenRead(openFileDialog1.FileName);
                SimGeomFile tempGeom = new SimGeomFile(input);
                this.simgeomfile.simgeom.boneHashes.Clear();
                for (int i = 0; i < tempGeom.simgeom.boneHashes.Count; i++)
                {
                    this.simgeomfile.simgeom.boneHashes.Add(tempGeom.simgeom.boneHashes[i]);
                }
                input.Close();
                tempGeom = null;

                showEntries();
            }
        }
        private void btnDumpFromFullbuild2_Click(object sender, EventArgs e)
        {
            // Go through the list of DDS files and dump them
            string s3root = MadScience.Helpers.findSims3Root();

            if (s3root != "")
            {

                bool hasShownDialog = false;

                toolStripProgressBar1.Visible = true;
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "Searching for textures... please wait";
                statusStrip1.Refresh();

                Stream fbuild2 = File.Open(Path.Combine(s3root, Helpers.getGameSubPath("\\GameData\\Shared\\Packages\\FullBuild2.package")), FileMode.Open, FileAccess.Read, FileShare.Read);
                MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(fbuild2, true);

                toolStripProgressBar1.Maximum = casPartSrc.tgi64list.Count;

                Dictionary<ulong, string> keyNames = new Dictionary<ulong, string>();
                long nowTicks = DateTime.Now.Ticks;
                Console.WriteLine("Started at: " + nowTicks);
                foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
                {
                    //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                    if (entry.typeId == (int)0x0166038C)
                    {
                        keyNames = Helpers.getKeyNames(db.GetResourceStream(entry));
                        break;
                    }
                }

                int numFound = 0;
                folderBrowserDialog1.SelectedPath = "";

                for (int j = 0; j < casPartSrc.tgi64list.Count; j++)
                {
                    toolStripProgressBar1.Value++;
                    //keyName tgi = new keyName((tgi64)casPartSrc.tgi64list[j]);
                    MadScience.Wrappers.ResourceKey tgi = casPartSrc.tgi64list[j];
                    if (tgi.typeId == (int)0x736884F1) // VPXY
                    {
                        // Find the meshes, then dump any textures the meshes reference too

                        // Use the VPXY to get the mesh lod
                        Stream vpxyStream = KeyUtils.findKey(tgi, 0);

                        //int numFound = 0;
                        //folderBrowserDialog1.SelectedPath = "";

                        if (vpxyStream != null)
                        {
                            VPXYFile vpxyFile = new VPXYFile(vpxyStream);
                            // Get the first VPXY internal link
                            if (vpxyFile.vpxy.linkEntries.Count >= 1 && vpxyFile.vpxy.linkEntries[0].tgiList.Count >= 1)
                            {
                                for (int i = 0; i < vpxyFile.vpxy.linkEntries[0].tgiList.Count; i++)
                                {
                                    //meshStreams.Add(KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0));
                                    //KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0);

                                    //ResourceKey entry = vpxyFile.vpxy.linkEntries[0].tgiList[i];

                                    Stream meshFile = KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0);

                                    SimGeomFile sgf = new SimGeomFile(meshFile);

                                    if (!hasShownDialog)
                                    {
                                        folderBrowserDialog1.Description = "Please select a folder to save the extracted textures to.";
                                        folderBrowserDialog1.ShowDialog();
                                        hasShownDialog = true;
                                    }
                                    if (folderBrowserDialog1.SelectedPath != "")
                                    {
                                        string extension = "";
                                        for (int k = 0; k < sgf.simgeom.keytable.keys.Count; k++)
                                        {
                                            ResourceKey entry = sgf.simgeom.keytable.keys[k];

                                            if (entry.typeId == 0x00B2D882)
                                            {
                                                extension = ".dds";

                                                string fileNameToSave = "";
                                                if (keyNames.ContainsKey(entry.instanceId))
                                                {
                                                    fileNameToSave = keyNames[entry.instanceId];
                                                    if (fileNameToSave.Contains("0x") == false) { fileNameToSave += "_0x" + entry.instanceId.ToString("X16"); }
                                                }
                                                else
                                                {
                                                    fileNameToSave = entry.typeId.ToString("X8") + "_" + entry.groupId.ToString("X8") + "_" + entry.instanceId.ToString("X16");
                                                }

                                                FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                                                StreamHelpers.CopyStream(KeyUtils.findKey(entry, 2, db), saveFile);
                                                saveFile.Close();
                                            }
                                        }
                                        //numFound++;
                                    }
                                    meshFile.Close();

                                    //output.Close();
                                }

                            }

                        }
                    }
                    if (tgi.typeId == (int)0x00B2D882) // DDS
                    {
                        //Stream textureStream = KeyUtils.searchForKey(tgi.ToString(), 2);
                        Stream textureStream = KeyUtils.findKey(tgi);
                        if (textureStream != null)
                        {
                            string fileNameToSave = "";
                            if (keyNames.ContainsKey(tgi.instanceId))
                            {
                                fileNameToSave = keyNames[tgi.instanceId];
                            }
                            else
                            {
                                fileNameToSave = tgi.typeId.ToString("X8") + "_" + tgi.groupId.ToString("X8") + "_" + tgi.instanceId.ToString("X16");
                            }

                            if (!hasShownDialog)
                            {
                                folderBrowserDialog1.Description = "Please select a folder to save the extracted textures to.";
                                folderBrowserDialog1.ShowDialog();
                                hasShownDialog = true;
                            }
                            if (folderBrowserDialog1.SelectedPath != "")
                            {

                                Stream output = db.GetResourceStream(tgi);
                                FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + ".dds"), FileMode.Create, FileAccess.Write);
                                StreamHelpers.CopyStream(output, saveFile);
                                saveFile.Close();
                                output.Close();
                                numFound++;
                            }

                        }
                    }
                }

                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = numFound + " textures found.";
                toolStripProgressBar1.Visible = false;
                statusStrip1.Refresh();

                fbuild2.Close();

            }
        }