/// <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);
        }
Example #2
0
            /// <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);
            }
Example #3
0
        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);
        }