simvx.core.node¶
Node: Base node class with tree hierarchy, groups, and coroutine support.
Module Contents¶
Classes¶
Data¶
API¶
- simvx.core.node.log¶
‘getLogger(…)’
- simvx.core.node.T¶
‘TypeVar(…)’
- class simvx.core.node.Node(name: str = '', **kwargs)[source]¶
Base node with tree hierarchy, groups, and coroutine support.
Attributes: name: Unique name within the parent’s children. Defaults to the class name. parent: The parent
Node, orNoneif this is the root. children: Ordered collection of child nodes, accessible by name or index. visible: Whether this node (and its descendants) should be drawn. update_mode: Controls processing behaviour during pause (INHERIT,PAUSABLE,PAUSED_ONLY,ALWAYS,DISABLED). script: Optional file path to an attached script. unique_name: WhenTrue, the node is registered in the tree for fast lookup viaSceneTree.get_unique_node().Example::
root = Node(name="Root") child = Node(name="Child") root.add_child(child) assert child.parent is root assert root.children["Child"] is child
Initialization
- strict_errors: ClassVar[bool]¶
True
- script_error_raised¶
‘Signal(…)’
- dynamic: bool¶
False
- property update_mode: simvx.core.descriptors.UpdateMode[source]¶
- add_child(node: simvx.core.node.Node) simvx.core.node.Node[source]¶
Add a node as a child, reparenting it if already in a tree.
Args: node: The node to add. Removed from its current parent first.
Raises: ValueError:
nodeisselfor one ofself’s ancestors – either would create a cycle in the scene tree.
- remove_child(node: simvx.core.node.Node)[source]¶
Remove a child node from this node’s children.
- reparent(new_parent: simvx.core.node.Node)[source]¶
Remove from current parent and add to new_parent.
- get_node(path: str) simvx.core.node.Node[source]¶
Navigate tree by path: ‘Child/GrandChild’ or ‘../Sibling’.
- get_node_or_none(path: str) simvx.core.node.Node | None[source]¶
Like :meth:
get_nodebut returnNoneinstead of raising when the path doesn’t resolve. Use when a node’s presence is optional.
- find(target, *, direct: bool = False)[source]¶
First descendant matching
target, orNone.targetmay be:a :class:
Nodesubclass: matches the firstisinstancedescendant. The result is typed as that subclass (find(Player) -> Player | None), so no cast is needed.a
str: matches the first descendant whosenameequals it.a predicate
(Node) -> bool: matches the first descendant it accepts.
Search is depth-first, pre-order, and recursive by default. Pass
direct=Trueto consider only this node’s direct children.
- find_all(target, *, direct: bool = False)[source]¶
All descendants matching
target(same matcher rules as :meth:find), in depth-first pre-order. Recursive by default;direct=Truelimits the search to direct children. Returns[]when nothing matches.
- walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node][source]¶
Iterate this node and all descendants in DFS pre-order.
- on_ready() None[source]¶
Called once after the node and all its children enter the scene tree.
Override to perform initialisation that requires the scene tree – finding sibling nodes, connecting signals, spawning children. The
treeproperty is available. Called afteron_enter_tree()and after all children’son_ready().Decorate other methods with
@on_readyto register additional ready handlers; they fire after the override in declaration order.Note: Fires again if the node is removed and re-added to the tree.
Example::
def on_ready(self): self.sprite = self.get_node("Sprite") self.health_changed.connect(self._update_hud)
- on_enter_tree() None[source]¶
Called when the node enters the scene tree, before
on_ready().Override for setup that must happen the moment the tree reference becomes available. Children have not entered yet at this point, so avoid querying child nodes here – use
on_ready()instead.Example::
def on_enter_tree(self): self.add_to_group("enemies")
- on_exit_tree() None[source]¶
Called when the node is about to leave the scene tree.
Override to clean up resources, disconnect external signals, or persist state. Children have already exited by the time this fires on the parent.
Example::
def on_exit_tree(self): self.save_progress() self.remove_from_group("enemies")
- on_update(dt: float) None[source]¶
Called every frame for game logic.
Args: dt: Seconds elapsed since the previous frame (variable timestep).
Override for movement, AI, animation triggers, or any per-frame update. Obeys
update_mode– disabled or paused nodes are skipped automatically.Decorate other methods with
@on_updateto register additional per-frame handlers; they fire after the override in declaration order. For state held while a button is pressed, pollInput.is_action_pressed("name")from insideon_update.Example::
def on_update(self, dt): self.position += self.velocity * dt
- on_fixed_update(dt: float) None[source]¶
Called at a fixed timestep (default 60 Hz) for physics logic.
Args: dt: Fixed time step in seconds (e.g. 1/60).
Override for deterministic physics updates – forces, collision responses, rigid-body integration. Runs independently of the render frame rate.
Example::
def on_fixed_update(self, dt): self.velocity += self.gravity * dt self.move_and_slide(dt)
- on_draw(renderer) None[source]¶
Called each frame for custom 2D drawing.
Args: renderer: The active draw-command recorder (e.g.
Draw2D).Override to issue immediate-mode draw calls such as
draw_line,draw_rect, ordraw_text. Called only whenvisibleisTrue.The 2D renderer is retained (“build once”): output is re-collected only when a
Propertychanges. Ifon_drawreads non-Property state (a plain attribute updated by a signal or timer,tree.nowanimation), call :meth:queue_redrawwhen that state changes so the new frame is collected. This is identical on live and headless: a body that mutates withoutqueue_redrawfreezes on both.Example::
def on_draw(self, renderer): renderer.draw_circle(self.world_position, 10, colour=(1, 0, 0, 1))
- on_picked(event: simvx.core.events.InputEvent) None[source]¶
Called when a 3D mouse-pick event hits this node’s collision shape.
Args: event: The input event containing click position, camera ray, etc.
Override to react to direct interaction with this 3D object – selection, dragging, context menus.
Example::
def on_picked(self, event): if event.button == MouseButton.LEFT: self.selected = True
- on_unhandled_input(event: simvx.core.events.TreeInputEvent) None[source]¶
Called for input events that no
@on_inputhandler consumed.Args: event: The unhandled input event.
Use for catch-all bindings such as global debug toggles or pause menus that should only fire when no other handler returned a truthy value to consume the event. For most input handling use
@on_input(...)decorators with explicit filters; the dispatch tables route them directly without walking the tree.Example::
def on_unhandled_input(self, event): if event.key == Key.F3: self.toggle_debug_overlay()
- start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle[source]¶
Register a generator coroutine to run each frame. Returns a cancellable handle.
- stop_coroutine(gen_or_handle)[source]¶
Stop and remove a running coroutine (accepts generator or CoroutineHandle).
- queue_redraw() None[source]¶
Mark this node’s
on_drawoutput stale (re-capture it next frame).The manual escape hatch for an
on_drawbody that reads non-Property state and changes ONCE (a signal/timer poke). For per-frame animation set- Attr:
dynamicinstead. Idempotent and cheap (a no-op once already dirty).
Drawable2D(everyNode2D/Control/CanvasLayer) also gets this called automatically by the blanketProperty.__set__hook on any changed Property, so drawing from Property state never needs it. A plainNodeHUD/menu (_render_auto_dirtyisFalse) calls it by hand.
- property render_dirty: bool[source]¶
Whether
on_drawoutput changed since the last upload (introspection).
- destroy()[source]¶
Schedule this node for removal at the end of the current frame.
Signal connections made through this node’s bound methods are proactively disconnected so emitters stop dispatching to it on the next emit (Godot 4 behaviour). Lazy weak-ref cleanup in
Signal.__call__covers nodes that are GC’d withoutdestroy().
- call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None[source]¶
Escape hatch: run
method(*args)at the end of this frame, outside tree traversal, instead of now.Discouraged: prefer a safe-by-default path when one exists. SimVX already makes the common cases safe without deferring: the process loop and signal dispatch iterate snapshots (so adding/removing nodes mid-loop does not corrupt iteration), :meth:
destroyis already a deferred delete,Property(coalesce=True)collapses repeated writes, andtree.events.publish_deferred(...)decouples event delivery. Reach forcall_deferredonly when you must mutate from a context none of those cover, and document why at the call site.methodis a bound method or any callable (type-safe; never a string method name). Calls run once, in queue order, at the end-of-frame sync point; anything queued during that drain runs on the next frame. A call bound to this node is dropped if the node has left the tree by the time the queue drains, and runs through :meth:_safe_callso a failure obeys the same strict/release policy as any other lifecycle hook.
- property tree: simvx.core.scene_tree.SceneTree[source]¶
The SceneTree this node belongs to.
- property physics[source]¶
Spatial-query accessor bound to this node’s physics world, or
None.Mirrors :attr:
app/ :attr:tree: available once in-tree. Returns aPhysicsQueryscoped to the same world the node’s body lives in (resolved via the nearestPhysicsRootancestor, else the tree default), exposingraycast/raycast_all/shapecast/overlapwith typed results andmask/excludefilters. Built fresh per access (not cached): the resolved world can change across re-parent / change_scene, and the wrapper is a thin two-reference object on the cold query path. Bind it locally if a hot loop wants to reuse it.
- property physics_2d[source]¶
2D spatial-query accessor bound to this node’s 2D physics world, or
None.The 2D sibling of :attr:
physics: available once in-tree, returns aPhysicsQuery2Dscoped to the same 2D world the node’s body lives in (resolved via the nearestPhysicsRoot2Dancestor, else the tree’s 2D default), exposingraycast/raycast_all/shapecast/overlapwith typed 2D results andmask/excludefilters. Built fresh per access (cold query path).
- classmethod get_properties() dict[str, simvx.core.descriptors.Property][source]¶
Return all Property descriptors declared on this node class and its bases.
- class simvx.core.node.Timer(duration: float = 1.0, one_shot: bool = True, autostart: bool = False, **kwargs)[source]¶
Bases:
simvx.core.node.NodeFires timeout signal after duration. Supports one-shot and repeating.
Initialization
- duration¶
‘Property(…)’
- one_shot¶
‘Property(…)’
- autostart¶
‘Property(…)’
- strict_errors: ClassVar[bool]¶
True
- script_error_raised¶
‘Signal(…)’
- dynamic: bool¶
False
- classmethod __init_subclass__(**kwargs)¶
- property name: str¶
- property update_mode: simvx.core.descriptors.UpdateMode¶
- property visible: bool¶
- reset_error() None¶
- add_child(node: simvx.core.node.Node) simvx.core.node.Node¶
- remove_child(node: simvx.core.node.Node)¶
- reparent(new_parent: simvx.core.node.Node)¶
- get_node(path: str) simvx.core.node.Node¶
- get_node_or_none(path: str) simvx.core.node.Node | None¶
- find(target, *, direct: bool = False)¶
- find_all(target, *, direct: bool = False)¶
- walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]¶
- property path: str¶
- add_to_group(group: str)¶
- remove_from_group(group: str)¶
- is_in_group(group: str) bool¶
- on_ready() None¶
- on_enter_tree() None¶
- on_exit_tree() None¶
- on_fixed_update(dt: float) None¶
- on_draw(renderer) None¶
- on_picked(event: simvx.core.events.InputEvent) None¶
- on_unhandled_input(event: simvx.core.events.TreeInputEvent) None¶
- start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle¶
- stop_coroutine(gen_or_handle)¶
- queue_redraw() None¶
- property render_dirty: bool¶
- clear_children()¶
- destroy()¶
- call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None¶
- property app¶
- property tree: simvx.core.scene_tree.SceneTree¶
- property physics¶
- property physics_2d¶
- __getitem__(key: str)¶
- classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
- __repr__()¶