131 lines
4.8 KiB
GDScript
131 lines
4.8 KiB
GDScript
class_name ControlsEditor
|
||
extends PanelContainer
|
||
|
||
var ui: GameUI
|
||
var settings_path := ControlBindings.PATH
|
||
var rows := VBoxContainer.new()
|
||
var notice := Label.new()
|
||
var pending_action := ""
|
||
var pending_slot := 0
|
||
var candidate: Dictionary = {}
|
||
var swap_button := Button.new()
|
||
|
||
func _ready() -> void:
|
||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
var background := StyleBoxFlat.new()
|
||
background.bg_color = Color("101d26")
|
||
add_theme_stylebox_override("panel", background)
|
||
var margin := MarginContainer.new()
|
||
for side: String in ["left", "right", "top", "bottom"]: margin.add_theme_constant_override("margin_" + side, 24)
|
||
add_child(margin)
|
||
var column := VBoxContainer.new()
|
||
column.add_theme_constant_override("separation", 12)
|
||
margin.add_child(column)
|
||
var heading := Label.new()
|
||
heading.text = "STEUERUNG / TASTENBELEGUNG"
|
||
heading.add_theme_font_size_override("font_size", 28)
|
||
column.add_child(heading)
|
||
notice.text = "Belegung anklicken, dann Taste oder Maustaste drücken. Esc bricht die Eingabe ab."
|
||
notice.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||
column.add_child(notice)
|
||
swap_button.text = "BELEGUNGEN TAUSCHEN"
|
||
swap_button.hide()
|
||
swap_button.pressed.connect(func(): finish(true))
|
||
column.add_child(swap_button)
|
||
var scroll := ScrollContainer.new()
|
||
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||
column.add_child(scroll)
|
||
rows.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
scroll.add_child(rows)
|
||
rebuild()
|
||
var footer := HBoxContainer.new()
|
||
column.add_child(footer)
|
||
var reset := Button.new()
|
||
reset.text = "STANDARD WIEDERHERSTELLEN"
|
||
reset.pressed.connect(func():
|
||
pending_action = ""
|
||
swap_button.hide()
|
||
ControlBindings.defaults()
|
||
persist()
|
||
rebuild())
|
||
footer.add_child(reset)
|
||
var back := Button.new()
|
||
back.text = "← ZURÜCK"
|
||
back.pressed.connect(ui.settings_menu)
|
||
footer.add_child(back)
|
||
|
||
func rebuild() -> void:
|
||
for child in rows.get_children():
|
||
rows.remove_child(child)
|
||
child.queue_free()
|
||
for index in ControlBindings.ACTIONS.size():
|
||
var action: String = ControlBindings.ACTIONS[index]
|
||
var row := HBoxContainer.new()
|
||
rows.add_child(row)
|
||
var label := Label.new()
|
||
label.text = ControlBindings.LABELS[index]
|
||
label.custom_minimum_size.x = 300
|
||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
row.add_child(label)
|
||
for slot in 2:
|
||
var button := Button.new()
|
||
button.text = ControlBindings.label(ControlBindings.bindings[action][slot])
|
||
button.custom_minimum_size = Vector2(180, 40)
|
||
button.pressed.connect(func():
|
||
pending_action = action
|
||
pending_slot = slot
|
||
candidate = {}
|
||
swap_button.hide()
|
||
notice.text = "%s: neue Taste / Maustaste drücken … (Esc: abbrechen)" % ControlBindings.LABELS[index])
|
||
row.add_child(button)
|
||
var clear := Button.new()
|
||
clear.text = "×"
|
||
clear.tooltip_text = "Diese Belegung entfernen"
|
||
clear.pressed.connect(func():
|
||
pending_action = ""
|
||
swap_button.hide()
|
||
if ControlBindings.assign(action, slot, {}):
|
||
persist()
|
||
rebuild()
|
||
else: notice.text = "Für das Menü muss mindestens eine Taste belegt bleiben.")
|
||
row.add_child(clear)
|
||
|
||
func _input(event: InputEvent) -> void:
|
||
if pending_action.is_empty(): return
|
||
if not (event is InputEventKey or event is InputEventMouseButton): return
|
||
if not event.is_pressed() or event.is_echo(): return
|
||
# A pending conflict has explicit buttons; don't capture their mouse clicks.
|
||
if swap_button.visible:
|
||
if event is InputEventKey and event.keycode == KEY_ESCAPE:
|
||
pending_action = ""
|
||
swap_button.hide()
|
||
notice.text = "Abgebrochen. Die bisherigen Belegungen bleiben bestehen."
|
||
get_viewport().set_input_as_handled()
|
||
return
|
||
get_viewport().set_input_as_handled()
|
||
if event is InputEventKey and event.keycode == KEY_ESCAPE:
|
||
pending_action = ""
|
||
notice.text = "Eingabe abgebrochen."
|
||
return
|
||
candidate = ControlBindings.encode(event)
|
||
if candidate.is_empty(): return
|
||
var conflicts := ControlBindings.conflicts(pending_action, pending_slot, candidate)
|
||
if not conflicts.is_empty():
|
||
var names := PackedStringArray()
|
||
for conflict in conflicts: names.append(ControlBindings.LABELS[ControlBindings.ACTIONS.find(conflict.action)])
|
||
notice.text = "%s ist bereits belegt: %s. Tauschen oder mit Esc abbrechen." % [ControlBindings.label(candidate), ", ".join(names)]
|
||
swap_button.show()
|
||
else: finish(false)
|
||
|
||
func finish(swap: bool) -> void:
|
||
if ControlBindings.assign(pending_action, pending_slot, candidate, swap):
|
||
persist()
|
||
else:
|
||
notice.text = "Diese Belegung ist nicht möglich: gehaltene Aktionen brauchen eine Taste / Maustaste; das Menü muss erreichbar bleiben."
|
||
pending_action = ""
|
||
swap_button.hide()
|
||
rebuild()
|
||
|
||
func persist() -> void:
|
||
notice.text = "Gespeichert. Die Steuerung ist sofort aktiv." if ControlBindings.save(settings_path) == OK else "Speichern fehlgeschlagen. Die Änderung ist nur für diese Sitzung aktiv."
|