Example #1
0
        public ParticleManifest(List <string> sourceDirectories, List <string> ignoreDirectories, List <string> excludedFiles, BSP map, string bspPath, string gameFolder)
        {
            CompilePalLogger.LogLine("Generating Particle Manifest...");

            baseDirectory = gameFolder + "\\";

            particles = new List <PCF>();

            //Search directories for pcf and find particles that match used particle names
            //TODO multithread this?
            foreach (string sourceDirectory in sourceDirectories)
            {
                string externalPath = sourceDirectory + "\\" + internalPath;

                if (Directory.Exists(externalPath) && !ignoreDirectories.Contains(externalPath.Remove(externalPath.Length - 1, 1), StringComparer.OrdinalIgnoreCase))
                {
                    foreach (string file in Directory.GetFiles(externalPath))
                    {
                        if (file.EndsWith(".pcf") && !excludedFiles.Contains(file.ToLower()))
                        {
                            PCF pcf = ParticleUtils.IsTargetParticle(file, map.ParticleList);
                            if (pcf != null && !particles.Exists(p => p.FilePath == pcf.FilePath))
                            {
                                particles.Add(pcf);
                            }
                        }
                    }
                }
            }

            if (particles == null || particles.Count == 0)
            {
                CompilePalLogger.LogCompileError("Could not find any PCFs that contained used particles!\n", new Error("Could not find any PCFs that contained used particles!\n", ErrorSeverity.Warning));
                return;
            }


            //Check for pcfs that contain the same particle name
            //List<ParticleConflict> conflictingParticles = new List<ParticleConflict>();
            List <PCF> conflictingParticles = new List <PCF>();

            if (particles.Count > 1)
            {
                for (int i = 0; i < particles.Count - 1; i++)
                {
                    for (int j = i + 1; j < particles.Count; j++)
                    {
                        //Create a list of names that intersect between the 2 lists
                        List <string> conflictingNames = particles[i].ParticleNames.Intersect(particles[j].ParticleNames).ToList();

                        if (conflictingNames.Count != 0 && particles[i].FilePath != particles[j].FilePath)
                        {
                            //pc.conflictingNames = conflictingNames;
                            conflictingParticles.Add(particles[i]);
                            conflictingParticles.Add(particles[j]);
                        }
                    }
                }
            }

            //Solve conflicts
            if (conflictingParticles.Count != 0)
            {
                //Remove particle if it is in a particle conflict, add back when conflict is manually resolved
                foreach (PCF conflictParticle in conflictingParticles)
                {
                    particles.Remove(conflictParticle);
                }

                List <PCF> resolvedConflicts = new List <PCF>();

                //Bring up conflict window
                //Have to run on STAthread
                Application.Current.Dispatcher.Invoke((Action) delegate
                {
                    //Make taskbar icon red
                    ProgressManager.ErrorProgress();

                    //Create window
                    ConflictWindow cw = new ConflictWindow(conflictingParticles, map.ParticleList);
                    cw.ShowDialog();

                    //Get resolved conflicts
                    resolvedConflicts = cw.selectedPCFS;
                });

                //Add resolved conflicts back into particle list
                particles.AddRange(resolvedConflicts);
            }

            //Remove duplicates
            particles = particles.Distinct().ToList();

            //Dont create particle manifest if there is no particles
            if (particles.Count == 0)
            {
                return;
            }

            //Generate manifest file
            filepath = bspPath.Remove(bspPath.Length - 4, 4) + "_particles.txt";

            //Write manifest
            using (StreamWriter sw = new StreamWriter(filepath))
            {
                sw.WriteLine("particles_manifest");
                sw.WriteLine("{");

                foreach (string source in sourceDirectories)
                {
                    foreach (PCF particle in particles)
                    {
                        if (particle.FilePath.StartsWith(source + "\\" + internalPath))
                        {
                            // add 1 for the backslash between source dir and particle path
                            string internalParticlePath = particle.FilePath.Remove(0, source.Length + 1);

                            sw.WriteLine($"      \"file\"    \"!{internalParticlePath}\"");
                            CompilePalLogger.LogLine($"PCF added to manifest: {internalParticlePath}");
                        }
                    }
                }

                sw.WriteLine("}");
            }

            string internalDirectory = filepath;

            if (filepath.ToLower().StartsWith(baseDirectory.ToLower()))
            {
                internalDirectory = filepath.Substring(baseDirectory.Length);
            }
            //Store internal/external dir so it can be packed
            particleManifest = new KeyValuePair <string, string>(internalDirectory, filepath);
        }
Example #2
0
        //Partially reads particle to get particle name to determine if it is a target particle
        //Returns null if not target particle
        public static PCF IsTargetParticle(string filePath, List <string> targetParticles)
        {
            FileStream fs;

            try
            {
                fs = new FileStream(filePath, FileMode.Open);
            }
            catch (FileNotFoundException e)
            {
                CompilePalLogger.LogCompileError($"Could not find {filePath}\n", new Error($"Could not find {filePath}", ErrorSeverity.Error));
                return(null);
            }

            PCF          pcf    = new PCF();
            BinaryReader reader = new BinaryReader(fs);

            pcf.FilePath = filePath;

            //Get Magic String
            string magicString = ReadNullTerminatedString(fs, reader);

            //Throw away unneccesary info
            magicString = magicString.Replace("<!-- dmx encoding binary ", "");
            magicString = magicString.Replace(" -->", "");

            //Extract info from magic string
            string[] magicSplit = magicString.Split(' ');

            //Store binary and pcf versions
            Int32.TryParse(magicSplit[0], out pcf.BinaryVersion);
            Int32.TryParse(magicSplit[3], out pcf.PcfVersion);

            //Different versions have different stringDict sizes
            if (pcf.BinaryVersion != 4 && pcf.BinaryVersion != 5)
            {
                pcf.NumDictStrings = reader.ReadInt16(); //Read as short
            }
            else
            {
                pcf.NumDictStrings = reader.ReadInt32(); //Read as int
            }

            //Add strings to string dict
            for (int i = 0; i < pcf.NumDictStrings; i++)
            {
                pcf.StringDict.Add(ReadNullTerminatedString(fs, reader));
            }

            //Read element dict for particle names
            int numElements = reader.ReadInt32();

            for (int i = 0; i < numElements; i++)
            {
                int    typeNameIndex = reader.ReadUInt16();
                string typeName      = pcf.StringDict[typeNameIndex];

                string elementName = "";

                if (pcf.BinaryVersion != 4 && pcf.BinaryVersion != 5)
                {
                    elementName = ReadNullTerminatedString(fs, reader);
                    //Skip data signature
                    fs.Seek(16, SeekOrigin.Current);
                }
                else if (pcf.BinaryVersion == 4)
                {
                    int elementNameIndex = reader.ReadUInt16();
                    elementName = pcf.StringDict[elementNameIndex];
                    fs.Seek(16, SeekOrigin.Current);
                }
                else if (pcf.BinaryVersion == 5)
                {
                    int elementNameIndex = reader.ReadUInt16();
                    elementName = pcf.StringDict[elementNameIndex];
                    fs.Seek(20, SeekOrigin.Current);
                }

                //Get particle names
                if (typeName == "DmeParticleSystemDefinition")
                {
                    pcf.ParticleNames.Add(elementName);
                }
            }

            bool containsParticle = false;

            foreach (string particleName in pcf.ParticleNames)
            {
                foreach (string targetParticle in targetParticles)
                {
                    if (particleName == targetParticle)
                    {
                        containsParticle = true;
                    }
                }
            }

            //If target particle is not in pcf dont read it
            reader.Close();
            fs.Close();

            if (!containsParticle)
            {
                return(null);
            }

            return(pcf);
        }
Example #3
0
        //Fully reads particle
        public static PCF ReadParticle(string filePath)
        {
            FileStream fs;

            try
            {
                fs = new FileStream(filePath, FileMode.Open);
            }
            catch (FileNotFoundException e)
            {
                CompilePalLogger.LogCompileError($"Could not find {filePath}\n", new Error($"Could not find {filePath}", ErrorSeverity.Error));
                return(null);
            }

            PCF          pcf    = new PCF();
            BinaryReader reader = new BinaryReader(fs);

            pcf.FilePath = filePath;

            //Get Magic String
            string magicString = ReadNullTerminatedString(fs, reader);

            //Throw away unneccesary info
            magicString = magicString.Replace("<!-- dmx encoding binary ", "");
            magicString = magicString.Replace(" -->", "");

            //Extract info from magic string
            string[] magicSplit = magicString.Split(' ');

            //Store binary and pcf versions
            Int32.TryParse(magicSplit[0], out pcf.BinaryVersion);
            Int32.TryParse(magicSplit[3], out pcf.PcfVersion);

            //Different versions have different stringDict sizes
            if (pcf.BinaryVersion != 4 && pcf.BinaryVersion != 5)
            {
                pcf.NumDictStrings = reader.ReadInt16(); //Read as short
            }
            else
            {
                pcf.NumDictStrings = reader.ReadInt32(); //Read as int
            }

            //Add strings to string dict
            for (int i = 0; i < pcf.NumDictStrings; i++)
            {
                pcf.StringDict.Add(ReadNullTerminatedString(fs, reader));
            }

            //Read element dict for particle names
            int numElements = reader.ReadInt32();

            for (int i = 0; i < numElements; i++)
            {
                int    typeNameIndex = reader.ReadUInt16();
                string typeName      = pcf.StringDict[typeNameIndex];

                string elementName = "";

                if (pcf.BinaryVersion != 4 && pcf.BinaryVersion != 5)
                {
                    elementName = ReadNullTerminatedString(fs, reader);
                    //Skip data signature
                    fs.Seek(16, SeekOrigin.Current);
                }
                else if (pcf.BinaryVersion == 4)
                {
                    int elementNameIndex = reader.ReadUInt16();
                    elementName = pcf.StringDict[elementNameIndex];
                    fs.Seek(16, SeekOrigin.Current);
                }
                else if (pcf.BinaryVersion == 5)
                {
                    int elementNameIndex = reader.ReadUInt16();
                    elementName = pcf.StringDict[elementNameIndex];
                    fs.Seek(20, SeekOrigin.Current);
                }

                //Get particle names
                if (typeName == "DmeParticleSystemDefinition")
                {
                    pcf.ParticleNames.Add(elementName);
                }
            }

            if (pcf.BinaryVersion == 4 || pcf.BinaryVersion == 5)
            {
                //Can extract all neccesary data from string dict

                //Add materials and models to the master list
                List <string> materialNames = pcf.GetMaterialNamesV4();
                if (materialNames != null && materialNames.Count != 0)
                {
                    pcf.MaterialNames.AddRange(materialNames);
                }

                List <string> modelNames = pcf.GetModelNames();
                if (modelNames != null && modelNames.Count != 0)
                {
                    pcf.ModelNames.AddRange(modelNames);
                }

                reader.Close();
                fs.Close();
                return(pcf);
            }

            //Have to read element attributes to get materials for binary version under 4

            //Read Element Attributes
            for (int a = 0; a < numElements; a++)
            {
                int numElementAttribs = reader.ReadInt32();
                for (int n = 0; n < numElementAttribs; n++)
                {
                    int    typeID            = reader.ReadUInt16();
                    int    attributeType     = reader.ReadByte();
                    string attributeTypeName = pcf.StringDict[typeID];

                    int count = (attributeType > 14) ? reader.ReadInt32() : 1;
                    attributeType = (attributeType > 14) ? attributeType - 14 : attributeType;

                    int[] typelength = { 0, 4, 4, 4, 1, 1, 4, 4, 4, 8, 12, 16, 12, 16, 64 };

                    switch (attributeType)
                    {
                    case 5:
                        string material = ReadNullTerminatedString(fs, reader);
                        if (attributeTypeName == "material")
                        {
                            pcf.MaterialNames.Add("materials/" + material);
                        }
                        break;

                    case 6:
                        for (int i = 0; i < count; i++)
                        {
                            uint len = reader.ReadUInt32();
                            fs.Seek(len, SeekOrigin.Current);
                        }
                        break;

                    default:
                        fs.Seek(typelength[attributeType] * count, SeekOrigin.Current);
                        break;
                    }
                }
            }

            reader.Close();
            fs.Close();

            return(pcf);
        }