mirror of
https://github.com/4sval/FModel.git
synced 2026-09-08 09:36:36 -05:00
Improvements
This commit is contained in:
@@ -17,16 +17,43 @@ namespace FModel.Extensions;
|
||||
|
||||
public static class KismetExtensions
|
||||
{
|
||||
public static string GetPrefix(string type, string extra = "") // todo: implement better handling
|
||||
public static string GetPrefix(this UStruct val)
|
||||
{
|
||||
return type switch
|
||||
var ret = string.Empty;
|
||||
var super = val;
|
||||
|
||||
while (super is not null)
|
||||
{
|
||||
"FNameProperty" or "FPackageIndex" or "FTextProperty" or "FStructProperty" => "F",
|
||||
"UBlueprintGeneratedClass" or "FActorProperty" => "A",
|
||||
"FObjectProperty" when extra.Contains("Actor") => "A",
|
||||
"ResolvedScriptObject" or "ResolvedLoadedObject" or "FSoftObjectProperty" or "FObjectProperty" => "U",
|
||||
_ => ""
|
||||
};
|
||||
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<UStruct>();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -77,36 +104,25 @@ public static class KismetExtensions
|
||||
_ => GetUnknownFieldType(property)
|
||||
};
|
||||
}
|
||||
public static string GetPropertyType(FProperty? 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";
|
||||
|
||||
bool isPointer(FProperty p) =>
|
||||
p.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) ||
|
||||
property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) ||
|
||||
p.PropertyFlags.HasFlag(EPropertyFlags.ContainsInstancedReference);
|
||||
|
||||
return property switch
|
||||
{
|
||||
FSetProperty s => $"TSet<{GetPrefix(s.ElementProp.GetType().Name)}{GetPropertyType(s.ElementProp)}{(isPointer(s) ? "*" : "")}>",
|
||||
FMapProperty m => $"TMap<{GetPrefix(m.KeyProp.GetType().Name)}{GetPropertyType(m.KeyProp)}, {GetPrefix(m.ValueProp.GetType().Name)}{GetPropertyType(m.ValueProp)}{(isPointer(m) ? "*" : "")}>",
|
||||
FArrayProperty a => $"TArray<{GetPrefix(a.Inner.GetType().Name)}{GetPropertyType(a.Inner)}{(isPointer(a) || GetPropertyProperty(a.Inner.GetType().Name) ? "*" : "")}>",
|
||||
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 bool GetPropertyProperty(object? property)
|
||||
{
|
||||
if (property is null)
|
||||
return false;
|
||||
|
||||
return property switch
|
||||
{
|
||||
FObjectProperty => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public static string FormatStructFallback(FStructFallback fallback)
|
||||
{
|
||||
if (fallback.Properties.Count == 0)
|
||||
@@ -245,7 +261,7 @@ public static class KismetExtensions
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append($"\t\t{GetPrefix(op?.StackNode?.ResolvedObject?.Outer?.GetType()?.Name ?? string.Empty)}{op?.StackNode?.Name.Replace(" ", "")}(");
|
||||
outputBuilder.Append($"\t\t{op?.StackNode?.ResolvedObject?.Outer?.GetType()?.Name.GetPrefix()}{op?.StackNode?.Name.Replace(" ", "")}(");
|
||||
}
|
||||
|
||||
for (int i = 0; i < opp.Length; i++)
|
||||
@@ -275,7 +291,7 @@ public static class KismetExtensions
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append($"\t\t{op?.StackNode?.Name.Replace(" ", "")}(");//{GetPrefix(op?.StackNode?.ResolvedObject?.Outer?.GetType()?.Name)}
|
||||
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++)
|
||||
@@ -296,7 +312,7 @@ public static class KismetExtensions
|
||||
EX_FinalFunction op = (EX_FinalFunction) expression;
|
||||
KismetExpression[] opp = op.Parameters;
|
||||
outputBuilder.Append(isParameter ? string.Empty : "\t\t");
|
||||
outputBuilder.Append($"{GetPrefix(op.StackNode.ResolvedObject.Outer.GetType().Name)}{op.StackNode.ResolvedObject.Outer.Name.ToString().Replace(" ", "")}::{op.StackNode.Name}(");
|
||||
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++)
|
||||
{
|
||||
@@ -606,7 +622,7 @@ public static class KismetExtensions
|
||||
case EExprToken.EX_StructConst:
|
||||
{
|
||||
EX_StructConst op = (EX_StructConst) expression;
|
||||
outputBuilder.Append($"{GetPrefix(op.Struct.GetType().Name)}{op.Struct.Name}");
|
||||
outputBuilder.Append($"{op.Struct.GetType().Name.GetPrefix()}{op.Struct.Name}");
|
||||
outputBuilder.Append('(');
|
||||
for (int i = 0; i < op.Properties.Length; i++)
|
||||
{
|
||||
@@ -627,11 +643,11 @@ public static class KismetExtensions
|
||||
if (classString?.Contains('.') == true)
|
||||
{
|
||||
|
||||
outputBuilder.Append(GetPrefix(op?.Value?.ResolvedObject?.Class?.GetType().Name) + classString.Split('.')[1]);
|
||||
outputBuilder.Append(op?.Value?.ResolvedObject?.Class?.GetType().Name.GetPrefix() + classString.Split('.')[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append(GetPrefix(op?.Value?.ResolvedObject?.Class?.GetType().Name) + classString);
|
||||
outputBuilder.Append(op?.Value?.ResolvedObject?.Class?.GetType().Name.GetPrefix() + classString);
|
||||
}
|
||||
outputBuilder.Append(">(\"");
|
||||
var resolvedObject = op?.Value?.ResolvedObject;
|
||||
@@ -883,7 +899,7 @@ public static class KismetExtensions
|
||||
if (!check)
|
||||
outputBuilder.Append(' ');
|
||||
ProcessExpression(op.ReturnExpression.Token, op.ReturnExpression, outputBuilder, jumpCodeOffsets, true);
|
||||
outputBuilder.AppendLine(";\n\n");
|
||||
outputBuilder.AppendLine(";");
|
||||
break;
|
||||
}
|
||||
case EExprToken.EX_RotationConst:
|
||||
|
||||
@@ -60,12 +60,12 @@ using SkiaSharp;
|
||||
using UE4Config.Parsing;
|
||||
using Application = System.Windows.Application;
|
||||
using FGuid = CUE4Parse.UE4.Objects.Core.Misc.FGuid;
|
||||
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.GameplayTags;
|
||||
using System.Text;
|
||||
using AssetRipper.TextureDecoder.Rgb;
|
||||
|
||||
|
||||
namespace FModel.ViewModels;
|
||||
@@ -353,7 +353,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
{
|
||||
var mappingsFolder = Path.Combine(UserSettings.Default.OutputDirectory, ".data");
|
||||
if (endpoint.Path == "$.[?(@.meta.compressionMethod=='Oodle')].['url','fileName']") endpoint.Path = "$.[0].['url','fileName']";
|
||||
var mappings = _apiEndpointView.DynamicApi.GetMappings(default, endpoint.Url, endpoint.Path);
|
||||
var mappings = _apiEndpointView.DynamicApi.GetMappings(CancellationToken.None, endpoint.Url, endpoint.Path);
|
||||
if (mappings is { Length: > 0 })
|
||||
{
|
||||
foreach (var mapping in mappings)
|
||||
@@ -428,7 +428,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
var ioStoreOnDemandPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud", inst[0].Value.SubstringAfterLast("/").SubstringBefore("\""));
|
||||
if (!File.Exists(ioStoreOnDemandPath)) return;
|
||||
|
||||
await _apiEndpointView.EpicApi.VerifyAuth(default);
|
||||
await _apiEndpointView.EpicApi.VerifyAuth(CancellationToken.None);
|
||||
await Provider.RegisterVfs(new IoChunkToc(ioStoreOnDemandPath), new IoStoreOnDemandOptions
|
||||
{
|
||||
ChunkBaseUri = new Uri("https://download.epicgames.com/ias/fortnite/", UriKind.Absolute),
|
||||
@@ -471,7 +471,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
if (!Provider.ProjectName.Equals("fortnitegame", StringComparison.OrdinalIgnoreCase) || HotfixedResourcesDone) return Task.CompletedTask;
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var hotfixes = ApplicationService.ApiEndpointView.CentralApi.GetHotfixes(default, Provider.GetLanguageCode(UserSettings.Default.AssetLanguage));
|
||||
var hotfixes = ApplicationService.ApiEndpointView.CentralApi.GetHotfixes(CancellationToken.None, Provider.GetLanguageCode(UserSettings.Default.AssetLanguage));
|
||||
if (hotfixes == null) return;
|
||||
|
||||
Provider.Internationalization.Override(hotfixes);
|
||||
@@ -796,7 +796,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckExport(CancellationToken cancellationToken, IPackage pkg, int index, EBulkType bulk = EBulkType.None) // return true once you wanna stop searching for exports
|
||||
private bool CheckExport(CancellationToken cancellationToken, IPackage pkg, int index, EBulkType bulk = EBulkType.None) // return true once you want to stop searching for exports
|
||||
{
|
||||
var isNone = bulk == EBulkType.None;
|
||||
var updateUi = !HasFlag(bulk, EBulkType.Auto);
|
||||
@@ -999,8 +999,9 @@ public class CUE4ParseViewModel : ViewModel
|
||||
if (dummy is not UClass || pointer.Object.Value is not UClass blueprint)
|
||||
continue;
|
||||
|
||||
var typePrefix = KismetExtensions.GetPrefix(blueprint.GetType().Name);
|
||||
outputBuilder.AppendLine($"class {typePrefix}{blueprint.Name} : public {typePrefix}{blueprint?.SuperStruct?.Name ?? string.Empty}\n{{\npublic:");
|
||||
var typePrefix = blueprint?.SuperStruct.Load<UStruct>().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;
|
||||
@@ -1110,21 +1111,19 @@ public class CUE4ParseViewModel : ViewModel
|
||||
|
||||
var propertyName = property.Name.ToString().Replace(" ", "");
|
||||
var type = KismetExtensions.GetPropertyType(property);
|
||||
var prefix = KismetExtensions.GetPrefix(property.GetType().Name);
|
||||
|
||||
string pointerIdentifier;
|
||||
if (property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference) ||
|
||||
property.PropertyFlags.HasFlag(EPropertyFlags.ReferenceParm) ||
|
||||
KismetExtensions.GetPropertyProperty(property))
|
||||
var prefix = "";
|
||||
switch (property)
|
||||
{
|
||||
pointerIdentifier = "*";
|
||||
}
|
||||
else
|
||||
{
|
||||
pointerIdentifier = string.Empty;
|
||||
case FFieldPathProperty pathProp:
|
||||
prefix = pathProp.PropertyClass.ToString().GetPrefix();
|
||||
break;
|
||||
case FObjectProperty objectProp:
|
||||
prefix = objectProp.PropertyClass.ToString().GetPrefix();
|
||||
break;
|
||||
}
|
||||
|
||||
outputBuilder.AppendLine($"\t{prefix}{type}{pointerIdentifier} {propertyName} = {propertyName}fmodelholder;");
|
||||
outputBuilder.AppendLine($"\t{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")} {propertyName} = {propertyName}fmodelholder;");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1155,8 +1154,8 @@ public class CUE4ParseViewModel : ViewModel
|
||||
|
||||
foreach (var property in function.ScriptBytecode)
|
||||
{
|
||||
string? label = null;
|
||||
int? offset = null;
|
||||
string label = string.Empty;
|
||||
int offset = 0;
|
||||
|
||||
switch (property.Token)
|
||||
{
|
||||
@@ -1173,20 +1172,20 @@ public class CUE4ParseViewModel : ViewModel
|
||||
case EExprToken.EX_LocalFinalFunction:
|
||||
{
|
||||
EX_FinalFunction op = (EX_FinalFunction) property;
|
||||
label = op.StackNode?.Name?.ToString()?.Split('.').Last().Split('[')[0];
|
||||
label = op.StackNode?.Name?.Split('.').Last().Split('[')[0];
|
||||
|
||||
if (op.Parameters.Length == 1 && op.Parameters[0] is EX_IntConst intConst)
|
||||
if (op is { Parameters: [EX_IntConst intConst] })
|
||||
offset = intConst.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(label) && offset.HasValue)
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
if (!jumpCodeOffsetsMap.TryGetValue(label, out var list))
|
||||
jumpCodeOffsetsMap[label] = list = new List<int>();
|
||||
|
||||
list.Add(offset.Value);
|
||||
list.Add(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1201,16 +1200,24 @@ public class CUE4ParseViewModel : ViewModel
|
||||
{
|
||||
var name = property.Name.ToString();
|
||||
var plainName = property.Name.PlainText;
|
||||
var prefix = KismetExtensions.GetPrefix(property.GetType().Name);
|
||||
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 isInstanced = property.PropertyFlags.HasFlag(EPropertyFlags.InstancedReference);
|
||||
var isEdit = property.PropertyFlags.HasFlag(EPropertyFlags.Edit);
|
||||
|
||||
if (plainName == "ReturnValue")
|
||||
{
|
||||
returnFunc = $"{(isConst ? "const " : "")}{prefix}{type}{(isInstanced || prefix == "U" ? "*" : "")}";
|
||||
returnFunc = $"{(isConst ? "const " : "")}{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")}";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1220,7 +1227,7 @@ public class CUE4ParseViewModel : ViewModel
|
||||
continue;
|
||||
|
||||
var strippedVerseName = Regex.Replace(name, @"^__verse_0x[0-9A-Fa-f]+_", "");
|
||||
argsList += $"{(isConst ? "const " : "")}{prefix}{type}{(isInstanced || prefix == "U" ? "*" : "")}{(isOut ? "&" : "")} {strippedVerseName}, ";
|
||||
argsList += $"{(isConst ? "const " : "")}{prefix}{type}{(KismetExtensions.isPointer(property) ? '*' : "")}{(isOut ? '&' : "")} {strippedVerseName}, ";
|
||||
}
|
||||
}
|
||||
argsList = argsList.TrimEnd(',', ' ');
|
||||
|
||||
Reference in New Issue
Block a user