simvx.core.ui.core¶
Core UI types: Control, Theme, Colour, UIInputEvent, FocusMode, AnchorPreset, SizeFlags, DragData.
Module Contents¶
Classes¶
Base class for all UI elements. |
Data¶
API¶
- simvx.core.ui.core.log¶
‘getLogger(…)’
- simvx.core.ui.core.__all__¶
[‘Control’, ‘Theme’, ‘ThemeColour’, ‘ThemeSize’, ‘ThemeStyleBox’, ‘Colour’, ‘UIInputEvent’, ‘FocusMo…
- class simvx.core.ui.core.Control(**kwargs)[source]¶
Bases:
simvx.core.nodes_2d.node2d.Node2DBase class for all UI elements.
Supports anchors, margins, sizing, focus, drag-and-drop, and input handling. Widgets draw themselves using the renderer passed to draw().
Example: control = Control(name=”panel”) control.size = Vec2(200, 100) control.set_anchor_preset(AnchorPreset.FULL_RECT)
Initialization
- 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[source]¶
Size backed by size_x/size_y Properties (inspector-synced).
- property min_size: simvx.core.math.types.Vec2[source]¶
Minimum size, backed by min_size_x/min_size_y Properties (inspector-synced).
A view, like :attr:
size: assign a whole vector to change it. Editing the returned vector in place changes nothing.
- content_signature() object[source]¶
What :meth:
get_minimum_sizemeasures, beyond the font metrics.Assigning new content to a control does not resize it; that is the caller’s to do. A re-fit therefore has to distinguish content it may re-measure from content that has changed underneath it since, because re-measuring the latter would apply a resize nobody asked for, at whatever moment the metrics happened to move. Subclasses whose minimum size depends on their own state return it here.
The default says “nothing that can change”, which is the safe answer: it makes every re-fit re-measure, as it would without this at all.
- content_uses(chars: str) bool[source]¶
Whether new metrics for chars can change this control’s minimum size.
A control answering
Falseis left alone when only those characters moved, which is what keeps a browser rasterising glyphs a few at a time from re-fitting an entire UI on every frame it does so. Subclasses that size themselves to a known string answer from it.The default says any character might matter, which is the safe answer.
- autosize_to_content() None[source]¶
Size this control to fit its content, and keep it fitted.
How wide a string is depends on the font it is drawn with, and a renderer can resolve that font after the scene has been built. Controls sized this way are measured again when that happens, so a button never ends up narrower than the label inside it.
A size set from anywhere else wins: a container that lays this control out, or a game that assigns
size, keeps its size, and only the layout is told to run again.
- touch_mode: str¶
‘mouse’
- property theme: simvx.core.ui.types.Theme | None[source]¶
- get_theme() simvx.core.ui.types.Theme[source]¶
Get effective theme (own -> parent -> default).
- queue_redraw()[source]¶
Mark this control as needing a redraw. Propagates upward to parent.
Extends :meth:
Drawable2D.queue_redrawadditively: it sets the item-pipeline render-dirty bit (read by the itemRenderItemCache) AND keeps the_draw_dirty/_DrawRecordercache path (read by theDraw2D_draw_recursivewalk the editor play-mode game viewport + web runtime still use).
- get_minimum_size() simvx.core.math.types.Vec2[source]¶
Minimum size needed to display content. Subclasses override.
- add_child(node: simvx.core.node.T) simvx.core.node.T[source]¶
Add a child, and forget the measurements it just changed (see :meth:
Node.add_child).
- get_global_rect() tuple[float, float, float, float][source]¶
Get (x, y, width, height) in screen space.
The origin is :attr:
world_position: the anchor/margin rect is part of the 2D transform chain (:meth:_layout_offset), so there is one walk up the tree and not two, and a control’s drawn position and its reported position cannot disagree.The extent still comes from :meth:
get_rect, which is why_rect_framestays a field of its own rather than merging into the transform epoch: the two are stamped at different moments, and one field would let a fresh transform certify a stale(width, height).Cached per layout frame, and auto-expires when the epoch advances.
One class diverges on purpose. While registered as an overlay,
SplashScreenandAttributionWatermark(_FullscreenOverlay) override both this and :meth:get_rectto cover the whole render target wherever they are parented, so for them this does NOT equalworld_position. The overlay collector draws them from their rect and never reads their world position.
- place_bottom_strip(height: float) None[source]¶
Anchor this control as a full-width horizontal strip at the bottom.
Equivalent to
set_anchor_preset(AnchorPreset.BOTTOM_WIDE)plusmargin_top = -height. The negative-margin convention is correct but surprising; this shortcut makes intent obvious.
- place_top_strip(height: float) None[source]¶
Anchor this control as a full-width horizontal strip at the top.
- set_anchor_preset(preset: simvx.core.ui.enums.AnchorPreset)[source]¶
Set anchors from a preset.
Example: panel.set_anchor_preset(AnchorPreset.FULL_RECT) # fills parent label.set_anchor_preset(AnchorPreset.CENTER) # centered
- activate() bool[source]¶
Act on this control as a completed click would; return whether it acted.
This is what the
ui_acceptkey (Enter by default) does to the focus owner. The router calls it only after the focused widget has declined the key, so a widget that wants Enter for itself keeps it by settingevent.handled– a text field submits, a code editor inserts a newline, and neither is activated.A plain
Controlhas no activation semantics and returnsFalse.Buttonfirespressed,CheckBoxtoggles andRadioButtonselects, which is what Godot’sui_acceptand Unity’sISubmitHandlerdo for the same widgets. Everything else is deliberately inert.It is public so activation is one call rather than a synthesised event:
button.activate()is exactly what the keyboard does.The call itself is unconditional: it does not consult
disabledorvisible, because the caller is the policy. Both engine paths into it apply their own – a click never reaches a disabled control, and the router activates only a focusable owner – so an application calling this directly is saying “do it now”, the way emittingpressedwould.
- grab_focus()[source]¶
Claim keyboard focus for this control.
Unfocuses the currently focused control (if any) and sets focus to this one. Respects focus_mode: NONE-mode controls cannot receive focus.
- focus_next_control()[source]¶
Move focus to the next control in tab order.
An explicit
focus_nextlink wins; otherwise the tab order is walked from this control’s position in the tree, wrapping at the end. Hidden and disabled controls are skipped. When this control sits inside an open capturing overlay the walk is confined to that overlay; a control outside one is unaffected by it.
- focus_previous_control()[source]¶
Move focus to the previous control in tab order (see :meth:
focus_next_control).
- set_drag_preview(control: simvx.core.ui.core.Control)[source]¶
Set a visual preview control for the current drag operation.
- 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[source]¶
Register this control as an on-top overlay until :meth:
close_overlay.modalityis one of"none"/"light"/"blocking"(a preset bundle of the flags below).dim/dismiss/inert(None= preset default) override individual flags.owneris the logical chain owner for whole-chain dismissal + input scope (e.g. aMenuBarfor its dropdown + submenu overlays); defaults toself.initial_focusis the descendant to focus when the overlay is capturing (None= the first focusable descendant). Positioning is the widget’s own job: position first, then callshow_overlayto register.
- close_overlay() None[source]¶
Pop this control (and its open chain) from the overlay registry. Idempotent.
Mirrors :meth:
show_overlay, which setsvisible = True: closing hides the control again so a persistent (non-freed) overlay – a reused title/menu screen – stops drawing over the scene once dismissed. A consumer that frees its overlay on close is unaffected (the hide is harmless); one that reuses it getsvisible = Trueback on the nextshow_overlay.
- 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_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)¶
- 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__()¶