- Implement test for popup anchor behavior in rule-builder menus to ensure consistent anchor positioning during menu transitions. - Create tests for stage logic, including mode transitions, toolbar visibility, and status bar updates. - Add terrain drag-painting tests to verify correct block placement behavior and conflict handling. - Introduce walk waypoint tests to check for arrival conditions and position stability after navigation.
123 lines
4.3 KiB
GDScript
123 lines
4.3 KiB
GDScript
@tool
|
|
class_name TerrainBlock
|
|
extends StaticBody2D
|
|
## TerrainBlock - Reusable StaticBody2D vector-terrain component (Phase 1).
|
|
##
|
|
## A self-contained terrain block: a StaticBody2D root with three children built
|
|
## in code — a Polygon2D (interior fill), a Line2D (crisp vector outline, closed
|
|
## by appending the first vertex, rounded joints/caps), and a CollisionPolygon2D
|
|
## configured with BUILD_SOLIDS so concave terrain blocks collide correctly.
|
|
## Fully @tool: exported properties update the children live in the editor.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Child node names
|
|
# ---------------------------------------------------------------------------
|
|
|
|
const POLYGON_NODE_NAME := "Polygon2D"
|
|
const OUTLINE_NODE_NAME := "Outline"
|
|
const COLLISION_NODE_NAME := "CollisionPolygon2D"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Exported properties
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## The terrain polygon's vertices (local space). The unified setter pushes the
|
|
## array to the Polygon2D and CollisionPolygon2D, and closes the Line2D loop by
|
|
## appending the first vertex to the end.
|
|
@export var polygon_points: PackedVector2Array = PackedVector2Array():
|
|
set(value):
|
|
polygon_points = value
|
|
_apply_points()
|
|
|
|
## Interior fill color (Polygon2D).
|
|
@export var fill_color: Color = Color(0.25, 0.55, 0.25, 1.0):
|
|
set(value):
|
|
fill_color = value
|
|
if _polygon != null:
|
|
_polygon.color = value
|
|
|
|
## Outline color (Line2D).
|
|
@export var outline_color: Color = Color(0.05, 0.10, 0.05, 1.0):
|
|
set(value):
|
|
outline_color = value
|
|
if _outline != null:
|
|
_outline.default_color = value
|
|
|
|
## Outline width in pixels (Line2D).
|
|
@export var outline_width: float = 2.0:
|
|
set(value):
|
|
outline_width = value
|
|
if _outline != null:
|
|
_outline.width = value
|
|
|
|
## Registry id of the spawn template that produced this block (Phase 4b). Used
|
|
## by the terrain drag-painting three-state overlap query to detect same-type
|
|
## overlaps. Plain var (not inspector-editable).
|
|
var spawn_id: String = ""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Internal node references (built in _ready, @tool-safe)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
var _polygon: Polygon2D
|
|
var _outline: Line2D
|
|
var _collision: CollisionPolygon2D
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Lifecycle
|
|
# ---------------------------------------------------------------------------
|
|
|
|
func _ready() -> void:
|
|
_ensure_children()
|
|
_apply_points()
|
|
_apply_style()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Internal build / apply
|
|
# ---------------------------------------------------------------------------
|
|
|
|
func _ensure_children() -> void:
|
|
_polygon = get_node_or_null(NodePath(POLYGON_NODE_NAME)) as Polygon2D
|
|
if _polygon == null:
|
|
_polygon = Polygon2D.new()
|
|
_polygon.name = POLYGON_NODE_NAME
|
|
add_child(_polygon)
|
|
|
|
_outline = get_node_or_null(NodePath(OUTLINE_NODE_NAME)) as Line2D
|
|
if _outline == null:
|
|
_outline = Line2D.new()
|
|
_outline.name = OUTLINE_NODE_NAME
|
|
_outline.joint_mode = Line2D.LINE_JOINT_ROUND
|
|
_outline.begin_cap_mode = Line2D.LINE_CAP_ROUND
|
|
_outline.end_cap_mode = Line2D.LINE_CAP_ROUND
|
|
add_child(_outline)
|
|
|
|
_collision = get_node_or_null(NodePath(COLLISION_NODE_NAME)) as CollisionPolygon2D
|
|
if _collision == null:
|
|
_collision = CollisionPolygon2D.new()
|
|
_collision.name = COLLISION_NODE_NAME
|
|
_collision.build_mode = CollisionPolygon2D.BUILD_SOLIDS
|
|
add_child(_collision)
|
|
|
|
|
|
## Pushes the current polygon_points to the Polygon2D and CollisionPolygon2D,
|
|
## and appends the first vertex to the Line2D to close the border loop.
|
|
func _apply_points() -> void:
|
|
if _polygon != null:
|
|
_polygon.polygon = polygon_points
|
|
if _collision != null:
|
|
_collision.polygon = polygon_points if polygon_points.size() >= 3 else PackedVector2Array()
|
|
if _outline != null:
|
|
var outline_points := polygon_points.duplicate()
|
|
if not outline_points.is_empty():
|
|
outline_points.append(polygon_points[0])
|
|
_outline.points = outline_points
|
|
|
|
|
|
func _apply_style() -> void:
|
|
if _polygon != null:
|
|
_polygon.color = fill_color
|
|
if _outline != null:
|
|
_outline.default_color = outline_color
|
|
_outline.width = outline_width
|