simvx.core.ui.core¶
Core UI types: Control, Theme, Colour, FocusMode, Anchor, 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’, ‘FocusMode’, ‘Anchor’, ‘…
- 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: hint = Label(“Hint”, anchor=Anchor.BOTTOM_LEFT, inset=16) panel = Panel(anchor=Anchor.TOP_RIGHT, size=(220, 120), inset=10)
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(…)’
- anchor¶
‘Property(…)’
- inset¶
‘Property(…)’
- dismiss_on_outside_click¶
‘Property(…)’
- clip_contents¶
‘Property(…)’
- focus_mode¶
‘Property(…)’
- tooltip¶
‘Property(…)’
- pointer_filter¶
‘Property(…)’
- cursor_shape¶
‘Property(…)’
- pointer_types: frozenset[simvx.core.input.enums.PointerType] | None¶
None
- touch_target: bool¶
False
- 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 resizes a control only where the control says so through :meth:
_content_changed, asLabeldoes. A metrics 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.
- accepts_pointers¶
‘Property(…)’
- property theme: simvx.core.ui.types.Theme | None[source]¶
- get_theme() simvx.core.ui.types.Theme[source]¶
Get effective theme (own -> parent -> default).
- property viewport_size: simvx.core.math.types.Vec2[source]¶
The size of the render target this control draws into, in UI pixels.
- Attr:
Node.viewport_size, divided by the tree’sui_scale: a control draws in UI pixels, and a render target that is 1600 pixels wide is 800 of them atui_scale == 2.0. At 1.0 the two are the same number. A draw that read it depends onui_scaleas well as on the target, and is re-captured when either changes.
- property viewport_insets: tuple[float, float, float, float][source]¶
- Attr:
Node.viewport_insetsin UI pixels, divided by the tree’sui_scaleas :attr:viewport_sizeis.
- 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).
- size_floor() tuple[float, float][source]¶
The smallest this control may be, whatever is asking: its declared :attr:
min_size.This is the one statement of that floor: every sizing path reads it rather than restating the rule, because a control is sized down three different routes and a floor written into one of them is absent from the other two.
- meth:
get_minimum_sizemeasures content against it, in the base and in every override, so a container laying out children respects it.
- meth:
_combined_minimum_sizeremembers the measurement it bounds.
- meth:
get_rectclamps to it, which is the path a control placed with anchors and margins takes.
A finger is not a reason to grow it: a touch target keeps the size its author chose and only its hit area grows (:meth:
is_hit).A tuple rather than a
Vec2: :meth:get_rectreads this for every control on every layout pass, and it has no use for an array.
- get_minimum_size() simvx.core.math.types.Vec2[source]¶
Minimum size needed to display content. Subclasses override.
An override measures its content and returns the larger of that and
- Meth:
size_flooron each axis. The base control has no content, so the floor is the whole answer.
- 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.
- property focus_rect: tuple[float, float, float, float] | None[source]¶
Where this control is on screen, as directional focus reads it, or None when it is off screen.
The same rect the eye and the pointer use, so the control a player sees above another is the one a press of Up moves to. A control that occupies a different area than it draws in overrides this.
- is_point_inside(point) bool[source]¶
Check if point (screen coords) is inside this control, moved, rotated and scaled as it is drawn.
- is_hit(event: simvx.core.input.events.PointerEvent) bool[source]¶
Whether event’s pointer lands on this control.
Its drawn rect, and for a finger on a :attr:
touch_targetthat rect grown evenly about its centre to at least the theme’smin_hit_sizeon each axis, so a 30-unit button is pressed by a thumb landing a few units off it while it stays 30 units on screen. A mouse and a pen are precise and hit the drawn rect alone. A widget deciding whether a press is its own asks this, which is the same question the hit test asked when it chose the widget.
- classmethod __init_subclass__(**kwargs)[source]¶
Keep placement working under a subclass that redeclares
anchorto change its default.anchor = Property(Anchor.FULL_RECT)in a class body is how a full-screen dialog says where it sits. A redeclared descriptor starts from scratch, so the change hook and theNone-accepting coerce are given back to it here rather than asking every such class to restate them.
- 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 returning True – 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.
- 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(…)’
- top_level¶
‘Property(…)’
- 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)¶
- to_global(point) simvx.core.math.types.Vec2¶
- to_local(point) simvx.core.math.types.Vec2¶
- transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]¶
- wrap_screen(margin: float = 20)¶
- post_processed¶
‘Property(…)’
- property transform_render_dirty: bool¶
- strict_errors: ClassVar[bool]¶
True
- dev_checks: ClassVar[bool]¶
None
- dev_warnings: ClassVar[bool]¶
None
- freeze_check_interval: ClassVar[float]¶
1.0
- dynamic: bool¶
False
- visible¶
‘Property(…)’
- update_mode¶
‘Property(…)’
- drag_threshold¶
‘Property(…)’
- focus_entered¶
‘Signal(…)’
- focus_exited¶
‘Signal(…)’
- __properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]¶
None
- property name: str¶
- property visible_in_tree: bool¶
- property input_player: simvx.core.input.players.InputPlayer¶
- property input_context: simvx.core.input.contexts.InputContext | None¶
- 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(canvas) None¶
- on_draw_3d(gizmos) None¶
- on_picked(event: simvx.core.input.events.PickEvent) bool | None¶
- on_gui_input(event: simvx.core.input.events.GuiInputEvent) bool | None¶
- start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle¶
- stop_coroutine(gen_or_handle)¶
- property focused: bool¶
- drag_threshold_for(pointer_type: simvx.core.input.enums.PointerType | str) float¶
- grab_focus() None¶
- release_focus() None¶
- capture_pointer(pointer_id: int | None = None) None¶
- release_pointer(pointer_id: int | None = None) None¶
- property render_dirty: bool¶
- clear_children()¶
- destroy()¶
- property destroying: bool¶
- property destroyed: 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__()¶