2023-01-23 19:28:14 +01:00
|
|
|
@tool
|
2023-01-16 19:25:35 +01:00
|
|
|
class_name TerrainInstance3D extends GeometryInstance3D
|
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
const _DETAIL := 2
|
|
|
|
|
|
|
|
const _SHADER := preload("res://terrain/terrain.gdshader")
|
|
|
|
|
2023-01-23 21:29:43 +01:00
|
|
|
##
|
|
|
|
## Slots representing the paintable channels.
|
|
|
|
##
|
2023-01-18 18:15:41 +01:00
|
|
|
enum PaintSlot {
|
|
|
|
ERASE,
|
2023-01-25 00:26:17 +01:00
|
|
|
PAINT_1,
|
|
|
|
PAINT_2,
|
|
|
|
PAINT_3,
|
2023-01-18 18:15:41 +01:00
|
|
|
}
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-26 00:35:36 +01:00
|
|
|
var _albedo_maps: Array[Texture2D] = []
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-18 18:15:41 +01:00
|
|
|
var _material := ShaderMaterial.new()
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-18 18:15:41 +01:00
|
|
|
var _mesh := PlaneMesh.new()
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-26 00:35:36 +01:00
|
|
|
var _normal_maps: Array[Texture2D] = []
|
2023-01-23 19:28:14 +01:00
|
|
|
|
|
|
|
##
|
2023-01-23 21:29:43 +01:00
|
|
|
## Range of the height channel value, ranging from [code]0.0[/code] to [code]100.0[/code].
|
2023-01-16 19:25:35 +01:00
|
|
|
##
|
|
|
|
@export
|
2023-01-18 18:15:41 +01:00
|
|
|
var height_scale := 100.0:
|
2023-01-23 19:28:14 +01:00
|
|
|
set(value):
|
|
|
|
value = maxf(value, 1.0)
|
|
|
|
|
|
|
|
if not(is_equal_approx(value, height_scale)):
|
|
|
|
_material.set_shader_parameter("HEIGHT_SCALE", value)
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
height_scale = value
|
|
|
|
|
|
|
|
##
|
|
|
|
## Size of the terrain geometry (in engine units).
|
|
|
|
##
|
|
|
|
@export
|
|
|
|
var size := Vector2i.ONE:
|
2023-01-16 19:25:35 +01:00
|
|
|
set(value):
|
2023-01-23 19:28:14 +01:00
|
|
|
value = Vector2i(maxi(value.x, 1), maxi(value.y, 1))
|
|
|
|
|
|
|
|
if (value.x != size.x) or (value.y != size.y):
|
|
|
|
_mesh.subdivide_width = value.x * _DETAIL
|
|
|
|
_mesh.subdivide_depth = value.y * _DETAIL
|
|
|
|
_mesh.size = value
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
_material.set_shader_parameter("SIZE", value)
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
size = value
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-18 18:15:41 +01:00
|
|
|
func _init() -> void:
|
2023-01-26 00:35:36 +01:00
|
|
|
var paint_channels := PaintSlot.values().size()
|
|
|
|
|
|
|
|
_albedo_maps.resize(paint_channels)
|
|
|
|
_normal_maps.resize(paint_channels)
|
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
_material.shader = _SHADER
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-18 18:15:41 +01:00
|
|
|
_mesh.surface_set_material(0, _material)
|
2023-01-23 19:28:14 +01:00
|
|
|
RenderingServer.instance_set_base(get_instance(), _mesh)
|
2023-01-16 19:25:35 +01:00
|
|
|
|
|
|
|
##
|
2023-01-23 19:28:14 +01:00
|
|
|
## Updates the terrain map being used by the terrain to be [code]terrain_map[/code].
|
2023-01-16 19:25:35 +01:00
|
|
|
##
|
2023-01-23 19:28:14 +01:00
|
|
|
func update_map(terrain_map: Texture2D) -> void:
|
|
|
|
_material.set_shader_parameter("TERRAIN_MAP", terrain_map)
|
2023-01-16 19:25:35 +01:00
|
|
|
|
|
|
|
##
|
2023-01-23 19:28:14 +01:00
|
|
|
## Updates the [TerrainPaint] being used by the terrain in [code]paint_slot[/code] to be
|
2023-01-18 18:15:41 +01:00
|
|
|
## [code]terrain_paint[/code].
|
2023-01-16 19:25:35 +01:00
|
|
|
##
|
2023-01-23 19:28:14 +01:00
|
|
|
func update_paint(paint_slot: PaintSlot, terrain_paint: TerrainPaint) -> void:
|
|
|
|
if _albedo_maps[paint_slot] != terrain_paint.albedo_map:
|
|
|
|
_albedo_maps[paint_slot] = terrain_paint.albedo_map
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
_material.set_shader_parameter("ALBEDO_MAPS", _albedo_maps)
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
if _normal_maps[paint_slot] != terrain_paint.normal_map:
|
|
|
|
_normal_maps[paint_slot] = terrain_paint.normal_map
|
2023-01-16 19:25:35 +01:00
|
|
|
|
2023-01-23 19:28:14 +01:00
|
|
|
_material.set_shader_parameter("NORMAL_MAPS", _normal_maps)
|