// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. namespace FlaxEngine.GUI { /// /// Base class for container controls that can offset controls in a view (eg. scroll panels). /// /// [HideInEditor] public class ScrollableControl : ContainerControl { /// /// The view offset. Useful to offset contents of the container (used by the scrollbars and drop panels). /// protected Float2 _viewOffset; /// /// Gets current view offset for all the controls (used by the scroll bars). /// [HideInEditor, NoSerialize] public Float2 ViewOffset { get => _viewOffset; set => SetViewOffset(ref value); } /// /// Sets the view offset. /// /// The value. protected virtual void SetViewOffset(ref Float2 value) { _viewOffset = value; OnViewOffsetChanged(); } /// /// Called when view offset gets changed. /// protected virtual void OnViewOffsetChanged() { } /// protected override void DrawChildren() { // Draw all visible child controls bool hasViewOffset = !_viewOffset.IsZero; for (int i = 0; i < _children.Count; i++) { var child = _children[i]; if (child.Visible) { Matrix3x3 transform = child._cachedTransform; if (hasViewOffset && child.IsScrollable) { transform.M31 += _viewOffset.X; transform.M32 += _viewOffset.Y; } Render2D.PushTransform(ref transform); child.Draw(); Render2D.PopTransform(); } } } /// public override bool IntersectsChildContent(Control child, Float2 location, out Float2 childSpaceLocation) { // Apply offset on scrollable controls if (child.IsScrollable) location -= _viewOffset; return child.IntersectsContent(ref location, out childSpaceLocation); } /// public override bool IntersectsContent(ref Float2 locationParent, out Float2 location) { // Little workaround to prevent applying offset when performing intersection test with this scrollable control. // Note that overriden PointFromParent applies view offset. location = base.PointFromParent(ref locationParent); return ContainsPoint(ref location); } /// public override Float2 PointToParent(ref Float2 location) { return base.PointToParent(ref location) + _viewOffset; } /// public override Float2 PointFromParent(ref Float2 location) { return base.PointFromParent(ref location) - _viewOffset; } } }