/// <summary> /// Converts an AnimSet export to an import /// </summary> /// <param name="origEntry"></param> /// <param name="targetPackage"></param> /// <returns></returns> private static IEntry ConvertAnimSetExportToImport(IEntry origEntry, IMEPackage targetPackage) { // Check if this item is available already var found = targetPackage.FindEntry(origEntry.InstancedFullPath); if (found != null) { return(found); } // Setup the link for our import var parentPackage = targetPackage.FindEntry(origEntry.Parent.InstancedFullPath); if (parentPackage == null) { // We must add a package import parentPackage = new ImportEntry(targetPackage) { idxLink = 0, ClassName = "Package", ObjectName = origEntry.Parent.ObjectName, PackageFile = "Core" }; targetPackage.AddImport((ImportEntry)parentPackage); } // Install the import ImportEntry imp = new ImportEntry(targetPackage) { ClassName = origEntry.ClassName, idxLink = parentPackage.UIndex, ObjectName = origEntry.ObjectName, PackageFile = "Engine" }; targetPackage.AddImport(imp); return(imp); }
/// <summary> /// Populates the Entry variable, locating the animsequence in the specified package /// </summary> /// <param name="exportFileRef"></param> /// <returns></returns> private bool PopulateEntry(IMEPackage exportFileRef) { if (Entry != null) { return(true); } if (GestureSetNameToPackageExportName.TryGetValue(GestureSet, out var pName)) { Entry = exportFileRef.FindEntry($"{pName}.{GestureSet}_{GestureAnim}"); return(Entry != null); } return(false); }
public bool ApplyUpdate(IMEPackage package, PropertyCollection properties, MergeFileChange1 mfc) { var propKeys = PropertyName.Split('.'); PropertyCollection operatingCollection = properties; int i = 0; while (i < propKeys.Length - 1) { var matchingProp = operatingCollection.FirstOrDefault(x => x.Name.Instanced == propKeys[i]); if (matchingProp is StructProperty sp) { operatingCollection = sp.Properties; } // ARRAY PROPERTIES NOT SUPPORTED i++; } Log.Information($@"Applying property update: {PropertyName} -> {PropertyValue}"); switch (PropertyType) { case @"FloatProperty": FloatProperty fp = new FloatProperty(float.Parse(PropertyValue, CultureInfo.InvariantCulture), propKeys.Last()); operatingCollection.AddOrReplaceProp(fp); break; case @"IntProperty": IntProperty ip = new IntProperty(int.Parse(PropertyValue), propKeys.Last()); operatingCollection.AddOrReplaceProp(ip); break; case @"BoolProperty": BoolProperty bp = new BoolProperty(bool.Parse(PropertyValue), propKeys.Last()); operatingCollection.AddOrReplaceProp(bp); break; case @"NameProperty": var index = 0; var baseName = PropertyValue; var indexIndex = PropertyValue.IndexOf(@"|", StringComparison.InvariantCultureIgnoreCase); if (indexIndex > 0) { baseName = baseName.Substring(0, indexIndex); index = int.Parse(baseName.Substring(indexIndex + 1)); } NameProperty np = new NameProperty(new NameReference(baseName, index), PropertyName); operatingCollection.AddOrReplaceProp(np); break; case @"ObjectProperty": // This does not support porting in, only relinking existing items ObjectProperty op = new ObjectProperty(0, PropertyName); if (PropertyValue != null && PropertyValue != @"M3M_NULL") //M3M_NULL is a keyword for setting it to null to satisfy the schema { var entry = package.FindEntry(PropertyValue); if (entry == null) { throw new Exception(M3L.GetString(M3L.string_interp_mergefile_failedToUpdateObjectPropertyItemNotInPackage, PropertyName, PropertyValue, PropertyValue, package.FilePath)); } op.Value = entry.UIndex; } operatingCollection.AddOrReplaceProp(op); break; case @"EnumProperty": var enumInfo = PropertyValue.Split('.'); EnumProperty ep = new EnumProperty(enumInfo[0], mfc.OwningMM.Game, PropertyName); ep.Value = NameReference.FromInstancedString(enumInfo[1]); operatingCollection.AddOrReplaceProp(ep); break; case @"StrProperty": var sp = new StrProperty(PropertyValue, propKeys.Last()); operatingCollection.AddOrReplaceProp(sp); break; default: throw new Exception(M3L.GetString(M3L.string_interp_mergefile_unsupportedPropertyType, PropertyType)); } return(true); }
/// <summary> /// Ports an export into a package. Checks if the export already exists, and if it does, returns that instead. /// </summary> /// <param name="targetPackage">The target package to port into.</param> /// <param name="sourceExport">The source export to port over, including all dependencies and references.</param> /// <param name="targetLink">The target link UIndex. Only used if createParentPackages is false.</param> /// <param name="createParentPackages">If the export should be ported in the same way as it was cooked into the package natively, e.g. create the parent package paths. The export must directly sit under a Package or an exception will be thrown.</param> /// <param name="ensureMemoryUniqueness">If this object is an instance, such as a sequence object, and should be made memory-unique so it is properly used</param> /// <returns></returns> public static ExportEntry PortExportIntoPackage(IMEPackage targetPackage, ExportEntry sourceExport, int targetLink = 0, bool createParentPackages = true, bool ensureMemoryUniqueness = false, bool useMemorySafeImport = false, PackageCache cache = null) { #if DEBUG // in preprocessor to prevent this from running in release mode if (sourceExport.FileRef.FilePath != null && targetPackage.FilePath != null) { Debug.WriteLine($"Porting {sourceExport.InstancedFullPath} from {Path.GetFileName(sourceExport.FileRef.FilePath)} into {Path.GetFileName(targetPackage.FilePath)}"); } #endif var existing = targetPackage.FindExport(sourceExport.InstancedFullPath); if (existing != null) { return(existing); } // Create parent hierarchy IEntry newParent = null; if (createParentPackages) { List <IEntry> parents = new List <IEntry>(); var parent = sourceExport.Parent; while (parent != null) { if (parent.ClassName != "Package") { throw new Exception("Parent is not package!"); } parents.Add(parent); parent = parent.Parent; } // Create the parents parents.Reverse(); foreach (var p in parents) { var sourceFullPath = p.InstancedFullPath; var matchingParent = targetPackage.FindEntry(sourceFullPath); if (matchingParent != null) { newParent = matchingParent; continue; } newParent = ExportCreator.CreatePackageExport(targetPackage, p.ObjectName, newParent); } } else { newParent = targetPackage.GetEntry(targetLink); } IEntry newEntry; if (!useMemorySafeImport) { Dictionary <IEntry, IEntry> crossPCCObjectMap = new Dictionary <IEntry, IEntry>(); // Not sure what this is used for these days. Should probably just be part of the method var relinkResults = EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, sourceExport, targetPackage, newParent, true, out newEntry, crossPCCObjectMap); if (relinkResults.Any()) { Debugger.Break(); } } else { // Memory safe, fixes upstream var relinkedResults = EntryExporter.ExportExportToPackage(sourceExport, targetPackage, out newEntry, MERFileSystem.GetGlobalCache(), cache); if (relinkedResults.Any()) { Debugger.Break(); } } #if DEBUG //(sourceExport.FileRef as MEPackage).CompareToPackageDetailed(targetPackage); #endif // Helps ensure we don't have memory duplicates if (ensureMemoryUniqueness) { newEntry.ObjectName = targetPackage.GetNextIndexedName(newEntry.ObjectName); } return(newEntry as ExportEntry); }