public static bool PerformRandomization(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information($"{export.FileRef.FilePath}\t{export.FullPath}");
            var props = export.GetProperties();

            if (export.ClassName == "BioSunFlareComponent" || export.ClassName == "BioSunFlareStreakComponent")
            {
                var tint = props.GetProp <StructProperty>("FlareTint");
                if (tint != null)
                {
                    RStructs.RandomizeTint(tint, false);
                }
                RProperty.RandFloat(props, "Intensity", 0.0001f, 100f, false);
                RProperty.RandFloat(props, "BrightPercent", 0.0001f, 0.1f, false);
                RProperty.RandFloat(props, "Scale", 0.05f, 3f, false);
            }
            else if (export.ClassName == "BioSunActor")
            {
                var tint = props.GetProp <StructProperty>("SunTint");
                if (tint != null)
                {
                    RStructs.RandomizeTint(tint, false);
                }
            }

            export.WriteProperties(props);
            return(true);
        }
Example #2
0
        public static void RemoveAllLinks(ExportEntry export)
        {
            var props        = export.GetProperties();
            var outLinksProp = props.GetProp <ArrayProperty <StructProperty> >("OutputLinks");

            if (outLinksProp != null)
            {
                foreach (var prop in outLinksProp)
                {
                    prop.GetProp <ArrayProperty <StructProperty> >("Links").Clear();
                }
            }

            var varLinksProp = props.GetProp <ArrayProperty <StructProperty> >("VariableLinks");

            if (varLinksProp != null)
            {
                foreach (var prop in varLinksProp)
                {
                    prop.GetProp <ArrayProperty <ObjectProperty> >("LinkedVariables").Clear();
                }
            }

            var eventLinksProp = props.GetProp <ArrayProperty <StructProperty> >("EventLinks");

            if (eventLinksProp != null)
            {
                foreach (var prop in eventLinksProp)
                {
                    prop.GetProp <ArrayProperty <ObjectProperty> >("LinkedEvents").Clear();
                }
            }

            export.WriteProperties(props);
        }
Example #3
0
        /// <summary>
        /// Sets the reach spec size and commits the results back to the export
        /// </summary>
        /// <param name="spec"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        public static void SetReachSpecSize(ExportEntry spec, int radius, int height)
        {
            PropertyCollection specProperties = spec.GetProperties();

            SetReachSpecSize(specProperties, radius, height);
            spec.WriteProperties(specProperties); //write it back.
        }
Example #4
0
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            var properties = export.GetProperties();
            var lightColor = properties.GetProp <StructProperty>("LightColor");

            if (lightColor != null)
            {
                lightColor.GetProp <ByteProperty>("R").Value = (byte)ThreadSafeRandom.Next(256);
                lightColor.GetProp <ByteProperty>("G").Value = (byte)ThreadSafeRandom.Next(256);
                lightColor.GetProp <ByteProperty>("B").Value = (byte)ThreadSafeRandom.Next(256);

                var density = properties.GetProp <FloatProperty>("Density");
                if (density != null)
                {
                    var thicknessRandomizer = ThreadSafeRandom.NextFloat(-density * .03, density * 1.15);
                    density.Value = density + thicknessRandomizer;
                }

                //Debug.WriteLine($"Updating fog {export.InstancedFullPath} in {export.FileRef.FilePath}");
                export.WriteProperties(properties);
                return(true);
            }
            return(false);
        }
        public static bool RandomizeExport(ExportEntry exp, RandomizationOption option)
        {
            if (!CanRandomize(exp))
            {
                return(false);
            }
            var props = exp.GetProperties();

            var navs = props.GetProp <ArrayProperty <StructProperty> >("NavList").Select(x => x.Properties.GetProp <ObjectProperty>("Nav")).ToList();

            var destNavs = exp.FileRef.Exports.Where(x => x.IsA("NavigationPoint")).ToList();

            destNavs.Shuffle();
            foreach (var n in navs)
            {
                n.Value = destNavs[0].UIndex;
                destNavs.RemoveAt(0);
            }

            //foreach (var nav in navs)
            //{
            //    var entry = nav.ResolveToEntry(exp.FileRef) as ExportEntry;
            //}

            exp.WriteProperties(props);
            return(true);
        }
        /// <summary>
        /// Changes a single output link to a new target and commits the properties.
        /// </summary>
        /// <param name="export">Export to operate on</param>
        /// <param name="outputLinkIndex">The index of the item in 'OutputLinks'</param>
        /// <param name="linksIndex">The index of the item in the Links array</param>
        /// <param name="newTarget">The UIndex of the new target</param>
        public static void ChangeOutlink(ExportEntry export, int outputLinkIndex, int linksIndex, int newTarget)
        {
            var props = export.GetProperties();

            ChangeOutlink(props, outputLinkIndex, linksIndex, newTarget);
            export.WriteProperties(props);
        }
Example #7
0
        public void SaveChanges()
        {
            Export.WriteProperties(Props);
            MemoryStream m = new MemoryStream();

            m.WriteInt32(CompressedBlob.Length);
            m.WriteFromBuffer(CompressedBlob);
            Export.setBinaryData(m.ToArray());
        }
Example #8
0
        public static void WriteDefaultPose(ExportEntry export, Gesture newPose)
        {
            var props = export.GetProperties();

            props.AddOrReplaceProp(new NameProperty(newPose.GestureSet, "nmStartingPoseSet"));
            props.AddOrReplaceProp(new NameProperty(newPose.GestureAnim, "nmStartingPoseAnim"));
            export.WriteProperties(props);
            ExportEntry owningSeq = null;

            InstallDynamicAnimSetRefForSeq(ref owningSeq, export, newPose);
        }
        public static bool RandomizeExport(ExportEntry material, RandomizationOption option)
        {
            if (!CanRandomize(material))
            {
                return(false);
            }
            var props = material.GetProperties();

            {
                var vectors = props.GetProp <ArrayProperty <StructProperty> >("VectorParameterValues");
                if (vectors != null)
                {
                    foreach (var vector in vectors)
                    {
                        var pc = vector.GetProp <StructProperty>("ParameterValue");
                        if (pc != null)
                        {
                            RStructs.RandomizeTint(pc, false);
                        }
                    }
                }

                var scalars = props.GetProp <ArrayProperty <StructProperty> >("ScalarParameterValues");
                if (scalars != null)
                {
                    for (int i = 0; i < scalars.Count; i++)
                    {
                        var scalar       = scalars[i];
                        var parameter    = scalar.GetProp <NameProperty>("ParameterName");
                        var currentValue = scalar.GetProp <FloatProperty>("ParameterValue");
                        if (currentValue > 1)
                        {
                            scalar.GetProp <FloatProperty>("ParameterValue").Value = ThreadSafeRandom.NextFloat(0, currentValue * 1.3);
                        }
                        else
                        {
                            //Debug.WriteLine("Randomizing parameter " + scalar.GetProp<NameProperty>("ParameterName"));
                            scalar.GetProp <FloatProperty>("ParameterValue").Value = ThreadSafeRandom.NextFloat(0, 1);
                        }
                    }

                    //foreach (var scalar in vectors)
                    //{
                    //    var paramValue = vector.GetProp<StructProperty>("ParameterValue");
                    //    RandomizeTint( paramValue, false);
                    //}
                }
            }
            material.WriteProperties(props);
            return(true);
        }
Example #10
0
        private static void SlightlyRandomizeMovementData(ExportEntry export)
        {
            var props = export.GetProperties();

            foreach (var prop in props)
            {
                if (prop is FloatProperty fp)
                {
                    // We try to make sure it weights more towards faster not slower
                    fp.Value = ThreadSafeRandom.NextFloat(fp.Value - (fp * .35), fp.Value + (fp * .75));
                }
            }
            export.WriteProperties(props);
        }
Example #11
0
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            PropertyCollection props = export.GetProperties();
            var colorOverrides       = props.GetProp <ArrayProperty <StructProperty> >("m_aColorOverrides");

            if (colorOverrides != null)
            {
                foreach (StructProperty colorParameter in colorOverrides)
                {
                    //Debug.WriteLine("Randomizing Color Parameter");
                    RStructs.RandomizeTint(colorParameter.GetProp <StructProperty>("cValue"), false);
                }
            }
            var scalarOverrides = props.GetProp <ArrayProperty <StructProperty> >("m_aScalarOverrides");

            if (scalarOverrides != null)
            {
                foreach (StructProperty scalarParameter in scalarOverrides)
                {
                    var name = scalarParameter.GetProp <NameProperty>("nName");
                    if (name != null)
                    {
                        if (name.Value.Name.Contains("_Frek_") || name.Value.Name.StartsWith("HAIR") || name.Value.Name.StartsWith("HED_Scar"))
                        {
                            var currentValue = scalarParameter.GetProp <FloatProperty>("sValue");
                            if (currentValue != null)
                            {
                                //Debug.WriteLine("Randomizing FREK HAIR HEDSCAR");

                                if (currentValue > 1)
                                {
                                    scalarParameter.GetProp <FloatProperty>("sValue").Value = ThreadSafeRandom.NextFloat(0, currentValue * 1.3);
                                }
                                else
                                {
                                    scalarParameter.GetProp <FloatProperty>("sValue").Value = ThreadSafeRandom.NextFloat(0, 1);
                                }
                            }
                        }
                    }
                }
            }
            export.WriteProperties(props);
            return(true);
        }
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            var props = export.GetProperties();

            if (export.ObjectName.Name.Contains("SFXPower"))
            {
                props.AddOrReplaceProp(new BoolProperty(true, "bCustomDroneColor"));
                props.AddOrReplaceProp(new BoolProperty(true, "bCustomDroneColor2"));
            }
            else
            {
                //sfxpawn
                props.AddOrReplaceProp(new BoolProperty(true, "bCustomColor"));
                props.AddOrReplaceProp(new BoolProperty(true, "bCustomColor2"));
            }

            PropertyCollection randColors = new PropertyCollection();

            randColors.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 60), "X"));
            randColors.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 60), "Y"));
            randColors.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 60), "Z"));

            PropertyCollection randColors2 = new PropertyCollection();

            randColors2.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 128), "X"));
            randColors2.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 128), "Y"));
            randColors2.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, 128), "Z"));

            if (export.ObjectName.Name.Contains("SFXPower"))
            {
                props.AddOrReplaceProp(new StructProperty("Vector", randColors, "CustomDroneColor", true));
                props.AddOrReplaceProp(new StructProperty("Vector", randColors2, "CustomDroneColor2", true));
            }
            else
            {
                //sfxpawn
                props.AddOrReplaceProp(new StructProperty("Vector", randColors, "DroneColor", true));
                props.AddOrReplaceProp(new StructProperty("Vector", randColors2, "DroneColor2", true));
            }

            export.WriteProperties(props);
            return(true);
        }
Example #13
0
        public static void AddObjectToSequence(ExportEntry newObject, ExportEntry sequenceExport, bool removeLinks = false)
        {
            ArrayProperty <ObjectProperty> seqObjs = sequenceExport.GetProperty <ArrayProperty <ObjectProperty> >("SequenceObjects") ?? new ArrayProperty <ObjectProperty>("SequenceObjects");

            seqObjs.Add(new ObjectProperty(newObject));
            sequenceExport.WriteProperty(seqObjs);

            PropertyCollection newObjectProps = newObject.GetProperties();

            newObjectProps.AddOrReplaceProp(new ObjectProperty(sequenceExport, "ParentSequence"));
            newObject.WriteProperties(newObjectProps);
            if (removeLinks)
            {
                RemoveAllLinks(newObject);
            }
            newObject.Parent = sequenceExport;
        }
Example #14
0
        public static bool RandomizeExport(ExportEntry exp, RandomizationOption option)
        {
            if (!CanRandomize(exp))
            {
                return(false);
            }
            MERLog.Information($"Randomizing illusive eye color in {exp.FileRef.FilePath}");
            var props = exp.GetProperties();

            //eye color
            var emisVector = props.GetProp <ArrayProperty <StructProperty> >("VectorParameterValues").First(x => x.GetProp <NameProperty>("ParameterName").Value.Name == "Emis_Color").GetProp <StructProperty>("ParameterValue");

            //tint is float based
            RStructs.RandomizeTint(emisVector, false);

            var emisScalar = props.GetProp <ArrayProperty <StructProperty> >("ScalarParameterValues").First(x => x.GetProp <NameProperty>("ParameterName").Value.Name == "Emis_Scalar").GetProp <FloatProperty>("ParameterValue");

            emisScalar.Value = 3; //very vibrant
            exp.WriteProperties(props);
            return(true);
        }
        /// <summary>
        /// Randomizes the export. Does not check CanRandomize()
        /// </summary>
        /// <param name="export"></param>
        /// <param name="option"></param>
        private static void RandomizeInternal(ExportEntry export, RandomizationOption option)
        {
            var props = export.GetProperties();
            ArrayProperty <StructProperty> m_aMorphFeatures = props.GetProp <ArrayProperty <StructProperty> >("m_aMorphFeatures");

            if (m_aMorphFeatures != null)
            {
                foreach (StructProperty morphFeature in m_aMorphFeatures)
                {
                    FloatProperty offset = morphFeature.GetProp <FloatProperty>("Offset");
                    if (offset != null)
                    {
                        //Debug.WriteLine("Randomizing morph face " + Path.GetFilePath(export.FileRef.FilePath) + " " + export.UIndex + " " + export.FullPath + " offset");
                        offset.Value = offset.Value * ThreadSafeRandom.NextFloat(1 - (option.SliderValue / 3), 1 + (option.SliderValue / 3));
                    }
                }
            }

            ArrayProperty <StructProperty> m_aFinalSkeleton = props.GetProp <ArrayProperty <StructProperty> >("m_aFinalSkeleton");

            if (m_aFinalSkeleton != null)
            {
                foreach (StructProperty offsetBonePos in m_aFinalSkeleton)
                {
                    StructProperty vPos = offsetBonePos.GetProp <StructProperty>("vPos");
                    if (vPos != null)
                    {
                        //Debug.WriteLine("Randomizing morph face " + Path.GetFilePath(export.FileRef.FilePath) + " " + export.UIndex + " " + export.FullPath + " vPos");
                        FloatProperty x = vPos.GetProp <FloatProperty>("X");
                        FloatProperty y = vPos.GetProp <FloatProperty>("Y");
                        FloatProperty z = vPos.GetProp <FloatProperty>("Z");
                        x.Value = x.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                        y.Value = y.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                        z.Value = z.Value * ThreadSafeRandom.NextFloat(1 - (option.SliderValue / .85), 1 + (option.SliderValue / .85));
                    }
                }
            }

            export.WriteProperties(props);
        }
        private static void randomizeFrontEnd(ExportEntry frontEnd)
        {
            var props = frontEnd.GetProperties();

            //read categories
            var morphCategories = props.GetProp <ArrayProperty <StructProperty> >("MorphCategories");
            var sliders         = new Dictionary <string, StructProperty>();

            foreach (var cat in morphCategories)
            {
                var catSliders = cat.GetProp <ArrayProperty <StructProperty> >("m_aoSliders");
                foreach (var cSlider in catSliders)
                {
                    var name = cSlider.GetProp <StrProperty>("m_sName");
                    sliders[name.Value] = cSlider;
                }
            }

            //Default Settings
            var defaultSettings = props.GetProp <ArrayProperty <StructProperty> >("m_aDefaultSettings");

            foreach (var basehead in defaultSettings)
            {
                randomizeBaseHead(basehead, frontEnd, sliders);
            }

            //randomize base heads ?
            var baseHeads = props.GetProp <ArrayProperty <StructProperty> >("m_aBaseHeads");

            foreach (var basehead in baseHeads)
            {
                randomizeBaseHead(basehead, frontEnd, sliders);
            }


            frontEnd.WriteProperties(props);
        }
Example #17
0
        public static void CreateCurveFromSavedCams(ExportEntry export)
        {
            POV[] cams = ReadSavedCamsFile();

            var props       = export.GetProperties();
            var posTrack    = props.GetProp <StructProperty>("PosTrack").GetProp <ArrayProperty <StructProperty> >("Points");
            var rotTrack    = props.GetProp <StructProperty>("EulerTrack").GetProp <ArrayProperty <StructProperty> >("Points");
            var lookupTrack = props.GetProp <StructProperty>("LookupTrack").GetProp <ArrayProperty <StructProperty> >("Points");

            posTrack.Clear();
            rotTrack.Clear();


            for (int i = 0; i < cams.Length; i++)
            {
                POV cam = cams[i];
                if (cam.IsZero)
                {
                    break;
                }

                posTrack.Add(new InterpCurvePoint <Vector3>
                {
                    InVal      = i * 2,
                    OutVal     = cam.Position,
                    InterpMode = EInterpCurveMode.CIM_CurveUser
                }.ToStructProperty(MEGame.ME3));
                rotTrack.Add(new InterpCurvePoint <Vector3>
                {
                    InVal      = i * 2,
                    OutVal     = cam.Rotation,
                    InterpMode = EInterpCurveMode.CIM_CurveUser
                }.ToStructProperty(MEGame.ME3));
                lookupTrack.Add(new StructProperty("InterpLookupPoint", false, new NameProperty("None", "GroupName"), new FloatProperty(0, "Time")));
            }
            export.WriteProperties(props);
        }
Example #18
0
        public static List <string> Relink(ExportEntry sourceExport, ExportEntry relinkingExport, OrderedMultiValueDictionary <IEntry, IEntry> crossPCCObjectMappingList, bool importExportDependencies = false)
        {
            var        relinkFailedReport = new List <string>();
            IMEPackage sourcePcc          = sourceExport.FileRef;

            //Relink stack
            if (relinkingExport.HasStack)
            {
                byte[] stack = relinkingExport.GetStack();

                int    uIndex       = BitConverter.ToInt32(stack, 0);
                string relinkResult = relinkUIndex(sourceExport.FileRef, relinkingExport, ref uIndex, "Stack: Node",
                                                   crossPCCObjectMappingList, "", importExportDependencies);
                if (relinkResult is null)
                {
                    stack.OverwriteRange(0, BitConverter.GetBytes(uIndex));
                }
                else
                {
                    relinkFailedReport.Add(relinkResult);
                }

                uIndex       = BitConverter.ToInt32(stack, 4);
                relinkResult = relinkUIndex(sourceExport.FileRef, relinkingExport, ref uIndex, "Stack: StateNode",
                                            crossPCCObjectMappingList, "", importExportDependencies);
                if (relinkResult is null)
                {
                    stack.OverwriteRange(4, BitConverter.GetBytes(uIndex));
                }
                else
                {
                    relinkFailedReport.Add(relinkResult);
                }

                relinkingExport.SetStack(stack);
            }

            //Relink Properties
            PropertyCollection transplantProps = sourceExport.GetProperties();

            relinkFailedReport.AddRange(relinkPropertiesRecursive(sourcePcc, relinkingExport, transplantProps, crossPCCObjectMappingList, "", importExportDependencies));
            relinkingExport.WriteProperties(transplantProps);

            //Relink Binary
            try
            {
                if (relinkingExport.Game != sourcePcc.Game && (relinkingExport.IsClass || relinkingExport.ClassName == "State" || relinkingExport.ClassName == "Function"))
                {
                    relinkFailedReport.Add($"{relinkingExport.UIndex} {relinkingExport.FullPath} binary relinking failed. Cannot port {relinkingExport.ClassName} between games!");
                    return(relinkFailedReport);
                }

                if (ObjectBinary.From(relinkingExport) is ObjectBinary objBin)
                {
                    List <(UIndex, string)> indices = objBin.GetUIndexes(relinkingExport.FileRef.Game);

                    foreach ((UIndex uIndex, string propName) in indices)
                    {
                        string result = relinkUIndex(sourcePcc, relinkingExport, ref uIndex.value, $"(Binary Property: {propName})", crossPCCObjectMappingList, "",
                                                     importExportDependencies);
                        if (result != null)
                        {
                            relinkFailedReport.Add(result);
                        }
                    }

                    //UStruct is abstract baseclass for Class, State, and Function, and can have script in it
                    if (objBin is UStruct uStructBinary && uStructBinary.ScriptBytes.Length > 0)
                    {
                        if (relinkingExport.Game == MEGame.ME3)
                        {
                            (List <Token> tokens, _) = Bytecode.ParseBytecode(uStructBinary.ScriptBytes, sourceExport);
                            foreach (Token token in tokens)
                            {
                                relinkFailedReport.AddRange(RelinkToken(token, uStructBinary.ScriptBytes, sourceExport, relinkingExport, crossPCCObjectMappingList,
                                                                        importExportDependencies));
                            }
                        }
                        else
                        {
                            relinkFailedReport.Add($"{relinkingExport.UIndex} {relinkingExport.FullPath} binary relinking failed. {relinkingExport.ClassName} contains script, " +
                                                   $"which cannot be relinked for {relinkingExport.Game}");
                        }
                    }

                    relinkingExport.setBinaryData(objBin.ToBytes(relinkingExport.FileRef, relinkingExport.DataOffset + relinkingExport.propsEnd()));
                    return(relinkFailedReport);
                }

                byte[] binarydata = relinkingExport.getBinaryData();

                if (binarydata.Length > 0)
                {
                    switch (relinkingExport.ClassName)
                    {
                    //todo: make a WwiseEvent ObjectBinary class
                    case "WwiseEvent":
                    {
                        void relinkAtPosition(int binaryPosition, string propertyName)
                        {
                            int    uIndex       = BitConverter.ToInt32(binarydata, binaryPosition);
                            string relinkResult = relinkUIndex(sourcePcc, relinkingExport, ref uIndex, propertyName,
                                                               crossPCCObjectMappingList, "", importExportDependencies);

                            if (relinkResult is null)
                            {
                                binarydata.OverwriteRange(binaryPosition, BitConverter.GetBytes(uIndex));
                            }
                            else
                            {
                                relinkFailedReport.Add(relinkResult);
                            }
                        }

                        if (relinkingExport.FileRef.Game == MEGame.ME3)
                        {
                            int count = BitConverter.ToInt32(binarydata, 0);
                            for (int j = 0; j < count; j++)
                            {
                                relinkAtPosition(4 + (j * 4), $"(Binary Property: WwiseStreams[{j}])");
                            }

                            relinkingExport.setBinaryData(binarydata);
                        }
                        else if (relinkingExport.FileRef.Game == MEGame.ME2)
                        {
                            int parsingPos = 4;
                            int linkCount  = BitConverter.ToInt32(binarydata, parsingPos);
                            parsingPos += 4;
                            for (int j = 0; j < linkCount; j++)
                            {
                                int bankcount = BitConverter.ToInt32(binarydata, parsingPos);
                                parsingPos += 4;
                                for (int k = 0; k < bankcount; k++)
                                {
                                    relinkAtPosition(parsingPos, $"(Binary Property: link[{j}].WwiseBanks[{k}])");

                                    parsingPos += 4;
                                }

                                int wwisestreamcount = BitConverter.ToInt32(binarydata, parsingPos);
                                parsingPos += 4;
                                for (int k = 0; k < wwisestreamcount; k++)
                                {
                                    relinkAtPosition(parsingPos, $"(Binary Property: link[{j}].WwiseStreams[{k}])");

                                    parsingPos += 4;
                                }
                            }

                            relinkingExport.setBinaryData(binarydata);
                        }
                    }
                    break;

                    case "DominantDirectionalLightComponent":
                    case "SphericalHarmonicLightComponent":
                    case "DominantPointLightComponent":
                    case "StaticLightCollectionActor":
                    case "DominantSpotLightComponent":
                    case "DirectionalLightComponent":
                    case "StaticMeshCollectionActor":
                    case "TerrainWeightMapTexture":
                    case "PhysicsAssetInstance":
                    case "PointLightComponent":
                    case "ShadowMapTexture2D":
                    case "SpotLightComponent":
                    case "LightMapTexture2D":
                    case "SkyLightComponent":
                    case "TextureFlipBook":
                    case "BrushComponent":
                    case "FaceFXAnimSet":
                    case "TextureMovie":
                    case "AnimSequence":
                    case "RB_BodySetup":
                    case "MorphTarget":
                    case "ShadowMap1D":
                    case "WwiseStream":
                    case "WwiseBank":
                    case "Texture2D":
                        //these classes have binary but do not need relinking
                        break;

                    default:
                        if (binarydata.Any(b => b != 0))
                        {
                            relinkFailedReport.Add($"{relinkingExport.UIndex} {relinkingExport.FullPath} has unparsed binary. " +
                                                   $"This binary may contain items that need to be relinked. Come to the Discord server " +
                                                   $"(click ME3Tweaks logo in main window for invite) and ask devs to parse this class.");
                        }

                        break;
                    }
                }
            }
            catch (Exception e) when(!App.IsDebug)
            {
                relinkFailedReport.Add($"{relinkingExport.UIndex} {relinkingExport.FullPath} binary relinking failed due to exception: {e.Message}");
            }

            return(relinkFailedReport);
        }
Example #19
0
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information($"[{Path.GetFileNameWithoutExtension(export.FileRef.FilePath)}] Randomizing movement interpolations for " + export.UIndex + ": " + export.InstancedFullPath);
            var props    = export.GetProperties();
            var posTrack = props.GetProp <StructProperty>("PosTrack");

            if (posTrack != null)
            {
                var points = posTrack.GetProp <ArrayProperty <StructProperty> >("Points");
                if (points != null)
                {
                    foreach (StructProperty s in points)
                    {
                        var outVal = s.GetProp <StructProperty>("OutVal");
                        if (outVal != null)
                        {
                            FloatProperty x = outVal.GetProp <FloatProperty>("X");
                            FloatProperty y = outVal.GetProp <FloatProperty>("Y");
                            FloatProperty z = outVal.GetProp <FloatProperty>("Z");
                            x.Value = x.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            y.Value = y.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            z.Value = z.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                        }
                    }
                }
            }

            var eulerTrack = props.GetProp <StructProperty>("EulerTrack");

            if (eulerTrack != null)
            {
                var points = eulerTrack.GetProp <ArrayProperty <StructProperty> >("Points");
                if (points != null)
                {
                    foreach (StructProperty s in points)
                    {
                        var outVal = s.GetProp <StructProperty>("OutVal");
                        if (outVal != null)
                        {
                            FloatProperty x = outVal.GetProp <FloatProperty>("X");
                            FloatProperty y = outVal.GetProp <FloatProperty>("Y");
                            FloatProperty z = outVal.GetProp <FloatProperty>("Z");
                            if (x.Value != 0)
                            {
                                x.Value = x.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                x.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }

                            if (y.Value != 0)
                            {
                                y.Value = y.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                y.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }

                            if (z.Value != 0)
                            {
                                z.Value = z.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                z.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }
                        }
                    }
                }
            }

            export.WriteProperties(props);
            return(true);
        }
Example #20
0
        public static void CreateReachSpec(ExportEntry startNode, bool createTwoWay, ExportEntry destinationNode, string reachSpecClass, ReachSpecSize size, PropertyCollection externalGUIDProperties = null)
        {
            IMEPackage  Pcc = startNode.FileRef;
            ExportEntry reachSpectoClone = Pcc.Exports.FirstOrDefault(x => x.ClassName == "ReachSpec");

            if (externalGUIDProperties != null) //EXTERNAL
            {
                //external node

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var            properties            = outgoingSpec.GetProperties();
                    ObjectProperty outgoingSpecStartProp = properties.GetProp <ObjectProperty>("Start");                                                                   //START
                    StructProperty outgoingEndStructProp = properties.GetProp <StructProperty>("End");                                                                     //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = 0;
                    var endGuid = outgoingEndStructProp.GetProp <StructProperty>("Guid");
                    endGuid.Properties = externalGUIDProperties; //set the other guid values to our guid values

                    //Add to source node prop
                    ArrayProperty <ObjectProperty> PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);
                    outgoingSpec.WriteProperties(properties);


                    //Write Spec Size
                    SharedPathfinding.SetReachSpecSize(outgoingSpec, size.SpecRadius, size.SpecHeight);

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
            else
            {
                //Debug.WriteLine("Source Node: " + startNode.Index);

                //Debug.WriteLine("Num Exports: " + pcc.Exports.Count);
                //int outgoingSpec = pcc.ExportCount;
                //int incomingSpec = pcc.ExportCount + 1;


                if (reachSpectoClone != null)
                {
                    ExportEntry outgoingSpec = reachSpectoClone.Clone();
                    Pcc.addExport(outgoingSpec);
                    ExportEntry incomingSpec = null;
                    if (createTwoWay)
                    {
                        incomingSpec = reachSpectoClone.Clone();
                        Pcc.addExport(incomingSpec);
                    }

                    IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type.

                    outgoingSpec.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    var outgoingSpecProperties = outgoingSpec.GetProperties();
                    if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                    {
                        outgoingSpecProperties.Add(new ByteProperty(1, "SpecDirection")); //We might need to find a way to support this edit
                    }

                    //Debug.WriteLine("Outgoing UIndex: " + outgoingSpecExp.UIndex);

                    ObjectProperty outgoingSpecStartProp = outgoingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                    StructProperty outgoingEndStructProp = outgoingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                    ObjectProperty outgoingSpecEndProp   = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END
                    outgoingSpecStartProp.Value = startNode.UIndex;
                    outgoingSpecEndProp.Value   = destinationNode.UIndex;

                    //Add to source node prop
                    var PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                    PathList.Add(new ObjectProperty(outgoingSpec.UIndex));
                    startNode.WriteProperty(PathList);

                    //Write Spec Size
                    SetReachSpecSize(outgoingSpecProperties, size.SpecRadius, size.SpecHeight);
                    outgoingSpec.WriteProperties(outgoingSpecProperties);

                    if (createTwoWay)
                    {
                        incomingSpec.idxClass      = reachSpecClassImp.UIndex;
                        incomingSpec.idxObjectName = reachSpecClassImp.idxObjectName;
                        var incomingSpecProperties = incomingSpec.GetProperties();
                        if (reachSpecClass == "Engine.SlotToSlotReachSpec")
                        {
                            incomingSpecProperties.Add(new ByteProperty(2, "SpecDirection"));
                        }

                        ObjectProperty incomingSpecStartProp = incomingSpecProperties.GetProp <ObjectProperty>("Start");                                                       //START
                        StructProperty incomingEndStructProp = incomingSpecProperties.GetProp <StructProperty>("End");                                                         //Embeds END
                        ObjectProperty incomingSpecEndProp   = incomingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(incomingSpec)); //END

                        incomingSpecStartProp.Value = destinationNode.UIndex;                                                                                                  //Uindex
                        incomingSpecEndProp.Value   = startNode.UIndex;


                        //Add reachspec to destination node's path list (returning)
                        var DestPathList = destinationNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList");
                        DestPathList.Add(new ObjectProperty(incomingSpec.UIndex));
                        destinationNode.WriteProperty(DestPathList);

                        //destNode.WriteProperty(DestPathList);
                        SetReachSpecSize(incomingSpecProperties, size.SpecRadius, size.SpecHeight);

                        incomingSpec.WriteProperties(incomingSpecProperties);
                    }

                    //Reindex reachspecs.
                    SharedPathfinding.ReindexMatchingObjects(outgoingSpec);
                }
            }
        }
Example #21
0
        public static string GenerateUDKFileForLevel(string udkPath, IMEPackage pcc)
        {
            #region AssetPackage

            string meshPackageName = $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}Meshes";
            string meshFile        = Path.Combine(udkPath, @"UDKGame\Content\Shared\", $"{meshPackageName}.upk");
            MEPackageHandler.CreateAndSavePackage(meshFile, MEGame.UDK);
            using IMEPackage meshPackage = MEPackageHandler.OpenUDKPackage(meshFile);
            meshPackage.getEntryOrAddImport("Core.Package");

            IEntry defMat    = meshPackage.getEntryOrAddImport("EngineMaterials.DefaultMaterial", "Material", "Engine");
            var    allMats   = new HashSet <int>();
            var    relinkMap = new Dictionary <IEntry, IEntry>();
            #region StaticMeshes

            List <ExportEntry> staticMeshes = pcc.Exports.Where(exp => exp.ClassName == "StaticMesh").ToList();
            foreach (ExportEntry mesh in staticMeshes)
            {
                var        mats = new Queue <int>();
                StaticMesh stm  = ObjectBinary.From <StaticMesh>(mesh);
                foreach (StaticMeshRenderData lodModel in stm.LODModels)
                {
                    foreach (StaticMeshElement meshElement in lodModel.Elements)
                    {
                        mats.Enqueue(meshElement.Material);
                        allMats.Add(meshElement.Material);
                        meshElement.Material = 0;
                    }
                }
                if (pcc.GetEntry(stm.BodySetup) is ExportEntry rbBodySetup)
                {
                    rbBodySetup.RemoveProperty("PhysMaterial");
                }
                mesh.WriteBinary(stm);
                IEntry newParent = EntryImporter.GetOrAddCrossImportOrPackage(mesh.ParentFullPath, pcc, meshPackage);
                EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, mesh, meshPackage, newParent, false, out IEntry ent, relinkMap);
                ExportEntry portedMesh = (ExportEntry)ent;
                stm = ObjectBinary.From <StaticMesh>(portedMesh);
                foreach (StaticMeshRenderData lodModel in stm.LODModels)
                {
                    foreach (StaticMeshElement meshElement in lodModel.Elements)
                    {
                        meshElement.Material = mats.Dequeue();
                    }
                }
                portedMesh.WriteBinary(stm);
            }

            #endregion

            #region Materials
            using (IMEPackage udkResources = MEPackageHandler.OpenMEPackageFromStream(Utilities.GetCustomAppResourceStream(MEGame.UDK)))
            {
                ExportEntry normDiffMat = udkResources.Exports.First(exp => exp.ObjectName == "NormDiffMat");
                foreach (int matUIndex in allMats)
                {
                    if (pcc.GetEntry(matUIndex) is ExportEntry matExp)
                    {
                        List <IEntry> textures = new MaterialInstanceConstant(matExp).Textures;
                        ExportEntry   diff     = null;
                        ExportEntry   norm     = null;
                        foreach (IEntry texEntry in textures)
                        {
                            if (texEntry is ExportEntry texport)
                            {
                                if (texport.ObjectName.Name.ToLower().Contains("diff"))
                                {
                                    diff = texport;
                                }
                                else if (texport.ObjectName.Name.ToLower().Contains("norm"))
                                {
                                    norm = texport;
                                }
                            }
                        }
                        if (diff == null)
                        {
                            relinkMap[matExp] = defMat;
                            continue;
                        }
                        else
                        {
                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, diff, meshPackage, null, false, out IEntry ent);
                            diff = (ExportEntry)ent;
                            diff.RemoveProperty("TextureFileCacheName");
                            diff.RemoveProperty("TFCFileGuid");
                            diff.RemoveProperty("LODGroup");
                        }
                        if (norm != null)
                        {
                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, norm, meshPackage, null, false, out IEntry ent);
                            norm = (ExportEntry)ent;
                            norm.RemoveProperty("TextureFileCacheName");
                            norm.RemoveProperty("TFCFileGuid");
                            norm.RemoveProperty("LODGroup");
                        }
                        EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, normDiffMat, meshPackage, null, true, out IEntry matEnt);
                        ExportEntry newMat = (ExportEntry)matEnt;
                        newMat.ObjectName = matExp.ObjectName;
                        Material matBin = ObjectBinary.From <Material>(newMat);
                        matBin.SM3MaterialResource.UniformExpressionTextures = new UIndex[] { norm?.UIndex ?? 0, diff.UIndex };
                        newMat.WriteBinary(matBin);
                        relinkMap[matExp] = newMat;
                        if (newMat.GetProperty <ArrayProperty <ObjectProperty> >("Expressions") is {} expressionsProp&& expressionsProp.Count >= 2)
                        {
                            ExportEntry diffExpression = meshPackage.GetUExport(expressionsProp[0].Value);
                            ExportEntry normExpression = meshPackage.GetUExport(expressionsProp[1].Value);
                            diffExpression.WriteProperty(new ObjectProperty(diff.UIndex, "Texture"));
                            normExpression.WriteProperty(new ObjectProperty(norm?.UIndex ?? 0, "Texture"));
                        }
                    }
                    else if (pcc.GetEntry(matUIndex) is ImportEntry matImp)
                    {
                        relinkMap[matImp] = defMat;
                    }
                }

                var relinkMapping = new OrderedMultiValueDictionary <IEntry, IEntry>(relinkMap);
                foreach (ExportEntry stmExport in staticMeshes)
                {
                    if (relinkMap.TryGetValue(stmExport, out IEntry destEnt) && destEnt is ExportEntry destExp)
                    {
                        Relinker.Relink(stmExport, destExp, relinkMapping);
                    }
                }
            }
            #endregion


            meshPackage.Save();

            #endregion


            var    staticMeshActors = new List <ExportEntry>();
            var    lightActors      = new List <ExportEntry>();
            string tempPackagePath  = Path.Combine(App.ExecFolder, $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk");
            File.Copy(Path.Combine(App.ExecFolder, "empty.udk"), tempPackagePath, true);
            using IMEPackage udkPackage = MEPackageHandler.OpenUDKPackage(tempPackagePath);
            {
                var topLevelMeshPackages = new List <IEntry>();
                foreach (ExportEntry exportEntry in staticMeshes)
                {
                    IEntry imp = udkPackage.getEntryOrAddImport($"{exportEntry.FullPath}", "StaticMesh", "Engine", exportEntry.ObjectName.Number);
                    while (imp.Parent != null)
                    {
                        imp = imp.Parent;
                    }
                    if (!topLevelMeshPackages.Contains(imp))
                    {
                        topLevelMeshPackages.Add(imp);
                    }
                }

                ExportEntry levelExport          = udkPackage.Exports.First(exp => exp.ClassName == "Level");
                List <int>  actorsInLevel        = ObjectBinary.From <Level>(pcc.Exports.First(exp => exp.ClassName == "Level")).Actors.Select(u => u.value).ToList();
                var         componentToMatrixMap = new Dictionary <int, Matrix>();
                foreach (int uIndex in actorsInLevel)
                {
                    if (pcc.GetEntry(uIndex) is ExportEntry stcExp)
                    {
                        if (stcExp.ClassName == "StaticMeshCollectionActor")
                        {
                            StaticMeshCollectionActor stmc = ObjectBinary.From <StaticMeshCollectionActor>(stcExp);
                            var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("StaticMeshComponents");
                            for (int i = 0; i < components.Count; i++)
                            {
                                componentToMatrixMap[components[i].Value] = stmc.LocalToWorldTransforms[i];
                            }
                        }
                        else if (stcExp.ClassName == "StaticLightCollectionActor")
                        {
                            StaticLightCollectionActor stlc = ObjectBinary.From <StaticLightCollectionActor>(stcExp);
                            var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("LightComponents");
                            for (int i = 0; i < components.Count; i++)
                            {
                                componentToMatrixMap[components[i].Value] = stlc.LocalToWorldTransforms[i];
                            }
                        }
                    }
                }

                #region StaticMeshActors
                {
                    var    emptySMCBin          = new StaticMeshComponent();
                    IEntry staticMeshActorClass = udkPackage.getEntryOrAddImport("Engine.StaticMeshActor");
                    udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor", "StaticMeshActor", "Engine");
                    IEntry staticMeshComponentArchetype = udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor.StaticMeshComponent0",
                                                                                         "StaticMeshComponent", "Engine");
                    int smaIndex = 2;
                    int smcIndex = 2;
                    foreach (ExportEntry smc in pcc.Exports.Where(exp => exp.ClassName == "StaticMeshComponent"))
                    {
                        if (smc.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex) && parent.IsA("StaticMeshActorBase"))
                        {
                            StructProperty locationProp;
                            StructProperty rotationProp;
                            StructProperty scaleProp = null;
                            smc.CondenseArchetypes();
                            if (!(smc.GetProperty <ObjectProperty>("StaticMesh") is { } meshProp) || !pcc.IsUExport(meshProp.Value))
                            {
                                continue;
                            }

                            smc.WriteBinary(emptySMCBin);
                            smc.RemoveProperty("bBioIsReceivingDecals");
                            smc.RemoveProperty("bBioForcePrecomputedShadows");
                            //smc.RemoveProperty("bUsePreComputedShadows");
                            smc.RemoveProperty("bAcceptsLights");
                            smc.RemoveProperty("IrrelevantLights");
                            smc.RemoveProperty("Materials"); //should make use of this?
                            smc.ObjectName = new NameReference("StaticMeshComponent", smcIndex++);
                            if (parent.ClassName == "StaticMeshCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(smc.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                                //smc.WriteProperty(CommonStructs.Matrix(m, "CachedParentToWorld"));
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry sma = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, staticMeshActorClass.UIndex))
                            {
                                ObjectName = new NameReference("StaticMeshActor", smaIndex++),
                                Class      = staticMeshActorClass,
                                Parent     = levelExport
                            };
                            sma.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(sma);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, smc, udkPackage,
                                                                 sma, true, out IEntry result);
                            var props = new PropertyCollection
                            {
                                new ObjectProperty(result.UIndex, "StaticMeshComponent"),
                                new NameProperty(new NameReference(Path.GetFileNameWithoutExtension(smc.FileRef.FilePath), smc.UIndex),
                                                 "Tag"),
                                new ObjectProperty(result.UIndex, "CollisionComponent")
                            };
                            if (locationProp != null)
                            {
                                props.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                props.Add(rotationProp);
                            }

                            if (scaleProp != null)
                            {
                                props.Add(scaleProp);
                            }
                            sma.WriteProperties(props);
                            staticMeshActors.Add(sma);
                        }
                    }
                    IEntry topMeshPackageImport = udkPackage.getEntryOrAddImport(meshPackageName, "Package");
                    foreach (IEntry mp in topLevelMeshPackages)
                    {
                        mp.Parent = topMeshPackageImport;
                    }
                }
                #endregion

                #region LightActors
                {
                    IEntry pointLightClass       = udkPackage.getEntryOrAddImport("Engine.PointLight");
                    IEntry spotLightClass        = udkPackage.getEntryOrAddImport("Engine.SpotLight");
                    IEntry directionalLightClass = udkPackage.getEntryOrAddImport("Engine.DirectionalLight");

                    int plaIndex = 1;
                    int plcIndex = 1;
                    int slaIndex = 1;
                    int slcIndex = 1;
                    int dlaIndex = 1;
                    int dlcIndex = 1;
                    foreach (ExportEntry lightComponent in pcc.Exports)
                    {
                        if (!(lightComponent.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex)))
                        {
                            continue;
                        }
                        StructProperty locationProp;
                        StructProperty rotationProp;
                        StructProperty scaleProp;
                        switch (lightComponent.ClassName)
                        {
                        case "PointLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("PointLightComponent", plcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry pla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, pointLightClass.UIndex))
                            {
                                ObjectName = new NameReference("PointLight", plaIndex++),
                                Class      = pointLightClass,
                                Parent     = levelExport
                            };
                            pla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(pla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, pla, true,
                                                                 out IEntry portedPLC);
                            var plsProps = new PropertyCollection
                            {
                                new ObjectProperty(portedPLC.UIndex, "LightComponent"),
                                new NameProperty("PointLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                plsProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                plsProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                plsProps.Add(scaleProp);
                            }
                            pla.WriteProperties(plsProps);
                            lightActors.Add(pla);
                            break;

                        case "SpotLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("SpotLightComponent", slcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry sla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, spotLightClass.UIndex))
                            {
                                ObjectName = new NameReference("SpotLight", slaIndex++),
                                Class      = spotLightClass,
                                Parent     = levelExport
                            };
                            sla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(sla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, sla, true,
                                                                 out IEntry portedSLC);
                            var slaProps = new PropertyCollection
                            {
                                new ObjectProperty(portedSLC.UIndex, "LightComponent"),
                                new NameProperty("SpotLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                slaProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                slaProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                slaProps.Add(scaleProp);
                            }
                            sla.WriteProperties(slaProps);
                            lightActors.Add(sla);
                            break;

                        case "DirectionalLightComponent":
                            lightComponent.CondenseArchetypes();
                            lightComponent.ObjectName = new NameReference("DirectionalLightComponent", dlcIndex++);
                            if (parent.ClassName == "StaticLightCollectionActor")
                            {
                                if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m))
                                {
                                    continue;
                                }
                                (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose();
                                locationProp = CommonStructs.Vector3Prop(posVec, "Location");
                                rotationProp = CommonStructs.RotatorProp(rotator, "Rotation");
                                scaleProp    = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D");
                            }
                            else
                            {
                                locationProp = parent.GetProperty <StructProperty>("Location");
                                rotationProp = parent.GetProperty <StructProperty>("Rotation");
                                scaleProp    = parent.GetProperty <StructProperty>("DrawScale3D");
                                if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale)
                                {
                                    Vector3 scaleVec = Vector3.One;
                                    if (scaleProp != null)
                                    {
                                        scaleVec = CommonStructs.GetVector3(scaleProp);
                                    }
                                    scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D");
                                }
                            }

                            ExportEntry dla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, directionalLightClass.UIndex))
                            {
                                ObjectName = new NameReference("DirectionalLight", dlaIndex++),
                                Class      = directionalLightClass,
                                Parent     = levelExport
                            };
                            dla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack;
                            udkPackage.AddExport(dla);

                            EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, dla, true,
                                                                 out IEntry portedDLC);
                            var dlaProps = new PropertyCollection
                            {
                                new ObjectProperty(portedDLC.UIndex, "LightComponent"),
                                new NameProperty("DirectionalLight", "Tag"),
                            };
                            if (locationProp != null)
                            {
                                dlaProps.Add(locationProp);
                            }
                            if (rotationProp != null)
                            {
                                dlaProps.Add(rotationProp);
                            }
                            if (scaleProp != null)
                            {
                                dlaProps.Add(scaleProp);
                            }
                            dla.WriteProperties(dlaProps);
                            lightActors.Add(dla);
                            break;
                        }
                    }
                }
                UDKifyLights(udkPackage);
                #endregion

                Level level = ObjectBinary.From <Level>(levelExport);
                level.Actors = levelExport.GetChildren().Where(ent => ent.IsA("Actor")).Select(ent => new UIndex(ent.UIndex)).ToList();
                levelExport.WriteBinary(level);

                udkPackage.Save();
            }

            string resultFilePath = Path.Combine(udkPath, @"UDKGame\Content\Maps\", $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk");
            using (IMEPackage udkPackage2 = MEPackageHandler.OpenUDKPackage(Path.Combine(App.ExecFolder, "empty.udk")))
            {
                ExportEntry levelExport = udkPackage2.Exports.First(exp => exp.ClassName == "Level");
                Level       levelBin    = ObjectBinary.From <Level>(levelExport);
                foreach (ExportEntry actor in staticMeshActors)
                {
                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result);
                    levelBin.Actors.Add(result.UIndex);
                }
                foreach (ExportEntry actor in lightActors)
                {
                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result);
                    levelBin.Actors.Add(result.UIndex);
                }
                levelExport.WriteBinary(levelBin);
                udkPackage2.Save(resultFilePath);
            }
            File.Delete(tempPackagePath);
            return(resultFilePath);
        }
        public static bool RandomizeExportSkin(ExportEntry material, RandomizationOption option, ref StructProperty skinColorPV)
        {
            if (!CanRandomize(material))
            {
                return(false);
            }
            var props = material.GetProperties();

            {
                var vectors = props.GetProp <ArrayProperty <StructProperty> >("VectorParameterValues");
                if (vectors != null)
                {
                    foreach (var vector in vectors)
                    {
                        var pn = vector.GetProp <NameProperty>("ParameterName");
                        var pv = vector.GetProp <StructProperty>("ParameterValue");

                        if (pn != null && pn.Value == "SkinTone" && skinColorPV != null && pv != null)
                        {
                            vector.Properties.AddOrReplaceProp(skinColorPV);
                        }
                        else if (pv != null)
                        {
                            RStructs.RandomizeTint(pv, false);
                            if (pn.Value == "SkinTone")
                            {
                                skinColorPV = pv; // Below method will assign data to this structproperty.
                            }
                        }
                    }
                }

                var scalars = props.GetProp <ArrayProperty <StructProperty> >("ScalarParameterValues");
                if (scalars != null)
                {
                    for (int i = 0; i < scalars.Count; i++)
                    {
                        var scalar       = scalars[i];
                        var parameter    = scalar.GetProp <NameProperty>("ParameterName");
                        var currentValue = scalar.GetProp <FloatProperty>("ParameterValue");
                        if (currentValue > 1)
                        {
                            scalar.GetProp <FloatProperty>("ParameterValue").Value = ThreadSafeRandom.NextFloat(.1, currentValue * 1.3);
                        }
                        else
                        {
                            //Debug.WriteLine("Randomizing parameter " + scalar.GetProp<NameProperty>("ParameterName"));
                            scalar.GetProp <FloatProperty>("ParameterValue").Value = ThreadSafeRandom.NextFloat(0, 1);
                        }
                    }

                    //foreach (var scalar in vectors)
                    //{
                    //    var paramValue = vector.GetProp<StructProperty>("ParameterValue");
                    //    RandomizeTint( paramValue, false);
                    //}
                }
            }
            material.WriteProperties(props);
            return(true);
        }