Code/HumanoidRetargeter/Formats/Fbx/FbxMeshParts.cs
#nullable enable annotations
using System;
using System.Collections.Generic;
using System.Linq;
namespace HumanoidRetargeter.Formats.Fbx;
/// <summary>Names of mesh instances that ModelDoc can import independently.</summary>
public static class FbxMeshParts
{
public static IReadOnlyList<string> ReadNames(byte[] data)
{
var root = FbxTokenizer.Parse(data);
var objects = root.Child("Objects");
var connections = root.Child("Connections");
if (objects is null || connections is null)
return Array.Empty<string>();
var geometries = objects.Children
.Where(n => n.Name == "Geometry" && n.Properties.Count > 0
&& n.Properties[0] is long or int)
.Select(n => n.Prop<long>(0)).ToHashSet();
var models = connections.ChildrenNamed("C")
.Where(n => n.Properties.Count >= 3 && n.Properties[0] is "OO"
&& n.Properties[1] is long or int && n.Properties[2] is long or int
&& geometries.Contains(n.Prop<long>(1)))
.Select(n => n.Prop<long>(2)).ToHashSet();
return objects.Children
.Where(n => n.Name == "Model" && n.Properties.Count >= 2
&& n.Properties[0] is long or int && n.Properties[1] is string
&& models.Contains(n.Prop<long>(0)))
.Select(n => FbxNode.SplitName(n.Prop<string>(1)).Name)
.Where(n => !string.IsNullOrWhiteSpace(n))
.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
}
}