simvx.core.scene_io.emitter

Greenfield scene emitter — live Node tree → canonical .py source.

Produces a single class definition whose __init__ reconstructs the tree via add_child calls, with non-default :class:Property values passed as keyword arguments. The output is a string; round-trip identity through

func:

simvx.core.scene_io.parse_source is guaranteed by construction because the emitted form is canonical and parso preserves any text it parses verbatim under :meth:SourceTree.dump.

The emitter is intentionally string-based rather than parso-based: building a fresh tree is the right tool when there is no source to preserve. The diff-and-edit layer (Tier 3b) handles the round-trip case where source already exists on disk.

Module Contents

Functions

emit_scene

Emit a complete .py source file for the live tree rooted at root.

emit_node_construction

Emit a single var_name = Type(kwargs...) line for node.

iter_runtime_kwargs

Return the (kwarg_name, formatted_expr) pairs the emitter would emit for node in greenfield mode.

structural_type_name

Importable type name the emitter would use for node.

emit_value

Format val as Python source, or None when not serialisable.

Data

API

simvx.core.scene_io.emitter.__all__

[‘emit_node_construction’, ‘emit_scene’, ‘emit_value’, ‘iter_runtime_kwargs’, ‘structural_type_name’…

simvx.core.scene_io.emitter.emit_scene(root: simvx.core.node.Node, *, class_name: str | None = None, extra_imports: list[str] | None = None) str[source]

Emit a complete .py source file for the live tree rooted at root.

Args: root: Root node of the tree. class_name: Class name to use. Defaults to root.name when it is a valid identifier and differs from the engine type name; otherwise falls back to the engine type name. extra_imports: Additional verbatim import lines to include in place of the auto-generated from simvx.core import ... line. Empty/None → minimal generated imports.

Returns: Complete Python source string. The output round-trips through parse_source(s).dump() == s by construction (parso preserves any text it parses verbatim).

simvx.core.scene_io.emitter.emit_node_construction(node: simvx.core.node.Node, var_name: str, *, used_types: set[str] | None = None) str[source]

Emit a single var_name = Type(kwargs...) line for node.

used_types is mutated in place when supplied so callers can accumulate imports across multiple emissions; the type of node itself is added, plus the types of any complex kwarg values (Vec2/Vec3/Quat).

simvx.core.scene_io.emitter.iter_runtime_kwargs(node: simvx.core.node.Node, *, used_types: set[str] | None = None) list[tuple[str, str]][source]

Return the (kwarg_name, formatted_expr) pairs the emitter would emit for node in greenfield mode.

This is the canonical answer to “which constructor kwargs reflect the non-default state of this node?” — used by the editor’s round-trip save path (simvx.editor.scene_diff) to reconcile a parsed source file against a live runtime tree without duplicating the Property/spatial-default iteration logic.

The returned list includes:

  • name=... when node.name differs from the engine type name.

  • Spatial kwargs (position/rotation/scale) for Node2D / Node3D when they deviate from origin/identity/one.

  • One entry per declared Property whose current value differs from its declared default and is serialisable via :func:emit_value.

used_types is mutated in place when supplied so callers can accumulate import names (Vec2/Vec3/Quat) for emit.

simvx.core.scene_io.emitter.structural_type_name(node: simvx.core.node.Node) str[source]

Importable type name the emitter would use for node.

Returns the pre-script class name when a user script has rebound type(node) to a class living in a user file unreachable from simvx.core — see :func:_structural_type. Used by the round-trip diff layer to decide whether to add an import for a newly-introduced runtime child.

simvx.core.scene_io.emitter.emit_value(val: Any) str | None[source]

Format val as Python source, or None when not serialisable.

Non-serialisable values include :class:Node instances, callables, and modules. Numeric types use a compact canonical form (integers formatted as N.0 floats where appropriate); :class:Vec2,

Class:

Vec3, :class:Quat, lists, tuples, and str-keyed dicts serialise recursively.