Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
UISystem.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 
4 using System;
5 using System.Collections.Generic;
6 
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Diagnostics;
9 using SiliconStudio.Core.Mathematics;
10 using SiliconStudio.Paradox.Games;
11 using SiliconStudio.Paradox.Graphics;
12 using SiliconStudio.Paradox.Input;
13 using SiliconStudio.Paradox.UI.Controls;
14 
15 namespace SiliconStudio.Paradox.UI
16 {
17  /// <summary>
18  /// Interface of the UI system.
19  /// </summary>
20  public class UISystem : GameSystemBase
21  {
22  internal Matrix WorldMatrix;
23 
24  private UIElement rootElement;
25  /// <summary>
26  /// Gets or sets the root element of the UI
27  /// </summary>
28  /// <value>The root element.</value>
29  public UIElement RootElement
30  {
31  get { return rootElement;}
32  set
33  {
34  rootElement = value;
35 
36  if(rootElement != null)
37  ((IUIElementUpdate)rootElement).UpdateUISystemReference(this);
38  }
39  }
40 
41  internal Matrix ViewProjectionInternal;
42 
43  /// <summary>
44  /// The view matrix used to render the UI system
45  /// </summary>
46  /// <value>The view matrix.</value>
47  public Matrix ViewMatrix { get; private set; }
48 
49  /// <summary>
50  /// The project matrix used to render the UI system
51  /// </summary>
52  /// <value>The projection matrix.</value>
53  public Matrix ProjectionMatrix { get; private set; }
54 
55  /// <summary>
56  /// The view/project matrix used to render the UI system
57  /// </summary>
58  /// <value>The view projection matrix.</value>
59  public Matrix ViewProjectionMatrix { get { return ViewProjectionInternal; } }
60 
61  public event EventHandler<EventArgs> ResolutionChanged;
62 
63  internal UIBatch Batch { get; private set; }
64 
65  internal DepthStencilState KeepStencilValueState { get; private set; }
66 
67  internal DepthStencilState IncreaseStencilValueState { get; private set; }
68 
69  internal DepthStencilState DecreaseStencilValueState { get; private set; }
70 
71  internal Vector2 BackBufferVirtualResolutionRatio { get; private set; }
72 
73  private Vector3 virtualResolution;
74 
75  private InputManagerBase input;
76 
77  private UIElement lastTouchedElement;
78  private Vector3 lastIntersectionPoint;
79 
80  // object to avoid allocation at each element leave event
81  private readonly HashSet<UIElement> newlySelectedElementParents = new HashSet<UIElement>();
82 
83  private readonly List<PointerEvent> compactedPointerEvents = new List<PointerEvent>();
84 
85  private readonly IVirtualResolution gameVirtualResolution;
86 
87  private float uiFrustrumHeight;
88 
89  private Matrix inverseViewMatrix;
90 
91  /// <summary>
92  /// The position of the view camera along z axis.
93  /// </summary>
94  private float viewPositionZ;
95 
96  private float nearPlane;
97 
98  private float farPlane;
99 
100  private Vector2 lastMousePosition;
101 
102  private UIElement lastOveredElement;
103 
104  public UISystem(IServiceRegistry registry)
105  : base(registry)
106  {
107  Services.AddService(typeof(UISystem), this);
108 
109  gameVirtualResolution = (IVirtualResolution)Services.GetService(typeof(IVirtualResolution));
110  gameVirtualResolution.VirtualResolutionChanged += OnGameVirtualResolutionChanged;
111  }
112 
113  private void OnGameVirtualResolutionChanged(object sender, EventArgs eventArgs)
114  {
115  VirtualResolution = gameVirtualResolution.VirtualResolution;
116  }
117 
118  public override void Initialize()
119  {
120  base.Initialize();
121 
122  input = Services.GetSafeServiceAs<InputManager>();
123 
124  VirtualResolution = new Vector3(GraphicsDevice.BackBuffer.Width, GraphicsDevice.BackBuffer.Height, 1000);
125 
126  Enabled = true;
127  Visible = true;
128 
129  Game.Window.ClientSizeChanged += WindowOnClientSizeChanged;
130 
131  Game.Activated += OnApplicationResumed;
132  Game.Deactivated += OnApplicationPaused;
133  }
134 
135  protected override void Destroy()
136  {
137  gameVirtualResolution.VirtualResolutionChanged -= OnGameVirtualResolutionChanged;
138 
139  Game.Activated -= OnApplicationResumed;
140  Game.Deactivated -= OnApplicationPaused;
141 
142  // ensure that OnApplicationPaused is called before destruction, when Game.Deactivated event is not triggered.
143  OnApplicationPaused(this, EventArgs.Empty);
144 
145  base.Destroy();
146  }
147 
148  private void WindowOnClientSizeChanged(object sender, EventArgs eventArgs)
149  {
150  BackBufferVirtualResolutionRatio = CalculateBackBufferVirtualResolutionRatio();
151  }
152 
153  private Vector2 CalculateBackBufferVirtualResolutionRatio()
154  {
155  return new Vector2(GraphicsDevice.BackBuffer.Width / virtualResolution.X, GraphicsDevice.BackBuffer.Height / virtualResolution.Y);
156  }
157 
158  protected override void LoadContent()
159  {
160  base.LoadContent();
161 
162  // create effect and geometric primitives
163  Batch = new UIBatch(GraphicsDevice);
164 
165  // create depth stencil states
166  var depthStencilDescription = new DepthStencilStateDescription(true, true)
167  {
168  StencilEnable = true,
169  FrontFace = new DepthStencilStencilOpDescription
170  {
171  StencilDepthBufferFail = StencilOperation.Keep,
172  StencilFail = StencilOperation.Keep,
173  StencilPass = StencilOperation.Keep,
174  StencilFunction = CompareFunction.Equal
175  },
176  };
177  KeepStencilValueState = DepthStencilState.New(GraphicsDevice, depthStencilDescription);
178 
179  depthStencilDescription.FrontFace.StencilPass = StencilOperation.Increment;
180  IncreaseStencilValueState = DepthStencilState.New(GraphicsDevice, depthStencilDescription);
181 
182  depthStencilDescription.FrontFace.StencilPass = StencilOperation.Decrement;
183  DecreaseStencilValueState = DepthStencilState.New(GraphicsDevice, depthStencilDescription);
184 
185  // set the default design of the UI elements.
186  var designsTexture = TextureExtensions.CreateTextureFromFileData(GraphicsDevice, DefaultDesigns.Designs);
187  Button.PressedImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default button pressed design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(71, 3, 32, 32)});
188  Button.NotPressedImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default button not pressed design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(3, 3, 32, 32) });
189  Button.MouseOverImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default button overred design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(37, 3, 32, 32) });
190  EditText.ActiveImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default edit active design", designsTexture) { Borders = 12 * Vector4.One, Region = new RectangleF(105, 3, 32, 32) });
191  EditText.InactiveImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default edit inactive design", designsTexture) { Borders = 12 * Vector4.One, Region = new RectangleF(139, 3, 32, 32) });
192  EditText.MouseOverImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default edit overred design", designsTexture) { Borders = 12 * Vector4.One, Region = new RectangleF(173, 3, 32, 32) });
193  ToggleButton.CheckedImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default toggle button checked design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(71, 3, 32, 32) });
194  ToggleButton.UncheckedImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default toggle button unchecked design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(3, 3, 32, 32) });
195  ToggleButton.IndeterminateImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default toggle button indeterminate design", designsTexture) { Borders = 8 * Vector4.One, Region = new RectangleF(37, 3, 32, 32) });
196  Slider.TrackBackgroundImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default slider track background design", designsTexture) { Borders = 14 * Vector4.One, Region = new RectangleF(207, 3, 32, 32) });
197  Slider.TrackForegroundImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default slider track foreground design", designsTexture) { Borders = 0 * Vector4.One, Region = new RectangleF(3, 37, 32, 32) });
198  Slider.ThumbImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default slider thumb design", designsTexture) { Borders = 4 * Vector4.One, Region = new RectangleF(37, 37, 16, 32) });
199  Slider.MouseOverThumbImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default slider thumb overred design", designsTexture) { Borders = 4 * Vector4.One, Region = new RectangleF(71, 37, 16, 32) });
200  Slider.TickImagePropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new UIImage("Default slider track foreground design", designsTexture) { Region = new RectangleF(245, 3, 3, 6) });
201  Slider.TickOffsetPropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(13f);
202  Slider.TrackStartingOffsetsrPropertyKey.DefaultValueMetadata = DefaultValueMetadata.Static(new Vector2(3));
203  }
204 
205  /// <summary>
206  /// The method to call when the application is put on background.
207  /// </summary>
208  void OnApplicationPaused(object sender, EventArgs e)
209  {
210  // validate the edit text and close the keyboard, if any edit text is currently active
211  var focusedEdit = UIElement.FocusedElement as EditText;
212  if (focusedEdit != null)
213  focusedEdit.IsSelectionActive = false;
214  }
215 
216  /// <summary>
217  /// The method to call when the application is put on foreground.
218  /// </summary>
219  void OnApplicationResumed(object sender, EventArgs e)
220  {
221  // revert the state of the edit text here?
222  }
223 
224  /// <summary>
225  /// Gets or sets the virtual resolution of the screen in Pixels.
226  /// </summary>
227  /// <value>The virtual resolution.</value>
228  /// <exception cref="System.InvalidOperationException">
229  /// The resolution along the X axis is not valid. [Value= + value.X + ]
230  /// or
231  /// The resolution along the Y axis is not valid. [Value= + value.Y + ]
232  /// or
233  /// The resolution along the Z axis is not valid. [Value= + value.Z + ]
234  /// </exception>
235  internal Vector3 VirtualResolution
236  {
237  get
238  {
239  return virtualResolution;
240  }
241  set
242  {
243  if (value.X <= 0)
244  throw new InvalidOperationException("The resolution along the X axis is not valid. [Value=" + value.X + "]");
245  if (value.Y <= 0)
246  throw new InvalidOperationException("The resolution along the Y axis is not valid. [Value=" + value.Y + "]");
247  if (value.Z <= 0)
248  throw new InvalidOperationException("The resolution along the Z axis is not valid. [Value=" + value.Z + "]");
249 
250  if(virtualResolution == value)
251  return;
252 
253  virtualResolution = value;
254 
255  var uiFieldOfView = (float)Math.Atan2(virtualResolution.Y / 2, virtualResolution.Z + 1f) * 2;
256  uiFrustrumHeight = 2 * (float)Math.Tan(uiFieldOfView / 2);
257 
258  nearPlane = 1f;
259  farPlane = 1f + 2 * virtualResolution.Z;
260  var projection = Matrix.PerspectiveFovRH(uiFieldOfView, virtualResolution.X / virtualResolution.Y, nearPlane, farPlane);
261  projection.M22 = -projection.M22;
262 
263  ProjectionMatrix = projection;
264  viewPositionZ = virtualResolution.Z + 1f;
265  ViewMatrix = Matrix.LookAtRH(new Vector3(0, 0, viewPositionZ), Vector3.Zero, Vector3.UnitY);
266  inverseViewMatrix = Matrix.Invert(ViewMatrix);
267  ViewProjectionInternal = ViewMatrix * ProjectionMatrix;
268  WorldMatrix = Matrix.Translation(-VirtualResolution.X / 2, -VirtualResolution.Y / 2, 0);
269  BackBufferVirtualResolutionRatio = CalculateBackBufferVirtualResolutionRatio();
270 
271  var handler = ResolutionChanged;
272  if (handler != null)
273  handler(this, EventArgs.Empty);
274  }
275  }
276 
277  public override void Update(GameTime gameTime)
278  {
279  base.Update(gameTime);
280 
281  if (RootElement == null) // no update if no UI
282  return;
283 
284  // Analyze the input and trigger the UI element touch and key events
285  // ReSharper disable once UnusedVariable
286  using (var profiler = Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
287  {
288  UpdateMouseOver();
289  UpdateTouchEvents(gameTime);
290  }
291  UpdateKeyEvents();
292  }
293 
294  private void UpdateKeyEvents()
295  {
296  foreach (var keyEvent in input.KeyEvents)
297  {
298  if (UIElement.FocusedElement == null || !UIElement.FocusedElement.IsHierarchyEnabled) return;
299  var key = keyEvent.Key;
300  if (keyEvent.Type == KeyEventType.Pressed)
301  {
302  UIElement.FocusedElement.RaiseKeyPressedEvent(new KeyEventArgs { Key = key, Input = input });
303  }
304  else
305  {
306  UIElement.FocusedElement.RaiseKeyReleasedEvent(new KeyEventArgs { Key = key, Input = input });
307  }
308  }
309 
310  foreach (var key in input.KeyDown)
311  {
312  if (UIElement.FocusedElement == null || !UIElement.FocusedElement.IsHierarchyEnabled) return;
313  UIElement.FocusedElement.RaiseKeyDownEvent(new KeyEventArgs { Key = key, Input = input });
314  }
315  }
316 
317  private void UpdateMouseOver()
318  {
319  if(!input.HasMouse)
320  return;
321 
322  var intersectionPoint = Vector3.Zero;
323  var mousePosition = input.MousePosition;
324  var overredElement = lastOveredElement;
325 
326  // determine currently overred element.
327  if(mousePosition != lastMousePosition)
328  overredElement = GetElementFromPointerScreenPosition(mousePosition, ref intersectionPoint);
329 
330  // find the common parent between current and last overred elements
331  var commonElement = FindCommonParent(overredElement, lastOveredElement);
332 
333  // disable mouse over state to previously overred hierarchy
334  var parent = lastOveredElement;
335  while (parent != commonElement && parent != null)
336  {
337  parent.MouseOverState = MouseOverState.MouseOverNone;
338  parent = parent.VisualParent;
339  }
340 
341  // enable mouse over state to currently overred hierarchy
342  if(overredElement != null)
343  {
344  // the element itself
345  overredElement.MouseOverState = MouseOverState.MouseOverElement;
346 
347  // its hierarchy
348  parent = overredElement.VisualParent;
349  while (parent != null)
350  {
351  if (parent.IsHierarchyEnabled)
352  parent.MouseOverState = MouseOverState.MouseOverChild;
353 
354  parent = parent.VisualParent;
355  }
356  }
357 
358  // update cached values
359  lastOveredElement = overredElement;
360  lastMousePosition = mousePosition;
361  }
362 
363  private void UpdateTouchEvents(GameTime gameTime)
364  {
365  // compact all the move events of the frame together
366  var aggregatedTranslation = Vector2.Zero;
367  for (var index = 0; index < input.PointerEvents.Count; ++index)
368  {
369  var pointerEvent = input.PointerEvents[index];
370 
371  if (pointerEvent.State != PointerState.Move)
372  {
373  aggregatedTranslation = Vector2.Zero;
374  compactedPointerEvents.Add(pointerEvent.Clone());
375  continue;
376  }
377 
378  aggregatedTranslation += pointerEvent.DeltaPosition;
379 
380  if (index + 1 >= input.PointerEvents.Count || input.PointerEvents[index + 1].State != PointerState.Move)
381  {
382  var compactedMoveEvent = pointerEvent.Clone();
383  compactedMoveEvent.DeltaPosition = aggregatedTranslation;
384  compactedPointerEvents.Add(compactedMoveEvent);
385  }
386  }
387 
388  var intersectionPoint = Vector3.Zero;
389  var lastTouchPosition = new Vector2(float.NegativeInfinity);
390 
391  // analyze pointer event input and trigger UI touch events depending on hit Tests
392  foreach (var pointerEvent in compactedPointerEvents)
393  {
394  // performance optimization: skip all the events that started outside of the UI
395  if(lastTouchedElement == null && pointerEvent.State != PointerState.Down)
396  continue;
397 
398  var time = gameTime.Total;
399  var currentTouchPosition = pointerEvent.Position;
400  var currentTouchedElement = lastTouchedElement;
401 
402  // re-calculate the element under cursor if click position changed.
403  if (lastTouchPosition != currentTouchPosition)
404  currentTouchedElement = GetElementFromPointerScreenPosition(currentTouchPosition, ref intersectionPoint);
405 
406  if (pointerEvent.State == PointerState.Down || pointerEvent.State == PointerState.Up)
407  lastIntersectionPoint = intersectionPoint;
408 
409  var touchEvent = new TouchEventArgs
410  {
411  Action = TouchAction.Down,
412  Timestamp = time,
413  ScreenPosition = currentTouchPosition,
414  ScreenTranslation = pointerEvent.DeltaPosition,
415  WorldPosition = intersectionPoint,
416  WorldTranslation = intersectionPoint - lastIntersectionPoint
417  };
418 
419  switch (pointerEvent.State)
420  {
421  case PointerState.Down:
422  touchEvent.Action = TouchAction.Down;
423  if (currentTouchedElement != null)
424  currentTouchedElement.RaiseTouchDownEvent(touchEvent);
425  break;
426 
427  case PointerState.Up:
428  touchEvent.Action = TouchAction.Up;
429 
430  // generate enter/leave events if we passed from an element to another without move events
431  if (currentTouchedElement != lastTouchedElement)
432  ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
433 
434  // trigger the up event
435  if (currentTouchedElement != null)
436  currentTouchedElement.RaiseTouchUpEvent(touchEvent);
437  break;
438 
439  case PointerState.Move:
440  touchEvent.Action = TouchAction.Move;
441 
442  // first notify the move event (even if the touched element changed in between it is still coherent in one of its parents)
443  if (currentTouchedElement != null)
444  currentTouchedElement.RaiseTouchMoveEvent(touchEvent);
445 
446  // then generate enter/leave events if we passed from an element to another
447  if (currentTouchedElement != lastTouchedElement)
448  ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
449  break;
450 
451  case PointerState.Out:
452  case PointerState.Cancel:
453  touchEvent.Action = TouchAction.Move;
454 
455  // generate enter/leave events if we passed from an element to another without move events
456  if (currentTouchedElement != lastTouchedElement)
457  ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
458 
459  // then raise leave event to all the hierarchy of the previously selected element.
460  var element = currentTouchedElement;
461  while (element != null)
462  {
463  if(element.IsTouched)
464  element.RaiseTouchLeaveEvent(touchEvent);
465  element = element.VisualParent;
466  }
467  break;
468  default:
469  throw new ArgumentOutOfRangeException();
470  }
471 
472  lastTouchedElement = currentTouchedElement;
473  lastTouchPosition = currentTouchPosition;
474  lastIntersectionPoint = intersectionPoint;
475  }
476 
477  // collect back pointer event not used anymore
478  lock (PointerEvent.Pool)
479  {
480  foreach (var pointerEvent in compactedPointerEvents)
481  PointerEvent.Pool.Enqueue(pointerEvent);
482  }
483  compactedPointerEvents.Clear();
484  }
485 
486  private UIElement FindCommonParent(UIElement element1, UIElement element2)
487  {
488  // build the list of the parents of the newly selected element
489  newlySelectedElementParents.Clear();
490  var newElementParent = element1;
491  while (newElementParent != null)
492  {
493  newlySelectedElementParents.Add(newElementParent);
494  newElementParent = newElementParent.VisualParent;
495  }
496 
497  // find the common element into the previously and newly selected element hierarchy
498  var commonElement = element2;
499  while (commonElement != null && !newlySelectedElementParents.Contains(commonElement))
500  commonElement = commonElement.VisualParent;
501 
502  return commonElement;
503  }
504 
505  private void ThrowEnterAndLeaveTouchEvents(UIElement currentElement, UIElement previousElement, TouchEventArgs touchEvent)
506  {
507  var commonElement = FindCommonParent(currentElement, previousElement);
508 
509  // raise leave events to the hierarchy: previousElt -> commonElementParent
510  var previousElementParent = previousElement;
511  while (previousElementParent != commonElement && previousElementParent != null)
512  {
513  if (previousElementParent.IsHierarchyEnabled && previousElementParent.IsTouched)
514  {
515  touchEvent.Handled = false; // reset 'handled' because it corresponds to another event
516  previousElementParent.RaiseTouchLeaveEvent(touchEvent);
517  }
518  previousElementParent = previousElementParent.VisualParent;
519  }
520 
521  // raise enter events to the hierarchy: newElt -> commonElementParent
522  var newElementParent = currentElement;
523  while (newElementParent != commonElement && newElementParent != null)
524  {
525  if (newElementParent.IsHierarchyEnabled && !newElementParent.IsTouched)
526  {
527  touchEvent.Handled = false; // reset 'handled' because it corresponds to another event
528  newElementParent.RaiseTouchEnterEvent(touchEvent);
529  }
530  newElementParent = newElementParent.VisualParent;
531  }
532  }
533  private UIElement GetElementFromPointerScreenPosition(Vector2 position, ref Vector3 intersectionPoint)
534  {
535  // calculate the ray corresponding to the click
536  var touchPosition = position - new Vector2(0.5f);
537  var rayDirectionView = Vector3.Normalize(new Vector3(touchPosition.X * uiFrustrumHeight * virtualResolution.X / virtualResolution.Y, touchPosition.Y * uiFrustrumHeight, -1));
538  var clickRay = new Ray(inverseViewMatrix.TranslationVector, Vector3.TransformNormal(rayDirectionView, inverseViewMatrix));
539 
540  // perform the hit test
541  UIElement clickedElement = null;
542  var smallestDepth = float.PositiveInfinity;
543  PerformRecursiveHitTest(rootElement, ref clickRay, ref clickedElement, ref intersectionPoint, ref smallestDepth);
544 
545  return clickedElement;
546  }
547 
548  private void PerformRecursiveHitTest(UIElement element, ref Ray ray, ref UIElement clickedElement, ref Vector3 intersectionPoint, ref float smallestDepth)
549  {
550  // if the element is not visible, we also remove all its children
551  if (!element.IsVisible)
552  return;
553 
554  if (element.ClipToBounds || element.CanBeHitByUser)
555  {
556  Vector3 intersection;
557  var intersect = element.Intersects(ref ray, out intersection);
558 
559  // don't perform the hit test on children if clipped and parent no hit
560  if (element.ClipToBounds && !intersect)
561  return;
562 
563  // Calculate the depth of the element with the depth bias so that hit test corresponds to visuals.
564  var depthInView = (intersection.Z - viewPositionZ);
565  var depthWithBias = (nearPlane * farPlane) / depthInView / (farPlane - nearPlane) - element.DepthBias * BatchBase<int>.DepthBiasShiftOneUnit;
566 
567  // update the closest element hit
568  if (element.CanBeHitByUser && intersect && depthWithBias < smallestDepth)
569  {
570  smallestDepth = depthWithBias;
571  intersectionPoint = intersection;
572  clickedElement = element;
573  }
574  }
575 
576  // render the children
577  foreach (var child in element.HitableChildren)
578  PerformRecursiveHitTest(child, ref ray, ref clickedElement, ref intersectionPoint, ref smallestDepth);
579  }
580  }
581 }
Provides a base class for all the User Interface elements in Paradox applications.
Definition: UIElement.cs:21
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
bool IsHierarchyEnabled
Gets the value indicating whether this element and all its upper hierarchy are enabled or not...
Definition: UIElement.cs:391
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
EventHandler< EventArgs > ResolutionChanged
Definition: UISystem.cs:61
Contains depth-stencil state for the device.
Interface providing services to deal with the virtual resolution of the game. The virtual resolution ...
Interface for the update of the UIElements.
RenderTarget BackBuffer
Gets the back buffer sets by the current Presenter setup on this device.
A utility class to batch and draw UI images.
Definition: UIBatch.cs:15
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
A service registry is a IServiceProvider that provides methods to register and unregister services...
PointerState
State of a pointer event.
Definition: PointerState.cs:8
override void Destroy()
Disposes of object resources.
Definition: UISystem.cs:135
Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. See The+GraphicsDevice+class to learn more about the class.
Base class for a GameSystemBase component.
static void TransformNormal(ref Vector3 normal, ref Matrix transform, out Vector3 result)
Performs a normal transformation using the given SiliconStudio.Core.Mathematics.Matrix.
Definition: Vector3.cs:1263
override void LoadContent()
Loads the assets.
Definition: UISystem.cs:158
int Width
Gets the width in texel.
Definition: RenderTarget.cs:23
Current timing used for variable-step (real time) or fixed-step (game time) games.
Definition: GameTime.cs:31
Interface for input management system, including keyboard, mouse, gamepads and touch.
Represents a three dimensional line based on a point in space and a direction.
Definition: Ray.cs:42
Interface of the UI system.
Definition: UISystem.cs:20
int Height
Gets the height in texel.
Definition: RenderTarget.cs:29
override void Update(GameTime gameTime)
This method is called when this game component is updated.
Definition: UISystem.cs:277
SiliconStudio.Core.Mathematics.Vector3 Vector3
Class holding all the data required to define an UI image.
Definition: UIImage.cs:15
override void Initialize()
This method is called when the component is added to the game.
Definition: UISystem.cs:118
KeyEventType
Used by KeyEvent
Definition: KeyEventType.cs:8
SiliconStudio.Core.Mathematics.RectangleF RectangleF
Definition: SpriteFont.cs:17
UISystem(IServiceRegistry registry)
Definition: UISystem.cs:104
Represent an edit text where the user can enter text.
Definition: EditText.cs:20
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47