279 lines
11 KiB
GDScript
279 lines
11 KiB
GDScript
extends "res://src/ui/panels/editor_panel.gd"
|
|
## Terrain-Werkzeug-Panel (aus main.gd ausgezogen, Karte t_eaccbfed U1 —
|
|
## Logik unverändert, Karte t_9aba04f1 + t_603ec1a8): großer Modus-Button +
|
|
## Pinsel-Modi, Material-Palette, Größe/Stärke-Regler. Werkzeug-Ein/Aus bleibt
|
|
## im Koordinator (main.gd _enter/_leave terrain), das Panel hält nur die
|
|
## Widgets und die Regler-Verdrahtung.
|
|
|
|
var terrain_edit_btn: Button
|
|
var terrain_panel: VBoxContainer
|
|
var terrain_mode_raise: Button
|
|
var terrain_mode_lower: Button
|
|
var terrain_mode_smooth: Button
|
|
var terrain_mode_paint: Button
|
|
var terrain_palette: VBoxContainer
|
|
var terrain_mat_buttons: Array = [] # Gras/Sand/Fels (ButtonGroup)
|
|
var terrain_size_btn_small: Button
|
|
var terrain_size_btn_medium: Button
|
|
var terrain_size_btn_large: Button
|
|
var terrain_radius_slider: HSlider
|
|
var terrain_radius_label: Label
|
|
var terrain_strength_slider: HSlider
|
|
var terrain_strength_label: Label
|
|
|
|
# --- Bauen (Karte t_97ea59c5) — im selben Werkzeug-Tab (aus main.gd ausgezogen)
|
|
var build_edit_btn: Button
|
|
var build_panel: VBoxContainer
|
|
var build_kind_buttons: Dictionary = {} # kind_id → Button
|
|
|
|
|
|
static func spec() -> Dictionary:
|
|
return {"titel": "Terrain", "gruppe": "rechts", "order": 40}
|
|
|
|
|
|
func build() -> void:
|
|
terrain_edit_btn = Button.new()
|
|
terrain_edit_btn.text = "⛰ Terrain formen"
|
|
terrain_edit_btn.custom_minimum_size = UIScale.v2(0, 48)
|
|
terrain_edit_btn.toggle_mode = true
|
|
terrain_edit_btn.tooltip_text = "Boden heben, senken und glätten — direkt in der Karte malen"
|
|
terrain_edit_btn.pressed.connect(_on_terrain_btn_pressed)
|
|
add_child(terrain_edit_btn)
|
|
|
|
terrain_panel = VBoxContainer.new()
|
|
terrain_panel.add_theme_constant_override("separation", UIScale.px(6))
|
|
terrain_panel.visible = false
|
|
add_child(terrain_panel)
|
|
|
|
terrain_panel.add_child(_field_label("Pinsel-Werkzeug:"))
|
|
var mode_row := HBoxContainer.new()
|
|
mode_row.add_theme_constant_override("separation", UIScale.px(6))
|
|
terrain_panel.add_child(mode_row)
|
|
var mode_group := ButtonGroup.new()
|
|
terrain_mode_raise = _terrain_mode_button("Heben ⬆", mode_group)
|
|
terrain_mode_lower = _terrain_mode_button("Senken ⬇", mode_group)
|
|
terrain_mode_smooth = _terrain_mode_button("Glätten ≈", mode_group)
|
|
terrain_mode_paint = _terrain_mode_button("Malen 🖌", mode_group)
|
|
terrain_mode_raise.button_pressed = true
|
|
terrain_mode_raise.toggled.connect(_on_terrain_mode_changed)
|
|
terrain_mode_lower.toggled.connect(_on_terrain_mode_changed)
|
|
terrain_mode_smooth.toggled.connect(_on_terrain_mode_changed)
|
|
terrain_mode_paint.toggled.connect(_on_terrain_mode_changed)
|
|
mode_row.add_child(terrain_mode_raise)
|
|
mode_row.add_child(terrain_mode_lower)
|
|
mode_row.add_child(terrain_mode_smooth)
|
|
mode_row.add_child(terrain_mode_paint)
|
|
|
|
# Material-Palette (Karte t_603ec1a8): nur sichtbar im Malen-Modus.
|
|
terrain_palette = VBoxContainer.new()
|
|
terrain_palette.add_theme_constant_override("separation", UIScale.px(4))
|
|
terrain_palette.visible = false
|
|
terrain_panel.add_child(terrain_palette)
|
|
terrain_palette.add_child(_field_label("Material:"))
|
|
var mat_row := HBoxContainer.new()
|
|
mat_row.add_theme_constant_override("separation", UIScale.px(6))
|
|
terrain_palette.add_child(mat_row)
|
|
var mat_group := ButtonGroup.new()
|
|
var mat_labels := ["🌿 Gras", "🏖 Sand", "🪨 Fels"]
|
|
for mat_id in SvmapIO.MATERIAL_IDS.size():
|
|
var mat_btn := Button.new()
|
|
mat_btn.text = str(mat_labels[mat_id])
|
|
mat_btn.custom_minimum_size = UIScale.v2(0, 40)
|
|
mat_btn.toggle_mode = true
|
|
mat_btn.button_group = mat_group
|
|
mat_btn.tooltip_text = "Malen: %s" % str(SvmapIO.MATERIAL_IDS[mat_id])
|
|
if mat_id == 0:
|
|
mat_btn.button_pressed = true
|
|
mat_btn.toggled.connect(_on_terrain_material_changed.bind(mat_id))
|
|
terrain_mat_buttons.append(mat_btn)
|
|
mat_row.add_child(mat_btn)
|
|
|
|
# Pinselgrößen-Presets (Karte t_603ec1a8): drei große Buttons + freier Slider.
|
|
terrain_panel.add_child(_field_label("Pinselgröße:"))
|
|
var size_row := HBoxContainer.new()
|
|
size_row.add_theme_constant_override("separation", UIScale.px(6))
|
|
terrain_panel.add_child(size_row)
|
|
var size_group := ButtonGroup.new()
|
|
terrain_size_btn_small = _terrain_size_button("Klein\n(4 m)", size_group, 4.0)
|
|
terrain_size_btn_medium = _terrain_size_button("Mittel\n(12 m)", size_group, 12.0)
|
|
terrain_size_btn_large = _terrain_size_button("Groß\n(32 m)", size_group, 32.0)
|
|
# Kein Signal: Der Handler greift auf terrain_radius_slider zu, der erst
|
|
# unten erzeugt wird — beim Panel-Bau wäre das ein Crash (GUI-Start-Bug
|
|
# 15.10.). Der Slider startet unten passend mit 12 m (= Mittel).
|
|
terrain_size_btn_medium.set_pressed_no_signal(true)
|
|
size_row.add_child(terrain_size_btn_small)
|
|
size_row.add_child(terrain_size_btn_medium)
|
|
size_row.add_child(terrain_size_btn_large)
|
|
|
|
terrain_radius_label = _field_label("Pinsel-Größe: 12 m")
|
|
terrain_panel.add_child(terrain_radius_label)
|
|
terrain_radius_slider = HSlider.new()
|
|
terrain_radius_slider.min_value = 2.0
|
|
terrain_radius_slider.max_value = 64.0
|
|
terrain_radius_slider.step = 1.0
|
|
terrain_radius_slider.value = 12.0
|
|
terrain_radius_slider.custom_minimum_size = UIScale.v2(0, 32)
|
|
terrain_radius_slider.value_changed.connect(_on_terrain_radius_changed)
|
|
terrain_panel.add_child(terrain_radius_slider)
|
|
|
|
terrain_strength_label = _field_label("Stärke: 8 m pro Sekunde")
|
|
terrain_panel.add_child(terrain_strength_label)
|
|
terrain_strength_slider = HSlider.new()
|
|
terrain_strength_slider.min_value = 1.0
|
|
terrain_strength_slider.max_value = 20.0
|
|
terrain_strength_slider.step = 0.5
|
|
terrain_strength_slider.value = 8.0
|
|
terrain_strength_slider.custom_minimum_size = UIScale.v2(0, 32)
|
|
terrain_strength_slider.value_changed.connect(_on_terrain_strength_changed)
|
|
terrain_panel.add_child(terrain_strength_slider)
|
|
|
|
terrain_panel.add_child(_muted_label(
|
|
"Linksklick-Ziehen formt bzw. malt (je nach Werkzeug), Strg+Linksklick macht das Gegenteil — im Malen-Modus malt Strg+Klick Gras zurück. "
|
|
+ "Jeder Strich ist EIN Rückgängig-Schritt (Strg+Z). Rechte Maustaste = Flug, ESC beendet den Terrain-Modus."))
|
|
|
|
# --- Bauen (Karte t_97ea59c5): Modular-Builder-Pieces im App-Skelett ---
|
|
# (aus main.gd ausgezogen — liegt mit im Terrain-Tab, Werkzeug-Zusammenhang)
|
|
build_edit_btn = Button.new()
|
|
build_edit_btn.text = "🏠 Bauen (Häuser)"
|
|
build_edit_btn.custom_minimum_size = UIScale.v2(0, 48)
|
|
build_edit_btn.toggle_mode = true
|
|
build_edit_btn.tooltip_text = "Fundamente, Wände, Dächer, Treppen und Türen bauen — im 2-Meter-Raster, wie Bauklötze"
|
|
build_edit_btn.pressed.connect(_on_build_btn_pressed)
|
|
add_child(build_edit_btn)
|
|
|
|
build_panel = VBoxContainer.new()
|
|
build_panel.add_theme_constant_override("separation", UIScale.px(6))
|
|
build_panel.visible = false
|
|
add_child(build_panel)
|
|
|
|
build_panel.add_child(_field_label("Bauteil:"))
|
|
var build_grid := GridContainer.new()
|
|
build_grid.columns = 2
|
|
build_grid.add_theme_constant_override("h_separation", UIScale.px(6))
|
|
build_grid.add_theme_constant_override("v_separation", UIScale.px(6))
|
|
build_panel.add_child(build_grid)
|
|
var build_group := ButtonGroup.new()
|
|
for kind_id in BuildOps.KINDS.keys():
|
|
var kind_btn := Button.new()
|
|
kind_btn.text = str(BuildOps.KINDS[kind_id]["label"])
|
|
kind_btn.toggle_mode = true
|
|
kind_btn.button_group = build_group
|
|
kind_btn.custom_minimum_size = UIScale.v2(148, 44)
|
|
kind_btn.clip_text = true
|
|
kind_btn.tooltip_text = "%s — %s" % [str(BuildOps.KINDS[kind_id]["label"]), str(BuildOps.KINDS[kind_id].get("info", ""))]
|
|
kind_btn.pressed.connect(_on_build_kind_pressed.bind(str(kind_id)))
|
|
build_kind_buttons[str(kind_id)] = kind_btn
|
|
build_grid.add_child(kind_btn)
|
|
(build_kind_buttons["fundament"] as Button).set_pressed_no_signal(true)
|
|
|
|
build_panel.add_child(_muted_label(
|
|
"Linksklick setzt das Bauteil aufs 2-m-Raster — auch AUF andere Teile "
|
|
+ "(Wände aufs Fundament stapeln, Dach auf die Wände). Jedes Bauteil ist "
|
|
+ "EIN Rückgängig-Schritt (Strg+Z). ESC beendet den Bauen-Modus."))
|
|
|
|
|
|
func _on_build_btn_pressed() -> void:
|
|
if build_edit_btn.button_pressed:
|
|
main.call("_set_tool_mode", "bauen")
|
|
else:
|
|
main.call("_set_tool_mode", "objects")
|
|
|
|
|
|
func _on_build_kind_pressed(kind_id: String) -> void:
|
|
main.call("_on_build_kind_pressed", kind_id)
|
|
|
|
|
|
func _on_terrain_btn_pressed() -> void:
|
|
if terrain_edit_btn.button_pressed:
|
|
main.call("_set_tool_mode", "terrain")
|
|
else:
|
|
main.call("_set_tool_mode", "objects")
|
|
|
|
|
|
func _terrain_mode_button(text: String, group: ButtonGroup) -> Button:
|
|
var btn := Button.new()
|
|
btn.text = text
|
|
btn.toggle_mode = true
|
|
btn.button_group = group
|
|
btn.custom_minimum_size = UIScale.v2(0, 40)
|
|
return btn
|
|
|
|
|
|
func _selected_terrain_mode() -> int:
|
|
if terrain_mode_lower.button_pressed:
|
|
return TerrainField.Mode.LOWER
|
|
if terrain_mode_smooth.button_pressed:
|
|
return TerrainField.Mode.SMOOTH
|
|
if terrain_mode_paint.button_pressed:
|
|
return TerrainField.Mode.PAINT
|
|
return TerrainField.Mode.RAISE
|
|
|
|
|
|
## Mode-Buttons (ButtonGroup) → Pinsel-Modus; Palette nur im Malen-Modus.
|
|
func _on_terrain_mode_changed(_pressed: bool) -> void:
|
|
if terrain_palette != null:
|
|
terrain_palette.visible = _selected_terrain_mode() == TerrainField.Mode.PAINT
|
|
if main.terrain_tool != null:
|
|
main.terrain_tool.call("set_brush_mode", _selected_terrain_mode())
|
|
|
|
|
|
## Material-Palette (Karte t_603ec1a8): gewähltes Material an den Pinsel.
|
|
func _on_terrain_material_changed(pressed: bool, mat_id: int) -> void:
|
|
if pressed and main.terrain_tool != null:
|
|
main.terrain_tool.call("set_paint_material", mat_id)
|
|
|
|
|
|
## Pinselgrößen-Presets (Karte t_603ec1a8): setzen den Radius-Slider
|
|
## (der Label-Text + Ring-Optik hängen am value_changed-Signal).
|
|
func _terrain_size_button(text: String, group: ButtonGroup, radius_m: float) -> Button:
|
|
var btn := Button.new()
|
|
btn.text = text
|
|
btn.toggle_mode = true
|
|
btn.button_group = group
|
|
btn.custom_minimum_size = UIScale.v2(0, 48)
|
|
btn.tooltip_text = "Pinselradius %d m" % int(radius_m)
|
|
btn.toggled.connect(_on_terrain_size_preset.bind(radius_m))
|
|
return btn
|
|
|
|
|
|
func _on_terrain_size_preset(pressed: bool, radius_m: float) -> void:
|
|
# Null-Check als Schutznetz: beim Panel-Bau existiert der Slider noch
|
|
# nicht (Programmatic-Pressed darf den Handler nie früh treffen).
|
|
if pressed and terrain_radius_slider != null:
|
|
terrain_radius_slider.value = radius_m
|
|
|
|
|
|
func _on_terrain_radius_changed(value: float) -> void:
|
|
terrain_radius_label.text = "Pinsel-Größe: %d m" % int(value)
|
|
if main.terrain_tool != null:
|
|
main.terrain_tool.call("set_radius", value)
|
|
|
|
|
|
func _on_terrain_strength_changed(value: float) -> void:
|
|
terrain_strength_label.text = "Stärke: %.1f m pro Sekunde" % value
|
|
if main.terrain_tool != null:
|
|
main.terrain_tool.call("set_strength", value)
|
|
|
|
|
|
## Terrain-Pinsel-Größe per [ / ] (Karte t_55257792): durch die 3 Presets
|
|
## Klein/Mittel/Groß zyklisch — der Preset-Button wird mit gesetzt (set_pressed
|
|
## feuert toggled → Slider + Label + Pinssel-Ring wandern mit).
|
|
## (Aus main.gd ausgezogen, Logik unverändert; Koordinator ruft weiter.)
|
|
func terrain_brush_size_step(up: bool) -> void:
|
|
if terrain_radius_slider == null:
|
|
return
|
|
var next := MoveMath.brush_next_preset(float(terrain_radius_slider.value), up)
|
|
var btn: Button = null
|
|
match next:
|
|
4.0:
|
|
btn = terrain_size_btn_small
|
|
12.0:
|
|
btn = terrain_size_btn_medium
|
|
32.0:
|
|
btn = terrain_size_btn_large
|
|
if btn != null:
|
|
btn.set_pressed(true) # feuert _on_terrain_size_preset → Slider/Label
|
|
else:
|
|
terrain_radius_slider.value = next
|
|
main.terrain_tool.call("set_radius", next)
|
|
main.call("_set_status", "Pinsel-Größe: %d m (mit [ / ] durch Klein/Mittel/Groß zyklisch)." % int(next))
|