public void Update(ref Vector3 availableSize) { Vector3 parentPosition; Vector3 parentSize; Matrix parentMatrixInv; var parent = gameSideElement.VisualParent; if (parent is not null) { // parentCanvas is sized to the parent of the associated UIElement var parentMatrix = parent.WorldMatrix; parentPosition = parentMatrix.TranslationVector + availableSize * 0.5f; parentSize = parent.RenderSize; parentMatrixInv = Matrix.Invert(parent.WorldMatrix); } else { // Or to the total available size if it doesn't have a parent. parentPosition = availableSize * 0.5f; parentSize = availableSize; parentMatrixInv = Matrix.Identity; } parentCanvas.Size = parentSize; parentCanvas.SetCanvasAbsolutePosition(parentPosition); parentCanvas.SetCanvasPinOrigin(0.5f * Vector3.One); // Centered on origin var diffMatrix = Matrix.Multiply(parentMatrixInv, gameSideElement.WorldMatrix); var position = diffMatrix.TranslationVector + parentSize * 0.5f; // canvas is sized to the associated UIElement canvas.Size = gameSideElement.RenderSize; // canvas is Z-offset by depth bias (+1 to differentiate with the adorner root canvas) canvas.Margin = new Thickness(0, 0, 0, 0, 0, -1 * (gameSideElement.DepthBias + 1)); // Because we are inside a canvas, only Left, Top and Front margins can be used. canvas.SetCanvasAbsolutePosition(position); canvas.SetCanvasPinOrigin(0.5f * Vector3.One); // Centered on origin adorners.ForEach(a => a.Update(position)); highlightAdorner?.Update(position); }