diff --git a/engine/Definitions/tools/QtWidgets/DockManager.def b/engine/Definitions/tools/QtWidgets/DockManager.def
index 9339beb7..66987393 100644
--- a/engine/Definitions/tools/QtWidgets/DockManager.def
+++ b/engine/Definitions/tools/QtWidgets/DockManager.def
@@ -25,12 +25,6 @@ native class ads::CDockManager as Native.CDockManager : QWidget
ads::CDockManager::setConfigFlag( ads::CDockManager::OpaqueSplitterResize, true );
ads::CDockManager::setConfigFlag( ads::CDockManager::TabCloseButtonIsToolButton, true );
ads::CDockManager::setConfigFlag( ads::CDockManager::DisableStylesheet, true );
-
- // Dock containers host native render widgets (swapchains). Making dock/area/floating
- // windows native keeps the widget hierarchy natively parented, so floating and
- // re-docking doesn't destroy and recreate the render widget's window out from
- // under its swapchain.
- ads::CDockManager::setConfigFlag( ads::CDockManager::UseNativeWindows, true );
}
static CDockManager Create( QWidget parent ); [new]
diff --git a/engine/Definitions/tools/QtWidgets/QWidget.def b/engine/Definitions/tools/QtWidgets/QWidget.def
index 16322db7..7bdbd925 100644
--- a/engine/Definitions/tools/QtWidgets/QWidget.def
+++ b/engine/Definitions/tools/QtWidgets/QWidget.def
@@ -145,12 +145,6 @@ native class QWidget as Native.QWidget : QObject
QWidget parentWidget();
QWidget window();
- inline void setTransientParent( QWidget parent )
- {
- self->winId();
- parent->winId();
- self->windowHandle()->setTransientParent( parent->windowHandle() );
- }
void AddClassName( QString name );
void Polish();
diff --git a/engine/Sandbox.Tools/Editor/FullScreenManager.cs b/engine/Sandbox.Tools/Editor/FullScreenManager.cs
index e616e47f..dac526f0 100644
--- a/engine/Sandbox.Tools/Editor/FullScreenManager.cs
+++ b/engine/Sandbox.Tools/Editor/FullScreenManager.cs
@@ -27,24 +27,19 @@ internal partial class FullScreenManager
///
public void Clear()
{
- if ( Widget is null )
+ if ( !Widget.IsValid() )
return;
- EditorWindow.DockManager.Visible = true;
-
if ( EditorWindow.Console.IsValid() )
{
EditorWindow.Console.Input.FocusMode = FocusMode.TabOrClick;
}
- if ( Widget.IsValid() )
- {
- Widget.Parent = PreviousParent;
+ Widget.Parent = PreviousParent;
- if ( PreviousParent.IsValid() )
- {
- PreviousParent.Layout?.Add( Widget );
- }
+ if ( PreviousParent.IsValid() )
+ {
+ PreviousParent.Layout?.Add( Widget );
}
Widget = null;
@@ -54,15 +49,8 @@ internal partial class FullScreenManager
[EditorEvent.Frame]
public void OnFrame()
{
- if ( Widget is null )
- return;
-
- // If the widget died while fullscreen, restore the docks
if ( !Widget.IsValid() )
- {
- Clear();
return;
- }
if ( Widget.Size != GetTargetSize() || Widget.Position != GetTargetPosition() )
{
@@ -113,10 +101,6 @@ internal partial class FullScreenManager
// Set our target widget's parent to the editor's main window, so we can size it properly
widget.Parent = EditorWindow;
- // The docks are native windows, which always draw above sibling widget content,
- // so the fullscreen widget can't simply cover them - hide them while it's active
- EditorWindow.DockManager.Visible = false;
-
// Make sure we kill focus from the console
if ( EditorWindow.Console.IsValid() )
{
diff --git a/engine/Sandbox.Tools/Qt/SceneRenderingWidget.cs b/engine/Sandbox.Tools/Qt/SceneRenderingWidget.cs
index 58bd15ed..060728fe 100644
--- a/engine/Sandbox.Tools/Qt/SceneRenderingWidget.cs
+++ b/engine/Sandbox.Tools/Qt/SceneRenderingWidget.cs
@@ -12,9 +12,6 @@ public class SceneRenderingWidget : Frame
internal SwapChainHandle_t SwapChain;
- // A released swapchain is destroyed at frame end and owns our window until then
- private bool _destroyPending;
-
///
/// The active scene that we're rendering
///
@@ -39,10 +36,6 @@ public class SceneRenderingWidget : Frame
public SceneRenderingWidget( Widget parent = null ) : base( parent )
{
- // Keep ancestors non-native, otherwise every dock splitter above us becomes a
- // real HWND and resizes recurse through Win32 until stack overflow. Must be
- // set before WA_NativeWindow. See qtoolscenewidget.cpp for the full story.
- SetFlag( Flag.WA_DontCreateNativeAncestors, true );
SetFlag( Flag.WA_NativeWindow, true );
SetFlag( Flag.WA_PaintOnScreen, true );
SetFlag( Flag.WA_NoSystemBackground, true );
@@ -69,7 +62,10 @@ public class SceneRenderingWidget : Frame
All.Remove( this );
RenderSettings.Instance.OnVideoSettingsChanged -= HandleVideoChanged;
- ReleaseSwapChain();
+ // The swapchain might still be in use by native, so defer its destruction until the end of the frame.
+ // Otherwise, a race condition could occur where render targets are accessed after destruction, causing a delayed crash.
+ EngineLoop.DisposeAtFrameEnd( new Sandbox.Utility.DisposeAction( () => g_pRenderDevice.DestroySwapChain( SwapChain ) ) );
+ SwapChain = default;
GizmoInstance?.Dispose();
GizmoInstance = default;
@@ -162,43 +158,12 @@ public class SceneRenderingWidget : Frame
UpdateGizmoInputs( ref GizmoInstance.Input, camera, hasMouseFocus );
}
- // Qt destroys and recreates our native window when a dock reparents us into
- // another window - release the swapchain and Render will rebuild it against
- // the new handle.
- internal override void OnWinIdChanged()
- {
- ReleaseSwapChain();
- }
-
- void ReleaseSwapChain()
- {
- if ( SwapChain == default ) return;
-
- // The swapchain might still be in use by native, so defer its destruction until the end of the frame.
- // Otherwise, a race condition could occur where render targets are accessed after destruction, causing a delayed crash.
- var swapChain = SwapChain;
- _destroyPending = true;
- EngineLoop.DisposeAtFrameEnd( new Sandbox.Utility.DisposeAction( () =>
- {
- g_pRenderDevice.DestroySwapChain( swapChain );
- _destroyPending = false;
- } ) );
- SwapChain = default;
- }
-
void Render()
{
if ( !Scene.IsValid() ) return;
if ( !Visible ) return;
- if ( SwapChain == default )
- {
- // The retired swapchain still owns our window until it's destroyed at
- // frame end - creating a second one against it would fail, wait a frame.
- if ( _destroyPending ) return;
-
- SwapChain = WidgetUtil.CreateSwapChain( _widget, RenderSettings.Instance.AntiAliasQuality.ToEngine() );
- }
+ if ( SwapChain == default ) return;
using ( Scene.Push() )
{
@@ -280,10 +245,15 @@ public class SceneRenderingWidget : Frame
internal void HandleVideoChanged()
{
- // No swapchain right now - Render will create one with the current settings
- if ( SwapChain == default ) return;
+ var msaaAmount = RenderSettings.Instance.AntiAliasQuality.ToEngine();
- WidgetUtil.UpdateSwapChainMSAA( SwapChain, RenderSettings.Instance.AntiAliasQuality.ToEngine() );
+ if ( SwapChain == default )
+ {
+ SwapChain = WidgetUtil.CreateSwapChain( _widget, msaaAmount );
+ return;
+ }
+
+ WidgetUtil.UpdateSwapChainMSAA( SwapChain, msaaAmount );
}
internal static void RenderAll()
diff --git a/engine/Sandbox.Tools/Qt/Widget.cs b/engine/Sandbox.Tools/Qt/Widget.cs
index 99171707..ff95e600 100644
--- a/engine/Sandbox.Tools/Qt/Widget.cs
+++ b/engine/Sandbox.Tools/Qt/Widget.cs
@@ -1209,15 +1209,6 @@ namespace Editor
{
return QObject.FindOrCreate( _widget.window() ) as Widget;
}
-
- ///
- /// Keeps this window above its owner without making it globally topmost.
- ///
- public void SetTransientParent( Widget parent )
- {
- ArgumentNullException.ThrowIfNull( parent );
- _widget.setTransientParent( parent._widget );
- }
}
diff --git a/game/addons/tools/Code/Scene/SceneView/SceneOverlayWidget.cs b/game/addons/tools/Code/Scene/SceneView/SceneOverlayWidget.cs
index 42163cd6..b803bea7 100644
--- a/game/addons/tools/Code/Scene/SceneView/SceneOverlayWidget.cs
+++ b/game/addons/tools/Code/Scene/SceneView/SceneOverlayWidget.cs
@@ -12,7 +12,6 @@ public class SceneOverlayWidget : Widget
NoSystemBackground = true;
WindowFlags = WindowFlags.FramelessWindowHint | WindowFlags.Tool;
- SetTransientParent( EditorWindow );
Active = this;