class_name Terrain
## Tools for working with different terrain types.
## This provides a unified interface to Terrain3D and regular meshes.

## Basic terrain materials
enum Type {
	NONE,
	ROUGH,
	FAIRWAY,
	GREEN,
	SAND,
	CONCRETE,
	ROCK,
	WOOD,
	METAL,
	GLASS,
}

## We use the upper bits of collision layers to encode material data
const PHYSICAL_LAYERS := {
	1 << 31: Type.ROUGH,
	1 << 30: Type.SAND,
	1 << 29: Type.WOOD,
	1 << 28: Type.ROCK,
	1 << 27: Type.METAL,
	1 << 26: Type.GLASS,
}


## Get the `Terrain.Type` value which corresponds to the given Terrain3D texture ID.
##
## Note that this relies on the ordering of textures in our Terrain3DAsset resource!
## If the order textures are defined in changes, this will break!
static func from_texture_id(tex_id: int) -> Type:
	match tex_id:
		0:
			return Type.ROUGH
		1:
			return Type.FAIRWAY
		2:
			return Type.SAND
		3:
			return Type.GREEN
		4:
			return Type.ROCK
		_:
			return Type.NONE


## Get the `Terrain.Type` value encoded in the given collision layer setting.
##
## We use the upper bits in the collision layer to encode material data.
## Check the collision layer descriptions for more information.
static func from_physical_layer(collision_layer: int) -> Type:
	for bit: int in PHYSICAL_LAYERS:
		if collision_layer & bit:
			return PHYSICAL_LAYERS[bit]
	return Type.CONCRETE


## Get the `Terrain.Type` value at the given position in a Terrain3D node.
static func at_position(global_position: Vector3, terrain3d: Terrain3D) -> Type:
	var blend := terrain3d.data.get_texture_id(global_position)
	var id: int
	if terrain3d.data.get_control_auto(global_position):
		id = blend.x if blend.z > 0 else blend.y
	else:
		id = blend.x
	return from_texture_id(id)
