class_name M2StaticBatchMaterializer
extends RefCounted

## Builds and attaches one static M2 MultiMesh batch from an ordered transform
## slice. All Resource and SceneTree mutation belongs on the main thread.


## Returns the attached MultiMeshInstance3D, or null for invalid/empty input.
## The supplied parent owns the returned node and its MultiMesh Resource.
## Transform bounds are a build-planner precondition and are not clamped.
func materialize_batch(
	m2_parent_root: Node3D,
	relative_path: String,
	mesh: Mesh,
	transforms: Array,
	start_index: int,
	instance_count: int,
	batch_serial: int,
	visibility_range_end: float,
	visibility_range_margin: float,
	cast_shadows: bool
) -> MultiMeshInstance3D:
	if (
		m2_parent_root == null
		or mesh == null
		or transforms.is_empty()
		or instance_count <= 0
	):
		return null

	var multimesh := MultiMesh.new()
	multimesh.transform_format = MultiMesh.TRANSFORM_3D
	multimesh.mesh = mesh
	multimesh.instance_count = instance_count
	for batch_offset in instance_count:
		multimesh.set_instance_transform(
			batch_offset,
			transforms[start_index + batch_offset]
		)

	var multimesh_instance := MultiMeshInstance3D.new()
	multimesh_instance.name = "%s_%d" % [
		relative_path.get_file().get_basename(),
		batch_serial,
	]
	multimesh_instance.multimesh = multimesh
	multimesh_instance.cast_shadow = (
		GeometryInstance3D.SHADOW_CASTING_SETTING_ON
		if cast_shadows
		else GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
	)
	if visibility_range_end > 0.0:
		multimesh_instance.visibility_range_end = visibility_range_end
		multimesh_instance.visibility_range_end_margin = visibility_range_margin
	m2_parent_root.add_child(multimesh_instance)
	return multimesh_instance
