simvx.editor.autosave¶
Editor autosave + crash recovery.
The editor’s autosave is conceptually distinct from :class:~simvx.core.SaveManager:
SaveManagersnapshots onlyPropertydescriptors flaggedpersist=True– a deliberately narrow contract for in-game state.The editor’s autosave needs the full scene structure so that, after a crash, no newly-added nodes are lost. We therefore reuse the engine’s in-memory scene snapshot helper (:func:
simvx.core._scene_internal._serialize_node) and pickle that dict. Restoring goes through :func:_deserialize_node.
Both paths share :func:simvx.core.save_manager.pickle_atomic for the
write-tmp + fsync + rename + two-deep .bak/.bak2 rotation, so the
crash-safety guarantees are identical.
The autosave file lives at $XDG_DATA_HOME/simvx/editor/autosave.sav
(falling back to ~/.local/share/simvx/editor/autosave.sav). One file –
the most-recent project’s working tree – because the editor only ever has
one foreground workspace.
Module Contents¶
Classes¶
Periodic full-tree autosave with crash-recovery on launch. |
|
Modal prompt shown on startup when a fresh autosave is available. |
Functions¶
Build the human-readable message body for :class: |
Data¶
API¶
- simvx.editor.autosave.log¶
‘getLogger(…)’
- class simvx.editor.autosave.Autosave(state, autosave_dir: pathlib.Path | None = None)[source]¶
Periodic full-tree autosave with crash-recovery on launch.
Polled each frame via :meth:
poll. When the autosave interval has elapsed and the editor’s scene is marked modified, a pickle of- Func:
_serialize_node(scene_root)is written atomically to<autosave_dir>/autosave.sav. On startup, :meth:check_recoveryreturns the autosave envelope when it is newer than the most-recently opened project file (if any).
Initialization
- INTERVAL¶
60.0
- poll(now: float = 0.0) None[source]¶
Save the working tree if the interval has elapsed and it’s dirty.
- check_recovery(project_path: pathlib.Path | None = None) dict | None[source]¶
Return the autosave envelope when recovery should be offered.
Returns
Nonewhen:no autosave file exists, or
a
project_pathwas supplied and the autosave is older than the project file (i.e. the project’s on-disk state is already fresher).
Otherwise returns the decoded envelope dict (caller decides whether to show a dialog and/or restore).
- restore(envelope: dict)[source]¶
Reconstruct a Node tree from a recovery envelope.
The scene’s own module is imported first. A
.pyscene’s root class lives in a module named after the file’s path, which is on no search path, so nothing brings it back on its own: recovery runs in a process started after the crash, where neithersys.modulesnorNode._registryhas ever heard of the class. Without the import the rebuild raisesUnknown node typeon the scene’s own root.The caller is responsible for swapping the returned root into the editor’s active scene tab. Raises
RuntimeErrorif the envelope is malformed (missingscenekey); strict per the engine’s error philosophy.
- class simvx.editor.autosave.AutosaveRecoveryDialog(**kwargs)[source]¶
Bases:
simvx.core.PanelModal prompt shown on startup when a fresh autosave is available.
Three outcomes, exposed as signals:
- attr:
restore_requested– user wants the autosaved tree swapped in.
- attr:
discard_requested– delete the autosave and continue with the project file as-is.
- attr:
cancelled– close the dialog without acting (e.g. user wants to inspect things first; autosave is left intact for later).
Initialization
- DIALOG_WIDTH¶
380.0
- DIALOG_HEIGHT¶
180.0
- BUTTON_HEIGHT¶
32.0
- BUTTON_GAP¶
8.0
- show_dialog(message: str, parent_size: simvx.core.Vec2 | None = None) None[source]¶
Reveal the dialog with the given
messagebody.
- style¶
‘ThemeStyleBox(…)’
- property bg_colour¶
- property border_colour¶
- property border_width¶
- get_minimum_size() simvx.core.math.types.Vec2¶
- on_draw(renderer)¶
- size_x¶
‘Property(…)’
- size_y¶
‘Property(…)’
- min_size_x¶
‘Property(…)’
- min_size_y¶
‘Property(…)’
- anchor_left¶
‘Property(…)’
- anchor_top¶
‘Property(…)’
- anchor_right¶
‘Property(…)’
- anchor_bottom¶
‘Property(…)’
- margin_left¶
‘Property(…)’
- margin_top¶
‘Property(…)’
- margin_right¶
‘Property(…)’
- margin_bottom¶
‘Property(…)’
- dismiss_on_outside_click¶
‘Property(…)’
- clip_contents¶
‘Property(…)’
- focus_mode¶
‘Property(…)’
- tooltip¶
‘Property(…)’
- mouse_filter¶
‘Property(…)’
- size_flags_horizontal¶
‘Property(…)’
- size_flags_vertical¶
‘Property(…)’
- stretch_ratio¶
‘Property(…)’
- max_size¶
‘Property(…)’
- property size: simvx.core.math.types.Vec2¶
- property min_size: simvx.core.math.types.Vec2¶
- content_signature() object¶
- content_uses(chars: str) bool¶
- autosize_to_content() None¶
- touch_mode: str¶
‘mouse’
- property theme: simvx.core.ui.types.Theme | None¶
- property mouse_over: bool¶
- property focused: bool¶
- property disabled: bool¶
- get_theme() simvx.core.ui.types.Theme¶
- queue_redraw()¶
- add_child(node: simvx.core.node.T) simvx.core.node.T¶
- get_rect() tuple[float, float, float, float]¶
- get_global_rect() tuple[float, float, float, float]¶
- is_point_inside(point) bool¶
- place_bottom_strip(height: float) None¶
- place_top_strip(height: float) None¶
- set_anchor_preset(preset: simvx.core.ui.enums.AnchorPreset)¶
- activate() bool¶
- set_focus()¶
- grab_focus()¶
- release_focus()¶
- has_focus() bool¶
- focus_next_control()¶
- focus_previous_control()¶
- grab_mouse()¶
- release_mouse()¶
- set_drag_preview(control: simvx.core.ui.core.Control)¶
- property is_overlay_open: bool¶
- show_overlay(modality: str = 'light', *, dim: bool | None = None, dismiss: bool | None = None, inert: bool | None = None, owner: simvx.core.ui.core.Control | None = None, initial_focus: simvx.core.ui.core.Control | None = None) None¶
- close_overlay() None¶
- position¶
‘_SpatialVecProperty(…)’
- rotation¶
‘Property(…)’
- scale¶
‘_SpatialVecProperty(…)’
- z_index¶
‘Property(…)’
- z_as_relative¶
‘Property(…)’
- render_layer¶
‘Property(…)’
- set_render_layer(index: int, enabled: bool = True) None¶
- is_on_render_layer(index: int) bool¶
- property absolute_z_index: int¶
- property rotation_degrees: float¶
- property world_position: simvx.core.math.types.Vec2¶
- property world_rotation: float¶
- property world_scale: simvx.core.math.types.Vec2¶
- property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]¶
- property forward: simvx.core.math.types.Vec2¶
- property right: simvx.core.math.types.Vec2¶
- translate(offset: tuple[float, float] | numpy.ndarray)¶
- rotate(radians: float)¶
- rotate_deg(degrees: float)¶
- look_at(target: tuple[float, float] | numpy.ndarray)¶
- transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]¶
- draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)¶
- wrap_screen(margin: float = 20)¶
- hdr¶
‘Property(…)’
- property transform_render_dirty: bool¶
- strict_errors: ClassVar[bool]¶
True
- dev_checks: ClassVar[bool]¶
None
- script_error_raised¶
‘Signal(…)’
- dynamic: bool¶
False
- visible¶
‘Property(…)’
- update_mode¶
‘Property(…)’
- __properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]¶
None
- classmethod __init_subclass__(**kwargs)¶
- property name: str¶
- property visible_in_tree: bool¶
- reset_error() None¶
- remove_child(node: simvx.core.node.Node) None¶
- reparent(new_parent: simvx.core.node.Node)¶
- node_at(path, default=_NO_DEFAULT)¶
- find(target, *, direct: bool = False)¶
- find_all(target, *, direct: bool = False)¶
- expect(target, *, direct: bool = False)¶
- ancestor(target)¶
- walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]¶
- property path: str¶
- property is_scene_root: bool¶
- 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_update(dt: float) None¶
- on_fixed_update(dt: float) 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)¶
- property render_dirty: bool¶
- clear_children()¶
- destroy()¶
- property destroying: bool¶
- 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__()¶