Modes de la souris
Les quatre valeurs de Input.mouse_mode derrière quatre boutons. Le point suit event.relative, qui est ce qui continue de marcher une fois le pointeur capturé.
L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.
Classes Godot utilisées
InputInputEventMouseMotionButtonPanel
Le code
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