SceneBuilder.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Linq;
  5. using Avalonia.Media;
  6. using Avalonia.Threading;
  7. using Avalonia.VisualTree;
  8. namespace Avalonia.Rendering.SceneGraph
  9. {
  10. public static class SceneBuilder
  11. {
  12. public static Scene Update(Scene scene)
  13. {
  14. Dispatcher.UIThread.VerifyAccess();
  15. scene = scene.Clone();
  16. using (var impl = new DeferredDrawingContextImpl())
  17. using (var context = new DrawingContext(impl))
  18. {
  19. Update(context, scene, scene.Root.Visual, null);
  20. }
  21. return scene;
  22. }
  23. private static void Update(DrawingContext context, Scene scene, IVisual visual, VisualNode parent)
  24. {
  25. var opacity = visual.Opacity;
  26. var clipToBounds = visual.ClipToBounds;
  27. var bounds = new Rect(visual.Bounds.Size);
  28. var node = (VisualNode)scene.FindNode(visual) ?? CreateNode(visual, scene, parent);
  29. var contextImpl = (DeferredDrawingContextImpl)context.PlatformImpl;
  30. contextImpl.AddChild(node);
  31. if (visual.IsVisible && opacity > 0)
  32. {
  33. var m = Matrix.CreateTranslation(visual.Bounds.Position);
  34. var renderTransform = Matrix.Identity;
  35. if (visual.RenderTransform != null)
  36. {
  37. var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
  38. var offset = Matrix.CreateTranslation(origin);
  39. renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
  40. }
  41. m = renderTransform * m;
  42. using (contextImpl.Begin(node))
  43. using (context.PushPostTransform(m))
  44. using (context.PushTransformContainer())
  45. {
  46. node.Transform = contextImpl.Transform;
  47. node.ClipBounds = bounds * node.Transform;
  48. node.ClipToBounds = clipToBounds;
  49. node.GeometryClip = visual.Clip;
  50. node.Opacity = opacity;
  51. node.OpacityMask = visual.OpacityMask;
  52. visual.Render(context);
  53. foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
  54. {
  55. Update(context, scene, child, node);
  56. }
  57. }
  58. }
  59. }
  60. private static VisualNode CreateNode(IVisual visual, Scene scene, VisualNode parent)
  61. {
  62. var node = new VisualNode(visual);
  63. scene.Add(node);
  64. return node;
  65. }
  66. }
  67. }