UnitTests/MaterialGroupTests.cs

Unit tests for Vmdl bulk editor behavior around material groups, default material, and align-origin propagation to collision. Loads a KV3 document string, applies MeshEntryProperties via VmdlBulkEditor, and asserts resulting fields in parsed Kv3Document.

using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ModelPro.Vmdl;

[TestClass]
public class MaterialGroupTests
{
	const string WithMaterial = """
	{
		rootNode = 
		{
			_class = "RootNode"
			children = 
			[
				{
					_class = "MaterialGroupList"
					children = 
					[
						{
							_class = "DefaultMaterialGroup"
							remaps = [  ]
							use_global_default = true
							global_default_material = "materials/old.vmat"
						},
					]
				},
				{
					_class = "PhysicsShapeList"
					children = 
					[
						{
							_class = "PhysicsHullFromRender"
							parent_bone = ""
							surface_prop = "default"
							collision_tags = "solid"
							faceMergeAngle = 20.0
							maxHullVertices = 32
							hull_mode = "HullPerElement"
						},
					]
				},
				{
					_class = "RenderMeshList"
					children = 
					[
						{
							_class = "RenderMeshFile"
							filename = "models/foo.fbx"
							import_scale = 1.0
						},
					]
				},
			]
		}
	}
	""";

	[TestMethod]
	public void SetsDefaultMaterial()
	{
		var editor = VmdlBulkEditor.Load( WithMaterial );
		Assert.AreEqual( "materials/old.vmat", editor.ReadDefaultMaterial() );

		var props = new MeshEntryProperties { GlobalDefaultMaterial = "materials/new.vmat" };
		Assert.IsTrue( editor.Apply( props ) );

		var parsed = Kv3Document.Parse( editor.Source );
		var group = parsed.FindObjects( "DefaultMaterialGroup" ).Single();
		Assert.AreEqual( "materials/new.vmat", ((Kv3Scalar)group.FindField( "global_default_material" ).Value).Value );
		Assert.AreEqual( "true", ((Kv3Scalar)group.FindField( "use_global_default" ).Value).Value );
	}

	[TestMethod]
	public void NullMaterialLeavesUnchanged()
	{
		var editor = VmdlBulkEditor.Load( WithMaterial );

		var props = new MeshEntryProperties { ImportScale = 2.0f };
		Assert.IsTrue( editor.Apply( props ) );

		var parsed = Kv3Document.Parse( editor.Source );
		var group = parsed.FindObjects( "DefaultMaterialGroup" ).Single();
		Assert.AreEqual( "materials/old.vmat", ((Kv3Scalar)group.FindField( "global_default_material" ).Value).Value );
	}

	[TestMethod]
	public void AlignOriginAppliesToCollision()
	{
		var editor = VmdlBulkEditor.Load( WithMaterial );

		var props = new MeshEntryProperties
		{
			AlignOriginX = AlignOrigin.BoundsCenter,
			AlignOriginY = AlignOrigin.BoundsCenter,
			AlignOriginZ = AlignOrigin.BoundsMin
		};

		Assert.IsTrue( editor.Apply( props ) );

		var parsed = Kv3Document.Parse( editor.Source );

		// Render mesh
		var mesh = parsed.FindObjects( "RenderMeshFile" ).Single();
		Assert.AreEqual( "BoundsCenter", ((Kv3Scalar)mesh.FindField( "align_origin_x_type" ).Value).Value );
		Assert.AreEqual( "BoundsMin", ((Kv3Scalar)mesh.FindField( "align_origin_z_type" ).Value).Value );

		// Collision shape must match
		var hull = parsed.FindObjects( "PhysicsHullFromRender" ).Single();
		Assert.AreEqual( "BoundsCenter", ((Kv3Scalar)hull.FindField( "align_origin_x_type" ).Value).Value );
		Assert.AreEqual( "BoundsCenter", ((Kv3Scalar)hull.FindField( "align_origin_y_type" ).Value).Value );
		Assert.AreEqual( "BoundsMin", ((Kv3Scalar)hull.FindField( "align_origin_z_type" ).Value).Value );
	}
}