Files
mtgodot-poc/project/ui/view_equipment_ui.gd
T
2026-09-21 16:38:58 -07:00

159 lines
5.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ViewEquipmentUI — GC_VIEW_EQUIP 的 40250 EquipmentDialog 复刻。
#
# 参考:40250/root/uiequipmentdialog.py + uiscript/equipmentdialog.py。
# 原版不是文字列表:固定 180x230 的装备槽底图承载 11 个装备位;鼠标进入
# 一个非空槽位时,由同一 ItemToolTip.AddItemData 显示属性面板,离开立即隐藏。
extends Node
const UiAssets = preload("res://ui/ui_assets.gd")
# 40250 EquipmentSlotindex, x, y, width, height(相对 equipment_bg)。
const SLOT_RECTS := {
0: Rect2(39, 37, 32, 64), 1: Rect2(39, 2, 32, 32),
2: Rect2(39, 145, 32, 32), 3: Rect2(75, 67, 32, 32),
4: Rect2(3, 3, 32, 96), 5: Rect2(114, 67, 32, 32),
6: Rect2(114, 35, 32, 32), 7: Rect2(2, 145, 32, 32),
8: Rect2(75, 145, 32, 32), 9: Rect2(114, 2, 32, 32),
10: Rect2(75, 35, 32, 32),
}
const EQUIPMENT_BG := "d:/ymir work/ui/equipment_bg_without_ring.tga"
var client: Node
var ui: CanvasLayer
var proto: Node
var item_list: RefCounted
var _window: Control
var _slots: Dictionary = {} # wear -> Panel
func setup(m2client: Node, manager: CanvasLayer, proto_node: Node = null, il: RefCounted = null) -> void:
client = m2client
ui = manager
proto = proto_node
item_list = il
if client.has_signal("view_equipment"):
client.view_equipment.connect(show_for)
func show_for(vid: int) -> void:
if client == null or not client.has_method("get_view_equipment"):
return
var equipment: Array = client.get_view_equipment(vid)
if equipment.is_empty():
return
if is_instance_valid(_window):
_hide_item_tooltip()
ui.close(_window)
_window = _build_window(vid, equipment)
ui.open(_window)
func _build_window(vid: int, equipment: Array) -> Control:
var win := Panel.new()
win.name = "ViewEquipment"
win.position = Vector2(870, 300)
win.size = Vector2(180, 230)
var bg := StyleBoxFlat.new()
bg.bg_color = Color(0.05, 0.06, 0.09, 0.94)
bg.border_color = Color(0.65, 0.5, 0.2, 0.9)
bg.set_border_width_all(1)
win.add_theme_stylebox_override("panel", bg)
var title := Label.new()
title.position = Vector2(8, 4)
title.size = Vector2(142, 26)
title.text = "%s 的装备" % _character_name(vid)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title.add_theme_font_size_override("font_size", 13)
win.add_child(title)
var close := Button.new()
close.text = "×"
close.position = Vector2(150, 3)
close.size = Vector2(25, 25)
close.pressed.connect(func():
if is_instance_valid(_window):
_hide_item_tooltip()
ui.close(_window)
_window = null)
win.add_child(close)
var equipment_bg := TextureRect.new()
equipment_bg.name = "EquipmentBaseImage"
equipment_bg.position = Vector2(15, 35)
equipment_bg.size = Vector2(150, 182)
equipment_bg.texture = UiAssets.load_tex(AssetRoot.path(), EQUIPMENT_BG)
equipment_bg.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
equipment_bg.stretch_mode = TextureRect.STRETCH_SCALE
equipment_bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
win.add_child(equipment_bg)
_slots.clear()
var by_wear := {}
for d: Dictionary in equipment:
by_wear[int(d.get("wear", -1))] = d
for wear in SLOT_RECTS:
var slot := _make_slot(int(wear), SLOT_RECTS[wear], by_wear.get(wear, {}))
equipment_bg.add_child(slot)
_slots[int(wear)] = slot
return win
func _make_slot(wear: int, rect: Rect2, data: Dictionary) -> Panel:
var slot := Panel.new()
slot.name = "slot_%d" % wear
slot.position = rect.position + Vector2(3, 3) # 40250 EquipmentSlot 的偏移。
slot.size = rect.size
slot.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
slot.set_meta("item", data.duplicate(true))
var style := StyleBoxFlat.new()
style.bg_color = Color(0.03, 0.04, 0.06, 0.35)
style.border_color = Color(0.52, 0.44, 0.25, 0.70)
style.set_border_width_all(1)
slot.add_theme_stylebox_override("panel", style)
var vnum := int(data.get("vnum", 0))
if vnum > 0:
var icon := _item_icon(vnum)
if icon:
var image := TextureRect.new()
image.texture = icon
image.set_anchors_preset(Control.PRESET_FULL_RECT)
image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
image.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(image)
var count := int(data.get("count", 1))
if count > 1:
var count_label := Label.new()
count_label.text = str(count)
count_label.position = Vector2(1, rect.size.y - 15)
count_label.add_theme_font_size_override("font_size", 10)
count_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(count_label)
slot.mouse_entered.connect(func(): _on_slot_over_in(wear))
slot.mouse_exited.connect(_hide_item_tooltip)
return slot
func _on_slot_over_in(wear: int) -> void:
var slot: Panel = _slots.get(wear, null)
if slot == null:
return
var data: Dictionary = slot.get_meta("item", {})
var vnum := int(data.get("vnum", 0))
if vnum <= 0:
return
# 对应 EquipmentDialog.OverInItem:一个共享 ItemToolTip,先清旧内容再 AddItemData。
var proto_data: Dictionary = proto.item(vnum) if proto and proto.has_method("item") else {}
if ui and ui.has_method("show_item_tooltip"):
ui.show_item_tooltip(vnum, int(data.get("count", 1)), proto_data, data, {}, AssetRoot.path(), proto, item_list)
func _hide_item_tooltip() -> void:
if ui and ui.has_method("hide_item_tooltip"):
ui.hide_item_tooltip()
func _item_icon(vnum: int) -> Texture2D:
var path: String = item_list.icon(vnum) if item_list and item_list.has(vnum) else "icon/item/%05d.tga" % ((vnum / 10) * 10)
return UiAssets.load_tex(AssetRoot.path(), path)
func _character_name(vid: int) -> String:
if client.has_method("get_entity"):
var entity: Dictionary = client.get_entity(vid)
if not entity.is_empty() and not String(entity.get("name", "")).is_empty():
return String(entity["name"])
return "角色 #%d" % vid