feat(nativegen)!: refactor to struct-based native wrappers

Major overhaul of native wrapper generation for ufbx and nvtt.
Replaces all hand-written and class-based wrappers with auto-generated partial struct wrappers that directly expose native API methods via pointers. Introduces a new JSON-driven configuration system using "remaps" and "actions" for flexible parameter/return mapping and method routing. Removes legacy config sections and helper classes, focusing solely on method wrappers. Updates all usages and tests to use the new pointer-based API. Cleans up obsolete code and ensures resource management is handled via struct Dispose methods. The result is a thinner, more direct, and maintainable interop layer.

BREAKING CHANGE: All managed wrapper classes and helpers are removed in favor of struct-based pointer wrappers. API usage and resource management patterns have changed.
This commit is contained in:
2026-03-15 20:48:54 +09:00
parent 3e4084c42a
commit 6cadd8edeb
278 changed files with 5387 additions and 12057 deletions

View File

@@ -3,69 +3,50 @@ using Ghost.Ufbx;
namespace Ghost.MicroTest;
internal class UfbxBindingTest : ITest
internal unsafe class UfbxBindingTest : ITest
{
private static ReadOnlySpan<byte> TestFilePath => "F:/c/Third Parties/ufbx/data/blender_340_z_up_7400_binary.fbx"u8;
public void Setup()
{
}
public void Run()
{
// Smoke-test LoadOpts heap-pointer shape (construct, set, read back, dispose)
using var opts = new LoadOpts();
opts.IgnoreAnimation = true;
opts.IgnoreEmbedded = true;
var load_Opts = new ufbx_load_opts();
var error = new ufbx_error();
// Load scene using the safe high-level wrapper (no unsafe, no fixed blocks)
using var scene = Scene.LoadFile(TestFilePath, opts);
var pScene = ufbx_scene.load_file_len("F:/c/Third Parties/ufbx/data/blender_340_z_up_7400_binary.fbx"u8, &load_Opts, &error);
// Enumerate nodes using the wrapper's NodeList (ref struct, no allocation)
for (var i = 0; i < scene.Nodes.Count; i++)
if (pScene == null)
{
var node = scene.Nodes[i];
if (node.IsRoot)
Console.WriteLine(error.description.ToString());
}
for (var i = 0u; i < pScene->nodes.count; i++)
{
var node = pScene->nodes.data[i];
if (node->is_root)
{
continue;
}
// node.Name is a string property — no manual ToString() needed
Console.WriteLine($"Object: {node.Name}");
Console.WriteLine($"Object: {node->name}");
if (node.HasMesh)
if (node->mesh != null)
{
Console.WriteLine($"-> mesh with {node.Mesh.NumFaces} faces");
Console.WriteLine($"-> mesh with {node->mesh->num_faces} faces");
Console.WriteLine($"-> mesh with positions: {node->local_transform.translation}");
}
for (var j = 0u; j < node->materials.count; j++)
{
var mat = node->materials.data[j];
Console.WriteLine("-> material: " + mat->name);
Console.WriteLine(" -> shader type: " + mat->shader_type);
Console.WriteLine(" -> texture count: " + mat->textures.count);
}
}
// Find a node by name using the new instance method (no unsafe, no fixed)
var rootNode = scene.FindNode("RootNode"u8);
if (!rootNode.IsNull)
{
Console.WriteLine($"Found root node: {rootNode.Name}");
}
// Find a material by name
var material = scene.FindMaterial("Material"u8);
if (!material.IsNull)
{
Console.WriteLine($"Found material: {material.Name}");
// Find a prop on the material's props using the instance method
var prop = material.Props.FindProp("DiffuseColor"u8);
if (!prop.IsNull)
{
Console.WriteLine($" DiffuseColor prop type: {prop.Type}");
}
}
// Find an anim stack
var animStack = scene.FindAnimStack("Take 001"u8);
if (!animStack.IsNull)
{
Console.WriteLine($"Found anim stack: {animStack.Name}");
}
pScene->free();
Console.WriteLine("Done.");
}