class_name NeonPiece extends Node2D # One movable piece of neon art, rasterised ONCE and thereafter animated # only through node properties. # # Godot re-runs _draw() solely when a redraw is requested; changing # position/rotation/scale/modulate/visible reuses the cached geometry # instead. Since every NeonDraw call expands into four antialiased # polylines, redrawing a shape each frame just to move or fade it is the # expensive way to do the cheapest kind of animation. Ship.gd and # Asteroid.gd already work this way - this is the same idea packaged so a # building can be assembled out of independently movable parts. # # Geometry is defined in local space around the piece's own origin, so the # owner can move, spin, scale and fade it without touching the shape. var polygons: Array = [] # Open runs of points, as distinct from `polygons`, which close. An accretion # disc is arcs, not rings, so it needs the open form to be a piece at all. var paths: Array = [] var lines: Array = [] var glow_color: Color = Color.WHITE var core_color: Color = NeonDraw.DEFAULT_CORE var pulse: float = 1.0 static func create(parent: Node, at: Vector2, colour: Color, alpha: float = 1.0) -> NeonPiece: var piece: NeonPiece = NeonPiece.new() piece.position = at piece.glow_color = colour piece.modulate.a = alpha parent.add_child(piece) return piece func add_polygon(points: PackedVector2Array, piece_pulse: float = 1.0) -> void: polygons.append({"points": points, "pulse": piece_pulse}) func add_path(points: PackedVector2Array, piece_pulse: float = 1.0, width: float = 1.0) -> void: paths.append({"points": points, "pulse": piece_pulse, "width": width}) func add_line(from: Vector2, to: Vector2, width: float, piece_pulse: float = 1.0) -> void: lines.append({"from": from, "to": to, "width": width, "pulse": piece_pulse}) func _draw() -> void: for poly in polygons: NeonDraw.draw_glowing_polygon(self, poly.points, glow_color, poly.pulse * pulse, core_color) for path in paths: NeonDraw.draw_glowing_path(self, path.points, glow_color, path.pulse * pulse, path.width, core_color) for line in lines: NeonDraw.draw_glowing_line(self, line.from, line.to, glow_color, line.pulse * pulse, line.width, core_color)