diff --git a/FModel/Extensions/CUE4ParseExtensions.cs b/FModel/Extensions/CUE4ParseExtensions.cs index 463a668e..3e3ac993 100644 --- a/FModel/Extensions/CUE4ParseExtensions.cs +++ b/FModel/Extensions/CUE4ParseExtensions.cs @@ -3,6 +3,7 @@ using CUE4Parse.FileProvider; using CUE4Parse.FileProvider.Objects; using CUE4Parse.UE4.Assets; using CUE4Parse.UE4.Objects.UObject; +using CUE4Parse.Utils; using FModel.Settings; namespace FModel.Extensions; @@ -67,4 +68,19 @@ public static class CUE4ParseExtensions return result; } + + public static LoadPackageResult GetLoadPackageResult(this IFileProvider provider, string file, string objectName = null) + { + var result = new LoadPackageResult { Package = provider.LoadPackage(file) }; + if (result.IsPaginated || (result.Package.HasFlags(EPackageFlags.PKG_ContainsMap) && UserSettings.Default.PreviewWorlds)) // focus on UWorld if it's a map we want to preview + { + result.RequestedIndex = result.Package.GetExportIndex(file.SubstringBeforeLast('.')); + if (objectName != null) + { + result.RequestedIndex = int.TryParse(objectName, out var index) ? index : result.Package.GetExportIndex(objectName); + } + } + + return result; + } } diff --git a/FModel/Extensions/KismetExtensions.cs b/FModel/Extensions/KismetExtensions.cs deleted file mode 100644 index 76562497..00000000 --- a/FModel/Extensions/KismetExtensions.cs +++ /dev/null @@ -1,1051 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using CUE4Parse.UE4.Assets.Objects.Properties; -using CUE4Parse.UE4.Assets.Objects; -using CUE4Parse.UE4.Kismet; -using CUE4Parse.UE4.Objects.Core.Math; -using CUE4Parse.UE4.Objects.Core.Misc; -using CUE4Parse.UE4.Objects.Engine.Ai; -using CUE4Parse.UE4.Objects.Engine.GameFramework; -using CUE4Parse.UE4.Objects.GameplayTags; -using CUE4Parse.UE4.Objects.UObject; - -namespace FModel.Extensions; - -public static class KismetExtensions -{ - public static string GetPrefix(this UStruct val) - { - var ret = string.Empty; - var super = val; - - while (super is not null) - { - if (super.Name == "Actor") - { - ret += 'A'; - break; - } - - if (super.Name == "Interface") - { - ret += 'I'; - break; - } - - if (super.Name == "Object") - { - ret += 'U'; - break; - } - - super = super?.SuperStruct?.Load(); - } - - if (string.IsNullOrEmpty(ret)) - ret += 'U'; - - return ret; - } - - public static string GetPrefix(this string val) // todo: val.Contains("Struct") ? "F" findout - { - return val.Contains(".Actor") ? "A" : val.Contains("Interface") ? "I" : "U"; - } - - // GetUnknownFieldType and GetPropertyType from - // https://github.com/CrystalFerrai/UeBlueprintDumper/blob/main/UeBlueprintDumper/BlueprintDumper.cs#L352 - // nothing else is from UeBlueprintDumper - - public static string GetUnknownFieldType(object field) - { - string typeName = field.GetType().Name; - int suffixIndex = typeName.IndexOf("Property", StringComparison.Ordinal); - return suffixIndex < 0 ? typeName : typeName.Substring(1, suffixIndex - 1); - } - - public static string GetPropertyType(object? property) - { - if (property is null) - return "None"; - - return property switch - { - FIntProperty or int => "int", - FInt8Property or byte => "int8", - FInt16Property or short => "int16", - FInt64Property or long => "int64", - FUInt16Property or ushort => "uint16", - FUInt32Property or uint => "uint32", - FUInt64Property or ulong => "uint64", - FBoolProperty or bool => "bool", - FStrProperty or string => "FString", - FFloatProperty or float => "float", - FDoubleProperty or double => "double", - FObjectProperty objct => property switch - { - FClassProperty clss => $"{clss.MetaClass?.Name ?? "UKN_ObjectMetaClass"} Class", - FSoftClassProperty softClass => $"{softClass.MetaClass?.Name ?? "UKN_ObjectMetaClass"} Class (soft)", - _ => objct.PropertyClass?.Name ?? "UKN_ObjectPropertyClass" - }, - FPackageIndex pkg => pkg.ResolvedObject?.Class?.Name.ToString() ?? "Package", - FName fme => fme.PlainText.Contains("::") ? fme.PlainText.Split("::")[0] : fme.PlainText, - FEnumProperty enm => enm.Enum?.Name ?? "Enum", - FByteProperty bt => bt.Enum?.ResolvedObject?.Name.Text ?? "Byte", - FInterfaceProperty intrfc => $"{intrfc.InterfaceClass?.Name ?? "UKN_InterfaceClass"} interface", - FStructProperty strct => strct.Struct?.ResolvedObject?.Name.Text ?? "Struct", - FFieldPathProperty fieldPath => $"{fieldPath.PropertyClass.Text} field path", - FDelegateProperty dlgt => $"{dlgt.SignatureFunction?.Name ?? "UKN_SignatureFunction"} (Delegate)", - FMulticastDelegateProperty mdlgt => $"{mdlgt.SignatureFunction?.Name ?? "UKN_SignatureFunction"} (MulticastDelegateProperty)", - FMulticastInlineDelegateProperty midlgt => $"{midlgt.SignatureFunction?.Name ?? "UKN_SignatureFunction"} (MulticastInlineDelegateProperty)", - _ => GetUnknownFieldType(property) - }; - } - public static bool isPointer(FProperty p) => - p.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || - p.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || - p.PropertyFlags.HasFlag(EPropertyFlags.ContainsInstancedReference) || - p.GetType() == typeof(FObjectProperty); - - public static string GetPropertyType(FProperty property) - { - if (property is null) return "None"; - - return property switch - { - FSetProperty s => $"TSet<{s?.ElementProp.GetType().Name.GetPrefix()}{GetPropertyType(s.ElementProp)}{(isPointer(s) ? "*" : "")}>", - FMapProperty m => $"TMap<{m?.KeyProp.GetType().Name.GetPrefix()}{GetPropertyType(m.KeyProp)}, {m.ValueProp.GetType().Name.GetPrefix()}{GetPropertyType(m.ValueProp)}{(isPointer(m) ? "*" : "")}>", - FArrayProperty a => $"TArray<{a?.Inner.GetType().Name.GetPrefix()}{GetPropertyType(a.Inner)}{(isPointer(a) || a.Inner.GetType().Name == nameof(FObjectProperty) ? "*" : "")}>", - _ => GetPropertyType((object)property) - }; - } - - public static string FormatStructFallback(FStructFallback fallback) - { - if (fallback.Properties.Count == 0) - return "[]"; - - var tags = fallback.Properties.Select(tag => - { - string tagDataFormatted; - - switch (tag.Tag) - { - case TextProperty text: - tagDataFormatted = $"\"{text.Value.Text}\""; - break; - case NameProperty name: - tagDataFormatted = $"\"{name.Value.Text}\""; - break; - case ObjectProperty obj: - tagDataFormatted = $"\"{obj.Value}\""; - break; - default: - { - if (tag.Tag.GenericValue is FScriptStruct { StructType: FStructFallback nestedFallback }) - { - if (nestedFallback.Properties.Count > 0) - { - tagDataFormatted = "{ " + string.Join(", ", - nestedFallback.Properties.Select(nested => - { - string nestedVal = nested.Tag switch - { - TextProperty textProp => $"\"{textProp.Value.Text}\"", - NameProperty nameProp => $"\"{nameProp.Value.Text}\"", - _ => $"\"{nested.Tag.GenericValue}\"" - }; - - return $"\"{nested.Name}\": {nestedVal}"; - })) + " }"; - } - else - { - tagDataFormatted = "{}"; - } - } - else - { - tagDataFormatted = tag.Tag.GenericValue != null ? $"\"{tag.Tag.GenericValue}\"" : "{}"; - } - - break; - } - } - - return $"\t\t{{ \"{tag.Name}\": {tagDataFormatted} }}"; - }); - - return "[\n" + string.Join(",\n", tags) + "\n\t]"; - } - - public static string FormatGameplayTagContainer(FGameplayTagContainer container) - { - var tags = container.GameplayTags.ToList(); - return tags.Count switch - { - 0 => "[]", - 1 => $"\"{tags[0].TagName}\"", - _ => "[\n" + string.Join(",\n", tags.Select(tag => $"\t\t\"{tag.TagName}\"")) + "\n\t]" - }; - } - - public static string FormatStructType(object structType) - { - return structType switch - { - FVector vector => $"FVector({vector.X}, {vector.Y}, {vector.Z})", - FVector2D vector2D => $"FVector2D({vector2D.X}, {vector2D.Y})", - FRotator rotator => $"FRotator({rotator.Pitch}, {rotator.Yaw}, {rotator.Roll})", - FQuat quat => $"FQuat({quat.X}, {quat.Y}, {quat.Z}, {quat.W})", - FGuid guid => $"FGuid({guid.A}, {guid.B}, {guid.C}, {guid.D})", - FColor color => $"FColor({color.R}, {color.G}, {color.B}, {color.A})", - FLinearColor linearColor => $"FLinearColor({linearColor.R}, {linearColor.G}, {linearColor.B}, {linearColor.A})", - FSoftObjectPath path => $"FSoftObjectPath({path.AssetPathName})", - FUniqueNetIdRepl netId => $"FUniqueNetIdRepl({netId.UniqueNetId})", - FNavAgentSelector agent => $"FNavAgentSelector({agent.PackedBits})", - FBox box => $"FBox(FVector({box.Max.X}, {box.Max.Y}, {box.Max.Z}), FVector({box.Min.X}, {box.Min.Y}, {box.Min.Z}))", - FBox2D box2D => $"FBox2D(FVector2D({box2D.Max.X}, {box2D.Max.Y}), FVector2D({box2D.Min.X}, {box2D.Min.Y}))", - TIntVector3 intVec => $"FVector({intVec.X}, {intVec.Y}, {intVec.Z})", - TIntVector3 floatVec => $"FVector({floatVec.X}, {floatVec.Y}, {floatVec.Z})", - TIntVector2 floatVec2 => $"FVector2D({floatVec2.X}, {floatVec2.Y})", - FDateTime dateTime => $"FDateTime({dateTime})", - FStructFallback fallback => FormatStructFallback(fallback), - FGameplayTagContainer tagContainer => FormatGameplayTagContainer(tagContainer), - _ => structType?.ToString() ?? "Issue here" - }; - } - - private static string ProcessTextProperty(FKismetPropertyPointer property, bool temp) - { - if (property.New is null) - { - return property.Old?.Name ?? string.Empty; - } - return string.Join('.', property.New.Path.Select(n => n.Text)).Replace(" ", ""); - } - - public static void ProcessExpression(EExprToken token, KismetExpression expression, StringBuilder outputBuilder, List jumpCodeOffsets, bool isParameter = false) - { - if (jumpCodeOffsets.Contains(expression.StatementIndex)) - { - outputBuilder.Append("\t\tLabel_" + expression.StatementIndex + ":\n"); - } - - switch (token) - { - case EExprToken.EX_LetValueOnPersistentFrame: - { - EX_LetValueOnPersistentFrame op = (EX_LetValueOnPersistentFrame) expression; - EX_VariableBase opp = (EX_VariableBase) op.AssignmentExpression; - var destination = ProcessTextProperty(op.DestinationProperty, false); - var variable = ProcessTextProperty(opp.Variable, false); - - outputBuilder.Append($"\t\t{(destination.Contains("K2Node_") ? "UberGraphFrame->" + destination : destination)} = {variable}{(!isParameter ? ";\n\n" : "")}"); // Hardcoded but works - break; - } - case EExprToken.EX_LocalFinalFunction: - { - EX_FinalFunction op = (EX_FinalFunction) expression; - KismetExpression[] opp = op.Parameters; - if (isParameter) - { - outputBuilder.Append($"{op.StackNode.Name.Replace(" ", "")}("); - } - else if (opp.Length < 1) - { - outputBuilder.Append($"\t\t{op?.StackNode?.Name.Replace(" ", "")}("); - } - else - { - outputBuilder.Append($"\t\t{op?.StackNode?.ResolvedObject?.Outer?.GetType()?.Name.GetPrefix()}{op?.StackNode?.Name.Replace(" ", "")}("); - } - - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t"); - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(isParameter ? ")" : ");\n"); - break; - } - case EExprToken.EX_FinalFunction: - { - EX_FinalFunction op = (EX_FinalFunction) expression; - KismetExpression[] opp = op.Parameters; - if (isParameter) - { - outputBuilder.Append($"{op.StackNode.Name.Replace(" ", "")}("); - } - else if (opp.Length < 1) - { - outputBuilder.Append($"\t\t{op?.StackNode?.Name.Replace(" ", "")}("); - } - else - { - outputBuilder.Append($"\t\t{op?.StackNode?.Name.Replace(" ", "")}(");// maybe use GetPrefix(op?.StackNode?.ResolvedObject?.Outer?.GetType()?.Name)} - } - - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t"); - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(isParameter ? ")" : ");\n\n"); - break; - } - case EExprToken.EX_CallMath: - { - EX_FinalFunction op = (EX_FinalFunction) expression; - KismetExpression[] opp = op.Parameters; - outputBuilder.Append(isParameter ? string.Empty : "\t\t"); - outputBuilder.Append($"{op.StackNode.ResolvedObject.Outer.GetType().Name.GetPrefix()}{op.StackNode.ResolvedObject.Outer.Name.ToString().Replace(" ", "")}::{op.StackNode.Name}("); - - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t\t"); - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(isParameter ? ")" : ");\n\n"); - break; - } - case EExprToken.EX_LocalVirtualFunction: - case EExprToken.EX_VirtualFunction: - { - EX_VirtualFunction op = (EX_VirtualFunction) expression; - KismetExpression[] opp = op.Parameters; - if (isParameter) - { - outputBuilder.Append($"{op.VirtualFunctionName.PlainText.Replace(" ", "")}("); - } - else - { - outputBuilder.Append($"\t\t{op.VirtualFunctionName.PlainText.Replace(" ", "")}("); - } - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t"); - - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(isParameter ? ")" : ");\n\n"); - break; - } - case EExprToken.EX_ComputedJump: - { - EX_ComputedJump op = (EX_ComputedJump) expression; - if (op.CodeOffsetExpression is EX_VariableBase opp) - { - outputBuilder.AppendLine($"\t\tgoto {ProcessTextProperty(opp.Variable, false)};\n"); - } - else if (op.CodeOffsetExpression is EX_CallMath oppMath) - { - ProcessExpression(oppMath.Token, oppMath, outputBuilder, jumpCodeOffsets, true); - } - - break; - } - case EExprToken.EX_PopExecutionFlowIfNot: - { - EX_PopExecutionFlowIfNot op = (EX_PopExecutionFlowIfNot) expression; - outputBuilder.Append("\t\tif (!"); - ProcessExpression(op.BooleanExpression.Token, op.BooleanExpression, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(") \r\n"); - outputBuilder.Append($"\t\t FlowStack.Pop();\n\n"); - break; - } - case EExprToken.EX_Cast: - { - EX_Cast op = (EX_Cast) expression; // support CST_ObjectToInterface when I have an example of how it works - - if (op.ConversionType is ECastToken.CST_ObjectToBool or ECastToken.CST_InterfaceToBool) - { - outputBuilder.Append("(bool)"); - } - if (ECastToken.CST_DoubleToFloat == op.ConversionType) - { - outputBuilder.Append("(float)"); - } - if (ECastToken.CST_FloatToDouble == op.ConversionType) - { - outputBuilder.Append("(double)"); - } - ProcessExpression(op.Target.Token, op.Target, outputBuilder, jumpCodeOffsets); - break; - } - case EExprToken.EX_InterfaceContext: - { - EX_InterfaceContext op = (EX_InterfaceContext) expression; - ProcessExpression(op.InterfaceValue.Token, op.InterfaceValue, outputBuilder, jumpCodeOffsets); - break; - } - case EExprToken.EX_ArrayConst: - { - EX_ArrayConst op = (EX_ArrayConst) expression; - outputBuilder.Append("TArray {"); - foreach (KismetExpression element in op.Elements) - { - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets); - } - outputBuilder.Append(op.Elements.Length < 1 ? " " : ' '); - - outputBuilder.Append('}'); - break; - } - case EExprToken.EX_SetArray: - { - EX_SetArray op = (EX_SetArray) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.AssigningProperty.Token, op.AssigningProperty, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(" = "); - outputBuilder.Append("TArray {"); - for (int i = 0; i < op.Elements.Length; i++) - { - KismetExpression element = op.Elements[i]; - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets); - - outputBuilder.Append(i < op.Elements.Length - 1 ? "," : ""); - } - - outputBuilder.Append(op.Elements.Length < 1 ? " " : ' '); - - outputBuilder.Append("};\n\n"); - break; - } - case EExprToken.EX_SetSet: - { - EX_SetSet op = (EX_SetSet) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.SetProperty.Token, op.SetProperty, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(" = "); - outputBuilder.Append("TArray {"); - for (int i = 0; i < op.Elements.Length; i++) - { - KismetExpression element = op.Elements[i]; - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets); - - outputBuilder.Append(i < op.Elements.Length - 1 ? "," : ""); - } - - outputBuilder.Append(op.Elements.Length < 1 ? " " : ' '); - - outputBuilder.Append("};\n\n"); - break; - } - case EExprToken.EX_SetConst: - { - EX_SetConst op = (EX_SetConst) expression; - outputBuilder.Append("TArray {"); - for (int i = 0; i < op.Elements.Length; i++) - { - KismetExpression element = op.Elements[i]; - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets, true); - - outputBuilder.Append(i < op.Elements.Length - 1 ? "," : ""); - } - - outputBuilder.Append(op.Elements.Length < 1 ? " " : ' '); - - outputBuilder.Append("};\n\n"); - break; - } - case EExprToken.EX_SetMap: - { - EX_SetMap op = (EX_SetMap) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.MapProperty.Token, op.MapProperty, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(" = "); - outputBuilder.Append("TMap {"); - for (int i = 0; i < op.Elements.Length; i++) - { - var element = op.Elements[i]; - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets); // sometimes the start of an array is a byte not a variable - - if (i < op.Elements.Length - 1) - { - outputBuilder.Append(element.Token == EExprToken.EX_InstanceVariable ? ": " : ", "); - } - else - { - outputBuilder.Append(' '); - } - } - - if (op.Elements.Length < 1) - outputBuilder.Append(" "); - outputBuilder.Append("}\n"); - break; - } - case EExprToken.EX_MapConst: - { - EX_MapConst op = (EX_MapConst) expression; - outputBuilder.Append("TMap {"); - for (int i = 0; i < op.Elements.Length; i++) - { - var element = op.Elements[i]; - outputBuilder.Append(' '); - ProcessExpression(element.Token, element, outputBuilder, jumpCodeOffsets, true); // sometimes the start of an array is a byte not a variable - - if (i < op.Elements.Length - 1) - { - outputBuilder.Append(element.Token == EExprToken.EX_InstanceVariable ? ": " : ", "); - } - else - { - outputBuilder.Append(' '); - } - } - - if (op.Elements.Length < 1) - outputBuilder.Append(" "); - outputBuilder.Append("}\n"); - break; - } - case EExprToken.EX_SwitchValue: - { - EX_SwitchValue op = (EX_SwitchValue) expression; - - bool useTernary = op.Cases.Length <= 2 && - op.Cases.All(c => c.CaseIndexValueTerm.Token is EExprToken.EX_True or EExprToken.EX_False); - - if (useTernary) - { - ProcessExpression(op.IndexTerm.Token, op.IndexTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(" ? "); - - bool isFirst = true; - foreach (var caseItem in op.Cases.Where(c => c.CaseIndexValueTerm.Token == EExprToken.EX_True)) - { - if (!isFirst) - outputBuilder.Append(" : "); - - ProcessExpression(caseItem.CaseTerm.Token, caseItem.CaseTerm, outputBuilder, jumpCodeOffsets, true); - isFirst = false; - } - - foreach (var caseItem in op.Cases.Where(c => c.CaseIndexValueTerm.Token == EExprToken.EX_False)) - { - if (!isFirst) - outputBuilder.Append(" : "); - - ProcessExpression(caseItem.CaseTerm.Token, caseItem.CaseTerm, outputBuilder, jumpCodeOffsets, true); - } - } - else - { - outputBuilder.Append("switch ("); - ProcessExpression(op.IndexTerm.Token, op.IndexTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(")\n"); - outputBuilder.Append("\t\t{\n"); - - foreach (var caseItem in op.Cases) - { - if (caseItem.CaseIndexValueTerm.Token == EExprToken.EX_IntConst) - { - int caseValue = ((EX_IntConst) caseItem.CaseIndexValueTerm).Value; - outputBuilder.Append($"\t\t\tcase {caseValue}:\n"); - } - else - { - outputBuilder.Append("\t\t\tcase "); - ProcessExpression(caseItem.CaseIndexValueTerm.Token, caseItem.CaseIndexValueTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(":\n"); - } - - outputBuilder.Append("\t\t\t{\n"); - outputBuilder.Append("\t\t\t "); - ProcessExpression(caseItem.CaseTerm.Token, caseItem.CaseTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(";\n"); - outputBuilder.Append("\t\t\t break;\n"); - outputBuilder.Append("\t\t\t}\n"); - } - - outputBuilder.Append("\t\t\tdefault:\n"); - outputBuilder.Append("\t\t\t{\n"); - outputBuilder.Append("\t\t\t "); - ProcessExpression(op.DefaultTerm.Token, op.DefaultTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append("\n\t\t\t}\n"); - - outputBuilder.Append("\t\t}"); - } - break; - } - case EExprToken.EX_ArrayGetByRef: // I assume get array with index - { - EX_ArrayGetByRef op = (EX_ArrayGetByRef) expression; // FortniteGame/Plugins/GameFeatures/FM/PilgrimCore/Content/Player/Components/BP_PilgrimPlayerControllerComponent.uasset - ProcessExpression(op.ArrayVariable.Token, op.ArrayVariable, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append('['); - ProcessExpression(op.ArrayIndex.Token, op.ArrayIndex, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(']'); - break; - } - case EExprToken.EX_MetaCast: - case EExprToken.EX_DynamicCast: - case EExprToken.EX_ObjToInterfaceCast: - case EExprToken.EX_CrossInterfaceCast: - case EExprToken.EX_InterfaceToObjCast: - { - EX_CastBase op = (EX_CastBase) expression; - outputBuilder.Append($"Cast(");// m? - ProcessExpression(op.Target.Token, op.Target, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(')'); - break; - } - case EExprToken.EX_StructConst: - { - EX_StructConst op = (EX_StructConst) expression; - outputBuilder.Append($"{op.Struct.GetType().Name.GetPrefix()}{op.Struct.Name}"); - outputBuilder.Append('('); - for (int i = 0; i < op.Properties.Length; i++) - { - var property = op.Properties[i]; - ProcessExpression(property.Token, property, outputBuilder, jumpCodeOffsets); - if (i < op.Properties.Length - 1 && property.Token != EExprToken.EX_ArrayConst) - outputBuilder.Append(", "); - } - outputBuilder.Append(')'); - break; - } - case EExprToken.EX_ObjectConst: - { - EX_ObjectConst op = (EX_ObjectConst) expression; - outputBuilder.Append(!isParameter ? "\t\tFindObject<" : outputBuilder.ToString().EndsWith('\n') ? "\t\tFindObject<" : "FindObject<"); // please don't complain, I know this is bad but I MUST do it. - string classString = op.Value.ResolvedObject?.Class?.ToString().Replace("'", ""); - - if (classString?.Contains('.') == true) - { - - outputBuilder.Append(op?.Value?.ResolvedObject?.Class?.GetType().Name.GetPrefix() + classString.Split('.')[1]); - } - else - { - outputBuilder.Append(op?.Value?.ResolvedObject?.Class?.GetType().Name.GetPrefix() + classString); - } - outputBuilder.Append(">(\""); - var resolvedObject = op?.Value?.ResolvedObject; - var outerString = resolvedObject?.Outer?.ToString()?.Replace("'", "") ?? "outerUnknown"; - var outerClassString = resolvedObject?.Class?.ToString()?.Replace("'", "") ?? "outerClassUnknown"; - var name = op?.Value?.Name ?? string.Empty; - - outputBuilder.Append(outerString.Replace(outerClassString, "") + "." + name); - outputBuilder.Append("\")"); - break; - } - case EExprToken.EX_BindDelegate: - { - EX_BindDelegate op = (EX_BindDelegate) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(".BindUFunction("); - ProcessExpression(op.ObjectTerm.Token, op.ObjectTerm, outputBuilder, jumpCodeOffsets); - outputBuilder.Append($", \"{op.FunctionName}\""); - outputBuilder.Append(");\n\n"); - break; - } - // all the delegate functions suck - case EExprToken.EX_AddMulticastDelegate: - { - EX_AddMulticastDelegate op = (EX_AddMulticastDelegate) expression; - if (op.Delegate.Token is EExprToken.EX_LocalVariable or EExprToken.EX_InstanceVariable) - { - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(".AddDelegate("); - ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(");\n\n"); - } - else if (op.Delegate.Token != EExprToken.EX_Context) - {} - else - { - //EX_Context opp = (EX_Context) op.Delegate; - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - //outputBuilder.Append("->"); - //ProcessExpression(opp.ContextExpression.Token, opp.ContextExpression, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(".AddDelegate("); - ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(");\n\n"); - } - break; - } - case EExprToken.EX_RemoveMulticastDelegate: // everything here has been guessed not compared to actual UE but does work fine and displays all information - { - EX_RemoveMulticastDelegate op = (EX_RemoveMulticastDelegate) expression; - if (op.Delegate.Token is EExprToken.EX_LocalVariable or EExprToken.EX_InstanceVariable) - { - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(".RemoveDelegate("); - ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(");\n\n"); - } - else if (op.Delegate.Token != EExprToken.EX_Context) - { - - } - else - { - EX_Context opp = (EX_Context) op.Delegate; - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append("->"); - ProcessExpression(opp.ContextExpression.Token, opp.ContextExpression, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(".RemoveDelegate("); - ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets); - outputBuilder.Append(");\n\n"); - } - break; - } - case EExprToken.EX_ClearMulticastDelegate: // this also - { - EX_ClearMulticastDelegate op = (EX_ClearMulticastDelegate) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.DelegateToClear.Token, op.DelegateToClear, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(".Clear();\n\n"); - break; - } - case EExprToken.EX_CallMulticastDelegate: // this also - { - EX_CallMulticastDelegate op = (EX_CallMulticastDelegate) expression; - KismetExpression[] opp = op.Parameters; - if (op.Delegate.Token == EExprToken.EX_LocalVariable || op.Delegate.Token == EExprToken.EX_InstanceVariable) - { - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(".Call("); - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t"); - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(");\n\n"); - } - else if (op.Delegate.Token != EExprToken.EX_Context) - { - - } - else - { - outputBuilder.Append("\t\t"); - ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(".Call("); - for (int i = 0; i < opp.Length; i++) - { - if (opp.Length > 4) - outputBuilder.Append("\n\t\t"); - ProcessExpression(opp[i].Token, opp[i], outputBuilder, jumpCodeOffsets, true); - if (i < opp.Length - 1) - { - outputBuilder.Append(", "); - } - } - outputBuilder.Append(");\n\n"); - } - break; - } - case EExprToken.EX_ClassContext: - case EExprToken.EX_Context: - { - EX_Context op = (EX_Context) expression; - outputBuilder.Append(outputBuilder.ToString().EndsWith('\n') ? "\t\t" : ""); - ProcessExpression(op.ObjectExpression.Token, op.ObjectExpression, outputBuilder, jumpCodeOffsets, true); - - outputBuilder.Append("->"); - ProcessExpression(op.ContextExpression.Token, op.ContextExpression, outputBuilder, jumpCodeOffsets, true); - if (!isParameter) - { - outputBuilder.Append(";\n\n"); - } - break; - } - case EExprToken.EX_Context_FailSilent: - { - EX_Context op = (EX_Context) expression; - outputBuilder.Append("\t\t"); - ProcessExpression(op.ObjectExpression.Token, op.ObjectExpression, outputBuilder, jumpCodeOffsets, true); - if (!isParameter) - { - outputBuilder.Append("->"); - ProcessExpression(op.ContextExpression.Token, op.ContextExpression, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(";\n\n"); - } - break; - } - case EExprToken.EX_Let: - { - EX_Let op = (EX_Let) expression; - if (!isParameter) - { - outputBuilder.Append("\t\t"); - } - ProcessExpression(op.Variable.Token, op.Variable, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(" = "); - ProcessExpression(op.Assignment.Token, op.Assignment, outputBuilder, jumpCodeOffsets, true); - if (!isParameter) - { - outputBuilder.Append(";\n\n"); - } - break; - } - case EExprToken.EX_LetObj: - case EExprToken.EX_LetWeakObjPtr: - case EExprToken.EX_LetBool: - case EExprToken.EX_LetDelegate: - case EExprToken.EX_LetMulticastDelegate: - { - EX_LetBase op = (EX_LetBase) expression; - if (!isParameter) - { - outputBuilder.Append("\t\t"); - } - ProcessExpression(op.Variable.Token, op.Variable, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(" = "); - ProcessExpression(op.Assignment.Token, op.Assignment, outputBuilder, jumpCodeOffsets, true); - if (!isParameter || op.Assignment.Token == EExprToken.EX_LocalFinalFunction || op.Assignment.Token == EExprToken.EX_FinalFunction || op.Assignment.Token == EExprToken.EX_CallMath) - { - outputBuilder.Append(";\n\n"); - } - else - { - outputBuilder.Append(';'); - } - break; - } - case EExprToken.EX_JumpIfNot: - { - EX_JumpIfNot op = (EX_JumpIfNot) expression; - outputBuilder.Append("\t\tif (!"); - ProcessExpression(op.BooleanExpression.Token, op.BooleanExpression, outputBuilder, jumpCodeOffsets, true); - outputBuilder.Append(") \r\n"); - outputBuilder.Append("\t\t goto Label_"); - outputBuilder.Append(op.CodeOffset); - outputBuilder.Append(";\n\n"); - break; - } - case EExprToken.EX_Jump: - { - EX_Jump op = (EX_Jump) expression; - outputBuilder.Append($"\t\tgoto Label_{op.CodeOffset};\n\n"); - break; - } - // Static expressions - - case EExprToken.EX_TextConst: - { - EX_TextConst op = (EX_TextConst) expression; - - if (op.Value is FScriptText scriptText) - { - if (scriptText.SourceString == null) - { - outputBuilder.Append("nullptr"); - } - else - ProcessExpression(scriptText.SourceString.Token, scriptText.SourceString, outputBuilder, jumpCodeOffsets, true); - } - else - { - outputBuilder.Append(op.Value); // impossible to reach? - } - } - break; - case EExprToken.EX_StructMemberContext: - { - EX_StructMemberContext op = (EX_StructMemberContext) expression; - ProcessExpression(op.StructExpression.Token, op.StructExpression, outputBuilder, jumpCodeOffsets); - outputBuilder.Append('.'); - outputBuilder.Append(ProcessTextProperty(op.Property, false)); - break; - } - case EExprToken.EX_Return: - { - EX_Return op = (EX_Return) expression; - bool check = op.ReturnExpression.Token == EExprToken.EX_Nothing; - outputBuilder.Append("\t\treturn"); - if (!check) - outputBuilder.Append(' '); - ProcessExpression(op.ReturnExpression.Token, op.ReturnExpression, outputBuilder, jumpCodeOffsets, true); - outputBuilder.AppendLine(";"); - break; - } - case EExprToken.EX_RotationConst: - { - EX_RotationConst op = (EX_RotationConst) expression; - FRotator value = op.Value; - outputBuilder.Append($"FRotator({value.Pitch}, {value.Yaw}, {value.Roll})"); - break; - } - case EExprToken.EX_VectorConst: - { - EX_VectorConst op = (EX_VectorConst) expression; - FVector value = op.Value; - outputBuilder.Append($"FVector({value.X}, {value.Y}, {value.Z})"); - break; - } - case EExprToken.EX_Vector3fConst: - { - EX_Vector3fConst op = (EX_Vector3fConst) expression; - FVector value = op.Value; - outputBuilder.Append($"FVector3f({value.X}, {value.Y}, {value.Z})"); - break; - } - case EExprToken.EX_TransformConst: - { - EX_TransformConst op = (EX_TransformConst) expression; - FTransform value = op.Value; - outputBuilder.Append($"FTransform(FQuat({value.Rotation.X}, {value.Rotation.Y}, {value.Rotation.Z}, {value.Rotation.W}), FVector({value.Translation.X}, {value.Translation.Y}, {value.Translation.Z}), FVector({value.Scale3D.X}, {value.Scale3D.Y}, {value.Scale3D.Z}))"); - break; - } - - - case EExprToken.EX_LocalVariable: - case EExprToken.EX_DefaultVariable: - case EExprToken.EX_LocalOutVariable: - case EExprToken.EX_ClassSparseDataVariable: - outputBuilder.Append(ProcessTextProperty(((EX_VariableBase) expression).Variable, false)); - break; - case EExprToken.EX_InstanceVariable: - outputBuilder.Append(ProcessTextProperty(((EX_VariableBase) expression).Variable, true)); - break; - - case EExprToken.EX_ByteConst: - case EExprToken.EX_IntConstByte: - outputBuilder.Append($"0x{((KismetExpression) expression).Value.ToString("X")}"); - break; - case EExprToken.EX_SoftObjectConst: - ProcessExpression(((EX_SoftObjectConst) expression).Value.Token, ((EX_SoftObjectConst) expression).Value, outputBuilder, jumpCodeOffsets); - break; - case EExprToken.EX_DoubleConst: - { - double value = ((EX_DoubleConst) expression).Value; - outputBuilder.Append(Math.Abs(value - Math.Floor(value)) < 1e-10 ? (int) value : value.ToString("R")); - break; - } - case EExprToken.EX_NameConst: - outputBuilder.Append($"\"{((EX_NameConst) expression).Value}\""); - break; - case EExprToken.EX_IntConst: - outputBuilder.Append(((EX_IntConst) expression).Value.ToString()); - break; - case EExprToken.EX_PropertyConst: - outputBuilder.Append(ProcessTextProperty(((EX_PropertyConst) expression).Property, false)); - break; - case EExprToken.EX_StringConst: - outputBuilder.Append($"\"{((EX_StringConst) expression).Value}\""); - break; - case EExprToken.EX_FieldPathConst: - ProcessExpression(((EX_FieldPathConst) expression).Value.Token, ((EX_FieldPathConst) expression).Value, outputBuilder, jumpCodeOffsets); - break; - case EExprToken.EX_Int64Const: - outputBuilder.Append(((EX_Int64Const) expression).Value.ToString()); - break; - case EExprToken.EX_UInt64Const: - outputBuilder.Append(((EX_UInt64Const) expression).Value.ToString()); - break; - case EExprToken.EX_SkipOffsetConst: - outputBuilder.Append(((EX_SkipOffsetConst) expression).Value.ToString()); - break; - case EExprToken.EX_FloatConst: - outputBuilder.Append(((EX_FloatConst) expression).Value.ToString(CultureInfo.GetCultureInfo("en-US"))); - break; - case EExprToken.EX_BitFieldConst: - outputBuilder.Append(((EX_BitFieldConst) expression).ConstValue); - break; - case EExprToken.EX_UnicodeStringConst: - outputBuilder.Append(((EX_UnicodeStringConst) expression).Value); - break; - case EExprToken.EX_InstanceDelegate: - outputBuilder.Append($"\"{((EX_InstanceDelegate) expression).FunctionName}\""); - break; - case EExprToken.EX_EndOfScript: - case EExprToken.EX_EndParmValue: - outputBuilder.Append("\t}\n"); - break; - case EExprToken.EX_NoObject: - case EExprToken.EX_NoInterface: - outputBuilder.Append("nullptr"); - break; - case EExprToken.EX_IntOne: - outputBuilder.Append(1); - break; - case EExprToken.EX_IntZero: - outputBuilder.Append(0); - break; - case EExprToken.EX_True: - outputBuilder.Append("true"); - break; - case EExprToken.EX_False: - outputBuilder.Append("false"); - break; - case EExprToken.EX_Self: - outputBuilder.Append("this"); - break; - - case EExprToken.EX_Nothing: - case EExprToken.EX_NothingInt32: - case EExprToken.EX_EndFunctionParms: - case EExprToken.EX_EndStructConst: - case EExprToken.EX_EndArray: - case EExprToken.EX_EndArrayConst: - case EExprToken.EX_EndSet: - case EExprToken.EX_EndMap: - case EExprToken.EX_EndMapConst: - case EExprToken.EX_EndSetConst: - case EExprToken.EX_PushExecutionFlow: - case EExprToken.EX_PopExecutionFlow: - case EExprToken.EX_DeprecatedOp4A: - case EExprToken.EX_WireTracepoint: - case EExprToken.EX_Tracepoint: - case EExprToken.EX_Breakpoint: - case EExprToken.EX_AutoRtfmStopTransact: - case EExprToken.EX_AutoRtfmTransact: - case EExprToken.EX_AutoRtfmAbortIfNot: - // some here are "useful" and unsupported - break; - /* - Todo: check what uses these, fortnite has none instances - EExprToken.EX_Assert - EExprToken.EX_Skip - EExprToken.EX_InstrumentationEvent - EExprToken.EX_FieldPathConst - */ - default: - outputBuilder.Append($"{token}"); - break; - } - } -} diff --git a/FModel/Resources/Cpp.xshd b/FModel/Resources/Cpp.xshd index f02e55c0..f61b1264 100644 --- a/FModel/Resources/Cpp.xshd +++ b/FModel/Resources/Cpp.xshd @@ -82,6 +82,7 @@ friend inline constexpr + default @@ -119,6 +120,8 @@ [\[\]\{\}] + (\/\/.*|\/\*[\s\S]*?\*\/) + \b[A-Za-z_][A-Za-z0-9_]*\b(?=<) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 1b87ad79..2590b975 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -74,10 +74,12 @@ public class CUE4ParseViewModel : ViewModel { private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView; private ApiEndpointViewModel _apiEndpointView => ApplicationService.ApiEndpointView; + private readonly Regex _fnLiveRegex = new(@"^FortniteGame[/\\]Content[/\\]Paks[/\\]", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private bool _modelIsOverwritingMaterial; + public bool ModelIsOverwritingMaterial { get => _modelIsOverwritingMaterial; @@ -86,6 +88,7 @@ public class CUE4ParseViewModel : ViewModel public bool IsSnooperOpen => _snooper is { Exists: true, IsVisible: true }; private Snooper _snooper; + public Snooper SnooperViewer { get @@ -445,6 +448,7 @@ public class CUE4ParseViewModel : ViewModel public int LocalizedResourcesCount { get; set; } public bool LocalResourcesDone { get; set; } public bool HotfixedResourcesDone { get; set; } + public async Task LoadLocalizedResources() { var snapshot = LocalizedResourcesCount; @@ -458,6 +462,7 @@ public class CUE4ParseViewModel : ViewModel Utils.Typefaces = new Typefaces(this); } } + private Task LoadGameLocalizedResources() { if (LocalResourcesDone) return Task.CompletedTask; @@ -466,6 +471,7 @@ public class CUE4ParseViewModel : ViewModel LocalResourcesDone = Provider.TryChangeCulture(Provider.GetLanguageCode(UserSettings.Default.AssetLanguage)); }); } + private Task LoadHotfixedLocalizedResources() { if (!Provider.ProjectName.Equals("fortnitegame", StringComparison.OrdinalIgnoreCase) || HotfixedResourcesDone) return Task.CompletedTask; @@ -480,6 +486,7 @@ public class CUE4ParseViewModel : ViewModel } private int _virtualPathCount { get; set; } + public Task LoadVirtualPaths() { if (_virtualPathCount > 0) return Task.CompletedTask; @@ -698,7 +705,7 @@ public class CUE4ParseViewModel : ViewModel case "wav": case "WAV": case "ogg": - // todo: CSCore.MediaFoundation.MediaFoundationException The byte stream type of the given URL is unsupported. case "aif": + // todo: CSCore.MediaFoundation.MediaFoundationException The byte stream type of the given URL is unsupported. case "aif": { var data = Provider.SaveAsset(entry); SaveAndPlaySound(entry.PathWithoutExtension, entry.Extension, data); @@ -988,271 +995,34 @@ public class CUE4ParseViewModel : ViewModel var pkg = Provider.LoadPackage(entry); - var outputBuilder = new StringBuilder(); + string mypathisapathrealwhathowPath = Path.Combine( + Path.GetDirectoryName(entry.Path)!, + $"{Path.GetFileNameWithoutExtension(entry.Path)}.o.uasset" + ); + + string idkhowtogetitwithoutthis = string.Empty; + try + { + var whatisthisforealreal = Provider.GetLoadPackageResult(mypathisapathrealwhathowPath); + idkhowtogetitwithoutthis = JsonConvert.SerializeObject(whatisthisforealreal.GetDisplayData(false), Formatting.Indented); + } + catch (Exception e) {} + + + var cpp = string.Empty; for (var i = 0; i < pkg.ExportMapLength; i++) { var pointer = new FPackageIndex(pkg, i + 1).ResolvedObject; - if (pointer?.Object is null) + if (pointer?.Object is null && pointer.Class?.Object?.Value is null) continue; var dummy = ((AbstractUePackage) pkg).ConstructObject(pointer.Class?.Object?.Value as UStruct, pkg); if (dummy is not UClass || pointer.Object.Value is not UClass blueprint) continue; - var typePrefix = blueprint?.SuperStruct.Load().GetPrefix(); - var modifierStr = blueprint.Flags.HasAnyFlags(EObjectFlags.RF_Public) ? "public" : "private"; - outputBuilder.AppendLine($"class {typePrefix}{blueprint.Name} : {modifierStr} {typePrefix}{blueprint?.SuperStruct?.Name ?? string.Empty}\n{{\n{modifierStr}:"); - - if (!blueprint.ClassDefaultObject.TryLoad(out var bpObject)) - continue; - - var strings = new List(); - foreach (var property in bpObject.Properties) - { - var propertyName = property.Name.ToString(); - var propertyValue = property.Tag?.GenericValue; - strings.Add(propertyName); - string placeholder = $"{propertyName}fmodelholder"; // spelling mistake is intended - - void ShouldAppend(string value) - { - if (outputBuilder.ToString().Contains(placeholder)) - { - outputBuilder.Replace(placeholder, value); - } - else - { - outputBuilder.AppendLine($"\t{KismetExtensions.GetPropertyType(propertyValue)} {propertyName.Replace(" ", "")} = {value};"); - } - } - - string GetLineOfText(object value) - { - string text = null; - switch (value) - { - case FScriptStruct structTag: - switch (structTag.StructType) - { - case FVector vector: - text = $"FVector({vector.X}, {vector.Y}, {vector.Z})"; - break; - case FGuid guid: - text = $"FGuid({guid.A}, {guid.B}, {guid.C}, {guid.D})"; - break; - case TIntVector3 vector3: - text = $"FVector({vector3.X}, {vector3.Y}, {vector3.Z})"; - break; - case TIntVector3 floatVector3: - text = $"FVector({floatVector3.X}, {floatVector3.Y}, {floatVector3.Z})"; - break; - case TIntVector2 floatVector2: - text = $"FVector2D({floatVector2.X}, {floatVector2.Y})"; - break; - case FVector2D vector2d: - text = $"FVector2D({vector2d.X}, {vector2d.Y})"; - break; - case FRotator rotator: - text = $"FRotator({rotator.Pitch}, {rotator.Yaw}, {rotator.Roll})"; - break; - case FLinearColor linearColor: - text = $"FLinearColor({linearColor.R}, {linearColor.G}, {linearColor.B}, {linearColor.A})"; - break; - case FGameplayTagContainer gTag: - text = gTag.GameplayTags.Length switch - { - > 1 => "[\n" + string.Join(",\n", gTag.GameplayTags.Select(tag => $"\t\t\"{tag.TagName}\"")) + "\n\t]", - > 0 => $"\"{gTag.GameplayTags[0].TagName}\"", - _ => "[]" - }; - break; - case FStructFallback fallback: - if (fallback.Properties.Count > 0) - { - text = "[\n" + string.Join(",\n", fallback.Properties.Select(p => $"\t\"{GetLineOfText(p)}\"")) + "\n\t]"; - } - else - { - text = "[]"; - } - break; - } - break; - case UScriptSet: - case UScriptMap: - case UScriptArray: - IEnumerable inner = value switch - { - UScriptSet set => set.Properties.Select(p => $"\t\"{p.GenericValue}\""), - UScriptMap map => map.Properties.Select(kvp => $"\t{{\n\t\t\"{kvp.Key}\": \"{kvp.Value}\"\n\t}}"), - UScriptArray array => array.Properties.Select(p => $"\t\"{GetLineOfText(p)}\""), - _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) - }; - - text = "[\n" + string.Join(",\n", inner) + "\n\t]"; - break; - case FMulticastScriptDelegate multicast: - text = multicast.InvocationList.Length == 0 ? "[]" : $"[{string.Join(", ", multicast.InvocationList.Select(x => $"\"{x.FunctionName}\""))}]"; - break; - case bool: - text = value.ToString()?.ToLowerInvariant(); - break; - } - - return text ?? value.ToString(); - } - - ShouldAppend(GetLineOfText(propertyValue)); - } - - foreach (var field in blueprint.ChildProperties) - { - if (field is not FProperty property || strings.Contains(property.Name.Text)) continue; - - var propertyName = property.Name.ToString().Replace(" ", ""); - var type = KismetExtensions.GetPropertyType(property); - - var prefix = ""; - switch (property) - { - case FFieldPathProperty pathProp: - prefix = pathProp.PropertyClass.ToString().GetPrefix(); - break; - case FObjectProperty objectProp: - prefix = objectProp.PropertyClass.ToString().GetPrefix(); - break; - } - - outputBuilder.AppendLine($"\t{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")} {propertyName} = {propertyName}fmodelholder;"); - } - - { - var funcMapOrder = blueprint?.FuncMap?.Keys.Select(fname => fname.ToString()).ToList(); - var functions = pkg.ExportsLazy - .Where(e => e.Value is UFunction) - .Select(e => (UFunction) e.Value) - .OrderBy(f => - { - if (funcMapOrder != null) - { - var functionName = f.Name.ToString(); - int index = funcMapOrder.IndexOf(functionName); - return index >= 0 ? index : int.MaxValue; - } - - return int.MaxValue; - }) - .ThenBy(f => f.Name.ToString()) - .ToList(); - - var jumpCodeOffsetsMap = new Dictionary>(); - - foreach (var function in functions.AsEnumerable().Reverse()) - { - if (function?.ScriptBytecode == null) - continue; - - foreach (var property in function.ScriptBytecode) - { - string label = string.Empty; - int offset = 0; - - switch (property.Token) - { - case EExprToken.EX_JumpIfNot: - label = ((EX_JumpIfNot) property).ObjectPath?.ToString()?.Split('.').Last().Split('[')[0]; - offset = (int) ((EX_JumpIfNot) property).CodeOffset; - break; - - case EExprToken.EX_Jump: - label = ((EX_Jump) property).ObjectPath?.ToString()?.Split('.').Last().Split('[')[0]; - offset = (int) ((EX_Jump) property).CodeOffset; - break; - - case EExprToken.EX_LocalFinalFunction: - { - EX_FinalFunction op = (EX_FinalFunction) property; - label = op.StackNode?.Name?.Split('.').Last().Split('[')[0]; - - if (op is { Parameters: [EX_IntConst intConst] }) - offset = intConst.Value; - break; - } - } - - if (!string.IsNullOrEmpty(label)) - { - if (!jumpCodeOffsetsMap.TryGetValue(label, out var list)) - jumpCodeOffsetsMap[label] = list = new List(); - - list.Add(offset); - } - } - } - - foreach (var function in functions) - { - string argsList = ""; - string returnFunc = "void"; - if (function?.ChildProperties != null) - { - foreach (FProperty property in function.ChildProperties) - { - var name = property.Name.ToString(); - var plainName = property.Name.PlainText; - var prefix = ""; - switch (property) - { - case FFieldPathProperty pathProp: - prefix = pathProp.PropertyClass.ToString().GetPrefix(); - break; - case FObjectProperty objectProp: - prefix = objectProp.PropertyClass.ToString().GetPrefix(); - break; - } - var type = KismetExtensions.GetPropertyType(property); - var isConst = property.PropertyFlags.HasFlag(EPropertyFlags.ConstParm); - var isOut = property.PropertyFlags.HasFlag(EPropertyFlags.OutParm); - var isEdit = property.PropertyFlags.HasFlag(EPropertyFlags.Edit); - - if (plainName == "ReturnValue") - { - returnFunc = $"{(isConst ? "const " : "")}{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")}"; - continue; - } - - bool uselessIgnore = name.EndsWith("_ReturnValue") || name.StartsWith("CallFunc_") || name.StartsWith("K2Node_") || name.StartsWith("Temp_"); // read variable name - - if (uselessIgnore && !isEdit) - continue; - - var strippedVerseName = Regex.Replace(name, @"^__verse_0x[0-9A-Fa-f]+_", ""); - argsList += $"{(isConst ? "const " : "")}{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")}{(isOut ? '&' : "")} {strippedVerseName}, "; - } - } - argsList = argsList.TrimEnd(',', ' '); - - outputBuilder.AppendLine($"\n\t{returnFunc} {function.Name.Replace(" ", "")}({argsList})\n\t{{"); - if (function?.ScriptBytecode != null) - { - var jumpCodeOffsets = jumpCodeOffsetsMap.TryGetValue(function.Name, out var list) ? list : new List(); - foreach (KismetExpression property in function.ScriptBytecode) - { - KismetExtensions.ProcessExpression(property.Token, property, outputBuilder, jumpCodeOffsets); - } - } - else - { - outputBuilder.Append("\n\t // No Bytecode (Make sure \"Serialize Script Bytecode\" is enabled \n\n"); - outputBuilder.Append("\t}\n"); - } - } - - outputBuilder.Append("\n\n}"); - } + cpp += blueprint.DecompileBlueprintToPseudo(idkhowtogetitwithoutthis); } - var cpp = Regex.Replace(outputBuilder.ToString(), @"\w+fmodelholder", "nullptr"); TabControl.SelectedTab.SetDocumentText(cpp, false, false); } diff --git a/FModel/ViewModels/SearchViewModel.cs b/FModel/ViewModels/SearchViewModel.cs index 15585911..35cb9bc3 100644 --- a/FModel/ViewModels/SearchViewModel.cs +++ b/FModel/ViewModels/SearchViewModel.cs @@ -4,13 +4,38 @@ using System.ComponentModel; using System.Linq; using System.Text.RegularExpressions; using System.Windows.Data; +using System.Windows.Input; using CUE4Parse.FileProvider.Objects; using FModel.Framework; namespace FModel.ViewModels; +public class RelayCommand : ICommand +{ + private readonly Action _execute; + private readonly Func? _canExecute; + + public event EventHandler? CanExecuteChanged; + + public RelayCommand(Action execute, Func? canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true; + public void Execute(object? parameter) => _execute(); + +} + public class SearchViewModel : ViewModel { + public enum ESortSizeMode + { + None, + Ascending, + Descending + } + private string _filterText; public string FilterText { @@ -32,6 +57,29 @@ public class SearchViewModel : ViewModel set => SetProperty(ref _hasMatchCaseEnabled, value); } + private ESortSizeMode _currentSortSizeMode = ESortSizeMode.None; + public ESortSizeMode CurrentSortSizeMode + { + get => _currentSortSizeMode; + set => SetProperty(ref _currentSortSizeMode, value); + } + + public void CycleSortSizeMode() + { + CurrentSortSizeMode = CurrentSortSizeMode switch + { + ESortSizeMode.None => ESortSizeMode.Ascending, + ESortSizeMode.Ascending => ESortSizeMode.Descending, + ESortSizeMode.Descending => ESortSizeMode.None, + _ => ESortSizeMode.None + }; + + RefreshFilter(); + } + + private RelayCommand? _sortSizeModeCommand; + public ICommand SortSizeModeCommand => _sortSizeModeCommand ??= new RelayCommand(CycleSortSizeMode); + public int ResultsCount => SearchResults?.Count ?? 0; public RangeObservableCollection SearchResults { get; } public ICollectionView SearchResultsView { get; } @@ -48,6 +96,14 @@ public class SearchViewModel : ViewModel SearchResultsView.Filter = e => ItemFilter(e, FilterText.Trim().Split(' ')); else SearchResultsView.Refresh(); + + SearchResultsView.SortDescriptions.Clear(); + + if (CurrentSortSizeMode != ESortSizeMode.None) + SearchResultsView.SortDescriptions.Add(new SortDescription(nameof(GameFile.Size), + CurrentSortSizeMode == ESortSizeMode.Ascending + ? ListSortDirection.Ascending + : ListSortDirection.Descending)); } private bool ItemFilter(object item, IEnumerable filters) @@ -62,4 +118,4 @@ public class SearchViewModel : ViewModel if (!HasMatchCaseEnabled) o |= RegexOptions.IgnoreCase; return new Regex(FilterText, o).Match(entry.Path).Success; } -} +} \ No newline at end of file diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 1d1500ed..c42ee085 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -70,6 +70,7 @@ M1.8 6q-.525 0-.887-.35Q.55 5.3.55 4.8V4q0-1.425 1.012-2.438Q2.575.55 4 .55h.8q.5 0 .85.362.35.363.35.888 0 .5-.35.85T4.8 3H4q-.425 0-.712.287Q3 3.575 3 4v.8q0 .5-.35.85T1.8 6ZM4 23.45q-1.425 0-2.438-1.012Q.55 21.425.55 20v-.8q0-.5.363-.85.362-.35.887-.35.5 0 .85.35t.35.85v.8q0 .425.288.712Q3.575 21 4 21h.8q.5 0 .85.35t.35.85q0 .525-.35.887-.35.363-.85.363Zm15.2 0q-.5 0-.85-.363-.35-.362-.35-.887 0-.5.35-.85t.85-.35h.8q.425 0 .712-.288Q21 20.425 21 20v-.8q0-.5.35-.85t.85-.35q.525 0 .888.35.362.35.362.85v.8q0 1.425-1.012 2.438Q21.425 23.45 20 23.45ZM22.2 6q-.5 0-.85-.35T21 4.8V4q0-.425-.288-.713Q20.425 3 20 3h-.8q-.5 0-.85-.35T18 1.8q0-.525.35-.888.35-.362.85-.362h.8q1.425 0 2.438 1.012Q23.45 2.575 23.45 4v.8q0 .5-.362.85-.363.35-.888.35ZM12 17.35l1-.575v-4.1l3.55-2.075V9.425l-1-.575L12 10.925 8.45 8.85l-1 .575V10.6L11 12.675v4.1Zm-1.325 2.325-4.55-2.65q-.625-.35-.975-.963-.35-.612-.35-1.337V9.45q0-.725.35-1.337.35-.613.975-.963l4.55-2.65Q11.3 4.15 12 4.15t1.325.35l4.55 2.65q.625.35.975.963.35.612.35 1.337v5.275q0 .725-.35 1.337-.35.613-.975.963l-4.55 2.65q-.625.35-1.325.35t-1.325-.35Z M3.5 1.75v11.5c0 .09.048.173.126.217a.75.75 0 0 1-.752 1.298A1.748 1.748 0 0 1 2 13.25V1.75C2 .784 2.784 0 3.75 0h5.586c.464 0 .909.185 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v8.586A1.75 1.75 0 0 1 12.25 15h-.5a.75.75 0 0 1 0-1.5h.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177L9.513 1.573a.25.25 0 0 0-.177-.073H7.25a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5h-3a.25.25 0 0 0-.25.25Zm3.75 8.75h.5c.966 0 1.75.784 1.75 1.75v3a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1-.75-.75v-3c0-.966.784-1.75 1.75-1.75ZM6 5.25a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 6 5.25Zm.75 2.25h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM8 6.75A.75.75 0 0 1 8.75 6h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 8 6.75ZM8.75 3h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM8 9.75A.75.75 0 0 1 8.75 9h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 8 9.75Zm-1 2.5v2.25h1v-2.25a.25.25 0 0 0-.25-.25h-.5a.25.25 0 0 0-.25.25Z M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z + M8 16H4l6 6V2H8zm6-11v17h2V8h4l-6-6z