chobit/shared/godot/core/screen_cursor.gd
Claude Code 7067b6dded refactor(shared): ♻️ Improve shared utility structure for better maintainability
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-03-28 14:55:37 -07:00

61 lines
1.9 KiB
GDScript

class_name ScreenCursor
extends RefCounted
## Maps the global mouse position to a normalized -1..1 range
## relative to the window center, using screen edges as bounds.
## Handles multi-monitor and Wayland focus limitations.
## Max pixel distance from window center that maps to 1.0.
## Prevents over-sensitive tracking on ultra-wide setups.
const MAX_RANGE_PX: float = 2000.0
static var _last_valid: Vector2 = Vector2.ZERO
static func get_normalized_position() -> Vector2:
var ds := DisplayServer
var mouse := ds.mouse_get_position()
var win_pos := ds.window_get_position()
var win_size := ds.window_get_size()
var cx := win_pos.x + win_size.x / 2
var cy := win_pos.y + win_size.y / 2
var dx := float(mouse.x - cx)
var dy := float(mouse.y - cy)
# On Wayland, mouse position may freeze at (0,0) when unfocused
if mouse.x == 0 and mouse.y == 0:
return _last_valid
# Use screen the window is on for bounds
var screen_idx := ds.window_get_current_screen()
var screen_rect := ds.screen_get_usable_rect(screen_idx)
var screen_pos := screen_rect.position
var screen_size := screen_rect.size
# Distance from window center to each screen edge
var dist_left := maxf(float(cx - screen_pos.x), 1.0)
var dist_right := maxf(float(screen_pos.x + screen_size.x - cx), 1.0)
var dist_up := maxf(float(cy - screen_pos.y), 1.0)
var dist_down := maxf(float(screen_pos.y + screen_size.y - cy), 1.0)
# Cap range so ultra-wide screens don't make gaze too sensitive
dist_left = minf(dist_left, MAX_RANGE_PX)
dist_right = minf(dist_right, MAX_RANGE_PX)
dist_up = minf(dist_up, MAX_RANGE_PX)
dist_down = minf(dist_down, MAX_RANGE_PX)
var nx: float = 0.0
if dx > 0.0:
nx = clampf(dx / dist_right, 0.0, 1.0)
elif dx < 0.0:
nx = clampf(dx / dist_left, -1.0, 0.0)
var ny: float = 0.0
if dy > 0.0:
ny = -clampf(dy / dist_down, 0.0, 1.0)
elif dy < 0.0:
ny = -clampf(dy / dist_up, -1.0, 0.0)
_last_valid = Vector2(nx, ny)
return _last_valid