// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
namespace FlaxEngine.GUI
{
///
/// GUI root control that is represented by a window or an canvas and can contain children but has no parent at all. It's a source of the input events.
///
public abstract class RootControl : ContainerControl
{
private static ContainerControl _gameRoot;
private static CanvasContainer _canvasContainer = new CanvasContainer();
///
/// Gets the main GUI control (it can be window or editor overriden control). Use it to plug-in custom GUI controls.
///
public static ContainerControl GameRoot
{
get => _gameRoot;
internal set
{
_gameRoot = value;
_canvasContainer.Parent = _gameRoot;
}
}
///
/// Gets the canvas controls root container.
///
internal static CanvasContainer CanvasRoot => _canvasContainer;
///
/// Gets or sets the current focused control
///
public abstract Control FocusedControl { get; set; }
///
/// Gets the tracking mouse offset.
///
public abstract Float2 TrackingMouseOffset { get; }
///
/// Gets or sets the position of the mouse in the window space coordinates.
///
public abstract Float2 MousePosition { get; set; }
///
/// The update callbacks collection. Controls can register for this to get the update event for logic handling.
///
public readonly List UpdateCallbacks = new List(1024);
///
/// The update callbacks to add before invoking the update.
///
public List UpdateCallbacksToAdd = new List();
///
/// The update callbacks to remove before invoking the update.
///
public List UpdateCallbacksToRemove = new List();
///
/// Initializes a new instance of the class.
///
protected RootControl()
: base(0, 0, 100, 60)
{
AutoFocus = false;
}
#region Navigation
///
/// The custom callback function for UI navigation. Can be used to override the default behaviour.
///
public Action CustomNavigation;
///
/// Performs the UI navigation.
///
/// The navigation direction.
public void Navigate(NavDirection direction)
{
if (direction == NavDirection.None)
return;
if (CustomNavigation != null)
{
// Custom
CustomNavigation.Invoke(direction);
return;
}
var focused = FocusedControl;
if (focused == null)
{
// Nothing is focused so go to the first control
focused = OnNavigate(direction, Float2.Zero, this, new List());
focused?.NavigationFocus();
return;
}
var target = focused.GetNavTarget(direction);
if (target != null)
{
// Explicitly specified focus target
target.NavigationFocus();
return;
}
// Automatic navigation routine
target = focused.OnNavigate(direction, focused.GetNavOrigin(direction), this, new List());
target?.NavigationFocus();
}
///
/// Submits the currently focused control.
///
public void SubmitFocused()
{
FocusedControl?.OnSubmit();
}
#endregion
///
public override void Update(float deltaTime)
{
base.Update(deltaTime);
// Flush requests
Profiler.BeginEvent("RootControl.SyncCallbacks");
for (int i = 0; i < UpdateCallbacksToAdd.Count; i++)
{
UpdateCallbacks.Add(UpdateCallbacksToAdd[i]);
}
UpdateCallbacksToAdd.Clear();
for (int i = 0; i < UpdateCallbacksToRemove.Count; i++)
{
UpdateCallbacks.Remove(UpdateCallbacksToRemove[i]);
}
UpdateCallbacksToRemove.Clear();
Profiler.EndEvent();
// Perform the UI update
try
{
Profiler.BeginEvent("RootControl.Update");
for (int i = 0; i < UpdateCallbacks.Count; i++)
{
UpdateCallbacks[i](deltaTime);
}
}
finally
{
Profiler.EndEvent();
}
}
///
/// Starts the mouse tracking. Used by the scrollbars, splitters, etc.
///
/// The target control that want to track mouse. It will receive OnMouseMove event.
/// If set to true will use mouse screen offset.
public abstract void StartTrackingMouse(Control control, bool useMouseScreenOffset);
///
/// Ends the mouse tracking.
///
public abstract void EndTrackingMouse();
///
/// Gets keyboard key state.
///
/// Key to check.
/// True while the user holds down the key identified by id.
public abstract bool GetKey(KeyboardKeys key);
///
/// Gets keyboard key down state.
///
/// Key to check.
/// True during the frame the user starts pressing down the key.
public abstract bool GetKeyDown(KeyboardKeys key);
///
/// Gets keyboard key up state.
///
/// Key to check.
/// True during the frame the user releases the button.
public abstract bool GetKeyUp(KeyboardKeys key);
///
/// Gets mouse button state.
///
/// Mouse button to check.
/// True while the user holds down the button.
public abstract bool GetMouseButton(MouseButton button);
///
/// Gets mouse button down state.
///
/// Mouse button to check.
/// True during the frame the user starts pressing down the button.
public abstract bool GetMouseButtonDown(MouseButton button);
///
/// Gets mouse button up state.
///
/// Mouse button to check.
/// True during the frame the user releases the button.
public abstract bool GetMouseButtonUp(MouseButton button);
///
public override RootControl Root => this;
}
}