mirror of
https://github.com/4sval/FModel.git
synced 2026-03-22 01:34:37 -05:00
refactored parts of this hell
This commit is contained in:
parent
e78c7a7be9
commit
00bcb7ca16
|
|
@ -3,10 +3,6 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using CUE4Parse.FileProvider;
|
||||
using CUE4Parse.FileProvider.Objects;
|
||||
using CUE4Parse.UE4.Assets;
|
||||
using CUE4Parse.UE4.Assets.Objects.Properties;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Kismet;
|
||||
|
|
@ -16,14 +12,12 @@ using CUE4Parse.UE4.Objects.Engine.Ai;
|
|||
using CUE4Parse.UE4.Objects.Engine.GameFramework;
|
||||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Settings;
|
||||
using Microsoft.VisualBasic.Logging;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public static class KismetExtensions
|
||||
{
|
||||
public static string GetPrefix(string? type, string? extra = "")
|
||||
public static string GetPrefix(string type, string extra = "")
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
|
|
@ -43,18 +37,9 @@ public static class KismetExtensions
|
|||
{
|
||||
string typeName = field.GetType().Name;
|
||||
int suffixIndex = typeName.IndexOf("Property", StringComparison.Ordinal);
|
||||
if (suffixIndex < 0)
|
||||
return typeName;
|
||||
return typeName.Substring(1, suffixIndex - 1);
|
||||
}
|
||||
public static string GetUnknownFieldType(FField field)
|
||||
{
|
||||
string typeName = field.GetType().Name;
|
||||
int suffixIndex = typeName.IndexOf("Property", StringComparison.Ordinal);
|
||||
if (suffixIndex < 0)
|
||||
return typeName;
|
||||
return typeName.Substring(1, suffixIndex - 1);
|
||||
return suffixIndex < 0 ? typeName : typeName.Substring(1, suffixIndex - 1);
|
||||
}
|
||||
|
||||
public static string GetPropertyType(object? property)
|
||||
{
|
||||
if (property is null)
|
||||
|
|
@ -62,33 +47,33 @@ public static class KismetExtensions
|
|||
|
||||
return property switch
|
||||
{
|
||||
FIntProperty => "int",
|
||||
FInt8Property => "int8",
|
||||
FInt16Property => "int16",
|
||||
FInt64Property => "int64",
|
||||
FUInt16Property => "uint16",
|
||||
FUInt32Property => "uint32",
|
||||
FUInt64Property => "uint64",
|
||||
FBoolProperty or Boolean => "bool",
|
||||
FStrProperty => "FString",
|
||||
FFloatProperty or Single => "float",
|
||||
FDoubleProperty or Double => "double",
|
||||
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 ?? "UNKNOWN"}",
|
||||
FSoftClassProperty softClass => $"{softClass.MetaClass?.Name ?? "UNKNOWN"}",
|
||||
_ => objct.PropertyClass?.Name ?? "UNKNOWN"
|
||||
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 ?? "FName",
|
||||
FEnumProperty enm => enm.Enum?.Name.ToString() ?? "Enum",
|
||||
FByteProperty bt => bt.Enum.ResolvedObject?.Name.Text ?? "Byte",
|
||||
FInterfaceProperty intrfc => $"{intrfc.InterfaceClass.Name} interface",
|
||||
FStructProperty strct => strct.Struct.ResolvedObject?.Name.Text ?? "Struct",
|
||||
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 ?? "UNKNOWN"} (Delegate)",
|
||||
FMulticastDelegateProperty mdlgt => $"{mdlgt.SignatureFunction?.Name ?? "UNKNOWN"} (MulticastDelegateProperty)",
|
||||
FMulticastInlineDelegateProperty midlgt => $"{midlgt.SignatureFunction?.Name ?? "UNKNOWN"} (MulticastInlineDelegateProperty)",
|
||||
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)
|
||||
};
|
||||
}
|
||||
|
|
@ -99,31 +84,13 @@ public static class KismetExtensions
|
|||
|
||||
return property switch
|
||||
{
|
||||
FIntProperty => "int",
|
||||
FBoolProperty => "bool",
|
||||
FStrProperty => "FString",
|
||||
FFloatProperty => "float",
|
||||
FDoubleProperty => "double",
|
||||
FObjectProperty objct => property switch
|
||||
{
|
||||
FClassProperty clss => $"{clss.MetaClass?.Name ?? "UNKNOWN"} Class",
|
||||
FSoftClassProperty softClass => $"{softClass.MetaClass?.Name ?? "UNKNOWN"} Class (soft)",
|
||||
_ => objct.PropertyClass?.Name ?? "UNKNOWN"
|
||||
},
|
||||
FEnumProperty enm => enm.Enum?.Name.ToString() ?? "Enum",
|
||||
FSetProperty set => $"TSet<{GetPrefix(set.ElementProp.GetType().Name)}{GetPropertyType(set.ElementProp)}{(set.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || set.PropertyFlags.HasFlag(EPropertyFlags.ContainsInstancedReference) ? "*" : string.Empty)}>",
|
||||
FByteProperty bt => bt.Enum.ResolvedObject?.Name.Text ?? "Byte",
|
||||
FInterfaceProperty intrfc => $"{intrfc.InterfaceClass.Name} interface",
|
||||
FStructProperty strct => strct.Struct.ResolvedObject?.Name.Text ?? "Struct",
|
||||
FFieldPathProperty fieldPath => $"{fieldPath.PropertyClass.Text} field path",
|
||||
FDelegateProperty dlgt => $"{dlgt.SignatureFunction?.Name ?? "UNKNOWN"} (Delegate)",
|
||||
FMapProperty map => $"TMap<{GetPrefix(map.ValueProp.GetType().Name)}{GetPropertyType(map.KeyProp)}, {GetPrefix(map.ValueProp.GetType().Name)}{GetPropertyType(map.ValueProp)}{(map.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || map.PropertyFlags.HasFlag(EPropertyFlags.ContainsInstancedReference) ? "*" : string.Empty)}>",
|
||||
FMulticastDelegateProperty mdlgt => $"{mdlgt.SignatureFunction?.Name ?? "UNKNOWN"} (MulticastDelegateProperty)",
|
||||
FMulticastInlineDelegateProperty midlgt => $"{midlgt.SignatureFunction?.Name ?? "UNKNOWN"} (MulticastInlineDelegateProperty)",
|
||||
FArrayProperty array => $"TArray<{GetPrefix(array.Inner.GetType().Name)}{GetPropertyType(array.Inner)}{(array.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || array.PropertyFlags.HasFlag(EPropertyFlags.ContainsInstancedReference) || GetPropertyProperty(array.Inner.GetType().Name) ? "*" : string.Empty)}>",
|
||||
_ => GetUnknownFieldType(property)
|
||||
_ => GetPropertyType((object)property)
|
||||
};
|
||||
}
|
||||
|
||||
public static bool GetPropertyProperty(object? property)
|
||||
{
|
||||
if (property is null)
|
||||
|
|
@ -131,21 +98,11 @@ public static class KismetExtensions
|
|||
|
||||
return property switch
|
||||
{
|
||||
FObjectProperty objct => true,
|
||||
FObjectProperty => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
public static bool GetPropertyProperty(FProperty? property)
|
||||
{
|
||||
if (property is null)
|
||||
return false;
|
||||
|
||||
return property switch
|
||||
{
|
||||
FObjectProperty objct => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
public static string FormatStructFallback(FStructFallback fallback)
|
||||
{
|
||||
if (fallback.Properties.Count == 0)
|
||||
|
|
@ -155,44 +112,48 @@ public static class KismetExtensions
|
|||
{
|
||||
string tagDataFormatted;
|
||||
|
||||
if (tag.Tag is TextProperty text)
|
||||
switch (tag.Tag)
|
||||
{
|
||||
tagDataFormatted = $"\"{text.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is NameProperty name)
|
||||
{
|
||||
tagDataFormatted = $"\"{name.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is ObjectProperty obj)
|
||||
{
|
||||
tagDataFormatted = $"\"{obj.Value}\"";
|
||||
}
|
||||
else if (tag.Tag.GenericValue is FScriptStruct innerStruct && innerStruct.StructType is FStructFallback nestedFallback)
|
||||
{
|
||||
if (nestedFallback.Properties.Count > 0)
|
||||
case TextProperty text:
|
||||
tagDataFormatted = $"\"{text.Value.Text}\"";
|
||||
break;
|
||||
case NameProperty name:
|
||||
tagDataFormatted = $"\"{name.Value.Text}\"";
|
||||
break;
|
||||
case ObjectProperty obj:
|
||||
tagDataFormatted = $"\"{obj.Value}\"";
|
||||
break;
|
||||
default:
|
||||
{
|
||||
tagDataFormatted = "{ " + string.Join(", ",
|
||||
nestedFallback.Properties.Select(nested =>
|
||||
if (tag.Tag.GenericValue is FScriptStruct { StructType: FStructFallback nestedFallback })
|
||||
{
|
||||
if (nestedFallback.Properties.Count > 0)
|
||||
{
|
||||
string nestedVal;
|
||||
if (nested.Tag is TextProperty textProp)
|
||||
nestedVal = $"\"{textProp.Value.Text}\"";
|
||||
else if (nested.Tag is NameProperty nameProp)
|
||||
nestedVal = $"\"{nameProp.Value.Text}\"";
|
||||
else
|
||||
nestedVal = $"\"{nested.Tag.GenericValue}\"";
|
||||
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}";
|
||||
})) + " }";
|
||||
return $"\"{nested.Name}\": {nestedVal}";
|
||||
})) + " }";
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = "{}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = tag.Tag.GenericValue != null ? $"\"{tag.Tag.GenericValue}\"" : "{}";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = "{}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = tag.Tag.GenericValue != null ? $"\"{tag.Tag.GenericValue}\"" : "{}";
|
||||
}
|
||||
|
||||
return $"\t\t{{ \"{tag.Name}\": {tagDataFormatted} }}";
|
||||
|
|
@ -200,6 +161,7 @@ public static class KismetExtensions
|
|||
|
||||
return "[\n" + string.Join(",\n", tags) + "\n\t]";
|
||||
}
|
||||
|
||||
public static string FormatGameplayTagContainer(FGameplayTagContainer container)
|
||||
{
|
||||
var tags = container.GameplayTags.ToList();
|
||||
|
|
@ -210,49 +172,31 @@ public static class KismetExtensions
|
|||
_ => "[\n" + string.Join(",\n", tags.Select(tag => $"\t\t\"{tag.TagName}\"")) + "\n\t]"
|
||||
};
|
||||
}
|
||||
|
||||
public static string FormatStructType(object structType)
|
||||
{
|
||||
switch (structType)
|
||||
return structType switch
|
||||
{
|
||||
case FVector vector:
|
||||
return $"FVector({vector.X}, {vector.Y}, {vector.Z})";
|
||||
case FVector2D vector2D:
|
||||
return $"FVector2D({vector2D.X}, {vector2D.Y})";
|
||||
case FRotator rotator:
|
||||
return $"FRotator({rotator.Pitch}, {rotator.Yaw}, {rotator.Roll})";
|
||||
case FQuat quat:
|
||||
return $"FQuat({quat.X}, {quat.Y}, {quat.Z}, {quat.W})";
|
||||
case FGuid guid:
|
||||
return $"FGuid({guid.A}, {guid.B}, {guid.C}, {guid.D})";
|
||||
case FColor color:
|
||||
return $"FColor({color.R}, {color.G}, {color.B}, {color.A})";
|
||||
case FLinearColor linearColor:
|
||||
return $"FLinearColor({linearColor.R}, {linearColor.G}, {linearColor.B}, {linearColor.A})";
|
||||
case FSoftObjectPath path:
|
||||
return $"FSoftObjectPath({path.AssetPathName})";
|
||||
case FUniqueNetIdRepl netId:
|
||||
return $"FUniqueNetIdRepl({netId.UniqueNetId})";
|
||||
case FNavAgentSelector agent:
|
||||
return $"FNavAgentSelector({agent.PackedBits})";
|
||||
case FBox box:
|
||||
return $"FBox(FVector({box.Max.X}, {box.Max.Y}, {box.Max.Z}), FVector({box.Min.X}, {box.Min.Y}, {box.Min.Z}))";
|
||||
case FBox2D box2D:
|
||||
return $"FBox2D(FVector2D({box2D.Max.X}, {box2D.Max.Y}), FVector2D({box2D.Min.X}, {box2D.Min.Y}))";
|
||||
case TIntVector3<int> intVec:
|
||||
return $"FVector({intVec.X}, {intVec.Y}, {intVec.Z})";
|
||||
case TIntVector3<float> floatVec:
|
||||
return $"FVector({floatVec.X}, {floatVec.Y}, {floatVec.Z})";
|
||||
case TIntVector2<float> floatVec2:
|
||||
return $"FVector2D({floatVec2.X}, {floatVec2.Y})";
|
||||
case FDateTime dateTime:
|
||||
return $"FDateTime({dateTime})";
|
||||
case FStructFallback fallback:
|
||||
return FormatStructFallback(fallback);
|
||||
case FGameplayTagContainer tagContainer:
|
||||
return FormatGameplayTagContainer(tagContainer);
|
||||
default:
|
||||
return structType?.ToString() ?? "Issue here";
|
||||
}
|
||||
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<int> intVec => $"FVector({intVec.X}, {intVec.Y}, {intVec.Z})",
|
||||
TIntVector3<float> floatVec => $"FVector({floatVec.X}, {floatVec.Y}, {floatVec.Z})",
|
||||
TIntVector2<float> 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)
|
||||
|
|
@ -263,12 +207,14 @@ public static class KismetExtensions
|
|||
}
|
||||
return string.Join('.', property.New.Path.Select(n => n.Text)).Replace(" ", "");
|
||||
}
|
||||
|
||||
public static void ProcessExpression(EExprToken token, KismetExpression expression, StringBuilder outputBuilder, List<int> jumpCodeOffsets, bool isParameter = false)
|
||||
{
|
||||
if (jumpCodeOffsets.Contains(expression.StatementIndex))
|
||||
{
|
||||
outputBuilder.Append("\t\tLabel_" + expression.StatementIndex + ":\n");
|
||||
}
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case EExprToken.EX_LetValueOnPersistentFrame:
|
||||
|
|
@ -406,8 +352,7 @@ public static class KismetExtensions
|
|||
{
|
||||
ProcessExpression(oppMath.Token, oppMath, outputBuilder, jumpCodeOffsets, true);
|
||||
}
|
||||
else
|
||||
{}
|
||||
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_PopExecutionFlowIfNot:
|
||||
|
|
@ -423,7 +368,7 @@ public static class KismetExtensions
|
|||
{
|
||||
EX_Cast op = (EX_Cast) expression;// support CST_ObjectToInterface when I have an example of how it works
|
||||
|
||||
if (ECastToken.CST_ObjectToBool == op.ConversionType || ECastToken.CST_InterfaceToBool == op.ConversionType)
|
||||
if (op.ConversionType is ECastToken.CST_ObjectToBool or ECastToken.CST_InterfaceToBool)
|
||||
{
|
||||
outputBuilder.Append("(bool)");
|
||||
}
|
||||
|
|
@ -455,7 +400,7 @@ public static class KismetExtensions
|
|||
}
|
||||
outputBuilder.Append(op.Elements.Length < 1 ? " " : ' ');
|
||||
|
||||
outputBuilder.Append("}");
|
||||
outputBuilder.Append('}');
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_SetArray:
|
||||
|
|
@ -575,8 +520,8 @@ public static class KismetExtensions
|
|||
{
|
||||
EX_SwitchValue op = (EX_SwitchValue) expression;
|
||||
|
||||
bool useTernary = op.Cases.Length <= 2
|
||||
&& op.Cases.All(c => c.CaseIndexValueTerm.Token == EExprToken.EX_True || c.CaseIndexValueTerm.Token == EExprToken.EX_False);
|
||||
bool useTernary = op.Cases.Length <= 2 &&
|
||||
op.Cases.All(c => c.CaseIndexValueTerm.Token is EExprToken.EX_True or EExprToken.EX_False);
|
||||
|
||||
if (useTernary)
|
||||
{
|
||||
|
|
@ -644,9 +589,9 @@ public static class KismetExtensions
|
|||
{
|
||||
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("[");
|
||||
outputBuilder.Append('[');
|
||||
ProcessExpression(op.ArrayIndex.Token, op.ArrayIndex, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append("]");
|
||||
outputBuilder.Append(']');
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_MetaCast:
|
||||
|
|
@ -658,14 +603,14 @@ public static class KismetExtensions
|
|||
EX_CastBase op = (EX_CastBase) expression;
|
||||
outputBuilder.Append($"Cast<U{op.ClassPtr.Name}*>(");// m?
|
||||
ProcessExpression(op.Target.Token, op.Target, outputBuilder, jumpCodeOffsets, true);
|
||||
outputBuilder.Append(")");
|
||||
outputBuilder.Append(')');
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_StructConst:
|
||||
{
|
||||
EX_StructConst op = (EX_StructConst) expression;
|
||||
outputBuilder.Append($"{GetPrefix(op.Struct.GetType().Name)}{op.Struct.Name}");
|
||||
outputBuilder.Append($"(");
|
||||
outputBuilder.Append('(');
|
||||
for (int i = 0; i < op.Properties.Length; i++)
|
||||
{
|
||||
var property = op.Properties[i];
|
||||
|
|
@ -673,19 +618,19 @@ public static class KismetExtensions
|
|||
if (i < op.Properties.Length - 1 && property.Token != EExprToken.EX_ArrayConst)
|
||||
outputBuilder.Append(", ");
|
||||
}
|
||||
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("'", "");
|
||||
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)
|
||||
if (classString?.Contains('.') == true)
|
||||
{
|
||||
|
||||
outputBuilder.Append(GetPrefix(op?.Value?.ResolvedObject?.Class?.GetType().Name) + classString.Split(".")[1]);
|
||||
outputBuilder.Append(GetPrefix(op?.Value?.ResolvedObject?.Class?.GetType().Name) + classString.Split('.')[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -698,15 +643,7 @@ public static class KismetExtensions
|
|||
var name = op?.Value?.Name ?? string.Empty;
|
||||
|
||||
outputBuilder.Append(outerString.Replace(outerClassString, "") + "." + name);
|
||||
|
||||
if (isParameter)
|
||||
{
|
||||
outputBuilder.Append("\")");
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append("\")");
|
||||
}
|
||||
outputBuilder.Append("\")");
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_BindDelegate:
|
||||
|
|
@ -714,23 +651,23 @@ public static class KismetExtensions
|
|||
EX_BindDelegate op = (EX_BindDelegate) expression;
|
||||
outputBuilder.Append("\t\t");
|
||||
ProcessExpression(op.Delegate.Token, op.Delegate, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append($".BindUFunction(");
|
||||
outputBuilder.Append(".BindUFunction(");
|
||||
ProcessExpression(op.ObjectTerm.Token, op.ObjectTerm, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append($", \"{op.FunctionName}\"");
|
||||
outputBuilder.Append($");\n\n");
|
||||
outputBuilder.Append(");\n\n");
|
||||
break;
|
||||
}
|
||||
// all the delegate functions suck
|
||||
case EExprToken.EX_AddMulticastDelegate:
|
||||
{
|
||||
EX_AddMulticastDelegate op = (EX_AddMulticastDelegate) expression;
|
||||
if (op.Delegate.Token == EExprToken.EX_LocalVariable || op.Delegate.Token == EExprToken.EX_InstanceVariable)
|
||||
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");
|
||||
outputBuilder.Append(");\n\n");
|
||||
}
|
||||
else if (op.Delegate.Token != EExprToken.EX_Context)
|
||||
{}
|
||||
|
|
@ -743,23 +680,25 @@ public static class KismetExtensions
|
|||
//ProcessExpression(opp.ContextExpression.Token, opp.ContextExpression, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append(".AddDelegate(");
|
||||
ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append($");\n\n");
|
||||
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 == EExprToken.EX_LocalVariable || op.Delegate.Token == EExprToken.EX_InstanceVariable)
|
||||
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");
|
||||
outputBuilder.Append(");\n\n");
|
||||
}
|
||||
else if (op.Delegate.Token != EExprToken.EX_Context)
|
||||
{}
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
EX_Context opp = (EX_Context) op.Delegate;
|
||||
|
|
@ -769,7 +708,7 @@ public static class KismetExtensions
|
|||
ProcessExpression(opp.ContextExpression.Token, opp.ContextExpression, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append(".RemoveDelegate(");
|
||||
ProcessExpression(op.DelegateToAdd.Token, op.DelegateToAdd, outputBuilder, jumpCodeOffsets);
|
||||
outputBuilder.Append($");\n\n");
|
||||
outputBuilder.Append(");\n\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -800,10 +739,12 @@ public static class KismetExtensions
|
|||
outputBuilder.Append(", ");
|
||||
}
|
||||
}
|
||||
outputBuilder.Append($");\n\n");
|
||||
outputBuilder.Append(");\n\n");
|
||||
}
|
||||
else if (op.Delegate.Token != EExprToken.EX_Context)
|
||||
{}
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append("\t\t");
|
||||
|
|
@ -819,7 +760,7 @@ public static class KismetExtensions
|
|||
outputBuilder.Append(", ");
|
||||
}
|
||||
}
|
||||
outputBuilder.Append($");\n\n");
|
||||
outputBuilder.Append(");\n\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -827,7 +768,7 @@ public static class KismetExtensions
|
|||
case EExprToken.EX_Context:
|
||||
{
|
||||
EX_Context op = (EX_Context) expression;
|
||||
outputBuilder.Append(outputBuilder.ToString().EndsWith("\n") ? "\t\t" : "");
|
||||
outputBuilder.Append(outputBuilder.ToString().EndsWith('\n') ? "\t\t" : "");
|
||||
ProcessExpression(op.ObjectExpression.Token, op.ObjectExpression, outputBuilder, jumpCodeOffsets, true);
|
||||
|
||||
outputBuilder.Append("->");
|
||||
|
|
@ -847,7 +788,7 @@ public static class KismetExtensions
|
|||
{
|
||||
outputBuilder.Append("->");
|
||||
ProcessExpression(op.ContextExpression.Token, op.ContextExpression, outputBuilder, jumpCodeOffsets, true);
|
||||
outputBuilder.Append($";\n\n");
|
||||
outputBuilder.Append(";\n\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -883,11 +824,11 @@ public static class KismetExtensions
|
|||
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");
|
||||
outputBuilder.Append(";\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append($";");
|
||||
outputBuilder.Append(';');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -941,7 +882,7 @@ public static class KismetExtensions
|
|||
{
|
||||
EX_Return op = (EX_Return) expression;
|
||||
bool check = op.ReturnExpression.Token == EExprToken.EX_Nothing;
|
||||
outputBuilder.Append($"\t\treturn");
|
||||
outputBuilder.Append("\t\treturn");
|
||||
if (!check)
|
||||
outputBuilder.Append(' ');
|
||||
ProcessExpression(op.ReturnExpression.Token, op.ReturnExpression, outputBuilder, jumpCodeOffsets, true);
|
||||
|
|
|
|||
|
|
@ -24,29 +24,21 @@ public static partial class StringExtensions
|
|||
return $"{size:# ###.##} {sizes[order]}".TrimStart();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetNameLineNumberText(this string s, string lineToFind)
|
||||
{
|
||||
using var reader = new StringReader(s);
|
||||
var lineNum = 0;
|
||||
while (reader.ReadLine() is { } line)
|
||||
{
|
||||
lineNum++;
|
||||
if (line.Contains(lineToFind, StringComparison.OrdinalIgnoreCase))
|
||||
return lineNum;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetNameLineNumber(this string s, string lineToFind)
|
||||
{
|
||||
if (KismetRegex().IsMatch(lineToFind))
|
||||
return s.GetKismetLineNumber(lineToFind);
|
||||
|
||||
if (int.TryParse(lineToFind, out var index))
|
||||
return s.GetLineNumber(index);
|
||||
|
||||
lineToFind = $" \"Name\": \"{lineToFind}\",";
|
||||
return s.GetNameLineNumberText($" \"Name\": \"{lineToFind}\",");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetNameLineNumberText(this string s, string lineToFind)
|
||||
{
|
||||
using var reader = new StringReader(s);
|
||||
var lineNum = 0;
|
||||
while (reader.ReadLine() is { } line)
|
||||
|
|
@ -55,7 +47,6 @@ public static partial class StringExtensions
|
|||
if (line.Equals(lineToFind, StringComparison.OrdinalIgnoreCase))
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@
|
|||
<controls:Breadcrumb Grid.Row="0" MaxWidth="{Binding ActualWidth, ElementName=AssetsSearchName}" HorizontalAlignment="Left" Margin="0 5 0 5"
|
||||
DataContext="{Binding SelectedItem.PathAtThisPoint, ElementName=AssetsFolderName, FallbackValue='No/Directory/Detected/In/Folder'}"/>
|
||||
|
||||
<ListBox Grid.Row="1" x:Name="AssetsListName" Style="{StaticResource AssetsListBox}" PreviewMouseDoubleClick="OnAssetsListMouseDoubleClick" PreviewKeyDown="OnPreviewKeyDown" ContextMenuOpening="AssetsListName_ContextMenuOpening">
|
||||
<ListBox Grid.Row="1" x:Name="AssetsListName" Style="{StaticResource AssetsListBox}" PreviewMouseDoubleClick="OnAssetsListMouseDoubleClick" PreviewKeyDown="OnPreviewKeyDown">
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Extract in New Tab" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
|
|
@ -501,7 +501,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Name="Decompile" Header="Decompile Blueprint" Command="{Binding DataContext.RightClickMenuCommand}" Visibility="Collapsed">
|
||||
<MenuItem Header="Decompile Blueprint" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Decompile" />
|
||||
|
|
@ -515,6 +515,15 @@
|
|||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ShowDecompileOption, Source={x:Static settings:UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
|
|
|
|||
|
|
@ -165,18 +165,6 @@ public partial class MainWindow
|
|||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
|
||||
}
|
||||
|
||||
private void AssetsListName_ContextMenuOpening(object sender, ContextMenuEventArgs e)
|
||||
{
|
||||
var listBox = sender as ListBox;
|
||||
var contextMenu = listBox.ContextMenu;
|
||||
|
||||
var decompItem = contextMenu.Items
|
||||
.OfType<MenuItem>()
|
||||
.FirstOrDefault(mi => mi.Name == "Decompile");
|
||||
|
||||
decompItem.Visibility = UserSettings.Default.ShowDecompileOption ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private async void OnFolderExtractClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
|
|
|
|||
|
|
@ -960,15 +960,11 @@ public class CUE4ParseViewModel : ViewModel
|
|||
|
||||
public void Decompile(GameFile entry)
|
||||
{
|
||||
var package = Provider.LoadPackage(entry);
|
||||
|
||||
if (TabControl.CanAddTabs)
|
||||
TabControl.AddTab(entry);
|
||||
else
|
||||
TabControl.SelectedTab.SoftReset(entry);
|
||||
if (TabControl.CanAddTabs) TabControl.AddTab(entry);
|
||||
else TabControl.SelectedTab.SoftReset(entry);
|
||||
|
||||
TabControl.SelectedTab.TitleExtra = "Decompiled";
|
||||
TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("txt");
|
||||
TabControl.SelectedTab.Highlighter = AvalonExtensions.HighlighterSelector("cpp");
|
||||
|
||||
var pkg = Provider.LoadPackage(entry);
|
||||
|
||||
|
|
@ -979,472 +975,247 @@ public class CUE4ParseViewModel : ViewModel
|
|||
if (pointer?.Object is null)
|
||||
continue;
|
||||
|
||||
var dummy = ((AbstractUePackage) pkg).ConstructObject(
|
||||
pointer.Class?.Object?.Value as UStruct, pkg);
|
||||
switch (dummy)
|
||||
var dummy = ((AbstractUePackage) pkg).ConstructObject(pointer.Class?.Object?.Value as UStruct, pkg);
|
||||
if (dummy is not UBlueprintGeneratedClass || pointer.Object.Value is not UBlueprintGeneratedClass blueprint)
|
||||
continue;
|
||||
|
||||
var type = blueprint.GetType().Name;
|
||||
var typePrefix = KismetExtensions.GetPrefix(type);
|
||||
var className = blueprint.Name;
|
||||
var superClassName = blueprint?.SuperStruct?.Name ?? string.Empty;
|
||||
|
||||
outputBuilder.AppendLine($"class {typePrefix}{className} : public {typePrefix}{superClassName}\n{{\npublic:");
|
||||
|
||||
if (!blueprint.ClassDefaultObject.TryLoad(out var bpObject))
|
||||
continue;
|
||||
|
||||
var strings = new List<string>();
|
||||
foreach (var property in bpObject.Properties)
|
||||
{
|
||||
case UBlueprintGeneratedClass _:
|
||||
case UVerseClass _:
|
||||
var propertyName = property.Name.ToString();
|
||||
var propertyValue = property.Tag?.GenericValue;
|
||||
strings.Add(propertyName);
|
||||
string placeholder = $"{propertyName}placeholder";
|
||||
|
||||
void ShouldAppend(string value)
|
||||
{
|
||||
if (outputBuilder.ToString().Contains(placeholder))
|
||||
{
|
||||
var blueprintGeneratedClass = pkg.ExportsLazy.FirstOrDefault(e => e.Value is UBlueprintGeneratedClass)?.Value as UBlueprintGeneratedClass;
|
||||
var verseClass = pkg.ExportsLazy.Where(export => export.Value is UVerseClass).Select(export => (UVerseClass) export.Value).FirstOrDefault();
|
||||
|
||||
var stringsarray = new List<string>();
|
||||
if (blueprintGeneratedClass != null)
|
||||
{
|
||||
{
|
||||
var mainClass = blueprintGeneratedClass?.Name ?? verseClass?.Name;
|
||||
var superStructName = blueprintGeneratedClass?.SuperStruct?.Name ?? verseClass?.SuperStruct?.Name ?? string.Empty;
|
||||
outputBuilder.AppendLine(
|
||||
$"class {KismetExtensions.GetPrefix(blueprintGeneratedClass?.GetType().Name ?? verseClass?.GetType().Name)}{mainClass} : public {KismetExtensions.GetPrefix(blueprintGeneratedClass?.GetType().Name ?? verseClass?.GetType().Name)}{superStructName}\n{{\npublic:");
|
||||
|
||||
foreach (var export in pkg.ExportsLazy)
|
||||
{
|
||||
if (export.Value is not UBlueprintGeneratedClass)
|
||||
|
||||
if (export.Value.Name.StartsWith("Default__") &&
|
||||
export.Value.Name.EndsWith(mainClass ?? string.Empty))
|
||||
{
|
||||
var exportObject = export.Value;
|
||||
foreach (var key in exportObject.Properties)
|
||||
{
|
||||
stringsarray.Add(key.Name.PlainText);
|
||||
string placeholder = $"{key.Name}placenolder";
|
||||
string result = key.Tag.GenericValue.ToString();
|
||||
string keyName = key.Name.PlainText.Replace(" ", "");
|
||||
|
||||
var propertyTag = key.Tag.GetValue(typeof(object));
|
||||
|
||||
void ShouldAppend(string? value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
if (outputBuilder.ToString().Contains(placeholder))
|
||||
{
|
||||
outputBuilder.Replace(placeholder, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.AppendLine(
|
||||
$"\t{KismetExtensions.GetPropertyType(propertyTag)} {keyName} = {value};");
|
||||
}
|
||||
}
|
||||
|
||||
if (key.Tag.GenericValue is FScriptStruct structTag)
|
||||
{
|
||||
if (structTag.StructType is FVector vector)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FVector({vector.X}, {vector.Y}, {vector.Z})");
|
||||
}
|
||||
else if (structTag.StructType is FGuid guid)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FGuid({guid.A}, {guid.B}, {guid.C}, {guid.D})");
|
||||
}
|
||||
else if (structTag.StructType is TIntVector3<int> vector3)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FVector({vector3.X}, {vector3.Y}, {vector3.Z})");
|
||||
}
|
||||
else if (structTag.StructType is TIntVector3<float>
|
||||
floatVector3)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FVector({floatVector3.X}, {floatVector3.Y}, {floatVector3.Z})");
|
||||
}
|
||||
else if (structTag.StructType is TIntVector2<float>
|
||||
floatVector2)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FVector2D({floatVector2.X}, {floatVector2.Y})");
|
||||
}
|
||||
else if (structTag.StructType is FVector2D vector2d)
|
||||
{
|
||||
ShouldAppend($"FVector2D({vector2d.X}, {vector2d.Y})");
|
||||
}
|
||||
else if (structTag.StructType is FRotator rotator)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FRotator({rotator.Pitch}, {rotator.Yaw}, {rotator.Roll})");
|
||||
}
|
||||
else if (structTag.StructType is FStructFallback fallback)
|
||||
{
|
||||
string formattedTags;
|
||||
if (fallback.Properties.Count > 0)
|
||||
{
|
||||
formattedTags = "[\n" + string.Join(",\n",
|
||||
fallback.Properties.Select(tag =>
|
||||
{
|
||||
string tagDataFormatted;
|
||||
if (tag.Tag is TextProperty text)
|
||||
{
|
||||
tagDataFormatted = $"\"{text.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is NameProperty name)
|
||||
{
|
||||
tagDataFormatted = $"\"{name.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is ObjectProperty
|
||||
objectproperty)
|
||||
{
|
||||
tagDataFormatted =
|
||||
$"\"{objectproperty.Value}\"";
|
||||
}
|
||||
else if (tag.Tag.GenericValue is FScriptStruct innerStruct && innerStruct.StructType is FStructFallback nestedFallback)
|
||||
{
|
||||
if (nestedFallback.Properties.Count > 0)
|
||||
{
|
||||
tagDataFormatted = "{ " + string.Join(", ",
|
||||
nestedFallback.Properties.Select(nested =>
|
||||
{
|
||||
string nestedVal;
|
||||
if (nested.Tag is TextProperty textProp)
|
||||
nestedVal = $"\"{textProp.Value.Text}\"";
|
||||
else if (nested.Tag is NameProperty nameProp)
|
||||
nestedVal = $"\"{nameProp.Value.Text}\"";
|
||||
else
|
||||
nestedVal = $"\"{nested.Tag.GenericValue}\"";
|
||||
|
||||
return $"\"{nested.Name}\": {nestedVal}";
|
||||
})) + " }";
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = "{}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted = tag.Tag.GenericValue != null ? tag.Tag.GenericValue.ToString() : "{}";
|
||||
}
|
||||
;
|
||||
|
||||
return $"\t\t{{ \"{tag.Name}\": {tagDataFormatted} }}";
|
||||
})) + "\n\t]";
|
||||
}
|
||||
else
|
||||
{
|
||||
formattedTags = "[]";
|
||||
}
|
||||
|
||||
ShouldAppend(formattedTags);
|
||||
}
|
||||
else if (structTag.StructType is FGameplayTagContainer
|
||||
gameplayTag)
|
||||
{
|
||||
var tags = gameplayTag.GameplayTags.ToList();
|
||||
if (tags.Count > 1)
|
||||
{
|
||||
var formattedTags = "[\n" + string.Join(",\n",
|
||||
tags.Select(tag =>
|
||||
$"\t\t\"{tag.TagName}\"")) +
|
||||
"\n\t]";
|
||||
ShouldAppend(formattedTags);
|
||||
}
|
||||
else if (tags.Any())
|
||||
{
|
||||
ShouldAppend($"\"{tags.First().TagName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShouldAppend("[]");
|
||||
}
|
||||
}
|
||||
else if (structTag.StructType is FLinearColor color)
|
||||
{
|
||||
ShouldAppend(
|
||||
$"FLinearColor({color.R}, {color.G}, {color.B}, {color.A})");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShouldAppend($"\"{result}\"");
|
||||
}
|
||||
}
|
||||
else if (key.Tag.GetType().Name == "ObjectProperty" ||
|
||||
key.Tag.GetType().Name == "TextProperty" ||
|
||||
key.PropertyType == "StrProperty" ||
|
||||
key.PropertyType == "NameProperty" ||
|
||||
key.PropertyType == "ClassProperty")
|
||||
{
|
||||
ShouldAppend($"\"{result}\"");
|
||||
}
|
||||
else if (key.Tag.GenericValue is UScriptSet set)
|
||||
{
|
||||
var formattedSet = "[\n" + string.Join(",\n",
|
||||
set.Properties.Select(p =>
|
||||
$"\t\"{p.GenericValue}\"")) +
|
||||
"\n\t]";
|
||||
ShouldAppend(formattedSet);
|
||||
}
|
||||
else if (key.Tag.GenericValue is UScriptMap map)
|
||||
{
|
||||
var formattedMap = "[\n" + string.Join(",\n",
|
||||
map.Properties.Select(kvp =>
|
||||
$"\t{{\n\t\t\"{kvp.Key}\": \"{kvp.Value}\"\n\t}}")) +
|
||||
"\n\t]";
|
||||
ShouldAppend(formattedMap);
|
||||
}
|
||||
else if (key.Tag.GenericValue is UScriptArray array)
|
||||
{
|
||||
var formattedArray = "[\n" + string.Join(",\n",
|
||||
array.Properties.Select(p =>
|
||||
{
|
||||
if (p.GenericValue is FScriptStruct vectorInArray &&
|
||||
vectorInArray.StructType is FVector vector)
|
||||
{
|
||||
return
|
||||
$"FVector({vector.X}, {vector.Y}, {vector.Z})";
|
||||
}
|
||||
|
||||
if (p.GenericValue is FScriptStruct
|
||||
vector2dInArray &&
|
||||
vector2dInArray
|
||||
.StructType is FVector2D vector2d)
|
||||
{
|
||||
return $"FVector2D({vector2d.X}, {vector2d.Y})";
|
||||
}
|
||||
|
||||
if (p.GenericValue is FScriptStruct structInArray &&
|
||||
structInArray.StructType is FRotator rotator)
|
||||
{
|
||||
return
|
||||
$"FRotator({rotator.Pitch}, {rotator.Yaw}, {rotator.Roll})";
|
||||
}
|
||||
else if
|
||||
(p.GenericValue is FScriptStruct
|
||||
fallbacksInArray &&
|
||||
fallbacksInArray.StructType is FStructFallback
|
||||
fallback)
|
||||
{
|
||||
string formattedTags;
|
||||
if (fallback.Properties.Count > 0)
|
||||
{
|
||||
formattedTags = "\t[\n" + string.Join(",\n",
|
||||
fallback.Properties.Select(tag =>
|
||||
{
|
||||
string tagDataFormatted;
|
||||
if (tag.Tag is TextProperty text)
|
||||
{
|
||||
tagDataFormatted =
|
||||
$"\"{text.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is NameProperty
|
||||
name)
|
||||
{
|
||||
tagDataFormatted =
|
||||
$"\"{name.Value.Text}\"";
|
||||
}
|
||||
else if (tag.Tag is ObjectProperty
|
||||
objectproperty)
|
||||
{
|
||||
tagDataFormatted =
|
||||
$"\"{objectproperty.Value}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
tagDataFormatted =
|
||||
$"\"{tag.Tag.GenericValue}\"";
|
||||
}
|
||||
|
||||
return
|
||||
$"\t\t\"{tag.Name}\": {tagDataFormatted}";
|
||||
})) + "\n\t]";
|
||||
}
|
||||
else
|
||||
{
|
||||
formattedTags = "{}";
|
||||
}
|
||||
|
||||
return formattedTags;
|
||||
}
|
||||
else if
|
||||
(p.GenericValue is FScriptStruct
|
||||
gameplayTagsInArray &&
|
||||
gameplayTagsInArray.StructType is
|
||||
FGameplayTagContainer gameplayTag)
|
||||
{
|
||||
var tags = gameplayTag.GameplayTags.ToList();
|
||||
if (tags.Count > 1)
|
||||
{
|
||||
var formattedTags =
|
||||
"[\n" + string.Join(",\n",
|
||||
tags.Select(tag =>
|
||||
$"\t\t\"{tag.TagName}\"")) +
|
||||
"\n\t]";
|
||||
return formattedTags;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"\"{tags.First().TagName}\"";
|
||||
}
|
||||
}
|
||||
|
||||
return $"\t\t\"{p.GenericValue}\"";
|
||||
})) + "\n\t]";
|
||||
ShouldAppend(formattedArray);
|
||||
}
|
||||
else if (key.Tag.GenericValue is FMulticastScriptDelegate multicast)
|
||||
{
|
||||
var list = multicast.InvocationList;
|
||||
ShouldAppend(list.Length == 0 ? "[]" : $"[{string.Join(", ", list.Select(x => $"\"{x.FunctionName}\""))}]");
|
||||
}
|
||||
|
||||
else if (key.Tag.GenericValue is bool boolResult)
|
||||
{
|
||||
ShouldAppend(boolResult.ToString().ToLower());
|
||||
}
|
||||
else
|
||||
{
|
||||
ShouldAppend(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//outputBuilder.Append($"\nType: {export.Value.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var childProperties = blueprintGeneratedClass?.ChildProperties ??
|
||||
verseClass?.ChildProperties;
|
||||
if (childProperties != null)
|
||||
{
|
||||
foreach (FProperty property in childProperties)
|
||||
{
|
||||
if (!stringsarray.Contains(property.Name.PlainText))
|
||||
outputBuilder.AppendLine(
|
||||
$"\t{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || KismetExtensions.GetPropertyProperty(property) ? "*" : string.Empty)} {property.Name.PlainText.Replace(" ", "")} = {property.Name.PlainText.Replace(" ", "")}placenolder;");
|
||||
}
|
||||
}
|
||||
var funcMapOrder =
|
||||
blueprintGeneratedClass?.FuncMap?.Keys.Select(fname => fname.ToString())
|
||||
.ToList() ?? verseClass?.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 indexx = funcMapOrder.IndexOf(functionName);
|
||||
return indexx >= 0 ? indexx : int.MaxValue;
|
||||
}
|
||||
|
||||
return int.MaxValue;
|
||||
})
|
||||
.ThenBy(f => f.Name.ToString())
|
||||
.ToList();
|
||||
|
||||
var jumpCodeOffsetsMap = new Dictionary<string, List<int>>();
|
||||
|
||||
foreach (var function in functions.AsEnumerable().Reverse())
|
||||
{
|
||||
if (function?.ScriptBytecode == null)
|
||||
continue;
|
||||
|
||||
foreach (var property in function.ScriptBytecode)
|
||||
{
|
||||
string? label = null;
|
||||
int? offset = null;
|
||||
|
||||
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?.ToString()?.Split('.').Last().Split('[')[0];
|
||||
|
||||
if (op.Parameters.Length == 1 && op.Parameters[0] is EX_IntConst intConst)
|
||||
offset = intConst.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(label) && offset.HasValue)
|
||||
{
|
||||
if (!jumpCodeOffsetsMap.TryGetValue(label, out var list))
|
||||
jumpCodeOffsetsMap[label] = list = new List<int>();
|
||||
|
||||
list.Add(offset.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (var function in functions)
|
||||
{
|
||||
string argsList = "";
|
||||
string returnFunc = "void";
|
||||
if (function?.ChildProperties != null)
|
||||
{
|
||||
foreach (FProperty property in function.ChildProperties)
|
||||
{
|
||||
if (property.Name.PlainText == "ReturnValue")
|
||||
{
|
||||
returnFunc =
|
||||
$"{(property.PropertyFlags.HasFlag(EPropertyFlags.ConstParm) ? "const " : string.Empty)}{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || KismetExtensions.GetPrefix(property.GetType().Name) == "U" ? "*" : string.Empty)}";
|
||||
}
|
||||
else if (!(property.Name.ToString().EndsWith("_ReturnValue") ||
|
||||
property.Name.ToString().StartsWith("CallFunc_") ||
|
||||
property.Name.ToString().StartsWith("K2Node_") ||
|
||||
property.Name.ToString()
|
||||
.StartsWith("Temp_")) || // removes useless args
|
||||
property.PropertyFlags.HasFlag(EPropertyFlags.Edit))
|
||||
{
|
||||
argsList +=
|
||||
$"{(property.PropertyFlags.HasFlag(EPropertyFlags.ConstParm) ? "const " : string.Empty)}{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || KismetExtensions.GetPrefix(property.GetType().Name) == "U" ? "*" : string.Empty)}{(property.PropertyFlags.HasFlag(EPropertyFlags.OutParm) ? "&" : string.Empty)} {Regex.Replace(property.Name.ToString(), @"^__verse_0x[0-9A-Fa-f]+_", "")}, ";
|
||||
}
|
||||
}
|
||||
}
|
||||
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<int>();
|
||||
foreach (KismetExpression property in function.ScriptBytecode)
|
||||
{
|
||||
KismetExtensions.ProcessExpression(property.Token, property, outputBuilder, jumpCodeOffsets);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append(
|
||||
"\n\t // This function does not have Bytecode \n\n");
|
||||
outputBuilder.Append("\t}\n");
|
||||
}
|
||||
}
|
||||
|
||||
outputBuilder.Append("\n\n}");
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
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<int> vector3:
|
||||
text = $"FVector({vector3.X}, {vector3.Y}, {vector3.Z})";
|
||||
break;
|
||||
case TIntVector3<float> floatVector3:
|
||||
text = $"FVector({floatVector3.X}, {floatVector3.Y}, {floatVector3.Z})";
|
||||
break;
|
||||
case TIntVector2<float> 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<string> 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));
|
||||
}
|
||||
|
||||
{
|
||||
var childProperties = blueprint?.ChildProperties;
|
||||
if (childProperties != null)
|
||||
{
|
||||
foreach (FProperty property in childProperties)
|
||||
{
|
||||
if (!strings.Contains(property.Name.PlainText))
|
||||
outputBuilder.AppendLine(
|
||||
$"\t{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) || KismetExtensions.GetPropertyProperty(property) ? "*" : string.Empty)} {property.Name.PlainText.Replace(" ", "")} = {property.Name.PlainText.Replace(" ", "")}placeholder;");
|
||||
}
|
||||
}
|
||||
|
||||
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 indexx = funcMapOrder.IndexOf(functionName);
|
||||
return indexx >= 0 ? indexx : int.MaxValue;
|
||||
}
|
||||
|
||||
return int.MaxValue;
|
||||
})
|
||||
.ThenBy(f => f.Name.ToString())
|
||||
.ToList();
|
||||
|
||||
var jumpCodeOffsetsMap = new Dictionary<string, List<int>>();
|
||||
|
||||
foreach (var function in functions.AsEnumerable().Reverse())
|
||||
{
|
||||
if (function?.ScriptBytecode == null)
|
||||
continue;
|
||||
|
||||
foreach (var property in function.ScriptBytecode)
|
||||
{
|
||||
string? label = null;
|
||||
int? offset = null;
|
||||
|
||||
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?.ToString()?.Split('.').Last().Split('[')[0];
|
||||
|
||||
if (op.Parameters.Length == 1 && op.Parameters[0] is EX_IntConst intConst)
|
||||
offset = intConst.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(label) && offset.HasValue)
|
||||
{
|
||||
if (!jumpCodeOffsetsMap.TryGetValue(label, out var list))
|
||||
jumpCodeOffsetsMap[label] = list = new List<int>();
|
||||
|
||||
list.Add(offset.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (var function in functions)
|
||||
{
|
||||
string argsList = "";
|
||||
string returnFunc = "void";
|
||||
if (function?.ChildProperties != null)
|
||||
{
|
||||
foreach (FProperty property in function.ChildProperties)
|
||||
{
|
||||
if (property.Name.PlainText == "ReturnValue")
|
||||
{
|
||||
returnFunc =
|
||||
$"{(property.PropertyFlags.HasFlag(EPropertyFlags.ConstParm) ? "const " : string.Empty)}{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || KismetExtensions.GetPrefix(property.GetType().Name) == "U" ? "*" : string.Empty)}";
|
||||
}
|
||||
else if (!(property.Name.ToString().EndsWith("_ReturnValue") ||
|
||||
property.Name.ToString().StartsWith("CallFunc_") ||
|
||||
property.Name.ToString().StartsWith("K2Node_") ||
|
||||
property.Name.ToString()
|
||||
.StartsWith("Temp_")) || // removes useless args
|
||||
property.PropertyFlags.HasFlag(EPropertyFlags.Edit))
|
||||
{
|
||||
argsList +=
|
||||
$"{(property.PropertyFlags.HasFlag(EPropertyFlags.ConstParm) ? "const " : string.Empty)}{KismetExtensions.GetPrefix(property.GetType().Name)}{KismetExtensions.GetPropertyType(property)}{(property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) || KismetExtensions.GetPrefix(property.GetType().Name) == "U" ? "*" : string.Empty)}{(property.PropertyFlags.HasFlag(EPropertyFlags.OutParm) ? "&" : string.Empty)} {Regex.Replace(property.Name.ToString(), @"^__verse_0x[0-9A-Fa-f]+_", "")}, ";
|
||||
}
|
||||
}
|
||||
}
|
||||
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<int>();
|
||||
foreach (KismetExpression property in function.ScriptBytecode)
|
||||
{
|
||||
KismetExtensions.ProcessExpression(property.Token, property, outputBuilder, jumpCodeOffsets);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append("\n\t // This function does not have Bytecode \n\n");
|
||||
outputBuilder.Append("\t}\n");
|
||||
}
|
||||
}
|
||||
|
||||
outputBuilder.Append("\n\n}");
|
||||
}
|
||||
}
|
||||
string pattern = $@"\w+placenolder";
|
||||
string updatedOutput = Regex.Replace(outputBuilder.ToString(), pattern, "nullptr");
|
||||
|
||||
TabControl.SelectedTab.SetDocumentText(updatedOutput, false, false);
|
||||
var cpp = Regex.Replace(outputBuilder.ToString(), @"\w+placeholder", "nullptr");
|
||||
TabControl.SelectedTab.SetDocumentText(cpp, false, false);
|
||||
}
|
||||
|
||||
private void SaveAndPlaySound(string fullPath, string ext, byte[] data)
|
||||
{
|
||||
if (fullPath.StartsWith("/")) fullPath = fullPath[1..];
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@
|
|||
<CheckBox Grid.Row="17" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ReadShaderMaps, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
|
||||
<TextBlock Grid.Row="18" Grid.Column="0" Text="Show Blueprint Decompile" VerticalAlignment="Center" Margin="0 5 0 5" ToolTip="Shows Decompiled Blueprints in a cpp format" />
|
||||
<TextBlock Grid.Row="18" Grid.Column="0" Text="Show Blueprint Decompile" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Shows Decompiled Blueprints in a cpp format" />
|
||||
<CheckBox Grid.Row="18" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding ShowDecompileOption, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
</Grid>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user