API Reference · Overlays and labels

Ava3DOverlay

Namespace: Ava3D

public class Ava3DOverlay : Controls.Panel

Places ordinary Avalonia controls at positions in an Ava3DView's scene.

It positions; it does not draw. The children are whatever Avalonia can make — a TextBlock, a styled Border, a Button, a whole templated control — so text stays text at the device's real resolution, and layout, styling, bindings, hit-testing, input routing and accessibility all keep working. That division is not a compromise; it is what every 3D view embedded in a UI framework settled on. Qt Quick 3D's View3D is an Item with mapFrom3DScene beside it; three.js positions real DOM elements with CSS2DRenderer rather than drawing glyphs in WebGL; Babylon links a GUI control to a mesh. The 3D system says where, the UI system says what.

Put it in the same cell as the view, after it, so it composites on top:

<Grid>
  <a3d:Ava3DView x:Name="View" Scene="{Binding Deck}" />
  <a3d:Ava3DOverlay View="{Binding #View}">
    <Border Classes="contact"
            a3d:Ava3DOverlay.WorldPosition="{Binding Target.Position}"
            a3d:Ava3DOverlay.Anchor="Bottom"
            a3d:Ava3DOverlay.PixelOffset="0,-12">
      <TextBlock Text="{Binding Target.Name}" />
    </Border>
  </a3d:Ava3DOverlay>
</Grid>

A child with no Ava3DOverlay.WorldPositionProperty is laid out the way a plain Panel would lay it out, so a fixed corner of a HUD and a set of anchored markers can share one overlay.

What it writes to a child. Its arrangement, always — that is what a panel is. Its ZIndex, only under Ava3DOverlay.DepthSortProperty, which is opt-in. Nothing else: a child this panel declines to place is arranged off stage rather than having its IsVisible taken away, so that property stays the application's to use.

Under OverlayOcclusion.FadeWhenHidden, which is also opt-in, a hidden child is dimmed to Ava3DOverlay.HiddenOpacity at animation priority — on top of whatever Opacity the application set or bound, not in place of it. The dim is taken off again as soon as the child is in view, stops asking to be faded, loses its world position or leaves this panel, and the application's own value is what shows.

What the pointer does, exactly. Give this panel no Background and leave it that way. A Panel with no background is not hit-testable, so a press anywhere that is not on one of its children passes straight through to the view underneath and orbits, pans and picks as though the overlay were not there. A press that is on a child goes to the child, which is the point of having it.

It does not go to both, and it is worth being exact about why: the view is this panel's sibling, not its ancestor, and an unhandled pointer event bubbles up a tree rather than across it. So a child of this overlay consumes the press whether or not it marks it handled. That is the right behaviour for a button on a HUD and the wrong one for a decorative plate, and the way to get the second is IsHitTestVisible="False" on the plate — the framework's own answer, which keeps working for every other reason a control might want it.

Setting a Background on the overlay itself, even Transparent, makes the whole panel hit-testable and the view underneath receives nothing at all. That is the one way to break this, and it is invisible on screen.

When it re-places them. On Ava3DView.CameraChanged, on any of the attached properties changing, and on its own size changing — which together are exactly the things that move a projection. Not on a timer and not every frame: Ava3DView.InvalidateCamera is already what a moved camera has to call for the picture to follow it, so an overlay hung off the same signal is in step with the picture by construction, and an idle view under RenderTrigger.OnDemand costs its overlay nothing at all.

Properties

MemberDescription
double HiddenOpacity { get; set; }

What OverlayOcclusion.FadeWhenHidden fades to. A quarter by default — dim enough to read as behind something, present enough to keep tracking.

The opacity the child shows while hidden, not a factor on its own: a child at 0.6 fades to this value, and returns to 0.6 when it comes back into view.

OcclusionPrecision Precision { get; set; }

How exact the occlusion tests are, against what they cost. See OcclusionPrecision.

Ava3DView View { get; set; }

The view whose scene the Ava3DOverlay.WorldPositionProperty values are in.

Usually the sibling this overlay is stacked on: View="{Binding #View}". With none set the panel lays its children out as a plain Panel would, which is what a designer sees.

Fields

MemberDescription
static AttachedProperty<OverlayAnchor> AnchorProperty

See Ava3DOverlay.GetAnchor.

static AttachedProperty<OverlayBehind> BehindCameraProperty

See Ava3DOverlay.GetBehindCamera.

static AttachedProperty<bool> DepthSortProperty

See Ava3DOverlay.GetDepthSort.

static StyledProperty<double> HiddenOpacityProperty

Opacity of a child that is behind something, under OverlayOcclusion.FadeWhenHidden.

static AttachedProperty<OverlayOcclusion> OcclusionProperty

See Ava3DOverlay.GetOcclusion.

static AttachedProperty<OverlayOffScreen> OffScreenProperty

See Ava3DOverlay.GetOffScreen.

static AttachedProperty<Point> PixelOffsetProperty

See Ava3DOverlay.GetPixelOffset.

static StyledProperty<OcclusionPrecision> PrecisionProperty

How exact the occlusion tests are. See OcclusionPrecision.

static StyledProperty<Ava3DView> ViewProperty

The view whose scene these positions are in.

static AttachedProperty<Nullable<Vector3>> WorldPositionProperty

See Ava3DOverlay.GetWorldPosition.

Methods

MemberDescription
static OverlayAnchor GetAnchor(Controls.Control child)

Which point of the child sits on the projected position.

static OverlayBehind GetBehindCamera(Controls.Control child)

What to do when the position is not in front of the near plane.

static bool GetDepthSort(Controls.Control child)

Whether nearer children draw over further ones, by writing the child's ZIndex.

Off by default because it takes a property the application may be using itself. On, a stack of markers over a crowd reads correctly instead of in declaration order.

static OverlayOcclusion GetOcclusion(Controls.Control child)

Whether the child is hidden or dimmed while the scene is in front of its position.

static OverlayOffScreen GetOffScreen(Controls.Control child)

What to do when the projected point is outside the panel.

static Point GetPixelOffset(Controls.Control child)

Shifted by this many device-independent pixels after projecting, so a callout can stand clear of the thing it names without being anchored somewhere untrue.

static Nullable<Vector3> GetWorldPosition(Controls.Control child)

Where in the scene this child is anchored, or null to lay it out normally.

static void SetAnchor(Controls.Control child, OverlayAnchor value)

See Ava3DOverlay.GetAnchor.

static void SetBehindCamera(Controls.Control child, OverlayBehind value)

See Ava3DOverlay.GetBehindCamera.

static void SetDepthSort(Controls.Control child, bool value)

See Ava3DOverlay.GetDepthSort.

static void SetOcclusion(Controls.Control child, OverlayOcclusion value)

See Ava3DOverlay.GetOcclusion.

static void SetOffScreen(Controls.Control child, OverlayOffScreen value)

See Ava3DOverlay.GetOffScreen.

static void SetPixelOffset(Controls.Control child, Point value)

See Ava3DOverlay.GetPixelOffset.

static void SetWorldPosition(Controls.Control child, Nullable<Vector3> value)

See Ava3DOverlay.GetWorldPosition.

See also