public override void Update(ServerCompositionTarget root) { base.Update(root); foreach (var child in Children) { if (child.AdornedVisual != null) { root.EnqueueAdornerUpdate(child); } else { child.Update(root); } } IsDirtyComposition = false; }
public virtual void Update(ServerCompositionTarget root) { if (Parent == null && Root == null) { return; } var wasVisible = IsVisibleInFrame; // Calculate new parent-relative transform if (_combinedTransformDirty) { CombinedTransformMatrix = MatrixUtils.ComputeTransform(Size, AnchorPoint, CenterPoint, // HACK: Ignore RenderTransform set by the adorner layer AdornedVisual != null ? Matrix4x4.Identity : TransformMatrix, Scale, RotationAngle, Orientation, Offset); _combinedTransformDirty = false; } var parentTransform = (AdornedVisual ?? Parent)?.GlobalTransformMatrix ?? Matrix4x4.Identity; var newTransform = CombinedTransformMatrix * parentTransform; // Check if visual was moved and recalculate face orientation var positionChanged = false; if (GlobalTransformMatrix != newTransform) { _isBackface = Vector3.Transform( new Vector3(0, 0, float.PositiveInfinity), GlobalTransformMatrix).Z <= 0; positionChanged = true; } var oldTransformedContentBounds = TransformedOwnContentBounds; var oldCombinedTransformedClipBounds = _combinedTransformedClipBounds; if (_parent?.IsDirtyComposition == true) { IsDirtyComposition = true; _isDirtyForUpdate = true; } var invalidateOldBounds = _isDirtyForUpdate; var invalidateNewBounds = _isDirtyForUpdate; GlobalTransformMatrix = newTransform; var ownBounds = OwnContentBounds; if (ownBounds != _oldOwnContentBounds || positionChanged) { _oldOwnContentBounds = ownBounds; if (ownBounds.IsEmpty) { TransformedOwnContentBounds = default; } else { TransformedOwnContentBounds = ownBounds.TransformToAABB(MatrixUtils.ToMatrix(GlobalTransformMatrix)); } } if (_clipSizeDirty || positionChanged) { _transformedClipBounds = ClipToBounds ? new Rect(new Size(Size.X, Size.Y)) .TransformToAABB(MatrixUtils.ToMatrix(GlobalTransformMatrix)) : null; _clipSizeDirty = false; } _combinedTransformedClipBounds = Parent?._combinedTransformedClipBounds ?? new Rect(Root !.Size); if (_transformedClipBounds != null) { _combinedTransformedClipBounds = _combinedTransformedClipBounds.Intersect(_transformedClipBounds.Value); } EffectiveOpacity = Opacity * (Parent?.EffectiveOpacity ?? 1); IsVisibleInFrame = _parent?.IsVisibleInFrame != false && Visible && EffectiveOpacity > 0.04 && !_isBackface && !_combinedTransformedClipBounds.IsEmpty; if (wasVisible != IsVisibleInFrame || positionChanged) { invalidateOldBounds |= wasVisible; invalidateNewBounds |= IsVisibleInFrame; } // Invalidate new bounds if (invalidateNewBounds) { AddDirtyRect(TransformedOwnContentBounds.Intersect(_combinedTransformedClipBounds)); } if (invalidateOldBounds) { AddDirtyRect(oldTransformedContentBounds.Intersect(oldCombinedTransformedClipBounds)); } _isDirtyForUpdate = false; // Update readback indices var i = Root !.Readback; ref var readback = ref GetReadback(i.WriteIndex);