Add the planet setup map editor (#48)
PlanetSetupEditor authors PlanetSetup resources: pick a surface
profile (drives the real lunar_surface background, not a blank
sheet), place/move/delete capture points and enemies from a palette
generated straight off EnemyDefinitions.all() (a new enemy definition
shows up with no editor change), pan/pinch-zoom the canvas with the
same touch idiom as GameController, then save to
res://PlanetSetups/<id>.tres via ResourceSaver - reachable now from
the main menu's Map Editor button. The mutation methods
(new_setup/load_setup/add_*/move_*/remove_*/save_setup) are the whole
model and work standalone, which is what lets
tests/test_setup_editor.gd drive placement/move/delete/save/reload
directly without simulating touch input.
Every cross-file reference is a preloaded script const rather than a
bare global class name, matching #42/#44's load-order notes - this
file is instantiated from other scripts' function bodies, never as a
script-mode test entry point itself, so it wasn't at risk the same way
the test files were, but the pattern is kept consistent throughout.
Part of the #40 conquest-mechanic breakdown. This closes out the
breakdown: #41-#48 are now all implemented, tested, and merged.
2026-08-15 21:24:28 +02:00
|
|
|
[gd_scene load_steps=5 format=3]
|
|
|
|
|
|
|
|
|
|
[ext_resource type="Script" path="res://PlanetSetupEditor.gd" id="1"]
|
|
|
|
|
[ext_resource type="Script" path="res://LunarBackground.gd" id="2"]
|
|
|
|
|
[ext_resource type="Shader" path="res://lunar_surface.gdshader" id="3"]
|
|
|
|
|
[ext_resource type="Script" path="res://IconButton.gd" id="4"]
|
|
|
|
|
|
|
|
|
|
[sub_resource type="ShaderMaterial" id="1"]
|
|
|
|
|
shader = ExtResource("3")
|
|
|
|
|
shader_parameter/camera_zoom = 1.0
|
|
|
|
|
shader_parameter/viewport_size = Vector2(720, 1280)
|
|
|
|
|
shader_parameter/cell_size = 220.0
|
|
|
|
|
shader_parameter/base_color = Color(0.75, 0.75, 0.76, 1)
|
|
|
|
|
shader_parameter/crater_color = Color(0.44, 0.44, 0.45, 1)
|
|
|
|
|
shader_parameter/highlight_color = Color(0.89, 0.89, 0.9, 1)
|
|
|
|
|
|
|
|
|
|
[node name="PlanetSetupEditor" type="Node2D"]
|
|
|
|
|
script = ExtResource("1")
|
|
|
|
|
|
|
|
|
|
[node name="BackgroundLayer" type="CanvasLayer" parent="."]
|
|
|
|
|
layer = -10
|
|
|
|
|
|
|
|
|
|
[node name="Background" type="ColorRect" parent="BackgroundLayer"]
|
|
|
|
|
material = SubResource("1")
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
anchors_preset = 15
|
|
|
|
|
anchor_right = 1.0
|
|
|
|
|
anchor_bottom = 1.0
|
|
|
|
|
grow_horizontal = 2
|
|
|
|
|
grow_vertical = 2
|
|
|
|
|
script = ExtResource("2")
|
|
|
|
|
|
|
|
|
|
[node name="Camera2D" type="Camera2D" parent="."]
|
|
|
|
|
position = Vector2(0, 0)
|
|
|
|
|
zoom = Vector2(1, 1)
|
|
|
|
|
|
|
|
|
|
[node name="ItemHost" type="Node2D" parent="."]
|
|
|
|
|
|
|
|
|
|
[node name="UI" type="CanvasLayer" parent="."]
|
|
|
|
|
layer = 1
|
|
|
|
|
|
|
|
|
|
[node name="BackButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = 20
|
|
|
|
|
offset_right = 92
|
|
|
|
|
offset_bottom = 92
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 1
|
|
|
|
|
glow_color = Color(0.9, 0.35, 0.35, 1)
|
|
|
|
|
|
|
|
|
|
[node name="BackCaption" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = 96
|
|
|
|
|
offset_right = 92
|
|
|
|
|
offset_bottom = 122
|
|
|
|
|
theme_override_font_sizes/font_size = 18
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "Back"
|
|
|
|
|
|
|
|
|
|
[node name="ProfileButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 110
|
|
|
|
|
offset_top = 20
|
|
|
|
|
offset_right = 182
|
|
|
|
|
offset_bottom = 92
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 0
|
|
|
|
|
glow_color = Color(0.5, 0.75, 1, 1)
|
|
|
|
|
|
|
|
|
|
[node name="ProfileValueLabel" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 190
|
|
|
|
|
offset_top = 36
|
|
|
|
|
offset_right = 340
|
|
|
|
|
offset_bottom = 76
|
|
|
|
|
theme_override_font_sizes/font_size = 26
|
|
|
|
|
text = "ROCKY"
|
|
|
|
|
|
|
|
|
|
[node name="NameInput" type="LineEdit" parent="UI"]
|
|
|
|
|
offset_left = 350
|
|
|
|
|
offset_top = 36
|
|
|
|
|
offset_right = 696
|
|
|
|
|
offset_bottom = 76
|
|
|
|
|
placeholder_text = "Setup name"
|
|
|
|
|
text = "Untitled"
|
|
|
|
|
|
|
|
|
|
[node name="NewButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = 140
|
|
|
|
|
offset_right = 92
|
|
|
|
|
offset_bottom = 212
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 5
|
|
|
|
|
glow_color = Color(0.45, 0.9, 0.55, 1)
|
|
|
|
|
|
|
|
|
|
[node name="NewCaption" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = 216
|
|
|
|
|
offset_right = 92
|
|
|
|
|
offset_bottom = 242
|
|
|
|
|
theme_override_font_sizes/font_size = 18
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "New"
|
|
|
|
|
|
|
|
|
|
[node name="SaveButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 110
|
|
|
|
|
offset_top = 140
|
|
|
|
|
offset_right = 182
|
|
|
|
|
offset_bottom = 212
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 4
|
|
|
|
|
glow_color = Color(0.45, 0.9, 0.55, 1)
|
|
|
|
|
|
|
|
|
|
[node name="SaveCaption" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 110
|
|
|
|
|
offset_top = 216
|
|
|
|
|
offset_right = 182
|
|
|
|
|
offset_bottom = 242
|
|
|
|
|
theme_override_font_sizes/font_size = 18
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "Save"
|
|
|
|
|
|
|
|
|
|
[node name="LoadButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 200
|
|
|
|
|
offset_top = 140
|
|
|
|
|
offset_right = 272
|
|
|
|
|
offset_bottom = 212
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 3
|
|
|
|
|
glow_color = Color(0.5, 0.75, 1, 1)
|
|
|
|
|
|
|
|
|
|
[node name="LoadCaption" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 200
|
|
|
|
|
offset_top = 216
|
|
|
|
|
offset_right = 272
|
|
|
|
|
offset_bottom = 242
|
|
|
|
|
theme_override_font_sizes/font_size = 18
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "Load"
|
|
|
|
|
|
|
|
|
|
[node name="DeleteButton" type="Control" parent="UI"]
|
|
|
|
|
offset_left = 290
|
|
|
|
|
offset_top = 140
|
|
|
|
|
offset_right = 362
|
|
|
|
|
offset_bottom = 212
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 28
|
|
|
|
|
glow_color = Color(0.9, 0.35, 0.35, 1)
|
|
|
|
|
|
|
|
|
|
[node name="DeleteCaption" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 290
|
|
|
|
|
offset_top = 216
|
|
|
|
|
offset_right = 362
|
|
|
|
|
offset_bottom = 242
|
|
|
|
|
theme_override_font_sizes/font_size = 18
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "Delete"
|
|
|
|
|
|
|
|
|
|
[node name="StatusLabel" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 380
|
|
|
|
|
offset_top = 140
|
|
|
|
|
offset_right = 696
|
|
|
|
|
offset_bottom = 242
|
|
|
|
|
theme_override_font_sizes/font_size = 20
|
|
|
|
|
autowrap_mode = 2
|
|
|
|
|
text = ""
|
|
|
|
|
|
Map editor: real Load list, canvas panning, selected-item name (#64, #65, #66)
#64: Load used to blindly cycle to "the next" saved setup with no way
to see what existed or jump straight to one by name. It now opens a
real selectable ItemList of every saved setup (name + surface profile),
tap one to load it.
#65: a single-finger drag over empty canvas could never pan - the
touch handler placed an item on PRESS, before a drag had any chance to
happen, so the "pan" branch below it was unreachable dead code (it only
fired when selected_palette == "", which nothing in the UI can ever
produce). Placement now waits for release: released within
PAN_DEADZONE of where the finger went down is a tap (place), crossing
it partway through is a pan - the same tap-vs-drag deadzone idiom
GasBombController already uses for its own aim gesture.
#66: added a persistent "Selected: <kind> #<n>" label, refreshed
wherever selected_item changes (touch-select, new/load a setup,
delete), so a tap actually confirms what got picked instead of the
player inferring it from which dot on screen turned white.
Also widened test_space_time_distorder.gd's formation-lag margin after
it strayed 2.6x over its old allowance under one heavily loaded
JOBS=1 full-suite run and passed cleanly in isolation immediately
after - device jitter, not a regression; the wider margin still leaves
orders-of-magnitude headroom below a real desync bug's stray distance.
2026-08-17 19:49:43 +02:00
|
|
|
[node name="SelectedLabel" type="Label" parent="UI"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = 250
|
|
|
|
|
offset_right = 696
|
|
|
|
|
offset_bottom = 286
|
|
|
|
|
theme_override_font_sizes/font_size = 22
|
|
|
|
|
theme_override_colors/font_color = Color(1, 0.95, 0.9, 1)
|
|
|
|
|
autowrap_mode = 2
|
|
|
|
|
text = ""
|
|
|
|
|
|
Add the planet setup map editor (#48)
PlanetSetupEditor authors PlanetSetup resources: pick a surface
profile (drives the real lunar_surface background, not a blank
sheet), place/move/delete capture points and enemies from a palette
generated straight off EnemyDefinitions.all() (a new enemy definition
shows up with no editor change), pan/pinch-zoom the canvas with the
same touch idiom as GameController, then save to
res://PlanetSetups/<id>.tres via ResourceSaver - reachable now from
the main menu's Map Editor button. The mutation methods
(new_setup/load_setup/add_*/move_*/remove_*/save_setup) are the whole
model and work standalone, which is what lets
tests/test_setup_editor.gd drive placement/move/delete/save/reload
directly without simulating touch input.
Every cross-file reference is a preloaded script const rather than a
bare global class name, matching #42/#44's load-order notes - this
file is instantiated from other scripts' function bodies, never as a
script-mode test entry point itself, so it wasn't at risk the same way
the test files were, but the pattern is kept consistent throughout.
Part of the #40 conquest-mechanic breakdown. This closes out the
breakdown: #41-#48 are now all implemented, tested, and merged.
2026-08-15 21:24:28 +02:00
|
|
|
[node name="PaletteRow" type="Control" parent="UI"]
|
|
|
|
|
anchor_top = 1.0
|
|
|
|
|
anchor_bottom = 1.0
|
|
|
|
|
offset_left = 20
|
|
|
|
|
offset_top = -110
|
|
|
|
|
offset_right = 696
|
|
|
|
|
offset_bottom = -20
|
Map editor: real Load list, canvas panning, selected-item name (#64, #65, #66)
#64: Load used to blindly cycle to "the next" saved setup with no way
to see what existed or jump straight to one by name. It now opens a
real selectable ItemList of every saved setup (name + surface profile),
tap one to load it.
#65: a single-finger drag over empty canvas could never pan - the
touch handler placed an item on PRESS, before a drag had any chance to
happen, so the "pan" branch below it was unreachable dead code (it only
fired when selected_palette == "", which nothing in the UI can ever
produce). Placement now waits for release: released within
PAN_DEADZONE of where the finger went down is a tap (place), crossing
it partway through is a pan - the same tap-vs-drag deadzone idiom
GasBombController already uses for its own aim gesture.
#66: added a persistent "Selected: <kind> #<n>" label, refreshed
wherever selected_item changes (touch-select, new/load a setup,
delete), so a tap actually confirms what got picked instead of the
player inferring it from which dot on screen turned white.
Also widened test_space_time_distorder.gd's formation-lag margin after
it strayed 2.6x over its old allowance under one heavily loaded
JOBS=1 full-suite run and passed cleanly in isolation immediately
after - device jitter, not a regression; the wider margin still leaves
orders-of-magnitude headroom below a real desync bug's stray distance.
2026-08-17 19:49:43 +02:00
|
|
|
|
|
|
|
|
[node name="LoadPanel" type="Control" parent="UI"]
|
|
|
|
|
visible = false
|
|
|
|
|
anchor_right = 1.0
|
|
|
|
|
anchor_bottom = 1.0
|
|
|
|
|
|
|
|
|
|
[node name="Backdrop" type="ColorRect" parent="UI/LoadPanel"]
|
|
|
|
|
anchor_right = 1.0
|
|
|
|
|
anchor_bottom = 1.0
|
|
|
|
|
color = Color(0.03, 0.03, 0.08, 0.94)
|
|
|
|
|
|
|
|
|
|
[node name="TitleLabel" type="Label" parent="UI/LoadPanel"]
|
|
|
|
|
mouse_filter = 2
|
|
|
|
|
anchor_right = 1.0
|
|
|
|
|
offset_left = 24
|
|
|
|
|
offset_top = 36
|
|
|
|
|
offset_right = -24
|
|
|
|
|
offset_bottom = 90
|
|
|
|
|
theme_override_font_sizes/font_size = 34
|
|
|
|
|
horizontal_alignment = 1
|
|
|
|
|
text = "Load a setup"
|
|
|
|
|
|
|
|
|
|
[node name="List" type="ItemList" parent="UI/LoadPanel"]
|
|
|
|
|
offset_left = 24
|
|
|
|
|
offset_top = 110
|
|
|
|
|
offset_right = 696
|
|
|
|
|
offset_bottom = 1180
|
|
|
|
|
theme_override_font_sizes/font_size = 24
|
|
|
|
|
|
|
|
|
|
[node name="CloseButton" type="Control" parent="UI/LoadPanel"]
|
|
|
|
|
anchor_left = 1.0
|
|
|
|
|
anchor_right = 1.0
|
|
|
|
|
offset_left = -92
|
|
|
|
|
offset_top = 20
|
|
|
|
|
offset_right = -20
|
|
|
|
|
offset_bottom = 92
|
|
|
|
|
script = ExtResource("4")
|
|
|
|
|
icon = 1
|
|
|
|
|
glow_color = Color(0.9, 0.35, 0.35, 1)
|