2026-05-29 19:54:56 +08:00

176 lines
6.3 KiB
GDScript

class_name TopBarView
extends RefCounted
const BitmapFontLabelScript := preload("res://scripts/core/bitmap_font_label.gd")
const NumberFormatterScript := preload("res://scripts/core/number_formatter.gd")
const PowerFontTexturePath := "res://assets/egret/fonts/building_lv_font.png"
const PowerFontPath := "res://assets/egret/fonts/building_lv_font.json"
const TopShowTexture := preload("res://assets/egret/menu2/btn_top_show.png")
const TopHideTexture := preload("res://assets/egret/menu2/btn_top_hide.png")
const TOP_MENU_EXPANDED_Y := 1.0
const TOP_MENU_COLLAPSED_Y := -100.0
var _owner: Control
var _top_layer: Control
var _top_button_group: Control
var _top_hide: TextureRect
var _label_name: Label
var _label_level: Label
var _label_gold: Label
var _label_diamond: Label
var _label_score: Label
var _label_exp: Label
var _exp_fill: NinePatchRect
var _avatar: TextureRect
var _game_config
var _style_label: Callable
var _style_menu_title: Callable
var _score_bitmap: BitmapFontLabel
var _exp_tween: Tween
var _top_menu_tween: Tween
var _top_menu_expanded := true
var _initial_rendered := false
func setup(bindings: Dictionary, style_label: Callable, style_menu_title: Callable) -> void:
_owner = bindings.get("owner") as Control
_top_layer = bindings.get("top_layer") as Control
_top_button_group = bindings.get("top_button_group") as Control
_top_hide = bindings.get("top_hide") as TextureRect
_label_name = bindings.get("label_name") as Label
_label_level = bindings.get("label_level") as Label
_label_gold = bindings.get("label_gold") as Label
_label_diamond = bindings.get("label_diamond") as Label
_label_score = bindings.get("label_score") as Label
_label_exp = bindings.get("label_exp") as Label
_exp_fill = bindings.get("exp_fill") as NinePatchRect
_avatar = bindings.get("avatar") as TextureRect
_game_config = bindings.get("game_config")
_style_label = style_label
_style_menu_title = style_menu_title
_apply_label_theme()
_setup_power_bitmap_label()
_apply_top_menu_toggle_visual()
func toggle_top_button_group() -> bool:
if _top_button_group == null or _owner == null:
return _top_menu_expanded
if _top_menu_tween != null:
_top_menu_tween.kill()
_top_menu_expanded = not _top_menu_expanded
_apply_top_menu_toggle_visual()
_top_button_group.visible = true
var target_y := TOP_MENU_EXPANDED_Y if _top_menu_expanded else TOP_MENU_COLLAPSED_Y
_top_menu_tween = _owner.create_tween()
_top_menu_tween.tween_property(_top_button_group, "position:y", target_y, 0.25).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
if not _top_menu_expanded:
_top_menu_tween.finished.connect(_finish_collapse_top_menu)
return _top_menu_expanded
func set_visitor_mode(enabled: bool) -> void:
if _top_button_group != null:
_top_button_group.visible = not enabled and _top_menu_expanded
if _top_hide != null:
_top_hide.visible = not enabled
func render(player_data: Dictionary) -> void:
if _label_name == null:
return
var nickname := str(player_data.get("nickname", player_data.get("username", "")))
_label_name.text = nickname.left(10)
_label_level.text = "LV.%s" % int(player_data.get("level", 1))
_label_gold.text = NumberFormatterScript.compact(int(player_data.get("gold", 0)))
_label_diamond.text = NumberFormatterScript.compact(int(player_data.get("gem", 0)))
var score_text := NumberFormatterScript.compact(int(player_data.get("score", 0)))
_label_score.text = score_text
if _score_bitmap != null:
_score_bitmap.set_text(score_text)
var exp_value := int(player_data.get("exp", 0))
var exp_max := _get_level_exp_max(int(player_data.get("level", 1)))
_label_exp.text = "%s/%s" % [exp_value, exp_max]
var ratio := clampf(float(exp_value) / float(maxi(exp_max, 1)), 0.0, 1.0)
_set_exp_width(223.0 * ratio, _initial_rendered)
_initial_rendered = true
_apply_avatar(str(player_data.get("avatar", "1")))
func _apply_label_theme() -> void:
if not _style_label.is_valid():
return
_style_label.call(_label_name, 20, Color.html("#fffeef"), 1, Color.html("#7f5523"))
_style_label.call(_label_level, 20, Color.WHITE, 1, Color.html("#724f2e"))
_style_label.call(_label_gold, 18, Color.html("#fffbe5"), 1, Color.html("#724f2e"))
_style_label.call(_label_diamond, 18, Color.html("#fffbe5"), 1, Color.html("#724f2e"))
_style_label.call(_label_score, 24, Color.html("#fff05a"), 2, Color.html("#8a4b18"))
_style_label.call(_label_exp, 16, Color.html("#b0ff94"), 1, Color.html("#724f2e"))
func _setup_power_bitmap_label() -> void:
if _top_layer == null or _label_score == null:
return
_label_score.visible = false
_score_bitmap = BitmapFontLabelScript.new()
_score_bitmap.name = "PowerBitmapLabel"
_score_bitmap.position = Vector2(244.0, 8.0)
_score_bitmap.letter_spacing = -3.0
_score_bitmap.mouse_filter = Control.MOUSE_FILTER_IGNORE
_score_bitmap.setup(PowerFontTexturePath, PowerFontPath)
_top_layer.add_child(_score_bitmap)
func _set_exp_width(width: float, animated: bool) -> void:
if _exp_fill == null or _owner == null:
return
width = clampf(width, 0.0, 223.0)
if _exp_tween != null:
_exp_tween.kill()
if not animated:
_exp_fill.visible = width > 0.0
_exp_fill.size.x = width
return
_exp_fill.visible = true
_exp_tween = _owner.create_tween()
_exp_tween.tween_property(_exp_fill, "size:x", width, 0.24).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
if width <= 0.0:
_exp_tween.finished.connect(_hide_empty_exp_fill)
func _apply_top_menu_toggle_visual() -> void:
if _top_hide == null:
return
_top_hide.texture = TopShowTexture if _top_menu_expanded else TopHideTexture
func _finish_collapse_top_menu() -> void:
if _top_button_group != null and not _top_menu_expanded:
_top_button_group.visible = false
func _hide_empty_exp_fill() -> void:
if _exp_fill != null and _exp_fill.size.x <= 0.0:
_exp_fill.visible = false
func _apply_avatar(avatar_id: String) -> void:
if _avatar == null:
return
if avatar_id.is_empty() or avatar_id.contains("http"):
avatar_id = "1"
var resource_path := "res://assets/egret/head/head%s.png" % avatar_id
if not ResourceLoader.exists(resource_path):
resource_path = "res://assets/egret/head/head1.png"
_avatar.texture = load(resource_path)
func _get_level_exp_max(level: int) -> int:
if _game_config != null and _game_config.has_method("get_player_exp_max"):
return int(_game_config.get_player_exp_max(level + 1))
return mini(level + 1, 60)