feat: complete mobile UI implementation
This commit is contained in:
@@ -57,6 +57,9 @@ var rotation_speed_deg := ROT_SPEED_DEFAULT_DEG # 上/下马时由 net_play 切
|
||||
# (§3.2 __EnableSkipCollision,观战 / 服务器纠正时置真)。
|
||||
var skip_actor_collision := false
|
||||
var _last_wasd := Vector2.ZERO
|
||||
var _mobile_axis := Vector2.ZERO
|
||||
var _mobile_active := false
|
||||
var _mobile_ui_touches := {}
|
||||
|
||||
# --- §3.1 Src/Dst 移动模型(对齐 InstanceBaseMovement.cpp NEW_Goto / NEW_MoveToDirection)---
|
||||
# _is_going = m_isGoing(点地走向 Dst);方向键移动 _is_going 保持 false。
|
||||
@@ -100,6 +103,34 @@ func set_input_surfaces(cursor: Node, ui: Node = null, ground: Node = null,
|
||||
cancel_fishing_input = cancel_fishing_cb
|
||||
cancel_fishing_ground = ground_cancel_fishing_cb
|
||||
|
||||
# MobileUiRoot feeds a normalized left-thumb axis directly. Keeping it on the
|
||||
# controller (instead of synthesizing keyboard events) preserves the existing
|
||||
# camera-relative movement, collision and animation path for both platforms.
|
||||
func set_mobile_axis(axis: Vector2) -> void:
|
||||
_mobile_axis = axis.limit_length(1.0)
|
||||
|
||||
func clear_mobile_input() -> void:
|
||||
_mobile_axis = Vector2.ZERO
|
||||
_mobile_active = false
|
||||
_mobile_ui_touches.clear()
|
||||
if _touch_count == 0:
|
||||
_multi_gesture = false
|
||||
|
||||
## MobileInputOverlay calls this before/after a control consumes its touch.
|
||||
## World touch handling must know about that finger even though the GUI event
|
||||
## never reaches _unhandled_input; otherwise a joystick finger plus a world
|
||||
## finger can look like a single tap-to-move gesture.
|
||||
func set_mobile_ui_touch(index: int, pressed: bool) -> void:
|
||||
if pressed:
|
||||
_mobile_ui_touches[index] = true
|
||||
if _touch_count > 0:
|
||||
_multi_gesture = true
|
||||
_tap_index = -1
|
||||
else:
|
||||
_mobile_ui_touches.erase(index)
|
||||
if _touch_count == 0 and _mobile_ui_touches.is_empty():
|
||||
_multi_gesture = false
|
||||
|
||||
# 程序化下发一个点地目标(脚本化截图 / AI)——等价 NEW_MoveToDestPixelPositionDirection。
|
||||
func walk_to(world_pos: Vector3) -> void:
|
||||
_goto(Vector3(world_pos.x, 0.0, world_pos.z))
|
||||
@@ -136,7 +167,7 @@ func _unhandled_input(e: InputEvent) -> void:
|
||||
func _on_touch(e: InputEventScreenTouch) -> void:
|
||||
if e.pressed:
|
||||
_touch_count += 1
|
||||
if _touch_count >= 2:
|
||||
if _touch_count >= 2 or not _mobile_ui_touches.is_empty():
|
||||
_multi_gesture = true
|
||||
_tap_index = -1
|
||||
elif not _multi_gesture:
|
||||
@@ -151,7 +182,7 @@ func _on_touch(e: InputEventScreenTouch) -> void:
|
||||
if travel <= _TAP_TRAVEL_MAX and held <= _TAP_TIME_MAX:
|
||||
_on_click(e.position)
|
||||
_tap_index = -1
|
||||
if _touch_count == 0:
|
||||
if _touch_count == 0 and _mobile_ui_touches.is_empty():
|
||||
_multi_gesture = false
|
||||
|
||||
func _on_click(screen_pos: Vector2) -> void:
|
||||
@@ -319,8 +350,25 @@ func _process(dt: float) -> void:
|
||||
_run = force_run or Input.is_key_pressed(RUN_HOLD_KEY)
|
||||
var wish := Vector3.ZERO
|
||||
var wasd := _wasd()
|
||||
var mobile_axis := _mobile_axis
|
||||
|
||||
if wasd != Vector2.ZERO:
|
||||
if mobile_axis != Vector2.ZERO:
|
||||
# A new thumb gesture has the same fishing-cancel edge as a keyboard move.
|
||||
if not _mobile_active and cancel_fishing_input.is_valid() \
|
||||
and bool(cancel_fishing_input.call()):
|
||||
_mobile_active = true
|
||||
_last_wasd = Vector2.ZERO
|
||||
anim_state.emit("wait")
|
||||
return
|
||||
_mobile_active = true
|
||||
_is_going = false
|
||||
_last_wasd = Vector2.ZERO
|
||||
var mobile_yaw: float = (camera.heading() if camera and camera.has_method("heading") else 0.0)
|
||||
var mobile_fwd := Vector3(sin(mobile_yaw), 0, cos(mobile_yaw))
|
||||
var mobile_right := Vector3(mobile_fwd.z, 0, -mobile_fwd.x)
|
||||
wish = (mobile_fwd * -mobile_axis.y + mobile_right * mobile_axis.x).normalized()
|
||||
elif wasd != Vector2.ZERO:
|
||||
_mobile_active = false
|
||||
# PythonPlayerInputKeyboard 只在方向键按下时尝试取消钓鱼;记录方向
|
||||
# 边沿,避免按住键时每帧重复发送 CG_FISHING(0)。
|
||||
if wasd != _last_wasd and cancel_fishing_input.is_valid() \
|
||||
@@ -335,12 +383,14 @@ func _process(dt: float) -> void:
|
||||
var right := Vector3(fwd.z, 0, -fwd.x)
|
||||
wish = (fwd * -wasd.y + right * wasd.x).normalized()
|
||||
elif _is_going:
|
||||
_mobile_active = false
|
||||
var flat := Vector3(_dst_pos.x - player.position.x, 0, _dst_pos.z - player.position.z)
|
||||
if flat.length() <= ARRIVE_EPS:
|
||||
_is_going = false
|
||||
else:
|
||||
wish = flat.normalized()
|
||||
else:
|
||||
_mobile_active = false
|
||||
_last_wasd = Vector2.ZERO
|
||||
|
||||
var speed := 0.0
|
||||
|
||||
Reference in New Issue
Block a user