mirror of
https://github.com/4sval/FModel.git
synced 2026-05-31 21:12:49 -05:00
Enhance AnimGraphNode and AnimGraphPin with ChildPropertyIndex and LinkIndex properties
This commit is contained in:
parent
3bdfcd6b26
commit
152a23e83e
|
|
@ -12,6 +12,7 @@ public class AnimGraphNode
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public string ExportType { get; set; } = string.Empty;
|
public string ExportType { get; set; } = string.Empty;
|
||||||
|
public int ChildPropertyIndex { get; set; } = -1;
|
||||||
public string NodeComment { get; set; } = string.Empty;
|
public string NodeComment { get; set; } = string.Empty;
|
||||||
public int NodePosX { get; set; }
|
public int NodePosX { get; set; }
|
||||||
public int NodePosY { get; set; }
|
public int NodePosY { get; set; }
|
||||||
|
|
@ -29,6 +30,7 @@ public class AnimGraphPin
|
||||||
public bool IsOutput { get; set; }
|
public bool IsOutput { get; set; }
|
||||||
public string PinType { get; set; } = string.Empty;
|
public string PinType { get; set; } = string.Empty;
|
||||||
public string DefaultValue { get; set; } = string.Empty;
|
public string DefaultValue { get; set; } = string.Empty;
|
||||||
|
public int? LinkIndex { get; set; }
|
||||||
public AnimGraphNode OwnerNode { get; set; } = null!;
|
public AnimGraphNode OwnerNode { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,27 +114,32 @@ public class AnimGraphViewModel
|
||||||
return vm;
|
return vm;
|
||||||
|
|
||||||
// Collect all anim node struct properties from the class definition
|
// Collect all anim node struct properties from the class definition
|
||||||
var animNodeProps = new List<(string name, string structType)>();
|
var animNodeProps = new List<(string name, string structType, int childPropertyIndex)>();
|
||||||
foreach (var field in childProps)
|
for (var childPropertyIndex = 0; childPropertyIndex < childProps.Length; childPropertyIndex++)
|
||||||
{
|
{
|
||||||
|
var field = childProps[childPropertyIndex];
|
||||||
if (field is not FStructProperty structProp) continue;
|
if (field is not FStructProperty structProp) continue;
|
||||||
|
|
||||||
var structName = structProp.Struct.ResolvedObject?.Name.Text ?? string.Empty;
|
var structName = structProp.Struct.ResolvedObject?.Name.Text ?? string.Empty;
|
||||||
// Animation node structs typically start with "FAnimNode_" or "AnimNode_"
|
// Animation node structs may be prefixed by plugin/vendor identifiers
|
||||||
|
// (e.g. ACAnimNode_CopyParentPose), but LinkID still targets their original
|
||||||
|
// ChildProperties index. We therefore preserve any field/struct name that
|
||||||
|
// contains the anim node markers instead of only accepting strict prefixes.
|
||||||
if (!IsAnimNodeStruct(structName) && !IsAnimNodeStruct(field.Name.Text))
|
if (!IsAnimNodeStruct(structName) && !IsAnimNodeStruct(field.Name.Text))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
animNodeProps.Add((field.Name.Text, structName));
|
animNodeProps.Add((field.Name.Text, structName, childPropertyIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build nodes from the collected properties
|
// Build nodes from the collected properties
|
||||||
var nodeByName = new Dictionary<string, AnimGraphNode>();
|
var nodeByName = new Dictionary<string, AnimGraphNode>();
|
||||||
foreach (var (propName, structType) in animNodeProps)
|
foreach (var (propName, structType, childPropertyIndex) in animNodeProps)
|
||||||
{
|
{
|
||||||
var node = new AnimGraphNode
|
var node = new AnimGraphNode
|
||||||
{
|
{
|
||||||
Name = propName,
|
Name = propName,
|
||||||
ExportType = structType
|
ExportType = structType,
|
||||||
|
ChildPropertyIndex = childPropertyIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to extract property values from the CDO
|
// Try to extract property values from the CDO
|
||||||
|
|
@ -907,7 +914,7 @@ public class AnimGraphViewModel
|
||||||
/// state root nodes, and collect state/transition metadata for overview layers.
|
/// state root nodes, and collect state/transition metadata for overview layers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void AssociateStateMachineNames(UClass animBlueprintClass, UObject? cdo,
|
private static void AssociateStateMachineNames(UClass animBlueprintClass, UObject? cdo,
|
||||||
List<(string name, string structType)> animNodeProps,
|
List<(string name, string structType, int childPropertyIndex)> animNodeProps,
|
||||||
Dictionary<string, AnimGraphNode> nodeByName,
|
Dictionary<string, AnimGraphNode> nodeByName,
|
||||||
List<StateMachineMetadata> smMetadata)
|
List<StateMachineMetadata> smMetadata)
|
||||||
{
|
{
|
||||||
|
|
@ -942,7 +949,7 @@ public class AnimGraphViewModel
|
||||||
|
|
||||||
// Associate FAnimNode_StateMachine nodes that reference this machine index
|
// Associate FAnimNode_StateMachine nodes that reference this machine index
|
||||||
var machineIdxStr = machineIdx.ToString();
|
var machineIdxStr = machineIdx.ToString();
|
||||||
foreach (var (propName, structType) in animNodeProps)
|
foreach (var (propName, structType, _) in animNodeProps)
|
||||||
{
|
{
|
||||||
if (!structType.Contains("StateMachine", StringComparison.OrdinalIgnoreCase))
|
if (!structType.Contains("StateMachine", StringComparison.OrdinalIgnoreCase))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1117,9 +1124,8 @@ public class AnimGraphViewModel
|
||||||
|
|
||||||
private static bool IsAnimNodeStruct(string name)
|
private static bool IsAnimNodeStruct(string name)
|
||||||
{
|
{
|
||||||
return name.StartsWith("FAnimNode_", StringComparison.OrdinalIgnoreCase) ||
|
return name.Contains("AnimNode_", StringComparison.OrdinalIgnoreCase) ||
|
||||||
name.StartsWith("AnimNode_", StringComparison.OrdinalIgnoreCase) ||
|
name.Contains("AnimGraphNode_", StringComparison.OrdinalIgnoreCase);
|
||||||
name.StartsWith("AnimGraphNode_", StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsSaveCachedPoseNode(AnimGraphNode node)
|
private static bool IsSaveCachedPoseNode(AnimGraphNode node)
|
||||||
|
|
@ -1145,6 +1151,18 @@ public class AnimGraphViewModel
|
||||||
case "NodeComment":
|
case "NodeComment":
|
||||||
node.NodeComment = value;
|
node.NodeComment = value;
|
||||||
break;
|
break;
|
||||||
|
case "BoneToModify":
|
||||||
|
// Store additional properties for display
|
||||||
|
if (value.Length <= MaxPropertyValueDisplayLength)
|
||||||
|
{
|
||||||
|
var a = prop.Tag?.GenericValue?.ToString();
|
||||||
|
var V = prop.Tag?.GenericValue;
|
||||||
|
var vv = V as CUE4Parse.UE4.Assets.Objects.FScriptStruct;
|
||||||
|
var vvv = vv?.StructType as CUE4Parse.UE4.Assets.Objects.FStructFallback;
|
||||||
|
var vvvv = vvv?.Properties[0].Tag.ToString();
|
||||||
|
node.AdditionalProperties[name] = vvvv is not null ? vvvv : value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// Store additional properties for display
|
// Store additional properties for display
|
||||||
if (value.Length <= MaxPropertyValueDisplayLength)
|
if (value.Length <= MaxPropertyValueDisplayLength)
|
||||||
|
|
@ -1156,22 +1174,48 @@ public class AnimGraphViewModel
|
||||||
// Add input pins based on struct properties that reference other poses/nodes
|
// Add input pins based on struct properties that reference other poses/nodes
|
||||||
foreach (var prop in structValue.Properties)
|
foreach (var prop in structValue.Properties)
|
||||||
{
|
{
|
||||||
var name = prop.Name.Text;
|
AddInputPins(node, prop.Name.Text, prop.Tag);
|
||||||
|
|
||||||
// Properties referencing other animation poses are connections
|
|
||||||
if (IsPoseProperty(name) || IsLinkedNodeProperty(name))
|
|
||||||
{
|
|
||||||
node.Pins.Add(new AnimGraphPin
|
|
||||||
{
|
|
||||||
PinName = name,
|
|
||||||
IsOutput = false,
|
|
||||||
PinType = "pose",
|
|
||||||
OwnerNode = node
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddInputPins(AnimGraphNode node, string pinName, FPropertyTagType? tag)
|
||||||
|
{
|
||||||
|
if (!IsPoseProperty(pinName) && !IsLinkedNodeProperty(pinName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tag?.GenericValue is UScriptArray array)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < array.Properties.Count; i++)
|
||||||
|
{
|
||||||
|
AddPinIfMissing(node, $"{pinName}[{i}]", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array.Properties.Count == 0)
|
||||||
|
{
|
||||||
|
AddPinIfMissing(node, pinName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddPinIfMissing(node, pinName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddPinIfMissing(AnimGraphNode node, string pinName, int? linkIndex = null)
|
||||||
|
{
|
||||||
|
if (node.Pins.Any(pin => !pin.IsOutput && pin.PinName.Equals(pinName, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
node.Pins.Add(new AnimGraphPin
|
||||||
|
{
|
||||||
|
PinName = pinName,
|
||||||
|
IsOutput = false,
|
||||||
|
PinType = "pose",
|
||||||
|
LinkIndex = linkIndex,
|
||||||
|
OwnerNode = node
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsPoseProperty(string name)
|
private static bool IsPoseProperty(string name)
|
||||||
{
|
{
|
||||||
return name.Contains("Pose", StringComparison.OrdinalIgnoreCase) &&
|
return name.Contains("Pose", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
|
@ -1187,7 +1231,7 @@ public class AnimGraphViewModel
|
||||||
name.Contains("LinkedAnimGraph", StringComparison.OrdinalIgnoreCase);
|
name.Contains("LinkedAnimGraph", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ResolveConnections(UObject cdo, List<(string name, string structType)> animNodeProps,
|
private static void ResolveConnections(UObject cdo, List<(string name, string structType, int childPropertyIndex)> animNodeProps,
|
||||||
Dictionary<string, AnimGraphNode> nodeByName, AnimGraphViewModel vm)
|
Dictionary<string, AnimGraphNode> nodeByName, AnimGraphViewModel vm)
|
||||||
{
|
{
|
||||||
// Animation node connections in cooked assets are encoded via
|
// Animation node connections in cooked assets are encoded via
|
||||||
|
|
@ -1195,7 +1239,7 @@ public class AnimGraphViewModel
|
||||||
// These contain a "LinkID" integer that maps to the index of the target node
|
// These contain a "LinkID" integer that maps to the index of the target node
|
||||||
// in the class's animation node property list.
|
// in the class's animation node property list.
|
||||||
|
|
||||||
foreach (var (propName, _) in animNodeProps)
|
foreach (var (propName, _, _) in animNodeProps)
|
||||||
{
|
{
|
||||||
if (!cdo.TryGetValue(out FStructFallback structValue, propName))
|
if (!cdo.TryGetValue(out FStructFallback structValue, propName))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1215,7 +1259,7 @@ public class AnimGraphViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryResolvePoseLink(FPropertyTagType tag, string pinName,
|
private static void TryResolvePoseLink(FPropertyTagType tag, string pinName,
|
||||||
AnimGraphNode sourceNode, List<(string name, string structType)> animNodeProps,
|
AnimGraphNode sourceNode, List<(string name, string structType, int childPropertyIndex)> animNodeProps,
|
||||||
Dictionary<string, AnimGraphNode> nodeByName, AnimGraphViewModel vm)
|
Dictionary<string, AnimGraphNode> nodeByName, AnimGraphViewModel vm)
|
||||||
{
|
{
|
||||||
// Handle arrays of pose links (e.g., BlendPose TArray<FPoseLink>)
|
// Handle arrays of pose links (e.g., BlendPose TArray<FPoseLink>)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user