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.
This commit is contained in:
parent
def224667d
commit
df2f252970
12 changed files with 876 additions and 15 deletions
56
PaletteEntryButton.gd
Normal file
56
PaletteEntryButton.gd
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
class_name PaletteEntryButton
|
||||
extends Control
|
||||
|
||||
# One selectable tile in the setup editor's palette: either the generic
|
||||
# capture-point marker, or one enemy definition's own hull/colour. Drawn
|
||||
# directly from the definition rather than a fixed icon set, so a new
|
||||
# EnemyDefinitions entry shows up automatically with no editor code change.
|
||||
|
||||
signal pressed
|
||||
|
||||
@export var is_capture_point: bool = false
|
||||
@export var enemy_definition: Resource
|
||||
@export var selected: bool = false: set = set_selected
|
||||
|
||||
const RING_COLOR: Color = Color(0.55, 0.85, 1.0)
|
||||
|
||||
|
||||
func set_selected(value: bool) -> void:
|
||||
selected = value
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if event is InputEventScreenTouch and not event.pressed \
|
||||
and Rect2(Vector2.ZERO, size).has_point(event.position):
|
||||
pressed.emit()
|
||||
elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not event.pressed:
|
||||
pressed.emit()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
var center: Vector2 = size / 2.0
|
||||
var margin: float = 4.0
|
||||
var frame: PackedVector2Array = PackedVector2Array([
|
||||
Vector2(margin, margin), Vector2(size.x - margin, margin),
|
||||
Vector2(size.x - margin, size.y - margin), Vector2(margin, size.y - margin),
|
||||
])
|
||||
var frame_color: Color = Color(1.0, 0.95, 0.9) if selected else Color(0.4, 0.45, 0.5)
|
||||
NeonDraw.draw_glowing_polygon(self, frame, frame_color, 0.85 if selected else 0.5)
|
||||
|
||||
if is_capture_point:
|
||||
var points: PackedVector2Array = PackedVector2Array()
|
||||
for i in range(16):
|
||||
var angle: float = float(i) / 16.0 * TAU
|
||||
points.append(center + Vector2(cos(angle), sin(angle)) * (size.x * 0.28))
|
||||
NeonDraw.draw_glowing_polygon(self, points, RING_COLOR, 0.8)
|
||||
elif enemy_definition != null:
|
||||
var scale_factor: float = (size.x * 0.5) / 28.0
|
||||
var points: PackedVector2Array = PackedVector2Array()
|
||||
for p in enemy_definition.hull_points:
|
||||
points.append(center + p * scale_factor * 0.6)
|
||||
NeonDraw.draw_glowing_polygon(self, points, enemy_definition.glow_color, 0.9)
|
||||
Loading…
Reference in a new issue