@tool extends MeshInstance3D ## Dessine un rectangle (contour) représentant une zone de confinement. ## À attacher sur un MeshInstance3D vide, placé n'importe où dans la scène. ## Utilise les mêmes valeurs (zone_center / zone_size) que FleeingAnimal.gd. @export var zone_center: Vector3 = Vector3.ZERO: set(value): zone_center = value _update_rectangle() @export var zone_size: Vector2 = Vector2(30.0, 30.0): # largeur (x) et profondeur (z) set(value): zone_size = value _update_rectangle() @export var zone_rotation_degrees: float = 0.0: # rotation du rectangle autour de l'axe Y set(value): zone_rotation_degrees = value _update_rectangle() @export var line_color: Color = Color(1.0, 0.2, 0.2): set(value): line_color = value _update_material() @export var height_offset: float = 0.05 # légère élévation pour éviter le z-fighting avec le sol func _ready() -> void: _update_rectangle() _update_material() func _update_rectangle() -> void: var immediate := ImmediateMesh.new() immediate.surface_begin(Mesh.PRIMITIVE_LINE_STRIP) var half_width := zone_size.x * 0.5 var half_depth := zone_size.y * 0.5 var rot_rad := deg_to_rad(zone_rotation_degrees) var local_corners := [ Vector3(-half_width, 0.0, -half_depth), Vector3(half_width, 0.0, -half_depth), Vector3(half_width, 0.0, half_depth), Vector3(-half_width, 0.0, half_depth), Vector3(-half_width, 0.0, -half_depth), ] for corner in local_corners: var rotated_corner: Vector3 = corner.rotated(Vector3.UP, rot_rad) var final_point := zone_center + rotated_corner final_point.y += height_offset immediate.surface_add_vertex(final_point) immediate.surface_end() mesh = immediate func _update_material() -> void: var mat := StandardMaterial3D.new() mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED mat.albedo_color = line_color mat.vertex_color_use_as_albedo = false material_override = mat