simvx.editor.save_report_dialog

The prompt shown when a save would rewrite the author’s own __init__.

Most saves write the scene back into the author’s file and nothing else, and those go through in silence. Some cannot: a file that builds children in a loop, a conditional or a helper method has no statement the save can match against the scene, so those children are written out a second time, and removing a child takes the author’s statements that stood on it. Those are what this asks about.

A value with no source form, or one the file spells as an expression this save will not overwrite, is the other class: the line stays exactly as the author wrote it, nothing of theirs is lost, and the save writes and warns rather than stopping to ask – the answer Godot, Unity and Unreal all give. The prompt shows those too when it opens for something else, since the user answering is owed the whole of what the save would leave behind.

All of it is known before anything is written (:meth:~simvx.editor.scene_file_ops.SceneFileOps.plan_save), so it is put in front of the user while the file on disk is still the one they last saw. Cancel leaves it untouched; Save Anyway commits the plan that produced the report.

One caller cannot ask first (:meth:SaveReportDialog.show_written): converting a node to a class writes a class file, saves the scene and reloads it as one action, so what it could not do is known only once all three have happened. The same report is shown in the same words, with the one button that is left.

Module Contents

Classes

SaveReportDialog

Modal “this save will change the file” confirmation.

Data

API

simvx.editor.save_report_dialog.__all__

[‘SaveReportDialog’]

class simvx.editor.save_report_dialog.SaveReportDialog(**kwargs)[source]

Bases: simvx.editor.modal_dialog.BaseModalDialog

Modal “this save will change the file” confirmation.

Construct once per editor; call :meth:show_for with the plan the save produced and a callback that commits it. On “Save Anyway” the callback fires; on “Cancel” the dialog hides, emits :attr:cancelled, and the file is left exactly as it was.

Initialization

confirmed

‘Signal(…)’

cancelled

‘Signal(…)’

DIALOG_W

620.0

DIALOG_H

400.0

show_for(plan: simvx.editor.scene_file_ops.ScenePlan, on_confirm: collections.abc.Callable[[], None] | None = None) None[source]

Open on plan’s report; on_confirm fires on Save Anyway.

Cancel is the safe answer and the one the dialog opens on, since the alternative overwrites a file the user has not seen the terms for yet.

Both classes of entry are shown, under headings that say which is which: the editor opens this only for a plan carrying a destructive one (SceneFileOps._ask_or_commit), and the user answering for those is owed the rest of what the save would leave behind at the same time.

A plan with nothing to report is refused rather than shown. There is no question to put: the save changes nothing beyond the user’s edits, and a modal offering to “Save Anyway” over an empty list asks them to accept terms nobody has stated.

show_written(path: pathlib.Path, report: collections.abc.Sequence[simvx.editor.scene_diff.ReportEntry]) None[source]

Open on what a save has already done, where there is nothing left to ask.

Every entry normally reaches the user before the write, which is what planning a save is for. Converting a node to a class cannot: it writes a class file, saves the scene and reloads it as one action, so what the save could not do is known only once the file on disk is the new one – and the worst of those, a class file written that the scene was never pointed at, leaves the user with lines only they can finish. That is worth the same card the prompt uses, in the same words; what a log line buys is a user who thinks it worked.

There is no question, so there is no Save Anyway. A report with nothing in it is refused, as an empty prompt is.

dismiss() None[source]

Hide the dialog and forget the plan it was asking about.

property report_text: str[source]

The whole report as the dialog is showing it, wrapped as drawn.

on_draw(renderer)[source]

The scrim, plus the card centred in whatever the window is now.

PAUSE_TREE_WHEN_MODAL

False

open_modal(*, initial_focus=None) None
style

‘ThemeStyleBox(…)’

property bg_colour
property border_colour
property border_width
get_minimum_size() simvx.core.math.types.Vec2
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__()