Exemple #1
0
        public void InitInterpreter(BioTlkFileSet editorTalkset = null)
        {
            DynamicByteProvider db = new DynamicByteProvider(pcc.Exports[Index].Data);

            hb1.ByteProvider = db;
            memory           = pcc.Exports[Index].Data;
            memsize          = memory.Length;

            // attempt to find a TlkFileSet associated with the object, else just pick the first one and hope it's correct
            if (editorTalkset == null)
            {
                PropertyReader.Property tlkSetRef = PropertyReader.getPropList(pcc, pcc.Exports[Index].Data).FirstOrDefault(x => pcc.getNameEntry(x.Name) == "m_oTlkFileSet");
                if (tlkSetRef != null)
                {
                    tlkset = new BioTlkFileSet(pcc, tlkSetRef.Value.IntValue - 1);
                }
                else
                {
                    tlkset = new BioTlkFileSet(pcc);
                }
            }
            else
            {
                tlkset = editorTalkset;
            }
        }
Exemple #2
0
        private void ReadColors(PropertyReader.Property p, IMEPackage pcc)
        {
            int count = BitConverter.ToInt32(p.raw, 24);
            int start = 28;

            for (int i = 0; i < count; i++)
            {
                List <PropertyReader.Property> props = PropertyReader.ReadProp(pcc, p.raw, start);
                ColorOverride co = new ColorOverride();

                foreach (PropertyReader.Property sp in props)
                {
                    string propName = pcc.getNameEntry(sp.Name);
                    switch (propName)
                    {
                    case "nName":
                        int nameI = sp.Value.IntValue;
                        if (pcc.isName(nameI))
                        {
                            co.ParamName = pcc.Names[nameI];
                        }
                        break;

                    case "cValue":
                        co.Value = new LinearColor(sp);
                        break;

                    case "None":
                        break;
                    }
                }
                ColorOverrides.Add(co);
                start = props[props.Count - 1].offend;
            }
        }
Exemple #3
0
 public LinearColor(PropertyReader.Property p)
 {
     R = BitConverter.ToSingle(p.raw, 32);
     G = BitConverter.ToSingle(p.raw, 36);
     B = BitConverter.ToSingle(p.raw, 40);
     A = BitConverter.ToSingle(p.raw, 44);
 }
        private static Vector GetVector(PropertyReader.Property prop)
        {
            Vector vec;

            vec.X = BitConverter.ToSingle(prop.raw, 32);
            vec.Y = BitConverter.ToSingle(prop.raw, 36);
            vec.Z = BitConverter.ToSingle(prop.raw, 40);
            return(vec);
        }
Exemple #5
0
        private void ReadFinalSkeleton(PropertyReader.Property p)
        {
            int count     = BitConverter.ToInt32(p.raw, 24);
            int propStart = 28;

            for (int i = 0; i < count; i++)
            {
                List <PropertyReader.Property> BoneOffsetProps = PropertyReader.ReadProp(pcc, p.raw, propStart);
                propStart = BoneOffsetProps[BoneOffsetProps.Count - 1].offend;
                BoneOffset bone = new BoneOffset(BoneOffsetProps, pcc);
                m_aFinalSkeleton.Add(bone);
            }
        }
Exemple #6
0
        public byte[] ToArray(int pccExportDataOffset)
        {
            MemoryStream buffer = new MemoryStream();

            buffer.Write(headerData, 0, headerData.Length);
            foreach (KeyValuePair <string, PropertyReader.Property> kvp in properties)
            {
                PropertyReader.Property property = kvp.Value;

                // this is the part when I get rid of the LODGroup property!!!!!!!!!!!!!!!
                // the texture will use texturegroup_world as default texturegroup
                //if (kvp.Key == "LODGroup")
                //    continue;
                if (kvp.Key == "LODBias")
                {
                    continue;
                }
                if (kvp.Key == "InternalFormatLODBias")
                {
                    continue;
                }

                buffer.Write(property.raw, 0, property.raw.Length);
                if (kvp.Key == "UnpackMin")
                {
                    buffer.Write(property.raw, 0, property.raw.Length);
                    buffer.Write(property.raw, 0, property.raw.Length);
                }
            }
            buffer.WriteValueU32(numMipMaps);
            foreach (ImageInfo imgInfo in imgList)
            {
                buffer.WriteValueS32((int)imgInfo.storageType);
                buffer.WriteValueS32(imgInfo.uncSize);
                buffer.WriteValueS32(imgInfo.cprSize);
                if (imgInfo.storageType == storage.pccSto)
                {
                    buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset));
                    buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize);
                }
                else
                {
                    buffer.WriteValueS32(imgInfo.offset);
                }
                buffer.WriteValueU32(imgInfo.imgSize.width);
                buffer.WriteValueU32(imgInfo.imgSize.height);
            }
            // Texture2D footer, 24 bytes size
            buffer.Write(imageData, imageData.Length - 24, 24);
            return(buffer.ToArray());
        }
Exemple #7
0
        private void ReadMorphFeatures(PropertyReader.Property p)
        {
            int count = BitConverter.ToInt32(p.raw, 24);

            int propStart = 28;

            for (int i = 0; i < count; i++)
            {
                List <PropertyReader.Property> FeatureProps = PropertyReader.ReadProp(pcc, p.raw, propStart);
                propStart = FeatureProps[FeatureProps.Count - 1].offend;
                BioFeature Feature = new BioFeature(FeatureProps, pcc);
                m_aMorphFeatures.Add(Feature);
            }
        }
Exemple #8
0
        private void ReadTextures(PropertyReader.Property p, IMEPackage pcc)
        {
            int count = BitConverter.ToInt32(p.raw, 24);
            int start = 28;

            for (int i = 0; i < count; i++)
            {
                // read next 68 bytes
                List <PropertyReader.Property> props = PropertyReader.ReadProp(pcc, p.raw, start);
                TextureOverride to = new TextureOverride();

                foreach (PropertyReader.Property sp in props)
                {
                    string propName = pcc.getNameEntry(sp.Name);
                    switch (propName)
                    {
                    case "nName":
                        int nameI = sp.Value.IntValue;
                        if (pcc.isName(nameI))
                        {
                            to.ParamName = pcc.Names[nameI];
                        }
                        break;

                    case "m_pTexture":
                        int objTextIndex = sp.Value.IntValue;
                        if (pcc.isExport(objTextIndex - 1))
                        {
                            to.TextureName = pcc.Exports[objTextIndex - 1].ObjectName;
                        }
                        break;

                    case "None":
                        break;
                    }
                }
                TextureOverrides.Add(to);
                start = props[props.Count - 1].offend;
            }
        }
Exemple #9
0
        private void ReadScalars(PropertyReader.Property p, IMEPackage pcc)
        {
            int count = BitConverter.ToInt32(p.raw, 24);
            int start = 28;

            for (int i = 0; i < count; i++)
            {
                // read next 68 bytes
                List <PropertyReader.Property> props = PropertyReader.ReadProp(pcc, p.raw, start);
                ScalarOverride so = new ScalarOverride();

                foreach (PropertyReader.Property sp in props)
                {
                    string propName = pcc.getNameEntry(sp.Name);
                    switch (propName)
                    {
                    case "nName":
                        int nameI = sp.Value.IntValue;
                        if (pcc.isName(nameI))
                        {
                            so.ParamName = pcc.Names[nameI];
                        }
                        break;

                    case "sValue":
                        so.Value = BitConverter.ToSingle(sp.raw, sp.raw.Length - 4);
                        break;

                    case "None":
                        break;
                    }
                }
                ScalarOverrides.Add(so);
                start = props[props.Count - 1].offend;
            }
        }
Exemple #10
0
        public TreeNode MakeDefaultPropNode(PropertyReader.Property p)
        {
            string tp = PropertyReader.TypeToString((int)p.TypeVal);

            switch (tp)
            {
            case "Byte Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : (" + pcc.GetName(BitConverter.ToInt32(p.raw, 24)) + ") " + pcc.GetName(BitConverter.ToInt32(p.raw, 32))));

            case "Bool Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + (p.Value.IntValue == 1)));

            case "Object Property":
                string s = " ";
                if (p.Value.IntValue != 0)
                {
                    s = pcc.GetObject(p.Value.IntValue);
                }
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + p.Value.IntValue + s));

            case "Integer Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + p.Value.IntValue));

            case "Name Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + pcc.GetName(p.Value.IntValue)));

            case "Float Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + BitConverter.ToSingle(p.raw, 24)));

            case "String Property":
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ") : " + p.Value.StringValue));

            default:
                return(new TreeNode(pcc.GetName(p.Name) + " (" + tp + ")"));
            }
        }
Exemple #11
0
        }                                                    // showable image list

        public Texture2D(PCCObject pccObj, int texIdx)
        {
            pccRef = pccObj;
            // check if texIdx is an Export index and a Texture2D class
            if (pccObj.isExport(texIdx) && (pccObj.Exports[texIdx].ClassName == className))
            {
                PCCObject.ExportEntry expEntry = pccObj.Exports[texIdx];
                properties = new Dictionary <string, PropertyReader.Property>();
                byte[] rawData          = (byte[])expEntry.Data.Clone();
                int    propertiesOffset = PropertyReader.detectStart(pccObj, rawData);
                headerData = new byte[propertiesOffset];
                Buffer.BlockCopy(rawData, 0, headerData, 0, propertiesOffset);
                pccOffset = (uint)expEntry.DataOffset;
                List <PropertyReader.Property> tempProperties = PropertyReader.getPropList(pccObj, rawData);
                texName = expEntry.ObjectName;
                for (int i = 0; i < tempProperties.Count; i++)
                {
                    PropertyReader.Property property = tempProperties[i];
                    if (!properties.ContainsKey(pccObj.Names[property.Name]))
                    {
                        properties.Add(pccObj.Names[property.Name], property);
                    }

                    switch (pccObj.Names[property.Name])
                    {
                    case "Format": texFormat = pccObj.Names[property.Value.IntValue].Substring(3); break;

                    case "TextureFileCacheName": arcName = pccObj.Names[property.Value.IntValue]; break;

                    case "LODGroup": LODGroup = pccObj.Names[property.Value.IntValue]; break;

                    case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                    }
                }

                // if "None" property isn't found throws an exception
                if (dataOffset == 0)
                {
                    throw new Exception("\"None\" property not found");
                }
                else
                {
                    imageData = new byte[rawData.Length - dataOffset];
                    Buffer.BlockCopy(rawData, (int)dataOffset, imageData, 0, (int)(rawData.Length - dataOffset));
                }
            }
            else
            {
                throw new Exception("Texture2D " + texIdx + " not found");
            }

            pccExpIdx = texIdx;
            MemoryStream dataStream = new MemoryStream(imageData);

            numMipMaps = dataStream.ReadValueU32();
            uint count = numMipMaps;

            imgList = new List <ImageInfo>();
            while (dataStream.Position < dataStream.Length && count > 0)
            {
                ImageInfo imgInfo = new ImageInfo();
                imgInfo.storageType = (storage)dataStream.ReadValueS32();
                imgInfo.uncSize     = dataStream.ReadValueS32();
                imgInfo.cprSize     = dataStream.ReadValueS32();
                imgInfo.offset      = dataStream.ReadValueS32();
                if (imgInfo.storageType == storage.pccSto)
                {
                    //imgInfo.offset = (int)(pccOffset + dataOffset); // saving pcc offset as relative to exportdata offset, not absolute
                    imgInfo.offset = (int)dataStream.Position; // saving pcc offset as relative to exportdata offset, not absolute
                    //MessageBox.Show("Pcc class offset: " + pccOffset + "\nimages data offset: " + imgInfo.offset.ToString());
                    dataStream.Seek(imgInfo.uncSize, SeekOrigin.Current);
                }
                imgInfo.imgSize = new ImageSize(dataStream.ReadValueU32(), dataStream.ReadValueU32());
                imgList.Add(imgInfo);
                count--;
            }

            // save what remains

            /*int remainingBytes = (int)(dataStream.Length - dataStream.Position);
             * footerData = new byte[remainingBytes];
             * dataStream.Read(footerData, 0, footerData.Length);*/
        }
Exemple #12
0
        public void OneImageToRuleThemAll(string imageFileName, string archiveDir, out string newTextureGroup)
        {
            newTextureGroup = null;
            ImageMipMapHandler imgMipMap = new ImageMipMapHandler(imageFileName, null);

            // starts from the smaller image
            for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--)
            {
                ImageFile newImageFile = imgMipMap.imageList[i];

                // insert images only with size > 64
                if (newImageFile.imgSize.width < 64 && newImageFile.imgSize.height < 64)
                {
                    continue;
                }

                // write the new image into a file (I know that's crappy solution, I'll find another one later...)
                using (FileStream newImageStream = File.Create(newImageFile.fileName))
                {
                    byte[] buffer = newImageFile.ToArray();
                    newImageStream.Write(buffer, 0, buffer.Length);
                }

                // if the image size exists inside the texture2d image list then we have to replace it
                if (imgList.Exists(img => img.imgSize == newImageFile.imgSize))
                {
                    // ...but at least for now I can reuse my replaceImage function... ;)
                    replaceImage(newImageFile.imgSize.ToString(), newImageFile.fileName, archiveDir);
                }
                else // if the image doesn't exists then we have to add it
                {
                    // ...and use my addBiggerImage function! :P
                    addBiggerImage(newImageFile.fileName, archiveDir);
                }

                File.Delete(newImageFile.fileName);
            }

            // add texturegroup_world inside GamerSettings.ini in order to overwrite values
            ImageSize maxSize  = imgList.Max(image => image.imgSize);
            uint      maxValue = Math.Max(maxSize.width, maxSize.height);
            string    section  = "SystemSettings";
            string    key      = "texturegroup_shadowmap";
            string    newValue = "(MinLODSize=128,MaxLODSize=" + maxValue + ",LODBias=0)";
            IniFile   iniFile  = new IniFile(ME3Directory.GamerSettingsIniFile);
            string    oldValue = iniFile.IniReadValue(section, key);

            if (oldValue == "")
            {
                iniFile.IniWriteValue(section, key, newValue);
            }
            else
            {
                char[] delimiters = new char[] { '=', ',' };
                uint   maxLODSize = Convert.ToUInt32(oldValue.Split(delimiters)[3]);
                if (maxValue > maxLODSize)
                {
                    iniFile.IniWriteValue(section, key, newValue);
                }
            }

            // check that Texture2D has a TextureGroup
            if (!properties.ContainsKey("LODGroup"))
            {
                return;
            }

            // extracting values from LODGroup Property
            PropertyReader.Property LODGroup = properties["LODGroup"];
            string textureGroupName          = pccRef.Names[LODGroup.Value.IntValue];

            string newTextureGroupName = "TEXTUREGROUP_Shadowmap";

            textureGroupName = newTextureGroupName;
            if (!pccRef.Names.Exists(name => name == newTextureGroupName))
            {
                pccRef.Names.Add(newTextureGroupName);
            }
            using (MemoryStream rawStream = new MemoryStream(LODGroup.raw))
            {
                rawStream.Seek(32, SeekOrigin.Begin);
                rawStream.WriteValueS32(pccRef.Names.FindIndex(name => name == newTextureGroupName));
                //rawStream.Seek(32, SeekOrigin.Begin);
                rawStream.WriteValueS32(0);
                properties["LODGroup"].raw = rawStream.ToArray();
            }
            //LODGroup.Value.IntValue = pccRef.Names.FindIndex(name => name == newTextureGroupName);

            /*MessageBox.Show("Texturegroup Name: " + textureGroupName);
             * ImageSize maxImageSize = imgList.Max(image => image.imgSize);
             * int textureGroupValue = (int)Math.Max(maxImageSize.width, maxImageSize.height) + 1;
             *
             * // open Engine.pcc file and edit TextureGroup enumerator
             * {
             *  PCCObject pccEngine = new PCCObject(ME3Directory.cookedPath + "Engine.pcc");
             *  int idxTexGroups = pccEngine.Exports.FindIndex(export => export.ObjectName == "TextureGroup");
             *
             *  TextureGroup texGroup = new TextureGroup(pccEngine, pccEngine.Exports[idxTexGroups].Data);
             *  if (texGroup.ExistsTextureGroup(textureGroupName, textureGroupValue))
             *      return;
             *  else
             *  {
             *      if (!pccEngine.Names.Exists(name => name == newTextureGroupName))
             *          pccEngine.Names.Add(newTextureGroupName);
             *
             *      newTextureGroup = textureGroupName + "_" + (textureGroupValue - 1);
             *
             *      texGroup.Add(textureGroupName, textureGroupValue);
             *      MessageBox.Show("Now editing texgroup enum");
             *      pccEngine.Exports[idxTexGroups].Data = texGroup.ToArray();
             *      MessageBox.Show("Now saving engine.pcc");
             *      pccEngine.saveToFile(true, ME3Directory.cookedPath + "Engine.pcc");
             *      MessageBox.Show("Saved engine.pcc");
             *
             *
             *  }
             * }*/
        }
Exemple #13
0
        public void OneImageToRuleThemAll(string archiveDir, ImageFile im, out string newTextureGroup, byte[] imgData)
        {
            newTextureGroup = null;
            ImageMipMapHandler imgMipMap = new ImageMipMapHandler("", imgData);

            // starts from the smaller image
            for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--)
            {
                ImageFile newImageFile = imgMipMap.imageList[i];

                // insert images only with size > 64
                if (newImageFile.imgSize.width < 64 && newImageFile.imgSize.height < 64)
                {
                    continue;
                }


                // if the image size exists inside the texture2d image list then we have to replace it
                if (imgList.Exists(img => img.imgSize == newImageFile.imgSize))
                {
                    // ...but at least for now I can reuse my replaceImage function... ;)
                    replaceImage(newImageFile.imgSize.ToString(), newImageFile, archiveDir);
                }
                else // if the image doesn't exists then we have to add it
                {
                    // ...and use my addBiggerImage function! :P
                    addBiggerImage(newImageFile, archiveDir);
                }

                File.Delete(newImageFile.fileName);
            }

            // add texturegroup_world inside GamerSettings.ini in order to overwrite values
            ImageSize maxSize  = imgList.Max(image => image.imgSize);
            uint      maxValue = Math.Max(maxSize.width, maxSize.height);
            string    section  = "SystemSettings";
            string    key      = "texturegroup_shadowmap";
            string    newValue = "(MinLODSize=128,MaxLODSize=" + maxValue + ",LODBias=0)";
            IniFile   iniFile  = new IniFile(ME3Directory.GamerSettingsIniFile);
            string    oldValue = iniFile.IniReadValue(section, key);

            if (oldValue == "")
            {
                iniFile.IniWriteValue(section, key, newValue);
            }
            else
            {
                char[] delimiters = new char[] { '=', ',' };
                uint   maxLODSize = Convert.ToUInt32(oldValue.Split(delimiters)[3]);
                if (maxValue > maxLODSize)
                {
                    iniFile.IniWriteValue(section, key, newValue);
                }
            }

            // check that Texture2D has a TextureGroup
            if (!properties.ContainsKey("LODGroup"))
            {
                return;
            }

            // extracting values from LODGroup Property
            PropertyReader.Property LODGroup = properties["LODGroup"];
            string textureGroupName          = pccRef.Names[LODGroup.Value.IntValue];

            string newTextureGroupName = "TEXTUREGROUP_Shadowmap";

            textureGroupName = newTextureGroupName;
            if (!pccRef.Names.Exists(name => name == newTextureGroupName))
            {
                pccRef.Names.Add(newTextureGroupName);
            }
            using (MemoryStream rawStream = new MemoryStream(LODGroup.raw))
            {
                rawStream.Seek(32, SeekOrigin.Begin);
                rawStream.WriteValueS32(pccRef.Names.FindIndex(name => name == newTextureGroupName));
                //rawStream.Seek(32, SeekOrigin.Begin);
                rawStream.WriteValueS32(0);
                properties["LODGroup"].raw = rawStream.ToArray();
            }
        }
        public void LetsDump2(string classname)
        {
            if (string.IsNullOrEmpty(ME3Directory.cookedPath))
            {
                MessageBox.Show("This functionality requires ME3 to be installed. Set its path at:\n Options > Set Custom Path > Mass Effect 3");
                return;
            }
            string path = ME3Directory.cookedPath;

            string[] files = Directory.GetFiles(path, "*.pcc");
            pb1.Minimum = 0;
            rtb1.Text   = "";
            pauseToolStripMenuItem.Visible = true;
            pb2.Value   = 0;
            pb2.Maximum = files.Length;
            List <string> Names = new List <string>();
            List <string> Types = new List <string>();
            List <string> First = new List <string>();

            DebugOutput.Clear();
            for (int i = 0; i < files.Length; i++)
            {
                try
                {
                    while (pause)
                    {
                        Application.DoEvents();
                    }
                    using (ME3Package pcc = MEPackageHandler.OpenME3Package(files[i]))
                    {
                        DebugOutput.PrintLn(i + "/" + files.Length + " Scanning file : " + Path.GetFileName(files[i]));
                        IReadOnlyList <IExportEntry> Exports = pcc.Exports;
                        pb1.Maximum = Exports.Count;
                        pb2.Value   = i;
                        for (int j = 0; j < Exports.Count; j++)
                        {
                            IExportEntry ent = Exports[j];
                            if (ent.ClassName == classname)
                            {
                                List <PropertyReader.Property> p = PropertyReader.getPropList(ent);
                                for (int k = 0; k < p.Count; k++)
                                {
                                    PropertyReader.Property prop = p[k];
                                    int found = -1;
                                    for (int l = 0; l < Names.Count(); l++)
                                    {
                                        if (pcc.getNameEntry(prop.Name) == Names[l])
                                        {
                                            found = l;
                                        }
                                    }
                                    if (found == -1)
                                    {
                                        Names.Add(pcc.getNameEntry(prop.Name));
                                        Types.Add(PropertyReader.TypeToString((int)prop.TypeVal));
                                        First.Add(Path.GetFileName(files[i]) + " #" + j);
                                    }
                                }
                            }
                            if (j % 500 == 0)
                            {
                                pb1.Value   = j;
                                Status.Text = "State : " + j + " / " + Exports.Count;
                                string s = "Possible properties found so far for class \"" + classname + "\":\n";
                                for (int k = 0; k < Names.Count(); k++)
                                {
                                    s += Types[k] + " : \"" + Names[k] + "\" first found: " + First[k] + "\n";
                                }
                                Action action = () => rtb1.Text = s;
                                rtb1.Invoke(action);
                                action = () => rtb1.SelectionStart = s.Length;
                                rtb1.Invoke(action);
                                action = () => rtb1.ScrollToCaret();
                                rtb1.Invoke(action);
                                Application.DoEvents();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error:\n" + ex.Message);
                    DebugOutput.PrintLn("Could not open  file : " + Path.GetFileName(files[i]));
                }
            }
            Status.Text = "State : Done";
            string t = "Possible properties found for class \"" + classname + "\":\n";

            for (int k = 0; k < Names.Count(); k++)
            {
                t += Types[k] + " : \"" + Names[k] + "\" first found: " + First[k] + "\n";
            }
            rtb1.Text           = t;
            rtb1.SelectionStart = rtb1.TextLength;
            rtb1.ScrollToCaret();
            pb1.Value = 0;
            pauseToolStripMenuItem.Visible = false;
        }
        private void makeDialogDumpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(ME3Directory.cookedPath))
            {
                MessageBox.Show("This functionality requires ME3 to be installed. Set its path at:\n Options > Set Custom Path > Mass Effect 3");
                return;
            }
            string path = ME3Directory.cookedPath;

            string[] files = Directory.GetFiles(path);
            pb1.Minimum = 0;
            rtb1.Text   = "";
            int    count  = 0;
            int    count2 = 0;
            string t      = "";

            pauseToolStripMenuItem.Visible = true;
            pb2.Value   = 0;
            pb2.Maximum = files.Length;
            for (int i = 0; i < files.Length; i++)
            {
                try
                {
                    if (files[i].ToLower().EndsWith(".pcc"))
                    {
                        while (pause)
                        {
                            Application.DoEvents();
                        }
                        using (ME3Package pcc = MEPackageHandler.OpenME3Package(files[i]))
                        {
                            IReadOnlyList <IExportEntry> Exports = pcc.Exports;
                            pb1.Maximum = Exports.Count;
                            pb2.Value   = i;
                            string s = "String references for file " + files[i] + "\n";
                            for (int j = 0; j < Exports.Count; j++)
                            {
                                IExportEntry ent = Exports[j];
                                List <PropertyReader.Property> p = PropertyReader.getPropList(ent);

                                for (int k = 0; k < p.Count; k++)
                                {
                                    PropertyReader.Property prop = p[k];
                                    if (prop.TypeVal == PropertyType.StringRefProperty)
                                    {
                                        s += "Object #" + j + " : " + PropertyReader.PropertyToText(prop, pcc) + "\n";
                                    }
                                    if (prop.TypeVal == PropertyType.ArrayProperty)
                                    {
                                        string tt = DumpArray(pcc, ent.Data, prop.offsetval + 4, 1);
                                        if (tt.Length != 0)
                                        {
                                            s += "Object #" + j + " in : " + PropertyReader.PropertyToText(prop, pcc) + "\n";
                                            s += tt;
                                        }
                                    }
                                    if (prop.TypeVal == PropertyType.StructProperty)
                                    {
                                        string tt = DumpArray(pcc, ent.Data, prop.offsetval + 8, 1);
                                        if (tt.Length != 0)
                                        {
                                            s += "Object #" + j + " in : " + PropertyReader.PropertyToText(prop, pcc) + "\n";
                                            s += tt;
                                        }
                                    }
                                }
                                if (count++ > 500)
                                {
                                    count       = 0;
                                    pb1.Value   = j;
                                    Status.Text = "State : " + j + " / " + Exports.Count;
                                    if (count2++ > 10)
                                    {
                                        count2              = 0;
                                        rtb1.Text           = t;
                                        rtb1.SelectionStart = rtb1.TextLength;
                                        rtb1.ScrollToCaret();
                                        rtb1.Visible = true;
                                    }
                                    Application.DoEvents();
                                }
                            }
                            t += s + "\n";
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error:\n" + ex.Message);
                }
            }
            Status.Text         = "State : Done";
            rtb1.Text           = t;
            rtb1.SelectionStart = rtb1.TextLength;
            rtb1.ScrollToCaret();
            pb1.Value = 0;
            pauseToolStripMenuItem.Visible = false;
        }
        public InterpCurve(IMEPackage _pcc, PropertyReader.Property p)
        {
            pcc = _pcc;

            Curves    = new ObservableCollection <Curve>();
            Name      = pcc.getNameEntry(p.Name);
            curveType = (CurveType)Enum.Parse(typeof(CurveType), pcc.getNameEntry(p.Value.IntValue));

            float     InVal      = 0f;
            CurveMode InterpMode = CurveMode.CIM_Linear;
            var       points     = PropertyReader.ReadStructArrayProp(pcc, PropertyReader.getPropOrNull(pcc, p.raw, 32, "Points"));

            switch (curveType)
            {
            case CurveType.InterpCurveQuat:
                throw new NotImplementedException($"InterpCurveQuat has not been implemented yet.");

            case CurveType.InterpCurveFloat:
                float OutVal                 = 0f;
                float ArriveTangent          = 0f;
                float LeaveTangent           = 0f;
                LinkedList <CurvePoint> vals = new LinkedList <CurvePoint>();
                foreach (var point in points)
                {
                    foreach (var prop in point)
                    {
                        switch (pcc.getNameEntry(prop.Name))
                        {
                        case "InVal":
                            InVal = BitConverter.ToSingle(prop.raw, 24);
                            break;

                        case "OutVal":
                            OutVal = BitConverter.ToSingle(prop.raw, 24);
                            break;

                        case "ArriveTangent":
                            ArriveTangent = BitConverter.ToSingle(prop.raw, 24);
                            break;

                        case "LeaveTangent":
                            LeaveTangent = BitConverter.ToSingle(prop.raw, 24);
                            break;

                        case "InterpMode":
                            InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue));
                            break;

                        default:
                            break;
                        }
                    }
                    vals.AddLast(new CurvePoint(InVal, OutVal, ArriveTangent, LeaveTangent, InterpMode));
                }
                Curves.Add(new Curve("X", vals));
                break;

            case CurveType.InterpCurveVector:
                Vector OutValVec          = new Vector(0, 0, 0);
                Vector ArriveTangentVec   = new Vector(0, 0, 0);
                Vector LeaveTangentVec    = new Vector(0, 0, 0);
                LinkedList <CurvePoint> x = new LinkedList <CurvePoint>();
                LinkedList <CurvePoint> y = new LinkedList <CurvePoint>();
                LinkedList <CurvePoint> z = new LinkedList <CurvePoint>();
                foreach (var point in points)
                {
                    foreach (var prop in point)
                    {
                        switch (pcc.getNameEntry(prop.Name))
                        {
                        case "InVal":
                            InVal = BitConverter.ToSingle(prop.raw, 24);
                            break;

                        case "OutVal":
                            OutValVec = GetVector(prop);
                            break;

                        case "ArriveTangent":
                            ArriveTangentVec = GetVector(prop);
                            break;

                        case "LeaveTangent":
                            LeaveTangentVec = GetVector(prop);
                            break;

                        case "InterpMode":
                            InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue));
                            break;

                        default:
                            break;
                        }
                    }
                    x.AddLast(new CurvePoint(InVal, OutValVec.X, ArriveTangentVec.X, LeaveTangentVec.X, InterpMode));
                    y.AddLast(new CurvePoint(InVal, OutValVec.Y, ArriveTangentVec.Y, LeaveTangentVec.Y, InterpMode));
                    z.AddLast(new CurvePoint(InVal, OutValVec.Z, ArriveTangentVec.Z, LeaveTangentVec.Z, InterpMode));
                }
                if (Name == "EulerTrack")
                {
                    Curves.Add(new Curve("Roll", x));
                    Curves.Add(new Curve("Pitch", y));
                    Curves.Add(new Curve("Yaw", z));
                }
                else
                {
                    Curves.Add(new Curve("X", x));
                    Curves.Add(new Curve("Y", y));
                    Curves.Add(new Curve("Z", z));
                }
                break;

            case CurveType.InterpCurveVector2D:
                throw new NotImplementedException($"InterpCurveVector2D has not been implemented yet.");

            case CurveType.InterpCurveTwoVectors:
                throw new NotImplementedException($"InterpCurveTwoVectors has not been implemented yet.");

            case CurveType.InterpCurveLinearColor:
                throw new NotImplementedException($"InterpCurveLinearColor has not been implemented yet.");

            default:
                break;
            }
            foreach (var curve in Curves)
            {
                curve.SharedValueChanged += Curve_SharedValueChanged;
                curve.ListModified       += Curve_ListModified;
            }
        }