private int findChunkInTGIList(casPart casP, uint typeId, int counter)
 {
     int temp = 0;
     int curCount = 0;
     for (int i = 0; i < casP.tgi64list.Count; i++)
     {
         MadScience.Wrappers.ResourceKey tgi = casP.tgi64list[i];
         if (tgi.typeId == typeId)
         {
             curCount++;
             if (curCount == counter)
             {
                 temp = i;
                 break;
             }
         }
     }
     return temp;
 }
        public string generateXMLChunk(casPart casP, int chunkNo, bool addComments)
        {
            sb = new StringBuilder();

            if (addComments) sb.Append("<!-- XML generated by CTU -->");

            xmlChunkDetails chunk = (xmlChunkDetails)casP.xmlChunk[chunkNo];
            sb.Append("<preset>");
            sb.Append("<complate name=\"" + chunk.name + "\" reskey=\"" + chunk.reskey + "\">");
            avSB("assetRoot", "X:");
            addLine(casP, "daeFileName", chunk.daeFileName);

            addLine(casP, "age", chunk.age);
            addLine(casP, "gender", chunk.gender);
            addLine(casP, "bodyType", chunk.bodyType);
            addLine(casP, "partType", chunk.partType);
            addLine(casP, "filename", chunk.filename);
            addLine(casP, "IsHat", chunk.IsHat);

            addLine(casP, "DrawsOnFace", chunk.DrawsOnFace);
            addLine(casP, "DrawsOnScalp", chunk.DrawsOnScalp);

            addLine(casP, "Overlay", chunk.Overlay, true);
            addLine(casP, "Control Map", chunk.ControlMap, true);
            addLine(casP, "Diffuse Map", chunk.DiffuseMap, true);

            addLine(casP, "Clothing Specular", chunk.ClothingSpecular, true);
            addLine(casP, "Clothing Ambient", chunk.ClothingAmbient, true);

            addLine(casP, "Rotation", chunk.Rotation);

            // Hair
            addLine(casP, "Root Color", chunk.hair.RootColor);
            addLine(casP, "Diffuse Color", chunk.hair.DiffuseColor);
            addLine(casP, "Highlight Color", chunk.hair.HighlightColor);
            addLine(casP, "Tip Color", chunk.hair.TipColor);

            // Hair
            addLine(casP, "Scalp Diffuse Map", chunk.hair.ScalpDiffuseMap, true);
            addLine(casP, "Scalp Control Map", chunk.hair.ScalpControlMap, true);
            addLine(casP, "Scalp Specular Map", chunk.hair.ScalpSpecularMap, true);
            addLine(casP, "Scalp AO", chunk.hair.ScalpAO, true);
            addLine(casP, "Face Diffuse Map", chunk.hair.FaceDiffuseMap, true);
            addLine(casP, "Face Control Map", chunk.hair.FaceControlMap, true);
            addLine(casP, "Face Specular Map", chunk.hair.FaceSpecularMap, true);
            addLine(casP, "Face AO", chunk.hair.FaceAO, true);

            addLine(casP, "Mask", chunk.Mask, true);
            addLine(casP, "MaskHeight", chunk.MaskHeight);
            addLine(casP, "MaskWidth", chunk.MaskWidth);

            addLine(casP, "Multiplier", chunk.Multiplier, true);

            addLine(casP, "Tint Color", chunk.TintColor);
            addLine(casP, "Tint Color A", chunk.tint.A.color);
            addLine(casP, "Tint Color B", chunk.tint.B.color);
            addLine(casP, "Tint Color C", chunk.tint.C.color);
            addLine(casP, "Tint Color D", chunk.tint.D.color);
            addLine(casP, "Tint Color A Enabled", chunk.tint.A.enabled);
            addLine(casP, "Tint Color B Enabled", chunk.tint.B.enabled);
            addLine(casP, "Tint Color C Enabled", chunk.tint.C.enabled);
            addLine(casP, "Tint Color D Enabled", chunk.tint.D.enabled);

            addLine(casP, "Face Overlay", chunk.faceOverlay, true);
            addLine(casP, "Face Specular", chunk.faceSpecular, true);

            if (addComments) sb.Append("<!-- Did you get the satellite photos yet? -->");

            for (int i = 0; i < 4; i++)
            {
                if (!String.IsNullOrEmpty(chunk.pattern[i].name))
                {
                    string patternName = "";
                    string charName;
                    switch (i)
                    {
                        case 0: patternName = "Pattern A"; charName = "JackB"; break;
                        case 1: patternName = "Pattern B"; charName = "ChloeON"; break;
                        case 2: patternName = "Pattern C"; charName = "TonyA"; break;
                        case 3: patternName = "Pattern D"; charName = "BillB"; break;
                    }

                    avSB(patternName, chunk.pattern[i].nameHigh);
                    avSB(patternName + " Enabled", chunk.pattern[i].Enabled);
                    avSB(patternName + " Linked", chunk.pattern[i].Linked);
                    avSB(patternName + " Tiling", chunk.pattern[i].Tiling);
                }
            }

            addLine(casP, "Stencil A", chunk.stencil.A.key, true);
            addLine(casP, "Stencil B", chunk.stencil.B.key, true);
            addLine(casP, "Stencil C", chunk.stencil.C.key, true);
            addLine(casP, "Stencil D", chunk.stencil.D.key, true);
            addLine(casP, "Stencil E", chunk.stencil.E.key, true);
            addLine(casP, "Stencil F", chunk.stencil.F.key, true);

            addLine(casP, "Stencil A Tiling", chunk.stencil.A.Tiling);
            addLine(casP, "Stencil B Tiling", chunk.stencil.B.Tiling);
            addLine(casP, "Stencil C Tiling", chunk.stencil.C.Tiling);
            addLine(casP, "Stencil D Tiling", chunk.stencil.D.Tiling);
            addLine(casP, "Stencil E Tiling", chunk.stencil.E.Tiling);
            addLine(casP, "Stencil F Tiling", chunk.stencil.F.Tiling);

            addLine(casP, "Stencil A Rotation", chunk.stencil.A.Rotation);
            addLine(casP, "Stencil B Rotation", chunk.stencil.B.Rotation);
            addLine(casP, "Stencil C Rotation", chunk.stencil.C.Rotation);
            addLine(casP, "Stencil D Rotation", chunk.stencil.D.Rotation);
            addLine(casP, "Stencil E Rotation", chunk.stencil.E.Rotation);
            addLine(casP, "Stencil F Rotation", chunk.stencil.F.Rotation);

            addLine(casP, "Stencil A Enabled", chunk.stencil.A.Enabled);
            addLine(casP, "Stencil B Enabled", chunk.stencil.B.Enabled);
            addLine(casP, "Stencil C Enabled", chunk.stencil.C.Enabled);
            addLine(casP, "Stencil D Enabled", chunk.stencil.D.Enabled);
            addLine(casP, "Stencil E Enabled", chunk.stencil.E.Enabled);
            addLine(casP, "Stencil F Enabled", chunk.stencil.F.Enabled);

            if (addComments) sb.Append("<!-- Damnit! -->");

            addLine(casP, "IsNaked", chunk.IsNaked);
            addLine(casP, "IsNotNaked", chunk.IsNotNaked);

            addLine(casP, "Skin Specular", chunk.SkinSpecular, true);
            addLine(casP, "Skin Ambient", chunk.SkinAmbient, true);

            addLine(casP, "Logo UpperLeft", chunk.logo.upperLeft);
            addLine(casP, "Logo LowerRight", chunk.logo.lowerRight);
            addLine(casP, "Logo", chunk.logo.filename);
            addLine(casP, "Logo Enabled", chunk.logo.enabled);

            addLine(casP, "Part Mask", chunk.PartMask, true);

            if (addComments) sb.Append("<!-- We are running out of lime! -->");
            casP.tgi64list.Add(new MadScience.Wrappers.ResourceKey(chunk.reskey));

            for (int i = 0; i < 4; i++)
            {
                if (chunk.pattern[i].name != "")
                {
                    string patternName = "";
                    string charName = "";
                    switch (i)
                    {
                        case 0: patternName = "Pattern A"; charName = "JackB"; break;
                        case 1: patternName = "Pattern B"; charName = "ChloeON"; break;
                        case 2: patternName = "Pattern C"; charName = "TonyA"; break;
                        case 3: patternName = "Pattern D"; charName = "BillB"; break;
                    }

                    sb.AppendLine("<pattern name=\"" + chunk.pattern[i].name + "\" reskey=\"" + chunk.pattern[i].key + "\" variable=\"" + patternName + "\">");
                    //casP.tgi64list.Add(new keyName(chunk.pattern[i].key).ToTGI());
                    casP.tgi64list.Add(new MadScience.Wrappers.ResourceKey(chunk.pattern[i].key));
                    if (addComments) sb.Append("<!-- " + charName + "-->");
                    avSBL("assetRoot", "X:");

                    if (chunk.pattern[i].type == "solidColor")
                    {
                        avSBL("Color", chunk.pattern[i].Color);
                    }
                    if (chunk.pattern[i].type == "HSV")
                    {
                        if (!String.IsNullOrEmpty(chunk.pattern[i].BackgroundImage))
                        {
                            casP.tgi64list.Add(new MadScience.Wrappers.ResourceKey(chunk.pattern[i].BackgroundImage));
                            avSBL("Background Image", chunk.pattern[i].BackgroundImage);
                        }
                        if (!String.IsNullOrEmpty(chunk.pattern[i].HBg)) avSBL("H Bg", chunk.pattern[i].HBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].SBg)) avSBL("S Bg", chunk.pattern[i].SBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].VBg)) avSBL("V Bg", chunk.pattern[i].VBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].BaseHBg)) avSBL("Base H Bg", chunk.pattern[i].BaseHBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].BaseSBg)) avSBL("Base S Bg", chunk.pattern[i].BaseSBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].BaseVBg)) avSBL("Base V Bg", chunk.pattern[i].BaseVBg);
                        if (!String.IsNullOrEmpty(chunk.pattern[i].HSVShiftBg)) avSBL("HSVShift Bg", chunk.pattern[i].HSVShiftBg);
                    }
                    if (chunk.pattern[i].type == "Coloured")
                    {
                        for (int j = 0; j < 5; j++)
                        {
                            if (!String.IsNullOrEmpty(chunk.pattern[i].ColorP[j])) avSBL("Color " + j.ToString(), chunk.pattern[i].ColorP[j]);
                        }
                    }

                    if (!String.IsNullOrEmpty(chunk.pattern[i].rgbmask)) avSBL("rgbmask", chunk.pattern[i].rgbmask);
                    if (!String.IsNullOrEmpty(chunk.pattern[i].specmap)) avSBL("specmap", chunk.pattern[i].specmap);
                    avSBL("filename", chunk.pattern[i].filename);
                    sb.AppendLine("</pattern>");
                }
            }

            if (!String.IsNullOrEmpty(chunk.logo.name))
            {
                sb.Append("<pattern name=\"" + chunk.logo.name + "\" reskey=\"" + chunk.logo.key + "\" variable=\"Logo\">");
                casP.tgi64list.Add(new MadScience.Wrappers.ResourceKey(chunk.logo.key));
                avSB("assetRoot", "X:");
                //avSB("Color", chunk.pattern.Logo.Color);
                avSB("filename", chunk.logo.filename);
                sb.Append("</pattern>");
            }
            sb.Append("</complate>");
            if (addComments) sb.Append("<!-- Have you seen my daughter?! -->");
            sb.Append("</preset>");

            return sb.ToString();
        }
 private void addToTGI(casPart casP, MadScience.Wrappers.ResourceKey tgiNew)
 {
     // Remove duplicates from the tgi64list (just in case)
     bool hasTGI = false;
         for (int k = 0; k < casP.tgi64list.Count; k++)
         {
             MadScience.Wrappers.ResourceKey tgi = casP.tgi64list[k];
             if (tgi.typeId == tgiNew.typeId && tgi.groupId == tgiNew.groupId && tgi.instanceId == tgiNew.instanceId)
             {
                 hasTGI = true;
                 break;
             }
         }
         if (!hasTGI)
         {
             Console.WriteLine("Adding tgi64 " + tgiNew.ToString());
             casP.tgi64list.Add(tgiNew);
         }
 }
 private void addLine(casPart casP, string keyName, string value, bool addToKeylist)
 {
     if (!String.IsNullOrEmpty(value))
     {
         Console.WriteLine("Adding " + keyName);
         if (addToKeylist) addToTGI(casP, new MadScience.Wrappers.ResourceKey(value));
         avSB(keyName, value);
     }
 }
 private void addLine(casPart casP, string keyName, string value)
 {
     addLine(casP, keyName, value, false);
 }
        public void Save(Stream casFile, casPart casP, bool addComments)
        {
            int xmlSize = 0;
            int chunkCount = 0;
            //ArrayList newtgi64 = new ArrayList();

            if (casP.xmlChunk != null)
            {

                // Remove the textures and XML from the tgi64 list
                List<MadScience.Wrappers.ResourceKey> temp = new List<MadScience.Wrappers.ResourceKey>();
                for (int j = 0; j < casP.tgi64list.Count; j++)
                {
                    //tgi64 tgi = (tgi64)casP.tgi64list[j];
                    MadScience.Wrappers.ResourceKey tgi = casP.tgi64list[j];
                    switch (tgi.typeId)
                    {
                        case 0x00B2D882:
                        case 0x0333406C:
                            break;
                        default:
                            temp.Add(tgi);
                            break;
                    }
                }

                casP.tgi64list.Clear();

                // Make up the XML chunks first
                for (int j = 0; j < casP.xmlChunk.Count; j++)
                {

                    chunkCount++;

                    casP.xmlChunkRaw[j] = generateXMLChunk(casP, j, addComments);

                }

                for (int j = 0; j < temp.Count; j++)
                {
                    casP.tgi64list.Add(temp[j]);
                }

            }
            else
            {
                chunkCount = 0;
                //newtgi64 = casP.tgi64list;
            }

            // Okay remove any possible duplicates from the tgi list
            List<MadScience.Wrappers.ResourceKey> newTGIs = new List<MadScience.Wrappers.ResourceKey>();
            for (int i = 0; i < casP.tgi64list.Count; i++)
            {
                bool hasMatch = false;
                MadScience.Wrappers.ResourceKey srcTgi = casP.tgi64list[i];

                for (int j = 0; j < newTGIs.Count; j++)
                {
                    MadScience.Wrappers.ResourceKey dstTgi = newTGIs[j];

                    if (srcTgi.typeId == dstTgi.typeId && srcTgi.groupId == dstTgi.groupId && srcTgi.instanceId == dstTgi.instanceId)
                    {
                        hasMatch = true;
                        break;
                    }
                }
                if (!hasMatch) newTGIs.Add(srcTgi);

            }

            casP.tgi64list = newTGIs;

            BinaryWriter writer = new BinaryWriter(casFile);
            // Version is always 18
            uint casPversion = 18;
            writer.Write(casPversion);
            writer.Write(xmlSize);

            writer.Write(chunkCount);

            if (chunkCount > 0)
            {
                for (int i = 1; i <= casP.xmlChunk.Count; i++)
                {
                    string temp = (string)casP.xmlChunkRaw[i - 1];
                    writer.Write(temp.Length);
                    MadScience.StreamHelpers.WriteStringUTF16(casFile, true, temp);
                    writer.Write(i);
                }
            }

            writer.Write((byte)(casP.meshName.Length * 2));
            MadScience.StreamHelpers.WriteStringUTF16(casFile, false, casP.meshName);
            writer.Write(casP.clothingOrder);
            writer.Write(casP.unk2);
            writer.Write(casP.clothingType);
            writer.Write(casP.typeFlag);
            writer.Write(casP.ageGenderFlag);
            writer.Write(casP.clothingCategory);

            casP.tgiIndexBodyPart1 = (byte)findChunkInTGIList(casP, 0x034AEECB, 1);
            if (casP.tgiIndexBodyPart1 == 0) { casP.tgiIndexBodyPart1 = (byte)findChunkInTGIList(casP, 0x0, 1); }
            // If we still dont have a match... add a blank entry to the end.
            if (casP.tgiIndexBodyPart1 == 0)
            {
                casP.tgi64list.Add(new MadScience.Wrappers.ResourceKey());
                casP.tgiIndexBodyPart1 = (byte)(casP.tgi64list.Count - 1);
            }
            casP.tgiIndexBodyPart2 = (byte)findChunkInTGIList(casP, 0x034AEECB, 2);
            if (casP.tgiIndexBodyPart2 == 0) { casP.tgiIndexBodyPart2 = (byte)findChunkInTGIList(casP, 0x0, 1); }

            writer.Write(casP.tgiIndexBodyPart1);
            writer.Write(casP.tgiIndexBodyPart2);

            casP.tgiIndexBlendInfoFat = (byte)findChunkInTGIList(casP, 0x062C8204, 1);
            casP.tgiIndexBlendInfoFit = (byte)findChunkInTGIList(casP, 0x062C8204, 2);
            casP.tgiIndexBlendInfoThin = (byte)findChunkInTGIList(casP, 0x062C8204, 3);
            casP.tgiIndexBlendInfoSpecial = (byte)findChunkInTGIList(casP, 0x062C8204, 4);

            writer.Write(casP.tgiIndexBlendInfoFat);
            writer.Write(casP.tgiIndexBlendInfoFit);
            writer.Write(casP.tgiIndexBlendInfoThin);
            writer.Write(casP.tgiIndexBlendInfoSpecial);

            writer.Write(casP.unk5);

            if (casP.tgiIndexVPXY > 0)
            {
                casP.tgiIndexVPXY = (byte)findChunkInTGIList(casP, 0x736884F1, 1);

                writer.Write((byte)1);
                writer.Write(casP.tgiIndexVPXY);
            }
            else
            {
                writer.Write((byte)0);
            }

            writer.Write(casP.count2);
            for (int i = 0; i < casP.count2; i++)
            {
                unkRepeat uR = (unkRepeat)casP.count2repeat[i];
                writer.Write(uR.unkNum);
                writer.Write(uR.unk2);
                writer.Write(uR.unkRepeatInnerCount);
                for (int j = 0; j < uR.unkRepeatInnerCount; j++)
                {
                    intTriple iT = (intTriple)uR.unkRepeatInnerLoop[j];
                    writer.Write(iT.one);
                    writer.Write(iT.two);
                    writer.Write(iT.three);
                }

            }

            if (casP.tgiIndexDiffuse > 0)
            {
                casP.tgiIndexDiffuse = (byte)findChunkInTGIList(casP, 0x033A1435, 1);
                writer.Write((byte)1);
                writer.Write(casP.tgiIndexDiffuse);
            }
            else
            {
                writer.Write((byte)0);
            }
            if (casP.tgiIndexSpecular > 0)
            {
                casP.tgiIndexSpecular = (byte)findChunkInTGIList(casP, 0x033A1435, 2);
                writer.Write((byte)1);
                writer.Write(casP.tgiIndexSpecular);
            }
            else
            {
                writer.Write((byte)0);
            }

            // Diffuse files
            writer.Write(casP.count3);
            // WARNING: Assume 2 for now
            if (casP.count3 == 2)
            {
                byte c3r = (byte)findChunkInTGIList(casP, 0x033A1435, 3);
                writer.Write(c3r);
                c3r = (byte)findChunkInTGIList(casP, 0x033A1435, 4);
                writer.Write(c3r);
            }
            else
            {
                for (int i = 0; i < casP.count3; i++)
                {
                    byte c3r = (byte)casP.count3repeat[i];
                    writer.Write(c3r);
                }
            }

            // Specular files
            writer.Write(casP.count4);
            // WARNING: Assume 2 for now
            if (casP.count4 == 2)
            {
                byte c3r = (byte)findChunkInTGIList(casP, 0x033A1435, 5);
                writer.Write(c3r);
                c3r = (byte)findChunkInTGIList(casP, 0x033A1435, 6);
                writer.Write(c3r);
            } else {
                for (int i = 0; i < casP.count4; i++)
                {
                    byte c4r = (byte)casP.count4repeat[i];
                    writer.Write(c4r);
                }

            }

            writer.Write(casP.count5);
            // Construct the count5repeat based on the last X 0355E0A6 TGI refs
            for (int i = 0; i < casP.count5; i++)
            {
                byte c5r = (byte)findChunkInTGIList(casP, 0x0355E0A6, (i + 1));
                if (c5r == 0)
                {
                    // Find the first blank key
                    c5r = (byte)findChunkInTGIList(casP, 0x0, 1);
                }
                writer.Write(c5r);
            }

            writer.Write((byte)(casP.unkString.Length * 2));
            MadScience.StreamHelpers.WriteStringUTF16(casFile, false, casP.unkString);

            int tgiPos = (int)casFile.Position - 8;

            casP.count6 = (byte)newTGIs.Count;
            writer.Write(casP.count6);
            for (int i = 0; i < casP.count6; i++)
            {
                MadScience.Wrappers.ResourceKey tgi = newTGIs[i];
                Console.WriteLine("Writing tgi64 " + tgi.ToString());
                writer.Write(tgi.instanceId);
                writer.Write(tgi.groupId);
                writer.Write(tgi.typeId);
            }

            casFile.Seek(4, SeekOrigin.Begin);
            writer.Write(tgiPos);
        }
 public void Save(Stream casFile, casPart casP)
 {
     Save(casFile, casP, true);
 }