Modos del ratón
Los cuatro valores de Input.mouse_mode tras cuatro botones. El punto viaja con event.relative, que es lo que sigue funcionando una vez capturado el puntero.
El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.
Clases de Godot usadas
InputInputEventMouseMotionButtonPanel
El código
scripts/main.gd
extends Node
const ARENA: Vector2 = Vector2(720, 260)
const CURSOR: float = 16.0
var modes: Array[Dictionary] = []
var buttons: Array[Button] = []
var mode_label: Label
var delta_label: Label
var cursor: Panel
var offset: Vector2 = ARENA * 0.5
var last_relative: Vector2 = Vector2.ZERO
var travel: float = 0.0
func _ready() -> void:
modes = [
{name = 'Visible', mode = Input.MOUSE_MODE_VISIBLE, key = KEY_1},
{name = 'Hidden', mode = Input.MOUSE_MODE_HIDDEN, key = KEY_2},
{name = 'Captured', mode = Input.MOUSE_MODE_CAPTURED, key = KEY_3},
{name = 'Confined', mode = Input.MOUSE_MODE_CONFINED, key = KEY_4},
]
var column: VBoxContainer = _root()
var title: Label = Label.new()
title.text = 'Mouse modes'
title.add_theme_font_size_override('font_size', 28)
column.add_child(title)
var hint: Label = Label.new()
hint.text = 'click a mode or press 1 to 4, escape always goes back to visible'
hint.add_theme_color_override('font_color', Color('#9aa3b5'))
column.add_child(hint)
var row: HBoxContainer = HBoxContainer.new()
row.add_theme_constant_override('separation', 12)
column.add_child(row)
for i in modes.size():
var button: Button = Button.new()
button.text = '%s %s' % [modes[i].name, OS.get_keycode_string(modes[i].key)]
button.toggle_mode = true
button.custom_minimum_size = Vector2(170, 44)
button.pressed.connect(_set_mode.bind(modes[i].mode))
row.add_child(button)
buttons.append(button)
column.add_child(_arena())
mode_label = Label.new()
mode_label.add_theme_font_size_override('font_size', 20)
column.add_child(mode_label)
delta_label = Label.new()
delta_label.add_theme_color_override('font_color', Color('#8da5f3'))
column.add_child(delta_label)
print('switch the mode and move the mouse, the yellow dot rides on event.relative')
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
var motion: InputEventMouseMotion = event
last_relative = motion.relative
travel += motion.relative.length()
offset = (offset + motion.relative).clamp(Vector2(CURSOR, CURSOR), ARENA - Vector2(CURSOR, CURSOR))
cursor.position = offset - Vector2(CURSOR, CURSOR)
elif event is InputEventKey:
var key: InputEventKey = event
if not key.pressed or key.echo:
return
if key.keycode == KEY_ESCAPE:
_set_mode(Input.MOUSE_MODE_VISIBLE)
for entry: Dictionary in modes:
if key.keycode == entry.key:
_set_mode(entry.mode)
func _process(_delta: float) -> void:
# the browser owns the pointer lock and drops it on escape without asking godot first
var current: int = Input.mouse_mode
for i in modes.size():
buttons[i].set_pressed_no_signal(modes[i].mode == current)
mode_label.text = 'Input.mouse_mode is %s' % _mode_name(current)
delta_label.text = 'last relative %.0f, %.0f travelled %.0f px' % [last_relative.x, last_relative.y, travel]
func _set_mode(mode: int) -> void:
Input.mouse_mode = mode as Input.MouseMode
func _mode_name(mode: int) -> String:
for entry: Dictionary in modes:
if entry.mode == mode:
return entry.name
return 'unknown'
func _arena() -> Panel:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color('#1a1e28')
style.border_color = Color('#2a2f3d')
style.set_border_width_all(2)
style.set_corner_radius_all(14)
var panel: Panel = Panel.new()
panel.custom_minimum_size = ARENA
panel.size = ARENA
panel.add_theme_stylebox_override('panel', style)
panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
var caption: Label = Label.new()
caption.text = 'relative motion keeps arriving while the pointer is captured'
caption.position = Vector2(20, 18)
caption.add_theme_color_override('font_color', Color('#9aa3b5'))
caption.mouse_filter = Control.MOUSE_FILTER_IGNORE
panel.add_child(caption)
var dot_style: StyleBoxFlat = StyleBoxFlat.new()
dot_style.bg_color = Color('#f3d48d')
dot_style.set_corner_radius_all(int(CURSOR))
cursor = Panel.new()
cursor.size = Vector2(CURSOR * 2, CURSOR * 2)
cursor.position = offset - Vector2(CURSOR, CURSOR)
cursor.add_theme_stylebox_override('panel', dot_style)
cursor.mouse_filter = Control.MOUSE_FILTER_IGNORE
panel.add_child(cursor)
return panel
func _root() -> VBoxContainer:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var center: CenterContainer = CenterContainer.new()
add_child(center)
center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 18)
center.add_child(column)
return column