Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use shader for all brush decals and add crosshair
Browse files Browse the repository at this point in the history
Xtarsia committed Jan 2, 2025
1 parent e09d684 commit be83b7f
Showing 4 changed files with 111 additions and 173 deletions.
2 changes: 2 additions & 0 deletions project/addons/terrain_3d/src/tool_settings.gd
Original file line number Diff line number Diff line change
@@ -173,6 +173,8 @@ func _ready() -> void:
"unit":"γ", "range":Vector3(0.1, 2.0, 0.01) })
add_setting({ "name":"jitter", "type":SettingType.SLIDER, "list":advanced_list, "default":50,
"unit":"%", "range":Vector3(0, 100, 1) })
add_setting({ "name":"cross_hair_threshold", "type":SettingType.SLIDER, "list":advanced_list, "default":16.,
"unit":"m", "range":Vector3(0, 200, 1) })


func create_submenu(p_parent: Control, p_button_name: String, p_layout: Layout, p_hover_pop: bool = true) -> Container:
246 changes: 87 additions & 159 deletions project/addons/terrain_3d/src/ui.gd
Original file line number Diff line number Diff line change
@@ -42,21 +42,20 @@ var setting_has_changed: bool = false
var visible: bool = false
var picking: int = Terrain3DEditor.TOOL_MAX
var picking_callback: Callable
var decal: Decal
var decal_timer: Timer
var gradient_decals: Array[Decal]
var brush_data: Dictionary
var operation_builder: OperationBuilder
var last_tool: Terrain3DEditor.Tool
var last_operation: Terrain3DEditor.Operation
var last_rmb_time: int = 0 # Set in editor.gd

# Compatibility decals, indices; 0 = main brush, 1 = slope point A, 2 = slope point B
var editor_decal_position: Array[Vector2]
var editor_decal_rotation: Array[float]
var editor_decal_size: Array[float]
var editor_decal_color: Array[Color]
var editor_decal_visible: Array[bool]
# Editor decals, indices; 0 = main brush, 1 = slope point A, 2 = slope point B
var editor_decal_position: Array[Vector2] = [Vector2(), Vector2(), Vector2()]
var editor_decal_rotation: Array[float] = [float(), float(), float()]
var editor_decal_size: Array[float] = [float(), float(), float()]
var editor_decal_color: Array[Color] = [Color(), Color(), Color()]
var editor_decal_visible: Array[bool] = [bool(), bool(), bool()]
var editor_brush_texture_rid: RID = RID()
@onready var editor_ring_texture_rid: RID = ring_texture.get_rid()


func _enter_tree() -> void:
@@ -79,16 +78,6 @@ func _enter_tree() -> void:
plugin.add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, terrain_menu)

_on_tool_changed(Terrain3DEditor.REGION, Terrain3DEditor.ADD)

decal = Decal.new()
add_child(decal)
decal_timer = Timer.new()
decal_timer.wait_time = .5
decal_timer.one_shot = true
decal_timer.timeout.connect(Callable(func(node):
if node:
get_tree().create_tween().tween_property(node, "albedo_mix", 0.0, 0.15)).bind(decal))
add_child(decal_timer)


func _exit_tree() -> void:
@@ -97,11 +86,6 @@ func _exit_tree() -> void:
toolbar.queue_free()
tool_settings.queue_free()
terrain_menu.queue_free()
decal.queue_free()
decal_timer.queue_free()
for gradient_decal in gradient_decals:
gradient_decal.queue_free()
gradient_decals.clear()


func set_visible(p_visible: bool, p_menu_only: bool = false) -> void:
@@ -237,6 +221,7 @@ func _on_tool_changed(p_tool: Terrain3DEditor.Tool, p_operation: Terrain3DEditor
to_show.push_back("show_cursor_while_painting")
to_show.push_back("gamma")
to_show.push_back("jitter")
to_show.push_back("cross_hair_threshold")
tool_settings.show_settings(to_show)

operation_builder = null
@@ -259,7 +244,6 @@ func _on_setting_changed() -> void:
return
brush_data = tool_settings.get_settings()
brush_data["asset_id"] = plugin.asset_dock.get_current_list().get_selected_id()
update_decal()
plugin.editor.set_brush_data(brush_data)
plugin.editor.set_operation(_modify_operation(plugin.editor.get_operation()))

@@ -300,6 +284,10 @@ func _invert_operation(p_operation: Terrain3DEditor.Operation, flags: int = OP_N


func update_decal() -> void:
if !plugin.terrain:
return
var mat_rid: RID = plugin.terrain.material.get_material_rid()

# If not a state that should show the decal, hide everything and return
if not visible or \
not plugin.terrain or \
@@ -310,185 +298,125 @@ func update_decal() -> void:
brush_data.is_empty() or \
plugin.editor.get_tool() == Terrain3DEditor.REGION or \
(plugin._input_mode > 0 and not brush_data["show_cursor_while_painting"]):
decal.visible = false
for gradient_decal in gradient_decals:
gradient_decal.visible = false
editor_decal_visible[0] = false
editor_decal_visible[1] = false
editor_decal_visible[2] = false
RenderingServer.material_set_param(mat_rid, "_editor_decal_visible", editor_decal_visible)
return

decal.position = plugin.mouse_global_position
decal.visible = true
decal.size = Vector3.ONE * maxf(brush_data["size"], .5)
editor_decal_position[0] = Vector2(plugin.mouse_global_position.x, plugin.mouse_global_position.z)
editor_decal_visible[0] = true
editor_decal_size[0] = maxf(brush_data["size"], .5)
if brush_data["align_to_view"]:
var cam: Camera3D = plugin.terrain.get_camera();
if (cam):
decal.rotation.y = cam.rotation.y
editor_decal_rotation[0] = cam.rotation.y
else:
decal.rotation.y = 0

editor_decal_rotation[0] = 0
# Set texture and color
if picking != Terrain3DEditor.TOOL_MAX:
decal.texture_albedo = ring_texture
decal.size = Vector3.ONE * 10. * plugin.terrain.get_vertex_spacing()
editor_brush_texture_rid = ring_texture.get_rid()
editor_decal_size[0] = 10. * plugin.terrain.get_vertex_spacing()
match picking:
Terrain3DEditor.HEIGHT:
decal.modulate = COLOR_PICK_HEIGHT
editor_decal_color[0] = COLOR_PICK_HEIGHT
Terrain3DEditor.COLOR:
decal.modulate = COLOR_PICK_COLOR
editor_decal_color[0] = COLOR_PICK_COLOR
Terrain3DEditor.ROUGHNESS:
decal.modulate = COLOR_PICK_ROUGH
decal.modulate.a = 1.0
editor_decal_color[0] = COLOR_PICK_ROUGH
editor_decal_color[0].a = 1.0
else:
decal.texture_albedo = brush_data["brush"][1]
editor_brush_texture_rid = brush_data["brush"][1].get_rid()
match plugin.editor.get_tool():
Terrain3DEditor.SCULPT:
match plugin.editor.get_operation():
Terrain3DEditor.ADD:
if plugin.modifier_alt:
decal.modulate = COLOR_LIFT
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_LIFT
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
else:
decal.modulate = COLOR_RAISE
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_RAISE
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.SUBTRACT:
if plugin.modifier_alt:
decal.modulate = COLOR_FLATTEN
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_FLATTEN
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
else:
decal.modulate = COLOR_LOWER
decal.modulate.a = clamp(brush_data["strength"], .2, .5) + .5
editor_decal_color[0] = COLOR_LOWER
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5) + .5
Terrain3DEditor.AVERAGE:
decal.modulate = COLOR_SMOOTH
decal.modulate.a = clamp(brush_data["strength"], .2, .5) + .2
editor_decal_color[0] = COLOR_SMOOTH
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5) + .2
Terrain3DEditor.GRADIENT:
decal.modulate = COLOR_SLOPE
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_SLOPE
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.HEIGHT:
decal.modulate = COLOR_HEIGHT
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_HEIGHT
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.TEXTURE:
match plugin.editor.get_operation():
Terrain3DEditor.REPLACE:
decal.modulate = COLOR_PAINT
decal.modulate.a = .7
editor_decal_color[0] = COLOR_PAINT
editor_decal_color[0].a = .7
Terrain3DEditor.SUBTRACT:
decal.modulate = COLOR_PAINT
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_PAINT
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.ADD:
decal.modulate = COLOR_SPRAY
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_SPRAY
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.COLOR:
decal.modulate = brush_data["color"].srgb_to_linear()
decal.modulate.a *= clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = brush_data["color"].srgb_to_linear()
editor_decal_color[0].a *= clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.ROUGHNESS:
decal.modulate = COLOR_ROUGHNESS
decal.modulate.a = clamp(brush_data["strength"], .2, .5)
editor_decal_color[0] = COLOR_ROUGHNESS
editor_decal_color[0].a = clamp(brush_data["strength"], .2, .5)
Terrain3DEditor.AUTOSHADER:
decal.modulate = COLOR_AUTOSHADER
decal.modulate.a = .7
editor_decal_color[0] = COLOR_AUTOSHADER
editor_decal_color[0].a = .7
Terrain3DEditor.HOLES:
decal.modulate = COLOR_HOLES
decal.modulate.a = .85
editor_decal_color[0] = COLOR_HOLES
editor_decal_color[0].a = .85
Terrain3DEditor.NAVIGATION:
decal.modulate = COLOR_NAVIGATION
decal.modulate.a = .85
editor_decal_color[0] = COLOR_NAVIGATION
editor_decal_color[0].a = .85
Terrain3DEditor.INSTANCER:
decal.texture_albedo = ring_texture
decal.modulate = COLOR_INSTANCER
decal.modulate.a = 1.0
decal.size.y = max(1000, decal.size.y)
decal.albedo_mix = 1.0
decal.cull_mask = 1 << ( plugin.terrain.get_mouse_layer() - 1 )
decal_timer.start()

for gradient_decal in gradient_decals:
gradient_decal.visible = false
editor_brush_texture_rid = ring_texture.get_rid()
editor_decal_color[0] = COLOR_INSTANCER
editor_decal_color[0].a = 1.0

if plugin.editor.get_operation() == Terrain3DEditor.GRADIENT:
var index := 0
for point in brush_data["gradient_points"]:
if point != Vector3.ZERO:
var point_decal: Decal = _get_gradient_decal(index)
point_decal.visible = true
point_decal.position = point
index += 1

update_compatibility_decal()


func _get_gradient_decal(index: int) -> Decal:
if gradient_decals.size() > index:
return gradient_decals[index]
editor_decal_visible[1] = false
editor_decal_visible[2] = false

var gradient_decal := Decal.new()
gradient_decal = Decal.new()
gradient_decal.texture_albedo = ring_texture
gradient_decal.modulate = COLOR_SLOPE
gradient_decal.size = Vector3.ONE * 10. * plugin.terrain.get_vertex_spacing()
gradient_decal.size.y = 1000.
gradient_decal.cull_mask = decal.cull_mask
add_child(gradient_decal)
if plugin.editor.get_operation() == Terrain3DEditor.GRADIENT:
var point1: Vector3 = brush_data["gradient_points"][0]
if point1 != Vector3.ZERO:
editor_decal_color[1] = COLOR_SLOPE
editor_decal_size[1] = 10. * plugin.terrain.get_vertex_spacing()
editor_decal_visible[1] = true
editor_decal_position[1] = Vector2(point1.x, point1.z)
var point2: Vector3 = brush_data["gradient_points"][1]
if point2 != Vector3.ZERO:
editor_decal_color[2] = COLOR_SLOPE
editor_decal_size[2] = 10. * plugin.terrain.get_vertex_spacing()
editor_decal_visible[2] = true
editor_decal_position[2] = Vector2(point2.x, point2.z)

gradient_decals.push_back(gradient_decal)
return gradient_decal


func update_compatibility_decal() -> void:
if not plugin.terrain.is_compatibility_mode():
return

# Verify setup
if editor_decal_position.size() != 3:
editor_decal_position.resize(3)
editor_decal_rotation.resize(3)
editor_decal_size.resize(3)
editor_decal_color.resize(3)
editor_decal_visible.resize(3)
decal_timer.timeout.connect(func():
var mat_rid: RID = plugin.terrain.material.get_material_rid()
editor_decal_visible[0] = false
RenderingServer.material_set_param(mat_rid, "_editor_decal_visible", editor_decal_visible)
)

# Update compatibility decal
var mat_rid: RID = plugin.terrain.material.get_material_rid()
if decal.visible:
editor_decal_position[0] = Vector2(decal.global_position.x, decal.global_position.z)
editor_decal_rotation[0] = decal.rotation.y
editor_decal_size[0] = brush_data.get("size")
editor_decal_color[0] = decal.modulate
editor_decal_visible[0] = decal.visible
RenderingServer.material_set_param(
mat_rid, "_editor_decal_0", decal.texture_albedo.get_rid()
)
if gradient_decals.size() >= 1:
editor_decal_position[1] = Vector2(gradient_decals[0].global_position.x,
gradient_decals[0].global_position.z)
editor_decal_rotation[1] = gradient_decals[0].rotation.y
editor_decal_size[1] = 10.0
editor_decal_color[1] = gradient_decals[0].modulate
editor_decal_visible[1] = gradient_decals[0].visible
RenderingServer.material_set_param(
mat_rid, "_editor_decal_1", gradient_decals[0].texture_albedo.get_rid()
)
if gradient_decals.size() >= 2:
editor_decal_position[2] = Vector2(gradient_decals[1].global_position.x,
gradient_decals[1].global_position.z)
editor_decal_rotation[2] = gradient_decals[1].rotation.y
editor_decal_size[2] = 10.0
editor_decal_color[2] = gradient_decals[1].modulate
editor_decal_visible[2] = gradient_decals[1].visible
RenderingServer.material_set_param(
mat_rid, "_editor_decal_2", gradient_decals[1].texture_albedo.get_rid()
)
# Update Shader params
RenderingServer.material_set_param(mat_rid, "_editor_brush_texture", editor_brush_texture_rid)
RenderingServer.material_set_param(mat_rid, "_editor_ring_texture", editor_ring_texture_rid)
RenderingServer.material_set_param(mat_rid, "_editor_decal_position", editor_decal_position)
RenderingServer.material_set_param(mat_rid, "_editor_decal_rotation", editor_decal_rotation)
RenderingServer.material_set_param(mat_rid, "_editor_decal_size", editor_decal_size)
RenderingServer.material_set_param(mat_rid, "_editor_decal_color", editor_decal_color)
RenderingServer.material_set_param(mat_rid, "_editor_decal_visible", editor_decal_visible)

RenderingServer.material_set_param(mat_rid, "_editor_decal_timestamp", float(Time.get_ticks_msec()) / 1000.0 + 0.5)
RenderingServer.material_set_param(mat_rid, "_editor_cross_hair_threshold", brush_data["cross_hair_threshold"] + 0.1)

func set_decal_rotation(p_rot: float) -> void:
decal.rotation.y = p_rot
editor_decal_rotation[0] = p_rot
var mat_rid: RID = plugin.terrain.material.get_material_rid()
RenderingServer.material_set_param(mat_rid, "_editor_decal_rotation", editor_decal_rotation)


func _on_picking(p_type: int, p_callback: Callable) -> void:
Loading

0 comments on commit be83b7f

Please sign in to comment.