fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
+54
-31
@@ -7,12 +7,13 @@
|
||||
# 脚本格式(`CPythonEventManager`):纯文本 + `[命令 arg(值)]` token 交错。
|
||||
# [ENTER] 换行
|
||||
# [CLEAR] 清空
|
||||
# [NEXT] / [DONE] 「继续 / 关闭」按钮 -> M2Client.script_answer(255)
|
||||
# [NEXT] 「继续」按钮 -> M2Client.script_answer(254)
|
||||
# [DONE] 「关闭」按钮 -> CloseSelf only; DoneEvent fires while parsing
|
||||
# [QUESTION arg("是") arg("否")] 选项按钮 -> script_answer(0..N-1)
|
||||
# [LETTER value("...")] 追加文本(旧写法)
|
||||
# [INPUT] 显示文本输入框,提交 -> M2Client.quest_input()
|
||||
# [SELECT_ITEM] 要求从背包选一颗魔石 -> 发 select_item_requested 信号(打开 SelectItemUI)
|
||||
# [CONFIRM_WAIT] 等:本版忽略
|
||||
# [CONFIRM_WAIT] 等待:取消按钮按 BUTTON_TYPE_CANCEL 发送 script_answer(254)
|
||||
#
|
||||
# quest_confirm_ask(GC_QUEST_CONFIRM)也在这里弹 是/否 -> quest_confirm(yes, pid)。
|
||||
extends Node
|
||||
@@ -103,20 +104,19 @@ func begin_script(src: String) -> void:
|
||||
_active_cursor = 0
|
||||
_active_script = true
|
||||
# RegisterEventSetFromString replaces a leading RUN_CINEMA event set with
|
||||
# the referenced .msc file. Keep the signal for the presentation layer and
|
||||
# load the event text when the loose asset is available.
|
||||
# the referenced .msc file. A missing file makes registration fail in
|
||||
# 40250; RecvScriptPacket then does not call OnScriptEventStart and must not
|
||||
# leave an empty, locked quest window behind.
|
||||
if not _active_commands.is_empty() and String(_active_commands[0].get("literal", "")) == "" \
|
||||
and String(_active_commands[0].get("name", "")).to_upper().trim_prefix("/") == "RUN_CINEMA":
|
||||
var cinema := _arg_s(String(_active_commands[0].get("tok", "")), "value")
|
||||
if cinema != "":
|
||||
cinema_requested.emit(cinema)
|
||||
var cinema_text := _read_script_file(cinema)
|
||||
if cinema_text != "":
|
||||
_active_commands = _tokenize(cinema_text)
|
||||
else:
|
||||
# No local .msc: keep the empty event set alive so the caller can
|
||||
# show its own cinema player, but do not re-process RUN_CINEMA.
|
||||
_active_commands = []
|
||||
var cinema_text := _read_script_file(cinema) if cinema != "" else ""
|
||||
if cinema_text == "":
|
||||
_finish_runtime()
|
||||
_root.visible = false
|
||||
return
|
||||
cinema_requested.emit(cinema)
|
||||
_active_commands = _tokenize(cinema_text)
|
||||
_present_event_set(_active_set)
|
||||
_root.visible = true
|
||||
opened.emit()
|
||||
@@ -317,6 +317,35 @@ func _on_confirm(msg: String, _timeout: int, request_pid: int) -> void:
|
||||
_root.visible = true
|
||||
opened.emit()
|
||||
|
||||
func _send_script_answer(answer: int) -> void:
|
||||
if client and client.has_method("script_answer"):
|
||||
client.script_answer(answer)
|
||||
|
||||
func _escape_close() -> void:
|
||||
# uiquest.py::OnPressEscapeKey dispatches from the currently visible
|
||||
# button type. CANCEL and NEXT answer 254, DONE only closes, and a visible
|
||||
# QUESTION answers with the last option before OnCancel/CloseSelf. The
|
||||
# native quest_cancel() fallback is the stock 255 sentinel for a dialog that
|
||||
# has no answer button at all.
|
||||
var button_type := ""
|
||||
var choices: Array = []
|
||||
if _active_set != null:
|
||||
button_type = String(_active_set.next_button_type)
|
||||
choices = _active_set.choices
|
||||
if _confirm_wait or button_type == "CANCEL":
|
||||
_send_script_answer(254)
|
||||
elif button_type == "DONE":
|
||||
pass
|
||||
elif button_type == "NEXT":
|
||||
_send_script_answer(254)
|
||||
elif not choices.is_empty():
|
||||
_send_script_answer(choices.size() - 1)
|
||||
elif client and client.has_method("quest_cancel"):
|
||||
client.quest_cancel()
|
||||
else:
|
||||
_send_script_answer(255)
|
||||
close()
|
||||
|
||||
func close() -> void:
|
||||
_finish_runtime()
|
||||
if _root:
|
||||
@@ -329,17 +358,7 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
return
|
||||
var key := event as InputEventKey
|
||||
if key.pressed and not key.echo and key.keycode == KEY_ESCAPE:
|
||||
if _active_script:
|
||||
skip()
|
||||
var vp := get_viewport()
|
||||
if vp:
|
||||
vp.set_input_as_handled()
|
||||
return
|
||||
if client and client.has_method("quest_cancel"):
|
||||
client.quest_cancel()
|
||||
elif client and client.has_method("script_answer"):
|
||||
client.script_answer(254)
|
||||
close()
|
||||
_escape_close()
|
||||
var vp := get_viewport()
|
||||
if vp:
|
||||
vp.set_input_as_handled()
|
||||
@@ -663,8 +682,9 @@ func _process_event_set(es: EventSet, cmd: Dictionary) -> void:
|
||||
es.next_button_type = "NEXT"
|
||||
es.iAdjustLine += 2
|
||||
EVT_DONE:
|
||||
# MakeNextButton(BUTTON_TYPE_DONE); the reference invokes DoneEvent
|
||||
# from the button callback, not while the token is being parsed.
|
||||
# PythonEventManager::ProcessEventSet invokes DoneEvent immediately,
|
||||
# then MakeNextButton(BUTTON_TYPE_DONE) creates a close-only button.
|
||||
done_event.emit()
|
||||
es.has_next = true
|
||||
es.next_button_type = "DONE"
|
||||
es.iAdjustLine += 2
|
||||
@@ -1133,10 +1153,11 @@ func _fill_buttons(choices: Array, has_next: bool, has_input := false, confirm_w
|
||||
if confirm_wait:
|
||||
var cancel := _mkbtn("取消")
|
||||
cancel.pressed.connect(func():
|
||||
if client and client.has_method("quest_cancel"):
|
||||
client.quest_cancel()
|
||||
elif client and client.has_method("script_answer"):
|
||||
# MakeNextButton(BUTTON_TYPE_CANCEL): answer 254, then OnCancel.
|
||||
if client and client.has_method("script_answer"):
|
||||
client.script_answer(254)
|
||||
elif client and client.has_method("quest_cancel"):
|
||||
client.quest_cancel()
|
||||
close())
|
||||
return
|
||||
if choices.is_empty():
|
||||
@@ -1146,7 +1167,10 @@ func _fill_buttons(choices: Array, has_next: bool, has_input := false, confirm_w
|
||||
b.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
b.pressed.connect(func():
|
||||
if is_done:
|
||||
done_event.emit()
|
||||
# ClientVS22 uiquest.py::MakeNextButton(BUTTON_TYPE_DONE)
|
||||
# calls CloseSelf() and does not send SCRIPT_ANSWER(254).
|
||||
close()
|
||||
return
|
||||
if client and client.has_method("script_answer"):
|
||||
client.script_answer(254)
|
||||
close())
|
||||
@@ -1288,4 +1312,3 @@ func _mkbtn(text: String) -> Button:
|
||||
|
||||
_btnrow.add_child(b)
|
||||
return b
|
||||
|
||||
|
||||
Reference in New Issue
Block a user