fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
@@ -56,6 +56,7 @@ const WINDOW_INVENTORY := 1 # mtnet::WINDOW_INVENTORY
|
||||
const WINDOW_EQUIPMENT := 2 # mtnet::WINDOW_EQUIPMENT(旧 11 格 wear)
|
||||
const WINDOW_SAFEBOX := 3 # global mouse payload source, not an inventory window
|
||||
const WINDOW_MALL := 4 # global mouse payload source, not an inventory window
|
||||
const WINDOW_BELT := 7 # m2dev belt-inventory window
|
||||
const BELT_RULES := [1, 2, 4, 6, 3, 3, 4, 6, 5, 5, 5, 6, 7, 7, 7, 7]
|
||||
|
||||
var ui: CanvasLayer # UiManager
|
||||
@@ -99,8 +100,14 @@ func setup(ui_manager: CanvasLayer, m2client: Node, proto_node: Node, assets: St
|
||||
uiscript_dir = assets.path_join("uiscript/uiscript")
|
||||
if not DirAccess.dir_exists_absolute(uiscript_dir):
|
||||
uiscript_dir = assets.path_join("uiscript")
|
||||
if client and client.has_signal("inventory_changed"):
|
||||
if client and client.has_signal("inventory_state_changed"):
|
||||
# 40250 refreshes once after SetItemCount and once after sockets/attrs;
|
||||
# consume the state snapshots so the first refresh sees the old sockets.
|
||||
client.inventory_state_changed.connect(_on_inventory_state_changed)
|
||||
elif client and client.has_signal("inventory_changed"):
|
||||
client.inventory_changed.connect(_on_inv_changed)
|
||||
if client and client.has_signal("item_highlighted"):
|
||||
client.item_highlighted.connect(_on_item_highlighted)
|
||||
if ui and ui.has_signal("window_closed"):
|
||||
ui.window_closed.connect(func(w):
|
||||
if not _win.is_empty() and _win.get("root") == w:
|
||||
@@ -193,6 +200,35 @@ func refresh() -> void:
|
||||
func _on_inv_changed(_window: int, _cell: int) -> void:
|
||||
refresh()
|
||||
|
||||
func _on_inventory_state_changed(window: int, cell: int, item: Dictionary) -> void:
|
||||
if not is_open():
|
||||
return
|
||||
var ui_idx := _wire_to_ui(window, cell)
|
||||
var slot: Panel = _cells.get(ui_idx, null)
|
||||
if slot == null:
|
||||
return
|
||||
var vnum := int(item.get("vnum", 0))
|
||||
if vnum <= 0:
|
||||
_clear_cell(slot)
|
||||
else:
|
||||
_fill_cell(slot, vnum, int(item.get("count", 1)), item)
|
||||
if window == WINDOW_EQUIPMENT and client.has_method("get_equipment"):
|
||||
_apply_belt_locks(client.get_equipment())
|
||||
|
||||
func _on_item_highlighted(window: int, cell: int) -> void:
|
||||
if not is_open():
|
||||
return
|
||||
var ui_idx := _wire_to_ui(window, cell)
|
||||
var slot: Panel = _cells.get(ui_idx, null)
|
||||
if slot == null or int(slot.get_meta("vnum", 0)) <= 0:
|
||||
return
|
||||
slot.set_meta("highlighted", true)
|
||||
slot.modulate = Color.WHITE
|
||||
var pulse := create_tween()
|
||||
pulse.set_loops(2)
|
||||
pulse.tween_property(slot, "modulate", Color(1.0, 0.82, 0.28, 1.0), 0.12)
|
||||
pulse.tween_property(slot, "modulate", Color.WHITE, 0.12)
|
||||
|
||||
func _fill_cell(cell: Panel, vnum: int, count: int, instance_data: Dictionary = {}) -> void:
|
||||
_clear_cell(cell)
|
||||
cell.set_meta("vnum", vnum)
|
||||
@@ -204,10 +240,15 @@ func _fill_cell(cell: Panel, vnum: int, count: int, instance_data: Dictionary =
|
||||
proto_data = proto.item(vnum)
|
||||
if not proto_data.is_empty():
|
||||
name = String(proto_data.get("locale_name", proto_data.get("name", name)))
|
||||
var tooltip_body := ""
|
||||
if item_tooltip:
|
||||
cell.tooltip_text = item_tooltip.format(vnum, count, proto_data, instance_data)
|
||||
tooltip_body = item_tooltip.format(vnum, count, proto_data, instance_data)
|
||||
else:
|
||||
cell.tooltip_text = "%s\n#%d%s" % [name, vnum, (" x%d" % count) if count > 1 else ""]
|
||||
tooltip_body = "%s\n#%d%s" % [name, vnum, (" x%d" % count) if count > 1 else ""]
|
||||
# 40250 has one custom item-attribute panel owner. Do not also let Godot
|
||||
# create its native tooltip popup; the mobile detail dialog reads this body.
|
||||
cell.set_meta("tooltip_body", tooltip_body)
|
||||
cell.tooltip_text = ""
|
||||
var tex := _icon(vnum)
|
||||
if tex:
|
||||
var tr := TextureRect.new()
|
||||
@@ -238,6 +279,9 @@ func _clear_cell(cell: Panel) -> void:
|
||||
cell.set_meta("vnum", 0)
|
||||
cell.set_meta("count", 0)
|
||||
cell.set_meta("item_data", {})
|
||||
cell.set_meta("tooltip_body", "")
|
||||
cell.set_meta("highlighted", false)
|
||||
cell.modulate = Color.WHITE
|
||||
cell.tooltip_text = ""
|
||||
for c in cell.get_children():
|
||||
c.queue_free()
|
||||
@@ -618,7 +662,8 @@ func _show_mobile_detail(ui_idx: int) -> void:
|
||||
title.add_theme_color_override("font_color", Color(0.98, 0.84, 0.52))
|
||||
dialog.add_child(title)
|
||||
var detail := Label.new()
|
||||
detail.text = "物品编号:%d\n数量:%d\n\n%s" % [vnum, count, String(cell.tooltip_text)]
|
||||
detail.text = "物品编号:%d\n数量:%d\n\n%s" % [vnum, count,
|
||||
String(cell.get_meta("tooltip_body", ""))]
|
||||
detail.position = Vector2(18, 84)
|
||||
detail.size = Vector2(324, 70)
|
||||
detail.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
@@ -955,3 +1000,15 @@ func _to_wire(ui_idx: int) -> Array:
|
||||
# 旧 11 格(BODY..SHIELD)走 EQUIPMENT 窗(window=2)+ 零基 wear cell。
|
||||
return [WINDOW_EQUIPMENT, wear]
|
||||
return [WINDOW_INVENTORY, ui_idx]
|
||||
|
||||
# wire item position -> the same UI slot namespace used by _to_wire().
|
||||
func _wire_to_ui(window: int, cell: int) -> int:
|
||||
if window == WINDOW_EQUIPMENT:
|
||||
return EQUIP_BASE + (cell - EQUIP_BASE if cell >= EQUIP_BASE else cell)
|
||||
if window == WINDOW_BELT:
|
||||
return BELT_BASE + (cell - BELT_SLOT_START if cell >= BELT_SLOT_START else cell)
|
||||
if window == WINDOW_INVENTORY:
|
||||
if cell >= BELT_SLOT_START:
|
||||
return BELT_BASE + cell - BELT_SLOT_START
|
||||
return cell
|
||||
return -1
|
||||
|
||||
Reference in New Issue
Block a user