fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
+42
-7
@@ -15,10 +15,14 @@ enum CameraMode {
|
||||
# ClientVS22 stores camera settings in centimetres/degrees. The Godot scene
|
||||
# is metres/radians, so keep the conversion at this boundary instead of
|
||||
# leaking mixed units into the orbit controls.
|
||||
const DEFAULT_DISTANCE_CM := 2100.0
|
||||
const DEFAULT_PITCH_DEG := 34.0
|
||||
const DEFAULT_DISTANCE_CM := 1550.0
|
||||
const DEFAULT_PITCH_DEG := 27.0
|
||||
const DEFAULT_ROTATION_DEG := 0.0
|
||||
const DEFAULT_HEIGHT_CM := 100.0
|
||||
const CAMERA_TARGET_STANDARD_CM := 100.0
|
||||
const CAMERA_TARGET_FACE_CM := 150.0
|
||||
const CAMERA_WHEEL_DELTA_CM := 36.0 # 120 * CCamera's 0.3 resistance
|
||||
const CAMERA_ZOOM_SPEED := 0.05 # PythonApplication's default ratio speed
|
||||
|
||||
var target: Node3D
|
||||
var world: Node # Metin2World,用 sample_height 防穿(可空)
|
||||
@@ -32,7 +36,6 @@ var max_pitch := deg_to_rad(78.0)
|
||||
var min_dist := 2.0
|
||||
var max_dist := 25.0
|
||||
var sensitivity := 0.006
|
||||
var zoom_step := 1.4
|
||||
var follow_lerp := 12.0
|
||||
|
||||
# F7 触屏手势
|
||||
@@ -47,6 +50,7 @@ var _orbit_touch := -1 # 正在环绕的手指 index,-1 = 无
|
||||
var _orbit_active := false # 已越过 deadzone
|
||||
var _orbit_press := Vector2.ZERO
|
||||
var _pinch_last := -1.0 # 上一帧两指间距,<0 = 未在捏合
|
||||
var _wheel_zoom_velocity_cm := 0.0 # CCamera::m_v3AngularVelocity.y
|
||||
|
||||
# ClientVS22 game.py drives these while Q/E/R/F/T/G are held. Keeping the
|
||||
# state here (instead of applying one large step per key event) gives the
|
||||
@@ -88,10 +92,10 @@ func _unhandled_input(e: InputEvent) -> void:
|
||||
_dragging = e.pressed and not is_event_locked()
|
||||
elif e.button_index == MOUSE_BUTTON_WHEEL_UP and e.pressed:
|
||||
if not is_event_locked():
|
||||
dist = maxf(min_dist, dist - zoom_step)
|
||||
_wheel_zoom_velocity_cm = _wheel_delta_cm(e.factor)
|
||||
elif e.button_index == MOUSE_BUTTON_WHEEL_DOWN and e.pressed:
|
||||
if not is_event_locked():
|
||||
dist = minf(max_dist, dist + zoom_step)
|
||||
_wheel_zoom_velocity_cm = -_wheel_delta_cm(e.factor)
|
||||
elif e is InputEventMouseMotion and _dragging and not is_event_locked():
|
||||
yaw -= e.relative.x * sensitivity
|
||||
pitch = clampf(pitch + e.relative.y * sensitivity, min_pitch, max_pitch)
|
||||
@@ -143,6 +147,31 @@ func _pinch_dist() -> float:
|
||||
return 0.0
|
||||
return (_touches[ks[0]] as Vector2).distance_to(_touches[ks[1]] as Vector2)
|
||||
|
||||
func _wheel_delta_cm(factor: float) -> float:
|
||||
# Godot reports a wheel notch as factor=1, while Win32 sends 120. Accept
|
||||
# both forms so the conversion remains equivalent to CCamera::Wheel().
|
||||
var notches := absf(factor)
|
||||
if notches <= 0.0:
|
||||
notches = 1.0
|
||||
elif notches > 4.0:
|
||||
notches /= 120.0
|
||||
return notches * CAMERA_WHEEL_DELTA_CM
|
||||
|
||||
func _apply_wheel_zoom() -> void:
|
||||
if absf(_wheel_zoom_velocity_cm) < 0.001:
|
||||
return
|
||||
dist = clampf(dist - _wheel_zoom_velocity_cm * 0.01, min_dist, max_dist)
|
||||
_wheel_zoom_velocity_cm *= 0.5 # CCamera::Update damping
|
||||
if absf(_wheel_zoom_velocity_cm) < 1.0:
|
||||
_wheel_zoom_velocity_cm = 0.0
|
||||
|
||||
func _target_height_m() -> float:
|
||||
# CameraProcedure.cpp moves the target from chest to face as the camera
|
||||
# approaches: 100cm at max distance and 150cm at min distance.
|
||||
var movable := maxf(0.001, max_dist - min_dist)
|
||||
var close_fraction := clampf((max_dist - dist) / movable, 0.0, 1.0)
|
||||
return lerpf(CAMERA_TARGET_STANDARD_CM, CAMERA_TARGET_FACE_CM, close_fraction) * 0.01
|
||||
|
||||
func heading() -> float:
|
||||
# 相机方位角:相机在 head + (sin yaw, cos yaw) 一侧,视线水平前方是 -(sin yaw, cos yaw)。
|
||||
return yaw
|
||||
@@ -197,6 +226,7 @@ func _look_target() -> Vector3:
|
||||
if is_event_locked():
|
||||
return _event_center
|
||||
if target:
|
||||
head_offset.y = _target_height_m()
|
||||
return target.global_position + head_offset
|
||||
return global_position
|
||||
|
||||
@@ -346,9 +376,14 @@ func _process(dt: float) -> void:
|
||||
if camera_mode == CameraMode.NORMAL and _key_orbit != 0:
|
||||
yaw += float(_key_orbit) * dt * 1.8
|
||||
if camera_mode == CameraMode.NORMAL and _key_zoom != 0:
|
||||
dist = clampf(dist + float(_key_zoom) * dt * 5.0, min_dist, max_dist)
|
||||
# ZoomCamera() applies a ratio every update, rather than a fixed
|
||||
# distance step. Positive direction means zoom out in 40250.
|
||||
dist = clampf(dist * (1.0 + float(_key_zoom) * CAMERA_ZOOM_SPEED),
|
||||
min_dist, max_dist)
|
||||
if camera_mode == CameraMode.NORMAL and _key_pitch != 0:
|
||||
pitch = clampf(pitch + float(_key_pitch) * dt * 1.2, min_pitch, max_pitch)
|
||||
if camera_mode == CameraMode.NORMAL:
|
||||
_apply_wheel_zoom()
|
||||
var want := _desired_pos()
|
||||
if _pos_ready:
|
||||
global_position = global_position.lerp(want, clampf(follow_lerp * dt, 0.0, 1.0))
|
||||
@@ -370,7 +405,7 @@ func _fade_occluders() -> void:
|
||||
var world3d := get_world_3d()
|
||||
if world3d == null:
|
||||
return
|
||||
var head := target.global_position + head_offset
|
||||
var head := _look_target()
|
||||
var from := global_position
|
||||
var this_frame: Array[Node] = []
|
||||
var ss := world3d.direct_space_state
|
||||
|
||||
Reference in New Issue
Block a user