Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
UIRenderer.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 
5 using SiliconStudio.Core;
6 using SiliconStudio.Core.Mathematics;
7 using SiliconStudio.Paradox.Games;
8 using SiliconStudio.Paradox.Graphics;
9 using SiliconStudio.Paradox.UI;
10 using SiliconStudio.Paradox.UI.Renderers;
11 
12 namespace SiliconStudio.Paradox.Effects
13 {
14  /// <summary>
15  /// The renderer in charge of drawing the UI.
16  /// </summary>
18  {
19  private readonly IGame game;
20  private readonly UISystem uiSystem;
21 
22  private readonly UIBatch batch;
23 
24  private UIRenderingContext renderingContext;
25 
26  private readonly RendererManager rendererManager;
27 
28  private bool uiResolutionChanged;
29 
30  public UIRenderer(IServiceRegistry services)
31  : base(services)
32  {
33  game = (IGame)services.GetService(typeof(IGame));
34  uiSystem = (UISystem)services.GetService(typeof(UISystem));
35 
36  batch = uiSystem.Batch;
37 
38  rendererManager = new RendererManager(new DefaultRenderersFactory(services));
39 
40  DebugName = "UIRenderer";
41  }
42 
43  public override void Load()
44  {
45  base.Load();
46 
47  uiSystem.ResolutionChanged += UISystemOnResolutionChanged;
48 
49  renderingContext = new UIRenderingContext
50  {
51  DepthStencilBuffer = GraphicsDevice.DepthStencilBuffer,
52  RenderTarget = GraphicsDevice.BackBuffer,
53  };
54  }
55 
56  private void UISystemOnResolutionChanged(object sender, EventArgs eventArgs)
57  {
58  uiResolutionChanged = true;
59  }
60 
61  public override void Unload()
62  {
63  base.Unload();
64 
65  if (uiSystem != null)
66  uiSystem.ResolutionChanged -= UISystemOnResolutionChanged;
67  }
68 
69  protected override void OnRendering(RenderContext context)
70  {
71  if (uiSystem.RootElement == null)
72  return;
73 
74  var drawTime = game.DrawTime;
75  var rootElement = uiSystem.RootElement;
76  var virtualResolution = uiSystem.VirtualResolution;
77  var updatableRootElement = (IUIElementUpdate)rootElement;
78 
79  // perform the time-based updates of the UI element
80  updatableRootElement.Update(drawTime);
81 
82  // update the UI element disposition
83  rootElement.Measure(virtualResolution);
84  rootElement.Arrange(virtualResolution, false);
85 
86  // update the UI element hierarchical properties
87  updatableRootElement.UpdateWorldMatrix(ref uiSystem.WorldMatrix, uiResolutionChanged);
88  updatableRootElement.UpdateElementState(0);
89  uiResolutionChanged = false;
90 
91  // set render targets and reset Depth buffer
92  GraphicsDevice.SetRenderTarget(GraphicsDevice.DepthStencilBuffer, GraphicsDevice.BackBuffer);
93  GraphicsDevice.Clear(GraphicsDevice.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
94 
95  // update the context time
96  renderingContext.Time = game.DrawTime;
97 
98  // start the image draw session
99  renderingContext.StencilTestReferenceValue = 0;
100  batch.Begin(ref uiSystem.ViewProjectionInternal, GraphicsDevice.BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);
101 
102  // Render the UI elements in the final render target
103  ReccursiveDrawWithClipping(rootElement);
104 
105  // end the image draw session
106  batch.End();
107  }
108 
109  private void ReccursiveDrawWithClipping(UIElement element)
110  {
111  // if the element is not visible, we also remove all its children
112  if (!element.IsVisible)
113  return;
114 
115  var renderer = rendererManager.GetRenderer(element);
116  renderingContext.DepthBias = element.DepthBias;
117 
118  // render the clipping region of the element
119  if (element.ClipToBounds)
120  {
121  // flush current elements
122  batch.End();
123 
124  // render the clipping region
125  batch.Begin(ref uiSystem.ViewProjectionInternal, GraphicsDevice.BlendStates.ColorDisabled, uiSystem.IncreaseStencilValueState, renderingContext.StencilTestReferenceValue);
126  renderer.RenderClipping(element, renderingContext);
127  batch.End();
128 
129  // update context and restart the batch
130  renderingContext.StencilTestReferenceValue += 1;
131  batch.Begin(ref uiSystem.ViewProjectionInternal, GraphicsDevice.BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);
132  }
133 
134  // render the design of the element
135  renderer.RenderColor(element, renderingContext);
136 
137  // render the children
138  foreach (var child in element.VisualChildrenCollection)
139  ReccursiveDrawWithClipping(child);
140 
141  // clear the element clipping region from the stencil buffer
142  if (element.ClipToBounds)
143  {
144  // flush current elements
145  batch.End();
146 
147  renderingContext.DepthBias = element.MaxChildrenDepthBias;
148 
149  // render the clipping region
150  batch.Begin(ref uiSystem.ViewProjectionInternal, GraphicsDevice.BlendStates.ColorDisabled, uiSystem.DecreaseStencilValueState, renderingContext.StencilTestReferenceValue);
151  renderer.RenderClipping(element, renderingContext);
152  batch.End();
153 
154  // update context and restart the batch
155  renderingContext.StencilTestReferenceValue -= 1;
156  batch.Begin(ref uiSystem.ViewProjectionInternal, GraphicsDevice.BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);
157  }
158  }
159 
161  {
162  return rendererManager.GetRenderer(element);
163  }
164 
165  public void RegisterRendererFactory(Type uiElementType, IElementRendererFactory factory)
166  {
167  rendererManager.RegisterRendererFactory(uiElementType, factory);
168  }
169 
170  public void RegisterRenderer(UIElement element, ElementRenderer renderer)
171  {
172  rendererManager.RegisterRenderer(element, renderer);
173  }
174  }
175 }
Provides a base class for all the User Interface elements in Paradox applications.
Definition: UIElement.cs:21
override void OnRendering(RenderContext context)
Definition: UIRenderer.cs:69
The renderer in charge of drawing the UI.
Definition: UIRenderer.cs:17
bool ClipToBounds
Gets or sets a value indicating whether to clip the content of this element (or content coming from t...
Definition: UIElement.cs:631
Interface for the update of the UIElements.
override void Unload()
Unloads this instance. This method is called when a RenderPass is de-attached (directly or indirectly...
Definition: UIRenderer.cs:61
Performs render pipeline transformations attached to a specific RenderPass.
Definition: Renderer.cs:13
A utility class to batch and draw UI images.
Definition: UIBatch.cs:15
A service registry is a IServiceProvider that provides methods to register and unregister services...
ElementRenderer GetRenderer(UIElement element)
Get the renderer of the corresponding UIElement.
Definition: UIRenderer.cs:160
Base class for UI element renderers
bool IsVisible
Gets a value indicating whether this element is visible in the user interface (UI).
Definition: UIElement.cs:399
Thread-local storage context used during rendering.
void RegisterRenderer(UIElement element, ElementRenderer renderer)
Associate a renderer to an UIElement.
Definition: UIRenderer.cs:170
The interface for managing UI element renderers.
Interface of the UI system.
Definition: UISystem.cs:20
void RegisterRendererFactory(Type uiElementType, IElementRendererFactory factory)
Associate a renderer factory to an UI element type.
Definition: UIRenderer.cs:165
override void Load()
Loads this instance. This method is called when a RenderPass is attached (directly or indirectly) to ...
Definition: UIRenderer.cs:43
The class in charge to manage the renderer of the different UIElement
UIRenderer(IServiceRegistry services)
Definition: UIRenderer.cs:30
The UI drawing context. It provides information about how to render UIElements for drawing...