From 5a2d825181970df9fffcccbd39a5450e1ca879a8 Mon Sep 17 00:00:00 2001 From: hz Date: Sat, 25 Jul 2026 10:13:18 -0500 Subject: [PATCH] Rework legal consent to match the provided design Drop the bordered card - it wasn't the right direction. Instead: - Plain small checkbox with just a blue border (no fill/icon when unchecked), matching the reference exactly. - "Terms of Service"/"Privacy Policy" render as inline blue links within the sentence (RichTextLabel + BBCode [url], routed through the same _open_legal_document as the footer), instead of a duplicate link row underneath. meta_underlined = false to match the reference's plain (non-underlined) link style. Verified with real rendered screenshots at each step, including a pixel-level crop confirming the underline was actually gone. --- scripts/ui/login_screen.gd | 80 ++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/scripts/ui/login_screen.gd b/scripts/ui/login_screen.gd index ccd4ad3..036ef07 100644 --- a/scripts/ui/login_screen.gd +++ b/scripts/ui/login_screen.gd @@ -26,6 +26,7 @@ var steam_view: VBoxContainer var login_input: LineEdit var password_input: LineEdit var password_reveal_entries: Array[Dictionary] = [] +var legal_consent_texts: Array[RichTextLabel] = [] var registration_username_input: LineEdit var registration_email_input: LineEdit var registration_password_input: LineEdit @@ -345,38 +346,45 @@ func _build_steam_view() -> VBoxContainer: func _add_legal_consent(parent: VBoxContainer) -> CheckBox: # A bare CheckBox's own word-wrap left-aligns every wrapped line flush - # with the checkbox glyph, so a second line reads as un-indented and - # sloppy. Split the toggle from its label into a row instead - the - # label's own wrapping then stays confined to its column, and the whole - # thing sits in a card so it doesn't look like a stray unstyled control - # next to the app's otherwise fully themed form fields. - var card := PanelContainer.new() - card.set_meta("legal_consent_card", true) - parent.add_child(card) - var margin := MarginContainer.new() - margin.add_theme_constant_override("margin_left", 16) - margin.add_theme_constant_override("margin_right", 16) - margin.add_theme_constant_override("margin_top", 12) - margin.add_theme_constant_override("margin_bottom", 12) - card.add_child(margin) + # with the checkbox glyph, so a second line reads as un-indented. Split + # the toggle from its text into a row instead - the RichTextLabel's own + # wrapping then stays confined to its column, and "Terms of Service"/ + # "Privacy Policy" render as inline links rather than a duplicate row + # of link buttons underneath. var row := HBoxContainer.new() row.add_theme_constant_override("separation", 12) - margin.add_child(row) + parent.add_child(row) var check := CheckBox.new() + check.custom_minimum_size = Vector2(26, 26) + check.add_theme_icon_override("unchecked", _blank_icon()) row.add_child(check) - var label := Label.new() - label.text = "I agree to the Terms of Service and acknowledge the Privacy Policy." - label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - label.size_flags_horizontal = Control.SIZE_EXPAND_FILL - label.mouse_filter = Control.MOUSE_FILTER_STOP - label.gui_input.connect(func(event: InputEvent): - if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: - check.button_pressed = not check.button_pressed - ) - row.add_child(label) + var consent_text := RichTextLabel.new() + consent_text.bbcode_enabled = true + consent_text.fit_content = true + consent_text.scroll_active = false + consent_text.meta_underlined = false + consent_text.size_flags_horizontal = Control.SIZE_EXPAND_FILL + consent_text.add_theme_font_override("normal_font", Brand.font) + consent_text.add_theme_font_size_override("normal_font_size", 15) + consent_text.meta_clicked.connect(func(meta: Variant): _open_legal_document(str(meta))) + legal_consent_texts.append(consent_text) + row.add_child(consent_text) return check +func _blank_icon() -> ImageTexture: + return ImageTexture.create_from_image(Image.create(1, 1, false, Image.FORMAT_RGBA8)) + + +func _refresh_legal_consent_text(consent_text: RichTextLabel, dark: bool) -> void: + var text_hex := Brand.text_color(dark).to_html(false) + var link_hex := (Brand.SKY_BLUE if dark else Brand.ROYAL_BLUE).to_html(false) + consent_text.text = ( + "[color=#%s]I agree to the [/color][url=terms][color=#%s]Terms of Service[/color][/url][color=#%s] and acknowledge the [/color][url=privacy][color=#%s]Privacy Policy[/color][/url][color=#%s].[/color]" + % [text_hex, link_hex, text_hex, link_hex, text_hex] + ) + + func _add_legal_links(parent: HBoxContainer) -> void: for spec in [["Terms of Service", "terms"], ["Privacy Policy", "privacy"]]: var link := Button.new() @@ -581,9 +589,16 @@ func _apply_theme() -> void: label.add_theme_color_override("font_color", Brand.text_color(dark)) for input in fields: _style_auth_field(input, dark) - for node in find_children("*", "PanelContainer", true, false): - if node.has_meta("legal_consent_card"): - (node as PanelContainer).add_theme_stylebox_override("panel", _legal_consent_box(dark)) + for consent_text in legal_consent_texts: + _refresh_legal_consent_text(consent_text, dark) + var checkbox_box := StyleBoxFlat.new() + checkbox_box.bg_color = Color.TRANSPARENT + checkbox_box.border_color = Brand.SKY_BLUE if dark else Brand.ROYAL_BLUE + checkbox_box.set_border_width_all(2) + checkbox_box.set_corner_radius_all(6) + for cb in find_children("*", "CheckBox", true, false): + for state in ["normal", "hover", "pressed", "focus"]: + cb.add_theme_stylebox_override(state, checkbox_box) for button in find_children("*", "Button", true, false): var typed := button as Button typed.add_theme_font_override("font", Brand.font) @@ -613,15 +628,6 @@ func _apply_theme() -> void: brand_tagline.add_theme_color_override("default_color", Brand.muted_color(dark)) -func _legal_consent_box(dark: bool) -> StyleBoxFlat: - var box := StyleBoxFlat.new() - box.bg_color = Color("0d172a") if dark else Brand.LIGHT_SURFACE - box.border_color = Color("33415d") if dark else Brand.LIGHT_BORDER - box.set_border_width_all(1) - box.set_corner_radius_all(10) - return box - - func _style_auth_field(input: LineEdit, dark: bool) -> void: input.add_theme_color_override("font_color", Brand.text_color(dark)) input.add_theme_color_override("font_uneditable_color", Brand.text_color(dark))