extends PanelContainer const Brand := preload("res://scripts/ui/medmind_style.gd") const SHIELD_ICON := preload("res://assets/icons/lucide/shield.svg") const STAR_ICON := preload("res://assets/icons/lucide/star.svg") const CHEVRON_ICON := preload("res://assets/icons/lucide/chevron-down.svg") var rank_icon_panel: PanelContainer var rank_icon_texture: TextureRect var rank_tier_label: Label var rank_elo_label: Label var divider: ColorRect var icon_panel: PanelContainer var icon_texture: TextureRect var value_label: Label var caption_label: Label var displayed_value := 0 var _initialized := false func _ready() -> void: size_flags_vertical = Control.SIZE_SHRINK_CENTER _build_ui() refresh_theme_controls() _on_credits_changed() _on_ratings_changed() CreditsService.credits_changed.connect(_on_credits_changed) QuestionBankService.ratings_changed.connect(_on_ratings_changed) resized.connect(func(): pivot_offset = size * 0.5) func _build_ui() -> void: var margin := MarginContainer.new() margin.add_theme_constant_override("margin_left", 7) margin.add_theme_constant_override("margin_right", 7) margin.add_theme_constant_override("margin_top", 5) margin.add_theme_constant_override("margin_bottom", 5) add_child(margin) var row := HBoxContainer.new() row.add_theme_constant_override("separation", 5) margin.add_child(row) rank_icon_panel = PanelContainer.new() rank_icon_panel.custom_minimum_size = Vector2(22, 22) rank_icon_panel.size_flags_vertical = Control.SIZE_SHRINK_CENTER rank_icon_texture = TextureRect.new() rank_icon_texture.texture = SHIELD_ICON rank_icon_texture.custom_minimum_size = Vector2(13, 13) rank_icon_texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE rank_icon_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED rank_icon_panel.add_child(rank_icon_texture) row.add_child(rank_icon_panel) var rank_copy := VBoxContainer.new() rank_copy.size_flags_vertical = Control.SIZE_SHRINK_CENTER rank_copy.add_theme_constant_override("separation", 0) rank_tier_label = Label.new() rank_tier_label.add_theme_font_override("font", Brand.font) rank_tier_label.add_theme_font_size_override("font_size", 13) rank_copy.add_child(rank_tier_label) rank_elo_label = Label.new() rank_elo_label.add_theme_font_override("font", Brand.font) rank_elo_label.add_theme_font_size_override("font_size", 9) rank_copy.add_child(rank_elo_label) row.add_child(rank_copy) divider = ColorRect.new() divider.custom_minimum_size = Vector2(1, 22) divider.size_flags_vertical = Control.SIZE_SHRINK_CENTER row.add_child(divider) icon_panel = PanelContainer.new() icon_panel.custom_minimum_size = Vector2(22, 22) icon_panel.size_flags_vertical = Control.SIZE_SHRINK_CENTER icon_texture = TextureRect.new() icon_texture.texture = STAR_ICON icon_texture.custom_minimum_size = Vector2(13, 13) icon_texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE icon_texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED icon_panel.add_child(icon_texture) row.add_child(icon_panel) var copy := VBoxContainer.new() copy.size_flags_vertical = Control.SIZE_SHRINK_CENTER copy.add_theme_constant_override("separation", 0) value_label = Label.new() value_label.add_theme_font_override("font", Brand.font) value_label.add_theme_font_size_override("font_size", 13) copy.add_child(value_label) caption_label = Label.new() caption_label.text = "Rz Coins" caption_label.add_theme_font_override("font", Brand.font) caption_label.add_theme_font_size_override("font_size", 9) copy.add_child(caption_label) row.add_child(copy) var chevron := TextureRect.new() chevron.texture = CHEVRON_ICON chevron.custom_minimum_size = Vector2(12, 12) chevron.expand_mode = TextureRect.EXPAND_IGNORE_SIZE chevron.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED chevron.mouse_filter = Control.MOUSE_FILTER_IGNORE chevron.size_flags_vertical = Control.SIZE_SHRINK_CENTER row.add_child(chevron) func refresh_theme_controls() -> void: var dark := UIThemeService.is_dark_mode() add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.ROYAL_BLUE)) rank_icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 11)) rank_icon_texture.modulate = Brand.ROYAL_BLUE rank_tier_label.add_theme_color_override("font_color", Brand.text_color(dark)) rank_elo_label.add_theme_color_override("font_color", Brand.ROYAL_BLUE) divider.color = Color("2a365a") if dark else Brand.LIGHT_BORDER icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.AMBER, 11)) icon_texture.modulate = Brand.AMBER value_label.add_theme_color_override("font_color", Brand.text_color(dark)) caption_label.add_theme_color_override("font_color", Brand.muted_color(dark)) func bump() -> void: var tween := create_tween() tween.tween_property(self, "scale", Vector2(1.12, 1.12), 0.12).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) tween.tween_property(self, "scale", Vector2.ONE, 0.18).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN) func _on_ratings_changed() -> void: var roman := {1: "I", 2: "II", 3: "III"} var division_label: String = roman.get(QuestionBankService.rank_division, "") rank_tier_label.text = "%s %s" % [QuestionBankService.rank_tier, division_label] rank_elo_label.text = "%d ELO" % QuestionBankService.overall_elo func _on_credits_changed() -> void: if not CreditsService.loaded: _initialized = false displayed_value = 0 value_label.text = "--" return if not _initialized: _initialized = true displayed_value = CreditsService.credits value_label.text = _format_thousands(displayed_value) return var tween := create_tween() tween.tween_method(_set_displayed_value, displayed_value, CreditsService.credits, 0.5).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) func _set_displayed_value(value: int) -> void: displayed_value = value value_label.text = _format_thousands(value) func _format_thousands(value: int) -> String: var digits := str(absi(value)) var grouped := "" var count := 0 for index in range(digits.length() - 1, -1, -1): grouped = digits[index] + grouped count += 1 if count % 3 == 0 and index != 0: grouped = "," + grouped return ("-" if value < 0 else "") + grouped