UniTextSelectable
Selection capability for UniTextBase: caret + range state with explicit affinity, gesture interpretation (multi-click promotion, drag-to-select, word-by-word drag, context-menu coordination), and highlight rendering. Sits on the same GameObject as UniTextBase; requires an existing UniText or UniTextWorld — RequireComponent validates the dependency but cannot auto-add the abstract base, so add the text component first.
Remarks
ITextEditingLayer and adds no gestures of its own. Drag policy: mouse / pen drags select; touch drags forward to the enclosing scroll container (the iOS / Android convention — selection on touch starts from a long-press or a double-tap, never from a plain drag) unless a selection gesture armed word-drag mode or the field itself has content to scroll. Handles, magnifier, and context menu are owner-aware serialized entities. Their implementations choose the presentation mechanism; the component never instantiates UI itself. Multi-click thresholds default to desktop conventions (MultiClickMaxInterval, MultiClickMaxDistance). Single = caret, double = word, triple = paragraph. Touch-side multi-tap thresholds (different from desktop) are fed in via DispatchTap / DispatchDoubleTap / DispatchTripleTap by the gesture recogniser, which applies its own timing.public HighlightPresentation SelectionHighlight{ get; set }Selection highlight presentation emitted through the text component's shared range-decoration host. It uses the same paint, mapping and geometry contract as HighlightModifier.
public ITouchHandles SelectionHandles{ get; set }Touch handle entity. It may implement ISelectionHandles, IInsertionHandle, or both; shows no handles. This component drives the selection handles for touch-selected text; a sibling UniTextEditable, when present, takes over and drives the caret handle too.
public IMagnifier Magnifier{ get; set }Touch magnifier entity. The implementation owns how it is presented; shows no magnifier. It appears while a selection handle is dragged, and a sibling UniTextEditable additionally raises it for long-press caret placement.
Maximum distance between consecutive primary clicks for multi-click detection, in density-independent pixels (Android dp, 160 dpi baseline) — the comparison scales by the display density at use so the physical slop stays constant on high-density displays. Defaults to 8.
public UniTextBase TextComponent{ get }Gets the display component on the same GameObject, resolving it on first access.
public TextSelection Selection{ get }Current selection state (anchor / focus / affinity). Immutable.
True while word-by-word drag is active (started by a double-click on text). Drag extension snaps to whole-word boundaries instead of individual codepoints. Read by the touch gesture pipeline to decide whether to start a fresh caret-drag or continue extending the word selection.
public OrderedValueEvent<SelectionChangingArgs> SelectionChanging{ get }Occurs when Selection is about to change through any of the public mutators (SetCaret / SetSelection / ExtendSelection / Select* / Click+drag dispatchers). Subscribers may set Cancel to abort, or assign Proposed to clamp into a permitted range (P2.A atomic-token boundary, integrator-defined read-only ranges). Side-effect movements driven by text mutation (insert / delete / IME commit / undo) bypass this event by design — they go through an internal non-vetoable path. See SelectionChangingArgs. Callbacks run by ascending order and equal orders retain subscription order.
public ITextContextMenu ContextMenu{ get; set }Menu entity presented on a context-menu request. It owns its presentation and may use Unity UI, native platform UI, or another mechanism. leaves presentation to ContextMenuRequested subscribers.
Moves one selection endpoint to codepointIndex with the touch selection-handle contract (iOS / Android): the selection never collapses — when the dragged endpoint lands on the fixed one it is clamped one grapheme cluster away — and dragging past the fixed endpoint is allowed, inverting the anchor / focus orientation (the handles swap roles). draggingAnchor selects which endpoint moves; the other stays fixed.
Programmatic primary-click driver — runs the same press gesture the pointer pipeline uses (HandlePressGesture): single places the caret, double selects the word, triple the paragraph; Shift extends. Affinity defaults downstream — the bounding-box TextHitResult carries none.
public void RequestContextMenu(Vector2 screenPosition)Raises the assigned ContextMenu (if any) over the current selection, then raises ContextMenuRequested. The menu stays up until the selection, a gesture or a command takes it down.
public bool TryGetSelectionScreenRect(Rect screenRect)Gets the screen rect enclosing the current selection, clipped to the visible text viewport.
public bool TryGetCaretScreenPoint(int codepointIndex, Vector2 screenPoint)Gets the screen point at the bottom of the caret at codepointIndex in document space.
public Rect GetViewportScreenRect()Gets the screen rect of the visible text viewport in Unity screen pixels.
public Action<SelectionChangedArgs> SelectionChangedPost-change notification with previous and current state plus a hierarchical UserEvent string. See SelectionChangedArgs for category strings.
public Action<TextPointerEvent> SelectionDragStartedOccurs when a pointer drag has been routed to selection (mouse / pen always; touch only in an armed selection gesture — see the class drag policy). The event is anchored at the press position, not the position where the drag threshold was crossed. The instance is reused across emissions and Hit is not computed — hit-test from ScreenPosition.
public Action<TextPointerEvent> SelectionDragUpdatedpublic Action<TextPointerEvent> SelectionDragEndedpublic Action ContextMenuDismissRequestedOccurs when an open context menu should hide (drag, scroll, edit, focus loss).
