Compare commits
9 Commits
3dd9612ae4
...
1682411bdb
| Author | SHA1 | Date | |
|---|---|---|---|
| 1682411bdb | |||
| ad91bd6164 | |||
| 1c595b759c | |||
| 61531a576c | |||
| 6015550b61 | |||
| 70c2bd272b | |||
| ca78ae1ccf | |||
| c22ae8fca7 | |||
| 61f04110a6 |
@@ -170,7 +170,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
|
||||
{
|
||||
// Create docking hint window but in an async manner
|
||||
DockHintWindow.Create(_panel as FloatWindowDockPanel);
|
||||
WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -181,7 +181,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
_panel.SelectTab(index - 1);
|
||||
|
||||
// Create docking hint window
|
||||
DockHintWindow.Create(win, _panel.RootWindow.Window);
|
||||
WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
return;
|
||||
|
||||
// Create docking hint window
|
||||
DockHintWindow.Create(this);
|
||||
WindowDragHelper.StartDragging(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,37 +9,36 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <summary>
|
||||
/// Helper class used to handle docking windows dragging and docking.
|
||||
/// </summary>
|
||||
public class DockHintWindow
|
||||
public class WindowDragHelper
|
||||
{
|
||||
private FloatWindowDockPanel _toMove;
|
||||
|
||||
private Float2 _dragOffset;
|
||||
private Float2 _defaultWindowSize;
|
||||
private Rectangle _rectDock;
|
||||
private Rectangle _rectWindow;
|
||||
private Float2 _mouse;
|
||||
private DockState _toSet;
|
||||
private DockPanel _toDock;
|
||||
private bool _lateDragOffsetUpdate;
|
||||
private float _lateDragStartTimer;
|
||||
private bool _moveWindow;
|
||||
private Window _dragSourceWindow;
|
||||
|
||||
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
|
||||
private Control _dockHintDown, _dockHintUp, _dockHintLeft, _dockHintRight, _dockHintCenter;
|
||||
|
||||
private DockHintWindow(FloatWindowDockPanel toMove, Window dragSourceWindow)
|
||||
/// <summary>
|
||||
/// The hint control size.
|
||||
/// </summary>
|
||||
public const float HintControlSize = 32.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The opacity of the dragged window when hint controls are shown.
|
||||
/// </summary>
|
||||
public const float DragWindowOpacity = 0.4f;
|
||||
|
||||
private WindowDragHelper(FloatWindowDockPanel toMove, Window dragSourceWindow)
|
||||
{
|
||||
_toMove = toMove;
|
||||
_toSet = DockState.Float;
|
||||
var window = toMove.Window.Window;
|
||||
|
||||
// Remove focus from drag target
|
||||
//_toMove.Focus();
|
||||
//_toMove.Defocus();
|
||||
|
||||
// Focus window
|
||||
//window.Focus();
|
||||
|
||||
// Check if window is maximized and restore window.
|
||||
if (window.IsMaximized)
|
||||
{
|
||||
@@ -50,50 +49,14 @@ namespace FlaxEditor.GUI.Docking
|
||||
window.Position = Platform.MousePosition - mousePos * window.Size / previousSize;
|
||||
}
|
||||
|
||||
// If the _toMove window was not focused when initializing this window, the result vector only contains zeros
|
||||
// and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler.
|
||||
//if (mouseScreenPosition != Float2.Zero)
|
||||
// CalculateDragOffset(mouseScreenPosition);
|
||||
//else
|
||||
// _lateDragOffsetUpdate = true;
|
||||
|
||||
|
||||
|
||||
// Get initial size
|
||||
_defaultWindowSize = window.Size;
|
||||
|
||||
// Init proxy window
|
||||
/*Proxy.Init(ref _defaultWindowSize);
|
||||
|
||||
// Bind events
|
||||
*/
|
||||
|
||||
//FlaxEngine.Input.MouseMove += OnMouseMove;
|
||||
FlaxEngine.Scripting.Update += OnUpdate;
|
||||
_toMove.Window.Window.MouseUp += OnMouseUp;
|
||||
/*
|
||||
Proxy.Window.MouseUp += OnMouseUp;
|
||||
Proxy.Window.MouseMove += OnMouseMove;
|
||||
Proxy.Window.LostFocus += OnLostFocus;
|
||||
_toMove.Window.Window.MouseUp += OnMouseUp; // Intercept the drag release mouse event from source window
|
||||
*/
|
||||
// Update window GUI
|
||||
//Proxy.Window.GUI.PerformLayout();
|
||||
window.MouseUp += OnMouseUp;
|
||||
|
||||
// Update rectangles
|
||||
UpdateRects();
|
||||
|
||||
// Enable hit window presentation
|
||||
/*Proxy.Window.RenderingEnabled = true;
|
||||
Proxy.Window.Show();
|
||||
Proxy.Window.Focus();*/
|
||||
|
||||
// Hide base window
|
||||
//window.Hide();
|
||||
|
||||
// window.Show();
|
||||
_dragSourceWindow = dragSourceWindow;
|
||||
_moveWindow = _dragSourceWindow != null;
|
||||
if (_dragSourceWindow != null) // Detaching a tab from existing window
|
||||
{
|
||||
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
|
||||
@@ -106,23 +69,12 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
else
|
||||
{
|
||||
var mouseClientPosition = Platform.MousePosition;
|
||||
CalculateDragOffset(mouseClientPosition);
|
||||
|
||||
window.DoDragDrop("", _dragOffset, window);
|
||||
}
|
||||
|
||||
// Ensure the dragged window stays on top of every other window
|
||||
//window.Show();
|
||||
//window.BringToFront();
|
||||
//window.Focus();
|
||||
//toMove.OnShow();
|
||||
|
||||
// Perform layout again
|
||||
//windowGUI.PerformLayout();
|
||||
|
||||
|
||||
// Start tracking mouse
|
||||
//Proxy.Window.StartTrackingMouse(false);
|
||||
window.IsAlwaysOnTop = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,48 +82,32 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// End tracking mouse
|
||||
/*Proxy.Window.EndTrackingMouse();
|
||||
|
||||
// Disable rendering
|
||||
Proxy.Window.RenderingEnabled = false;
|
||||
var window = _toMove?.Window?.Window;
|
||||
|
||||
// Unbind events
|
||||
Proxy.Window.MouseUp -= OnMouseUp;
|
||||
Proxy.Window.MouseMove -= OnMouseMove;
|
||||
Proxy.Window.LostFocus -= OnLostFocus;
|
||||
if (_toMove?.Window?.Window)
|
||||
_toMove.Window.Window.MouseUp -= OnMouseUp;
|
||||
|
||||
// Hide the proxy
|
||||
Proxy.Hide();*/
|
||||
FlaxEngine.Scripting.Update -= OnUpdate;
|
||||
if (window != null)
|
||||
window.MouseUp -= OnMouseUp;
|
||||
if (_dragSourceWindow != null)
|
||||
_dragSourceWindow.MouseUp -= OnMouseUp;
|
||||
|
||||
RemoveDockHints();
|
||||
|
||||
//FlaxEngine.Input.MouseMove -= OnMouseMove;
|
||||
FlaxEngine.Scripting.Update -= OnUpdate;
|
||||
if (_toMove?.Window?.Window)
|
||||
_toMove.Window.Window.MouseUp -= OnMouseUp;
|
||||
|
||||
if (_dragSourceWindow != null)
|
||||
_dragSourceWindow.MouseUp -= OnMouseUp; // The mouse up event is sent to the source window on Windows
|
||||
|
||||
if (_toMove == null)
|
||||
return;
|
||||
|
||||
if (_toMove.Window != null)
|
||||
_toMove.Window.Window.Opacity = 1.0f;
|
||||
if (window != null)
|
||||
{
|
||||
window.Opacity = 1.0f;
|
||||
window.IsAlwaysOnTop = false;
|
||||
window.BringToFront();
|
||||
}
|
||||
|
||||
// Check if window won't be docked
|
||||
if (_toSet == DockState.Float)
|
||||
{
|
||||
var window = _toMove.Window?.Window;
|
||||
if (window == null)
|
||||
return;
|
||||
var mouse = Platform.MousePosition;
|
||||
|
||||
// Move base window
|
||||
//window.Position = mouse - _dragOffset;
|
||||
|
||||
// Show base window
|
||||
window.Show();
|
||||
@@ -224,88 +160,38 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the new dragging hit window.
|
||||
/// Start dragging a floating dock panel.
|
||||
/// </summary>
|
||||
/// <param name="toMove">Floating dock panel to move.</param>
|
||||
/// <returns>The dock hint window object.</returns>
|
||||
public static DockHintWindow Create(FloatWindowDockPanel toMove)
|
||||
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove)
|
||||
{
|
||||
if (toMove == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
return new DockHintWindow(toMove, null);
|
||||
return new WindowDragHelper(toMove, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the new dragging hit window.
|
||||
/// Start dragging a docked panel into a floating window.
|
||||
/// </summary>
|
||||
/// <param name="toMove">Dock window to move.</param>
|
||||
/// <returns>The dock hint window object.</returns>
|
||||
public static DockHintWindow Create(DockWindow toMove, Window dragSourceWindow)
|
||||
public static WindowDragHelper StartDragging(DockWindow toMove, Window dragSourceWindow)
|
||||
{
|
||||
if (toMove == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
// Show floating
|
||||
// Create floating window
|
||||
toMove.CreateFloating();
|
||||
|
||||
// Move window to the mouse position (with some offset for caption bar)
|
||||
var window = (WindowRootControl)toMove.Root;
|
||||
/*var mouse = Platform.MousePosition;
|
||||
window.Window.Position = mouse - new Float2(8, 8);*/
|
||||
|
||||
// Get floating panel
|
||||
var window = (WindowRootControl)toMove.Root;
|
||||
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
|
||||
|
||||
return new DockHintWindow(floatingPanelToMove, dragSourceWindow);
|
||||
return new WindowDragHelper(floatingPanelToMove, dragSourceWindow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates window rectangle in the dock window.
|
||||
/// </summary>
|
||||
/// <param name="state">Window dock state.</param>
|
||||
/// <param name="rect">Dock panel rectangle.</param>
|
||||
/// <returns>Calculated window rectangle.</returns>
|
||||
public static Rectangle CalculateDockRect(DockState state, ref Rectangle rect)
|
||||
{
|
||||
Rectangle result = rect;
|
||||
switch (state)
|
||||
{
|
||||
case DockState.DockFill:
|
||||
result.Location.Y += DockPanel.DefaultHeaderHeight;
|
||||
result.Size.Y -= DockPanel.DefaultHeaderHeight;
|
||||
break;
|
||||
case DockState.DockTop:
|
||||
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
||||
break;
|
||||
case DockState.DockLeft:
|
||||
result.Size.X *= DockPanel.DefaultSplitterValue;
|
||||
break;
|
||||
case DockState.DockBottom:
|
||||
result.Location.Y += result.Size.Y * (1 - DockPanel.DefaultSplitterValue);
|
||||
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
||||
break;
|
||||
case DockState.DockRight:
|
||||
result.Location.X += result.Size.X * (1 - DockPanel.DefaultSplitterValue);
|
||||
result.Size.X *= DockPanel.DefaultSplitterValue;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CalculateDragOffset(Float2 mouseScreenPosition)
|
||||
{
|
||||
var baseWinPos = _toMove.Window.Window.Position;
|
||||
//_dragOffset = mouseScreenPosition - baseWinPos;
|
||||
|
||||
//Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
|
||||
}
|
||||
|
||||
DockHintControl _dockHintDown;
|
||||
DockHintControl _dockHintUp;
|
||||
DockHintControl _dockHintLeft;
|
||||
DockHintControl _dockHintRight;
|
||||
DockHintControl _dockHintCenter;
|
||||
private void AddDockHints()
|
||||
{
|
||||
if (_toDock == null)
|
||||
@@ -320,14 +206,15 @@ namespace FlaxEditor.GUI.Docking
|
||||
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
|
||||
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
|
||||
|
||||
DockHintControl AddHintControl(Float2 pivot)
|
||||
Control AddHintControl(Float2 pivot)
|
||||
{
|
||||
DockHintControl hintControl = _toDock.AddChild<DockHintControl>();
|
||||
hintControl.Size = new Float2(Proxy.HintWindowsSize);
|
||||
Control hintControl = _toDock.AddChild<Control>();
|
||||
hintControl.AnchorPreset = AnchorPresets.StretchAll;
|
||||
hintControl.Offsets = Margin.Zero;
|
||||
hintControl.Size = new Float2(HintControlSize);
|
||||
hintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
hintControl.Pivot = pivot;
|
||||
hintControl.PivotRelative = true;
|
||||
//.SetAnchorPreset(AnchorPresets.StretchAll, true);
|
||||
return hintControl;
|
||||
}
|
||||
}
|
||||
@@ -354,9 +241,8 @@ namespace FlaxEditor.GUI.Docking
|
||||
_mouse = Platform.MousePosition;
|
||||
|
||||
// Check intersection with any dock panel
|
||||
var uiMouse = _mouse;
|
||||
DockPanel dockPanel = null;
|
||||
if (_toMove.MasterPanel.HitTest(ref uiMouse, _toMove, out var hitResults))
|
||||
if (_toMove.MasterPanel.HitTest(ref _mouse, _toMove, out var hitResults))
|
||||
{
|
||||
dockPanel = hitResults[0];
|
||||
|
||||
@@ -392,17 +278,16 @@ namespace FlaxEditor.GUI.Docking
|
||||
|
||||
// Make sure the all the dock hint areas are not under other windows
|
||||
_toDock?.RootWindow.Window.BringToFront();
|
||||
//_toMove.RootWindow.Window.BringToFront(); // Doesn't work on X11
|
||||
|
||||
// Make the dragged window transparent when dock hints are visible
|
||||
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : 0.4f;
|
||||
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
|
||||
}
|
||||
|
||||
// Check dock state to use
|
||||
bool showProxyHints = _toDock != null;
|
||||
bool showBorderHints = showProxyHints;
|
||||
bool showCenterHint = showProxyHints;
|
||||
DockHintControl hoveredHintControl = null;
|
||||
Control hoveredHintControl = null;
|
||||
Float2 hoveredSizeOverride = Float2.Zero;
|
||||
if (showProxyHints)
|
||||
{
|
||||
@@ -421,9 +306,9 @@ namespace FlaxEditor.GUI.Docking
|
||||
var size = _rectDock.Size / Platform.DpiScale;
|
||||
var offset = _toDock.PointFromScreen(_rectDock.Location);
|
||||
var borderMargin = 4.0f;
|
||||
var hintWindowsSize = Proxy.HintWindowsSize;
|
||||
var hintWindowsSize = HintControlSize;
|
||||
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
||||
var hintPreviewSize = new Float2(Math.Max(Proxy.HintWindowsSize * 2, size.X * 0.5f), Math.Max(Proxy.HintWindowsSize * 2, size.Y * 0.5f));
|
||||
var hintPreviewSize = new Float2(Math.Max(HintControlSize * 2, size.X * 0.5f), Math.Max(HintControlSize * 2, size.Y * 0.5f));
|
||||
var centerX = size.X * 0.5f;
|
||||
var centerY = size.Y * 0.5f;
|
||||
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||
@@ -432,7 +317,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||
|
||||
// Hit test
|
||||
// Hit test, and calculate the approximation for filled area when hovered over the hint
|
||||
DockState toSet = DockState.Float;
|
||||
if (showBorderHints)
|
||||
{
|
||||
@@ -468,9 +353,6 @@ namespace FlaxEditor.GUI.Docking
|
||||
hoveredSizeOverride = new Float2(size.X, size.Y);
|
||||
}
|
||||
|
||||
//if (toSet != DockState.Float)
|
||||
|
||||
|
||||
_toSet = toSet;
|
||||
}
|
||||
else
|
||||
@@ -478,52 +360,37 @@ namespace FlaxEditor.GUI.Docking
|
||||
_toSet = DockState.Float;
|
||||
}
|
||||
|
||||
Editor.Log($"docking: {_toSet}, pos: {_mouse}");
|
||||
|
||||
// Calculate proxy/dock/window rectangles
|
||||
if (_toDock == null)
|
||||
{
|
||||
// Floating window over nothing
|
||||
//_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||
if (hoveredHintControl != null)
|
||||
hoveredHintControl.BackgroundColor = Color.Green;
|
||||
}
|
||||
else
|
||||
// Update sizes and opacity of hint controls
|
||||
if (_toDock != null)
|
||||
{
|
||||
if (hoveredHintControl != _dockHintDown)
|
||||
{
|
||||
_dockHintDown.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintDown.Size = new Float2(HintControlSize);
|
||||
_dockHintDown.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintLeft)
|
||||
{
|
||||
_dockHintLeft.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintLeft.Size = new Float2(HintControlSize);
|
||||
_dockHintLeft.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintRight)
|
||||
{
|
||||
_dockHintRight.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintRight.Size = new Float2(HintControlSize);
|
||||
_dockHintRight.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintUp)
|
||||
{
|
||||
_dockHintUp.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintUp.Size = new Float2(HintControlSize);
|
||||
_dockHintUp.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintCenter)
|
||||
{
|
||||
_dockHintCenter.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintCenter.Size = new Float2(HintControlSize);
|
||||
_dockHintCenter.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (_toSet == DockState.Float)
|
||||
|
||||
if (_toSet != DockState.Float)
|
||||
{
|
||||
// Floating window over dock panel
|
||||
if (hoveredHintControl != null)
|
||||
hoveredHintControl.BackgroundColor = Color.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use only part of the dock panel to show hint
|
||||
if (hoveredHintControl != null)
|
||||
{
|
||||
hoveredHintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(1.0f);
|
||||
@@ -532,6 +399,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
}
|
||||
|
||||
// Update hint controls visibility and location
|
||||
if (showProxyHints)
|
||||
{
|
||||
if (hoveredHintControl != _dockHintDown)
|
||||
@@ -545,226 +413,33 @@ namespace FlaxEditor.GUI.Docking
|
||||
if (hoveredHintControl != _dockHintCenter)
|
||||
_dockHintCenter.Location = _rCenter.Location;
|
||||
|
||||
// Update proxy hint windows visibility
|
||||
_dockHintDown.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintLeft.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintRight.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintUp.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintCenter.Visible = showProxyHints & showCenterHint;
|
||||
}
|
||||
|
||||
// Update proxy window
|
||||
//Proxy.Window.ClientBounds = _rectWindow;
|
||||
}
|
||||
|
||||
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
||||
{
|
||||
Editor.Log("DockHintWindow.OnMouseUp");
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUpdate()
|
||||
{
|
||||
//Editor.Log("OnUpdate");
|
||||
var mousePos = Platform.MousePosition;
|
||||
if (_mouse != mousePos)
|
||||
{
|
||||
//Editor.Log($"mouse pos {_mouse} -> {mousePos}");
|
||||
OnMouseMove(mousePos);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseMove(Float2 mousePos)
|
||||
{
|
||||
if (_moveWindow)
|
||||
{
|
||||
if (_dragSourceWindow != null)
|
||||
_toMove.Window.Window.Position = mousePos - _dragOffset;
|
||||
}
|
||||
//Editor.Log("OnMouseMove");
|
||||
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
|
||||
if (_lateDragOffsetUpdate)
|
||||
{
|
||||
// Calculate dragging offset and move window to the destination position
|
||||
CalculateDragOffset(mousePos);
|
||||
|
||||
// Reset state
|
||||
_lateDragOffsetUpdate = false;
|
||||
}
|
||||
|
||||
UpdateRects();
|
||||
}
|
||||
|
||||
private void OnLostFocus()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public class DockHintControl : Control
|
||||
{
|
||||
public DockHintControl()
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll;
|
||||
Offsets = Margin.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
|
||||
/// </summary>
|
||||
public static class Proxy
|
||||
{
|
||||
/// <summary>
|
||||
/// The drag proxy window.
|
||||
/// </summary>
|
||||
public static Window Window;
|
||||
|
||||
/// <summary>
|
||||
/// The left hint proxy window.
|
||||
/// </summary>
|
||||
public static Window Left;
|
||||
|
||||
/// <summary>
|
||||
/// The right hint proxy window.
|
||||
/// </summary>
|
||||
public static Window Right;
|
||||
|
||||
/// <summary>
|
||||
/// The up hint proxy window.
|
||||
/// </summary>
|
||||
public static Window Up;
|
||||
|
||||
/// <summary>
|
||||
/// The down hint proxy window.
|
||||
/// </summary>
|
||||
public static Window Down;
|
||||
|
||||
/// <summary>
|
||||
/// The center hint proxy window.
|
||||
/// </summary>
|
||||
public static Window Center;
|
||||
|
||||
/// <summary>
|
||||
/// The hint windows size.
|
||||
/// </summary>
|
||||
public const float HintWindowsSize = 32.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the hit proxy windows. Those windows are used to indicate drag target areas (left, right, top, bottom, etc.).
|
||||
/// </summary>
|
||||
public static void InitHitProxy()
|
||||
{
|
||||
CreateProxy(ref Left, "DockHint.Left");
|
||||
CreateProxy(ref Right, "DockHint.Right");
|
||||
CreateProxy(ref Up, "DockHint.Up");
|
||||
CreateProxy(ref Down, "DockHint.Down");
|
||||
CreateProxy(ref Center, "DockHint.Center");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the hint window.
|
||||
/// </summary>
|
||||
/// <param name="initSize">Initial size of the proxy window.</param>
|
||||
public static void Init(ref Float2 initSize)
|
||||
{
|
||||
if (Window == null)
|
||||
{
|
||||
var settings = CreateWindowSettings.Default;
|
||||
settings.Title = "DockHint.Window";
|
||||
settings.Size = initSize;
|
||||
settings.AllowInput = true;
|
||||
settings.AllowMaximize = false;
|
||||
settings.AllowMinimize = false;
|
||||
settings.HasBorder = false;
|
||||
settings.HasSizingFrame = false;
|
||||
settings.Type = WindowType.Utility;
|
||||
settings.SupportsTransparency = true;
|
||||
settings.ShowInTaskbar = false;
|
||||
settings.ShowAfterFirstPaint = false;
|
||||
settings.IsTopmost = true;
|
||||
|
||||
Window = Platform.CreateWindow(ref settings);
|
||||
Window.Opacity = 0.6f;
|
||||
Window.GUI.BackgroundColor = Style.Current.DragWindow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resize proxy
|
||||
Window.ClientSize = initSize;
|
||||
}
|
||||
|
||||
InitHitProxy();
|
||||
}
|
||||
|
||||
private static void CreateProxy(ref Window win, string name)
|
||||
{
|
||||
if (win != null)
|
||||
return;
|
||||
|
||||
var settings = CreateWindowSettings.Default;
|
||||
settings.Title = name;
|
||||
settings.Size = new Float2(HintWindowsSize * Platform.DpiScale);
|
||||
settings.AllowInput = false;
|
||||
settings.AllowMaximize = false;
|
||||
settings.AllowMinimize = false;
|
||||
settings.HasBorder = false;
|
||||
settings.HasSizingFrame = false;
|
||||
settings.Type = WindowType.Utility;
|
||||
settings.SupportsTransparency = true;
|
||||
settings.ShowInTaskbar = false;
|
||||
settings.ActivateWhenFirstShown = false;
|
||||
settings.IsTopmost = true;
|
||||
settings.ShowAfterFirstPaint = false;
|
||||
|
||||
win = Platform.CreateWindow(ref settings);
|
||||
win.Opacity = 0.6f;
|
||||
win.GUI.BackgroundColor = Style.Current.DragWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides proxy windows.
|
||||
/// </summary>
|
||||
public static void Hide()
|
||||
{
|
||||
HideProxy(ref Window);
|
||||
HideProxy(ref Left);
|
||||
HideProxy(ref Right);
|
||||
HideProxy(ref Up);
|
||||
HideProxy(ref Down);
|
||||
HideProxy(ref Center);
|
||||
}
|
||||
|
||||
private static void HideProxy(ref Window win)
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
win.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases proxy data and windows.
|
||||
/// </summary>
|
||||
public static void Dispose()
|
||||
{
|
||||
DisposeProxy(ref Window);
|
||||
DisposeProxy(ref Left);
|
||||
DisposeProxy(ref Right);
|
||||
DisposeProxy(ref Up);
|
||||
DisposeProxy(ref Down);
|
||||
DisposeProxy(ref Center);
|
||||
}
|
||||
|
||||
private static void DisposeProxy(ref Window win)
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
win.Close(ClosingReason.User);
|
||||
win = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ using FlaxEditor.Windows;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Json;
|
||||
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
|
||||
using WindowDragHelper = FlaxEditor.GUI.Docking.WindowDragHelper;
|
||||
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
|
||||
using FlaxEditor.Content.Settings;
|
||||
using FlaxEditor.Options;
|
||||
@@ -456,13 +456,6 @@ namespace FlaxEditor.Modules
|
||||
UpdateToolstrip();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnExit()
|
||||
{
|
||||
// Cleanup dock panel hint proxy windows (Flax will destroy them by var but it's better to clear them earlier)
|
||||
DockHintWindow.Proxy.Dispose();
|
||||
}
|
||||
|
||||
private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing)
|
||||
{
|
||||
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);
|
||||
|
||||
@@ -164,6 +164,15 @@ void WindowBase::SetIsVisible(bool isVisible)
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowBase::IsAlwaysOnTop() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void WindowBase::SetIsAlwaysOnTop(bool isAlwaysOnTop)
|
||||
{
|
||||
}
|
||||
|
||||
String WindowBase::ToString() const
|
||||
{
|
||||
return GetTitle();
|
||||
|
||||
@@ -157,6 +157,17 @@ public:
|
||||
return _maximized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether a window is always on top of other windows.
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual bool IsAlwaysOnTop() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value that indicates whether a window is always on top of other windows.
|
||||
/// </summary>
|
||||
/// <param name="isAlwaysOnTop">True if always on top.</param>
|
||||
API_PROPERTY() virtual void SetIsAlwaysOnTop(bool isAlwaysOnTop);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the native window handle.
|
||||
/// </summary>
|
||||
|
||||
@@ -514,12 +514,6 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
else
|
||||
{
|
||||
const Float2 mousePos = window->ClientToScreen({ event.motion.x, event.motion.y });
|
||||
Int2 p;
|
||||
Float2 wp = window->ClientToScreen({0, 0});
|
||||
//SDL_GetWindowPosition(window->GetSDLWindow(), &p.X, &p.Y);
|
||||
p.X = wp.X;
|
||||
p.Y = wp.Y;
|
||||
//LOG(Info, "motion {},{}, mouse: {}, win: {}, winpos {},{}", event.motion.x, event.motion.y, mousePos, String(window->GetTitle()), p.X, p.Y);
|
||||
Input::Mouse->OnMouseMove(mousePos, window);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -77,21 +77,24 @@ bool SDLPlatform::Init()
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0");
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0"); //
|
||||
SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "8"); // Reduce the default mouse double-click radius
|
||||
|
||||
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1");
|
||||
|
||||
SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "1");
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
// Disable SDL clipboard support
|
||||
/*SDL_SetEventEnabled(SDL_EVENT_CLIPBOARD_UPDATE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_CLIPBOARD_UPDATE, false);
|
||||
|
||||
// Disable SDL drag and drop support
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_BEGIN, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_COMPLETE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_POSITION, false);*/
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_POSITION, false);
|
||||
#endif
|
||||
|
||||
//if (InitPlatform())
|
||||
// return true;
|
||||
@@ -217,9 +220,15 @@ void SDLPlatform::Tick()
|
||||
if (draggedWindow == nullptr)
|
||||
return true;
|
||||
|
||||
// When the window is being dragged on Windows, the internal message loop is blocking
|
||||
// the SDL event queue. We need to handle all relevant events in this event watch callback
|
||||
// to ensure dragging related functionality doesn't break due to engine not getting updated.
|
||||
// This also happens to fix the engine freezing during the dragging operation.
|
||||
|
||||
SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
|
||||
if (event->type == SDL_EVENT_WINDOW_EXPOSED)
|
||||
{
|
||||
// The internal timer is sending exposed events every ~16ms
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();
|
||||
return false;
|
||||
@@ -304,11 +313,6 @@ void SDLPlatform::Tick()
|
||||
buttonUpEvent.motion.x = mousePosition.X;
|
||||
buttonUpEvent.motion.y = mousePosition.Y;
|
||||
draggedWindow->HandleEvent(buttonUpEvent);
|
||||
//SDL_PushEvent(&buttonUpEvent);
|
||||
|
||||
SDL_SetWindowAlwaysOnTop(draggedWindow->GetSDLWindow(), false);
|
||||
draggedWindow->BringToFront();
|
||||
|
||||
draggedWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,11 @@ void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& pos
|
||||
Int2 GetSDLWindowScreenPosition(const SDLWindow* window);
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y);
|
||||
|
||||
bool IsPopupWindow(WindowType type)
|
||||
{
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
class SDLDropFilesData : public IGuiData
|
||||
{
|
||||
public:
|
||||
@@ -823,9 +828,9 @@ void SDLWindow::Show()
|
||||
else if (_settings.Parent == nullptr)
|
||||
BringToFront();
|
||||
|
||||
// Reused top-most windows (DockHintWindow) doesn't stay on top for some reason
|
||||
if (_settings.IsTopmost && _settings.Type != WindowType::Tooltip)
|
||||
SDL_SetWindowAlwaysOnTop(_window, true);
|
||||
// Reused top-most windows doesn't stay on top for some reason
|
||||
if (_settings.IsTopmost && !IsPopupWindow(_settings.Type))
|
||||
SetIsAlwaysOnTop(true);
|
||||
|
||||
if (_isTrackingMouse)
|
||||
{
|
||||
@@ -980,11 +985,6 @@ void SDLWindow::SetClientBounds(const Rectangle& clientArea)
|
||||
SDL_SetWindowSize(_window, newW, newH);
|
||||
}
|
||||
|
||||
bool IsPopupWindow(WindowType type)
|
||||
{
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset)
|
||||
{
|
||||
if (!IsPopupWindow(type))
|
||||
@@ -1051,12 +1051,25 @@ void SDLWindow::SetIsFullscreen(bool isFullscreen)
|
||||
if (!isFullscreen)
|
||||
{
|
||||
// The window is set to always-on-top for some reason when leaving fullscreen
|
||||
SDL_SetWindowAlwaysOnTop(_window, false);
|
||||
SetIsAlwaysOnTop(false);
|
||||
}
|
||||
|
||||
WindowBase::SetIsFullscreen(isFullscreen);
|
||||
}
|
||||
|
||||
bool SDLWindow::IsAlwaysOnTop() const
|
||||
{
|
||||
SDL_WindowFlags flags = SDL_GetWindowFlags(_window);
|
||||
return (flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0;
|
||||
}
|
||||
|
||||
void SDLWindow::SetIsAlwaysOnTop(bool isAlwaysOnTop)
|
||||
{
|
||||
if (!SDL_SetWindowAlwaysOnTop(_window, isAlwaysOnTop))
|
||||
LOG(Warning, "SDL_SetWindowAlwaysOnTop failed: {0}", String(SDL_GetError()));
|
||||
// Not sure if this should change _settings.IsTopmost to reflect the new value?
|
||||
}
|
||||
|
||||
Float2 SDLWindow::GetPosition() const
|
||||
{
|
||||
Int2 topLeftBorder;
|
||||
@@ -1332,7 +1345,6 @@ DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offse
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SDL_SetWindowAlwaysOnTop(_window, true);
|
||||
Show();
|
||||
|
||||
//draggingActive = true;
|
||||
|
||||
@@ -91,6 +91,8 @@ public:
|
||||
void SetPosition(const Float2& position) override;
|
||||
void SetClientPosition(const Float2& position) override;
|
||||
void SetIsFullscreen(bool isFullscreen) override;
|
||||
bool IsAlwaysOnTop() const override;
|
||||
void SetIsAlwaysOnTop(bool isAlwaysOnTop) override;
|
||||
Float2 GetPosition() const override;
|
||||
Float2 GetSize() const override;
|
||||
Float2 GetClientSize() const override;
|
||||
|
||||
@@ -601,7 +601,8 @@ DragDropEffect Window::DoDragDrop(const StringView& data)
|
||||
::POINT point;
|
||||
::GetCursorPos(&point);
|
||||
#if PLATFORM_SDL
|
||||
Input::Mouse->OnMouseUp(Float2((float)point.x, (float)point.y), MouseButton::Left, (Window*)this);
|
||||
// Reset the internal button state in SDL
|
||||
SendMessageA((HWND)_handle, WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y));
|
||||
#else
|
||||
Input::Mouse->OnMouseUp(Float2((float)point.x, (float)point.y), MouseButton::Left, this);
|
||||
#endif
|
||||
|
||||
BIN
Source/Platforms/Windows/Binaries/ThirdParty/x64/SDL3.lib
(Stored with Git LFS)
vendored
BIN
Source/Platforms/Windows/Binaries/ThirdParty/x64/SDL3.lib
(Stored with Git LFS)
vendored
Binary file not shown.
@@ -88,7 +88,8 @@ namespace Flax.Deps.Dependencies
|
||||
Path.Combine(root, "include", "SDL3"),
|
||||
};
|
||||
|
||||
CloneGitRepoFastSince(root, "https://github.com/libsdl-org/SDL", new DateTime(2025, 01, 19));
|
||||
CloneGitRepoFast(root, "https://github.com/libsdl-org/SDL");
|
||||
GitFetch(root);
|
||||
GitResetToCommit(root, "819628c6bf8e6c3e5357d7ee4bd2d3d43ddfe052");
|
||||
|
||||
foreach (var platform in options.Platforms)
|
||||
|
||||
@@ -131,6 +131,18 @@ namespace Flax.Deps
|
||||
Utilities.DirectoryCopy(src, dst);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if git repository exists at given path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
public static bool GitRepositoryExists(string path)
|
||||
{
|
||||
Console.WriteLine(path);
|
||||
string dotGitPath = Path.Combine(path, ".git");
|
||||
return Directory.Exists(dotGitPath) ||
|
||||
File.Exists(dotGitPath); // Worktree repository
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones the git repository from the remote url (full repository).
|
||||
/// </summary>
|
||||
@@ -141,7 +153,7 @@ namespace Flax.Deps
|
||||
/// <param name="submodules">True if initialize submodules of the repository (recursive).</param>
|
||||
public static void CloneGitRepo(string path, string url, string commit = null, string args = null, bool submodules = false)
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(path, ".git")))
|
||||
if (!GitRepositoryExists(path))
|
||||
{
|
||||
string cmdLine = string.Format("clone \"{0}\" \"{1}\"", url, path);
|
||||
if (args != null)
|
||||
@@ -166,7 +178,7 @@ namespace Flax.Deps
|
||||
/// <param name="submodules">True if initialize submodules of the repository (recursive).</param>
|
||||
public static void CloneGitRepoFast(string path, string url, string args = null, bool submodules = false)
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(path, ".git")))
|
||||
if (!GitRepositoryExists(path))
|
||||
{
|
||||
string cmdLine = string.Format("clone \"{0}\" \"{1}\" --depth 1", url, path);
|
||||
if (args != null)
|
||||
@@ -181,26 +193,15 @@ namespace Flax.Deps
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones the git repository from the remote url.
|
||||
/// Fetches the git repository from remote url.
|
||||
/// </summary>
|
||||
/// <param name="path">The local path for close.</param>
|
||||
/// <param name="url">The remote url.</param>
|
||||
/// <param name="time">The time after history is included in the local repository.</param>
|
||||
/// <param name="args">The custom arguments to add to the clone command.</param>
|
||||
/// <param name="submodules">True if initialize submodules of the repository (recursive).</param>
|
||||
public static void CloneGitRepoFastSince(string path, string url, DateTime time, string args = null, bool submodules = false)
|
||||
/// <param name="path">The git repository path</param>
|
||||
/// <param name="url">The remote url</param>
|
||||
public static void GitFetch(string path)
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(path, ".git")))
|
||||
if (GitRepositoryExists(path))
|
||||
{
|
||||
string cmdLine = string.Format("clone \"{0}\" \"{1}\" --shallow-since={2}", url, path, time.ToString("s"));
|
||||
if (args != null)
|
||||
cmdLine += " " + args;
|
||||
if (submodules)
|
||||
cmdLine += " --recurse-submodules";
|
||||
|
||||
Utilities.Run("git", cmdLine, null, path, Utilities.RunOptions.DefaultTool);
|
||||
if (submodules)
|
||||
Utilities.Run("git", "submodule update --init --recursive", null, path, Utilities.RunOptions.DefaultTool);
|
||||
Utilities.Run("git", $"fetch \"{path}\"", null, path, Utilities.RunOptions.DefaultTool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +216,7 @@ namespace Flax.Deps
|
||||
/// <param name="submodules">True if initialize submodules of the repository (recursive).</param>
|
||||
public static void CloneGitRepoSingleBranch(string path, string url, string branch, string commit = null, string args = null, bool submodules = false)
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(path, ".git")))
|
||||
if (!GitRepositoryExists(path))
|
||||
{
|
||||
string cmdLine = string.Format("clone --single-branch --branch {2} \"{0}\" \"{1}\"", url, path, branch);
|
||||
if (commit == null)
|
||||
|
||||
Reference in New Issue
Block a user