extends CPUParticles3D ## Root helper for a one-shot effect scene: fires this emitter (and any CPUParticles3D children) ## once when spawned, then frees the whole scene after the longest-lived particle has died. This ## is what lets an effect be nothing but a tunable CPUParticles3D scene — no per-effect code, so ## Siim owns the look entirely in the inspector. Fired by the Fx autoload; see fx/README.md. const _FREE_MARGIN := 0.5 func _ready() -> void: var ttl := _arm(self) for emitter: CPUParticles3D in _child_emitters(): ttl = maxf(ttl, _arm(emitter)) get_tree().create_timer(ttl + _FREE_MARGIN).timeout.connect(queue_free) func _arm(p: CPUParticles3D) -> float: p.one_shot = true p.emitting = true return p.lifetime func _child_emitters() -> Array[CPUParticles3D]: var out: Array[CPUParticles3D] = [] _gather(self, out) return out func _gather(node: Node, out: Array[CPUParticles3D]) -> void: for child: Node in node.get_children(): if child is CPUParticles3D: out.append(child) _gather(child, out)