Scroll Container Fade on Edges like Resident Evil HD

Godot Version

4.5

Question

Hi,
I made this Resident Evil HD inspired main menu screen for my game. I used a scrollcontainer to contain all my buttons.

I wanted to make it look as same as the Resident Evil HD intro main menu screen. Look how on the edges of whatever UI widget CAPCOM used for scroll container is FADED on the EDGES.

Is there any way to make the edges of the ScrollContainer Fade on the edges as well,
in GODOT 4. I’m using the latest GODOT 4.5.

You can use a NinePatchRect control node as a parent of your ScrollContainer with CanvasItem.clip_children set to Clip Only and using a TextureGradient2D with the gradient fading from top to bottom. You’ll need to add an extra Control node to the top and bottom of your list to avoid the first and last elements to be in the gradient zone.

Result:

Self-contained tscn file
[gd_scene load_steps=6 format=3 uid="uid://ckpnftnc1658o"]

[sub_resource type="GDScript" id="GDScript_ek47y"]
script/source = "extends Node

@onready var scroll_container: ScrollContainer = $NinePatchRect/ScrollContainer


func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed(&\"ui_up\", true):
		scroll_container.scroll_vertical -= 10
	elif event.is_action_pressed(&\"ui_down\", true):
		scroll_container.scroll_vertical += 10
"

[sub_resource type="Gradient" id="Gradient_i5skc"]
interpolation_mode = 2
offsets = PackedFloat32Array(0, 0.45, 0.65, 1)
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)

[sub_resource type="GradientTexture2D" id="GradientTexture2D_qhlfe"]
gradient = SubResource("Gradient_i5skc")
fill_to = Vector2(0, 1)

[sub_resource type="SystemFont" id="SystemFont_ek47y"]
font_names = PackedStringArray("Serif")
font_weight = 800

[sub_resource type="LabelSettings" id="LabelSettings_i5skc"]
font = SubResource("SystemFont_ek47y")
font_size = 24

[node name="TestScrollContainerGradient" type="Node"]
script = SubResource("GDScript_ek47y")

[node name="NinePatchRect" type="NinePatchRect" parent="."]
clip_children = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -84.5
offset_top = -257.0
offset_right = 84.5
offset_bottom = -122.0
grow_horizontal = 2
grow_vertical = 0
texture = SubResource("GradientTexture2D_qhlfe")
patch_margin_top = 30
patch_margin_bottom = 30

[node name="ScrollContainer" type="ScrollContainer" parent="NinePatchRect"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
vertical_scroll_mode = 3

[node name="VBoxContainer" type="VBoxContainer" parent="NinePatchRect/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3

[node name="Label" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label9" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Load Game"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label2" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "New Game"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label3" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Options"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label4" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Manual"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label5" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Leaderboard"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label6" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Gallery"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label7" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Credits"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label8" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
text = "Quit"
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

[node name="Label10" type="Label" parent="NinePatchRect/ScrollContainer/VBoxContainer"]
layout_mode = 2
label_settings = SubResource("LabelSettings_i5skc")
horizontal_alignment = 1

2 Likes

Damn Thats what I needed THANKYOU SOO MUCHH. But the thing is I’m using a controller friendly system that detects the next button to focus all the time.
This is what I’m referring to…

You’re just scrolling the menu with up and down but not focusing the individual buttons.
Anyways I’ll try your method too. People like you make the community cool af.

I came up with this and it quite hit the spot. Thanks for helping me out​:grin::grin:. Also, how did you send the tscn file as self cotained in your reply message??

My Test.tscn:

[gd_scene load_steps=6 format=3 uid=“uid://bblfe622bxfwf”]

[sub_resource type=“GDScript” id=“GDScript_ek47y”]
script/source = "extends Node

@onready var scroll_container: ScrollContainer = $NinePatchRect/ScrollContainer

func _ready() → void:
find_child("Label9").grab_focus.call_deferred()

#func _unhandled_input(event: InputEvent) → void:
#if event.is_action_pressed(&"ui_up", true):
#scroll_container.scroll_vertical -= 10
#elif event.is_action_pressed(&"ui_down", true):
#scroll_container.scroll_vertical += 10

func _on_label_9_focus_entered() → void:
scroll_container.scroll_vertical = 0

func _on_label_2_focus_entered() → void:
scroll_container.scroll_vertical = 30

func _on_label_3_focus_entered() → void:
scroll_container.scroll_vertical = 61

func _on_label_4_focus_entered() → void:
scroll_container.scroll_vertical = 91

func _on_label_5_focus_entered() → void:
scroll_container.scroll_vertical = 121

func _on_label_6_focus_entered() → void:
scroll_container.scroll_vertical = 151

func _on_label_7_focus_entered() → void:
scroll_container.scroll_vertical = 181

func _on_label_8_focus_entered() → void:
scroll_container.scroll_vertical = 213
"

[sub_resource type=“Gradient” id=“Gradient_i5skc”]
interpolation_mode = 2
offsets = PackedFloat32Array(0, 0.45, 0.65, 1)
colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)

[sub_resource type=“GradientTexture2D” id=“GradientTexture2D_qhlfe”]
gradient = SubResource(“Gradient_i5skc”)
fill_to = Vector2(0, 1)

[sub_resource type=“SystemFont” id=“SystemFont_ek47y”]
font_names = PackedStringArray(“Serif”)
font_weight = 800

[sub_resource type=“LabelSettings” id=“LabelSettings_i5skc”]
font = SubResource(“SystemFont_ek47y”)
font_size = 24

[node name=“TestScrollContainerGradient” type=“Node”]
script = SubResource(“GDScript_ek47y”)

[node name=“NinePatchRect” type=“NinePatchRect” parent=“.”]
clip_children = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -84.5
offset_top = -257.0
offset_right = 84.5
offset_bottom = -122.0
grow_horizontal = 2
grow_vertical = 0
texture = SubResource(“GradientTexture2D_qhlfe”)
region_rect = Rect2(0, 0, 64, 64)
patch_margin_top = 30
patch_margin_bottom = 30

[node name=“ScrollContainer” type=“ScrollContainer” parent=“NinePatchRect”]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
follow_focus = true
draw_focus_border = true
vertical_scroll_mode = 3

[node name=“VBoxContainer” type=“VBoxContainer” parent=“NinePatchRect/ScrollContainer”]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 1

[node name=“Label” type=“Label” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
label_settings = SubResource(“LabelSettings_i5skc”)
horizontal_alignment = 1

[node name=“Label9” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label8”)
focus_neighbor_bottom = NodePath(“../Label2”)
text = “Load Game”

[node name=“Label2” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label9”)
focus_neighbor_bottom = NodePath(“../Label3”)
text = “New Game”

[node name=“Label3” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label2”)
focus_neighbor_bottom = NodePath(“../Label4”)
text = “Options”

[node name=“Label4” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label3”)
focus_neighbor_bottom = NodePath(“../Label5”)
text = “Manual”

[node name=“Label5” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label4”)
focus_neighbor_bottom = NodePath(“../Label6”)
text = “Leaderboard”

[node name=“Label6” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label5”)
focus_neighbor_bottom = NodePath(“../Label7”)
text = “Gallery”

[node name=“Label7” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label6”)
focus_neighbor_bottom = NodePath(“../Label8”)
text = “Credits”

[node name=“Label8” type=“Button” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
focus_neighbor_top = NodePath(“../Label7”)
focus_neighbor_bottom = NodePath(“../Label9”)
text = “Quit”

[node name=“Label10” type=“Label” parent=“NinePatchRect/ScrollContainer/VBoxContainer”]
layout_mode = 2
label_settings = SubResource(“LabelSettings_i5skc”)
horizontal_alignment = 1

[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label9” to=“.” method=“_on_label_9_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label2” to=“.” method=“_on_label_2_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label3” to=“.” method=“_on_label_3_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label4” to=“.” method=“_on_label_4_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label5” to=“.” method=“_on_label_5_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label6” to=“.” method=“_on_label_6_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label7” to=“.” method=“_on_label_7_focus_entered”]
[connection signal=“focus_entered” from=“NinePatchRect/ScrollContainer/VBoxContainer/Label8” to=“.” method=“_on_label_8_focus_entered”]