예제 #1
0
        public void OpenAnimSet()
        {
            SourceAnimSet = null;
            SourcePcc?.Dispose();
            SourcePcc = null;
            LiveFile?.Dispose();
            LiveFile = null;
            ActorTag = null;

            var dlg = new OpenFileDialog
            {
                Filter          = App.ME3ME2SaveFileFilter,
                CheckFileExists = true,
                Multiselect     = false,
                Title           = "Select ME3 file containing the FaceFXAnimSet you want to edit"
            };

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    SourcePcc = MEPackageHandler.OpenME3Package(dlg.FileName);
                }
                catch (FormatException)
                {
                    MessageBox.Show("Must be an ME3 file!");
                    return;
                }

                if (EntrySelector.GetEntry <ExportEntry>(null, SourcePcc, "Choose FaceFxAnimSet to edit", exp => exp.ClassName == "FaceFXAnimSet") is ExportEntry animSetEntry)
                {
                    SourceAnimSet = animSetEntry.GetBinaryData <FaceFXAnimSet>();
                }
            }
        }
예제 #2
0
        private static ExportEntry searchPackageForEntry(string packagePath, string fullPath, string className, List <IMEPackage> openedPackages)
        {
            //Debug.WriteLine("ME2/3 External Asset lookup: Checking " + packagePath);
            IMEPackage package = null;

            if (openedPackages != null)
            {
                package = openedPackages.FirstOrDefault(x => x.FilePath == packagePath);
            }
            package ??= MEPackageHandler.OpenMEPackage(packagePath);
            if (openedPackages != null && !openedPackages.Contains(package))
            {
                openedPackages.Add(package);
            }
            var foundExp = package.Exports.FirstOrDefault(exp => exp.FullPath == fullPath && exp.ClassName == className);

            if (openedPackages == null)
            {
                package.Dispose();
            }
            return(foundExp);
            //Debug.WriteLine("ME2/3 External Asset lookup: Not found, disposing " + packagePath);
        }
예제 #3
0
        internal static ExportEntry FindExternalAsset(ImportEntry entry, List <ExportEntry> alreadyLoadedPackageEntries)
        {
            //Debug.WriteLine("Finding external asset " + entry.GetFullPath);
            if (entry.Game == MEGame.ME1)
            {
                var    sourcePackageInternalPath = entry.FullPath.Substring(entry.FullPath.IndexOf('.') + 1);
                string baseName = entry.FileRef.FollowLink(entry.idxLink).Split('.')[0].ToUpper() + ".upk"; //Get package filename
                var    preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(baseName, StringComparison.InvariantCultureIgnoreCase));
                if (preloadedPackageEntry == null && MELoadedFiles.GetFilesLoadedInGame(MEGame.ME1).TryGetValue(baseName, out string packagePath))
                {
                    var package  = MEPackageHandler.OpenMEPackage(packagePath);
                    var foundExp = package.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    package.Dispose();
                }
                else
                {
                    Debug.WriteLine("ME1 External Asset lookup: Using existing preloaded export package");
                    var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                }
            }
            else
            {
                // Next, split the filename by underscores
                string filenameWithoutExtension = Path.GetFileNameWithoutExtension(entry.FileRef.FilePath).ToLower();
                string containingDirectory      = Path.GetDirectoryName(entry.FileRef.FilePath);
                var    packagesToCheck          = new List <string>();
                var    gameFiles = MELoadedFiles.GetFilesLoadedInGame(entry.Game);

                if (filenameWithoutExtension.StartsWith("bioa_") || filenameWithoutExtension.StartsWith("biod_"))
                {
                    string[] parts = filenameWithoutExtension.Split('_');
                    if (parts.Length >= 2) //BioA_Nor_WowThatsAlot310.pcc
                    {
                        string bioad    = $"{parts[0]}_{parts[1]}.pcc";
                        string filename = Path.Combine(containingDirectory, bioad); //BioA_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }

                        string biop = $"BioP_{parts[1]}.pcc";
                        filename = Path.Combine(containingDirectory, biop); //BioP_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }
                    }
                }

                foreach (string packagePath in packagesToCheck)
                {
                    var preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(packagePath, StringComparison.InvariantCultureIgnoreCase));
                    if (preloadedPackageEntry == null)
                    {
                        Debug.WriteLine("ME2/3 External Asset lookup: Checking " + packagePath);
                        var package  = MEPackageHandler.OpenMEPackage(packagePath);
                        var foundExp = package.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                        if (foundExp != null)
                        {
                            return(foundExp);
                        }
                        //Debug.WriteLine("ME2/3 External Asset lookup: Not found, disposing " + packagePath);
                        package.Dispose();
                    }
                    else
                    {
                        Debug.WriteLine("ME2/3 External Asset lookup: Using existing preloaded export package");
                        var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                        if (foundExp != null)
                        {
                            return(foundExp);
                        }
                    }
                }

                //Check SFXGame
                string sfxgamePath = Path.Combine(MEDirectories.CookedPath(entry.Game), "SFXGame.pcc");
                if (File.Exists(sfxgamePath))
                {
                    //This is not in using statement as we have to keep this in memory.
                    IMEPackage pcc      = MEPackageHandler.OpenMEPackage(sfxgamePath);
                    var        foundExp = pcc.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    //Debug.WriteLine("ME2/3 External Asset lookup: Not SFXGame, disposing");

                    pcc.Dispose(); //Dump from memory
                }

                //Check EntryMenu
                string entryMenuPath = Path.Combine(MEDirectories.CookedPath(entry.Game), "EntryMenu.pcc");
                if (File.Exists(entryMenuPath))
                {
                    //This is not in using statement as we have to keep this in memory.
                    IMEPackage pcc      = MEPackageHandler.OpenMEPackage(entryMenuPath);
                    var        foundExp = pcc.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    //Debug.WriteLine("ME2/3 External Asset lookup: Not EntryMenu, disposing");

                    pcc.Dispose(); //Dump from memory
                }

                //Check Startup
                string startupPath = Path.Combine(MEDirectories.CookedPath(entry.Game), "Startup.pcc");
                if (File.Exists(startupPath))
                {
                    //This is not in using statement as we have to keep this in memory.
                    IMEPackage pcc      = MEPackageHandler.OpenMEPackage(startupPath);
                    var        foundExp = pcc.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    //Debug.WriteLine("ME2/3 External Asset lookup: Not Startup, disposing");
                    pcc.Dispose(); //Dump from memory
                }
            }
            Debug.WriteLine("Could not find external asset: " + entry.FullPath);
            return(null);
        }
예제 #4
0
        /// <summary>
        /// Copy ME2 Static art and collision into an ME3 file.
        /// By Kinkojiro
        /// </summary>
        /// <param name="Game">Target Game</param>
        /// <param name="BioPSource">Source BioP</param>
        /// <param name="tgtOutputfolder">OutputFolder</param>
        /// <param name="BioArtsToCopy">List of level source file locations</param>
        /// <param name="ActorsToMove">Dicitionary: key Actors, value filename, entry uid</param>
        /// <param name="AssetsToMove">Dictionary key: AssetInstancedPath, value filename, isimport, entry uid</param>
        /// <param name="fromreload">is reloaded json</param>
        public static async Task <List <string> > ConvertLevelToGame(MEGame Game, IMEPackage BioPSource, string tgtOutputfolder, string tgttfc, Action <string> callbackAction, LevelConversionData conversionData = null, bool fromreload = false, bool createtestlevel = false)
        {
            //VARIABLES / VALIDATION
            var actorclassesToMove = new List <string>()
            {
                "BlockingVolume", "SpotLight", "SpotLightToggleable", "PointLight", "PointLightToggleable", "SkyLight", "HeightFog", "LenseFlareSource", "StaticMeshActor", "BioTriggerStream", "BioBlockingVolume"
            };
            var actorclassesToSubstitute = new Dictionary <string, string>()
            {
                { "BioBlockingVolume", "Engine.BlockingVolume" }
            };
            var archetypesToSubstitute = new Dictionary <string, string>()
            {
                { "Default__BioBlockingVolume", "Default__BlockingVolume" }
            };
            var    fails    = new List <string>();
            string busytext = null;

            if ((BioPSource.Game == MEGame.ME2 && ME2Directory.DefaultGamePath == null) || (BioPSource.Game == MEGame.ME1 && ME1Directory.DefaultGamePath == null) || (BioPSource.Game == MEGame.ME3 && ME3Directory.DefaultGamePath == null) || BioPSource.Game == MEGame.UDK)
            {
                fails.Add("Source Game Directory not found");
                return(fails);
            }

            //Get filelist from BioP, Save a copy in outputdirectory, Collate Actors and asset information
            if (!fromreload)
            {
                busytext = "Collating level files...";
                callbackAction?.Invoke(busytext);
                conversionData = new LevelConversionData(Game, BioPSource.Game, null, null, null, new ConcurrentDictionary <string, string>(), new ConcurrentDictionary <string, (string, int)>(), new ConcurrentDictionary <string, (string, int, List <string>)>());
                var supportedExtensions = new List <string> {
                    ".pcc", ".u", ".upk", ".sfm"
                };
                if (Path.GetFileName(BioPSource.FilePath).ToLowerInvariant().StartsWith("biop_") && BioPSource.Exports.FirstOrDefault(x => x.ClassName == "BioWorldInfo") is ExportEntry BioWorld)
                {
                    string biopname = Path.GetFileNameWithoutExtension(BioPSource.FilePath);
                    conversionData.GameLevelName = biopname.Substring(5, biopname.Length - 5);
                    var lsks = BioWorld.GetProperty <ArrayProperty <ObjectProperty> >("StreamingLevels").ToList();
                    if (lsks.IsEmpty())
                    {
                        fails.Add("No files found in level.");
                        return(fails);
                    }
                    foreach (var l in lsks)
                    {
                        var lskexp   = BioPSource.GetUExport(l.Value);
                        var filename = lskexp.GetProperty <NameProperty>("PackageName");
                        if ((filename?.Value.ToString().ToLowerInvariant().StartsWith("bioa") ?? false) || (filename?.Value.ToString().ToLowerInvariant().StartsWith("biod") ?? false))
                        {
                            var filePath = Directory.GetFiles(ME2Directory.DefaultGamePath, $"{filename.Value.Instanced}.pcc", SearchOption.AllDirectories).FirstOrDefault();
                            conversionData.FilesToCopy.TryAdd(filename.Value.Instanced, filePath);
                        }
                    }
                    conversionData.BioPSource = $"{biopname}_{BioPSource.Game}";
                    BioPSource.Save(Path.Combine(tgtOutputfolder, $"{conversionData.BioPSource}.pcc"));
                    BioPSource.Dispose();
                }
                else
                {
                    fails.Add("Requires an BioP to work with.");
                    return(fails);
                }

                busytext = "Collating actors and assets...";
                callbackAction?.Invoke(busytext);
                Parallel.ForEach(conversionData.FilesToCopy, (pccref) =>
                {
                    using IMEPackage pcc = MEPackageHandler.OpenMEPackage(pccref.Value);
                    var sourcelevel      = pcc.Exports.FirstOrDefault(l => l.ClassName == "Level");
                    if (ObjectBinary.From(sourcelevel) is Level levelbin)
                    {
                        foreach (var act in levelbin.Actors)
                        {
                            if (act < 1)
                            {
                                continue;
                            }
                            var actor = pcc.GetUExport(act);
                            if (actorclassesToMove.Contains(actor.ClassName))
                            {
                                conversionData.ActorsToMove.TryAdd($"{pccref.Key}.{actor.InstancedFullPath}", (pccref.Key, act));
                                HashSet <int> actorrefs = pcc.GetReferencedEntries(true, true, actor);
                                foreach (var r in actorrefs)
                                {
                                    var objref = pcc.GetEntry(r);
                                    if (objref != null)
                                    {
                                        if (objref.InstancedFullPath.Contains("PersistentLevel"))  //remove components of actors
                                        {
                                            continue;
                                        }
                                        string instancedPath = objref.InstancedFullPath;
                                        if (objref.idxLink == 0)
                                        {
                                            instancedPath = $"{pccref.Key}.{instancedPath}";
                                        }
                                        var added = conversionData.AssetsToMove.TryAdd(instancedPath, (pccref.Key, r, new List <string>()
                                        {
                                            pccref.Key
                                        }));
                                        if (!added)
                                        {
                                            conversionData.AssetsToMove[instancedPath].Item3.FindOrAdd(pccref.Key);
                                            if (r > 0 && conversionData.AssetsToMove[instancedPath].Item2 < 0) //Replace  imports with exports if possible
                                            {
                                                var currentlist = conversionData.AssetsToMove[instancedPath].Item3;
                                                conversionData.AssetsToMove[instancedPath] = (pccref.Key, r, currentlist);
                                            }
                                        }