Scaling a patchwork control node

Godot Version

4.2

Question

Hello,

For my mobile game that needs to be responsive, I have a control node that needs to scale within a container. However, I’m not sure if I can use containers to achieve this.
Sans titre 3

So far, I’ve “succeeded” by placing everything in a subviewport and displaying it in a TextureRect with Ignore Size, Keep Aspect settings. However, my 2 red TextureButtons are no longer usable (which makes sense since TextureRect is just an image).

I haven’t found any other solutions; most of my tests (just the control, a subviewport container, etc.) simply display my node without any resizing.

Does anyone have any ideas?
Thanks <3

You could use a AspectRatioContainer to keep the aspect ratio of the main Control and setup the content’s anchors correctly. Once the anchors are correctly set you can set the TextureButtons and background TextureRect to Keep Aspect but for the Labels it’s not that simple. You’ll need to find out which minimum and maximum font size they can have and change the font size when the Control node gets resized.

Here’s a self contained tscn you can use to see how I did it.

scene.tscn
[gd_scene load_steps=6 format=3 uid="uid://etix820dwtio"]

[ext_resource type="Texture2D" uid="uid://caxnlrbgg5dij" path="res://icon.svg" id="1_jy3wm"]

[sub_resource type="GDScript" id="GDScript_nrm76"]
script/source = "@tool
extends AspectRatioContainer

@onready var control: Control = $Control
@onready var title_label: Label = $Control/TitleLabel
@onready var score_label: Label = $Control/ScoreLabel
@onready var top_button: TextureButton = $Control/TopButton
@onready var bottom_button: TextureButton = $Control/BottomButton


func _ready() -> void:
	top_button.pressed.connect(func(): print('pressed top'))
	bottom_button.pressed.connect(func(): print('pressed bottom'))
	control.resized.connect(func():
		var min_width = 256
		var max_width = 648
		title_label.add_theme_font_size_override(\"font_size\", remap(control.size.x, min_width, max_width, 48, 128))
		score_label.add_theme_font_size_override(\"font_size\", remap(control.size.x, min_width, max_width, 48, 128))
	)
"

[sub_resource type="Animation" id="Animation_1ucpi"]
resource_name = "new_animation"
length = 5.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("AspectRatioContainer:size")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector2(256, 256), Vector2(1152, 648)]
}

[sub_resource type="Animation" id="Animation_7lwhn"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("AspectRatioContainer:size")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(256, 256)]
}

[sub_resource type="AnimationLibrary" id="AnimationLibrary_otvd1"]
_data = {
"RESET": SubResource("Animation_7lwhn"),
"new_animation": SubResource("Animation_1ucpi")
}

[node name="TestAspectRatioContainer" type="Node"]

[node name="AspectRatioContainer" type="AspectRatioContainer" parent="."]
custom_minimum_size = Vector2(256, 256)
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -896.0
offset_bottom = -392.0
grow_horizontal = 2
grow_vertical = 2
script = SubResource("GDScript_nrm76")

[node name="Control" type="Control" parent="AspectRatioContainer"]
layout_mode = 2

[node name="ColorRect" type="ColorRect" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2

[node name="ColorRect2" type="ColorRect" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.068
anchor_top = 0.068
anchor_right = 0.932
anchor_bottom = 0.932
offset_left = -0.132004
offset_top = -0.132004
offset_right = 0.131958
offset_bottom = 0.131958
grow_horizontal = 2
grow_vertical = 2
color = Color(0.913725, 0.509804, 0.227451, 1)
metadata/_edit_use_anchors_ = true

[node name="TitleLabel" type="Label" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.059
anchor_top = -0.02
anchor_right = 0.652
anchor_bottom = 0.242
offset_left = -0.100003
offset_top = 0.12
offset_right = -53.278
offset_bottom = -21.51
size_flags_vertical = 1
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 48
text = "SCORE"
metadata/_edit_use_anchors_ = true

[node name="ScoreLabel" type="Label" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.07
anchor_top = 0.457156
anchor_right = 0.976875
anchor_bottom = 0.719156
offset_left = 0.0799999
offset_top = -0.0320053
offset_right = -0.0800171
offset_bottom = -0.104004
grow_horizontal = 2
grow_vertical = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 48
text = "25668"
horizontal_alignment = 2
metadata/_edit_use_anchors_ = true

[node name="TopButton" type="TextureButton" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.770531
anchor_top = 0.12
anchor_right = 0.991715
anchor_bottom = 0.343666
offset_left = -0.256012
offset_top = 0.279999
offset_right = 0.120911
offset_bottom = 0.0213928
grow_horizontal = 0
texture_normal = ExtResource("1_jy3wm")
ignore_texture_size = true
stretch_mode = 4
metadata/_edit_use_anchors_ = true

[node name="BottomButton" type="TextureButton" parent="AspectRatioContainer/Control"]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.122094
anchor_top = 0.741094
anchor_right = 0.343278
anchor_bottom = 0.96476
offset_left = -0.256012
offset_top = 0.279999
offset_right = 0.120911
offset_bottom = 0.0213928
grow_horizontal = 0
texture_normal = ExtResource("1_jy3wm")
ignore_texture_size = true
stretch_mode = 4
metadata/_edit_use_anchors_ = true

[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_otvd1")
}
autoplay = "new_animation"

Result:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.