mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-08-02 08:50:18 -04:00
Unfuck rendering widget (#5362)
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -27,24 +27,19 @@ internal partial class FullScreenManager
|
||||
/// </summary>
|
||||
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() )
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// The active scene that we're rendering
|
||||
/// </summary>
|
||||
@@ -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()
|
||||
|
||||
@@ -1209,15 +1209,6 @@ namespace Editor
|
||||
{
|
||||
return QObject.FindOrCreate( _widget.window() ) as Widget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keeps this window above its owner without making it globally topmost.
|
||||
/// </summary>
|
||||
public void SetTransientParent( Widget parent )
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull( parent );
|
||||
_widget.setTransientParent( parent._widget );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ public class SceneOverlayWidget : Widget
|
||||
NoSystemBackground = true;
|
||||
|
||||
WindowFlags = WindowFlags.FramelessWindowHint | WindowFlags.Tool;
|
||||
SetTransientParent( EditorWindow );
|
||||
|
||||
Active = this;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user