Merge remote-tracking branch 'origin/master' into 1.13

# Conflicts:
#	Source/Engine/Graphics/Materials/DeformableMaterialShader.h
#	Source/Engine/Platform/Windows/WindowsWindow.cpp
#	Source/Engine/Platform/Windows/WindowsWindow.h
This commit is contained in:
2026-08-08 06:40:11 +02:00
26 changed files with 241 additions and 52 deletions
@@ -1,10 +1,12 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.Content.Settings;
using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEngine;
using System.Collections.Generic;
using System.Linq;
namespace FlaxEditor.CustomEditors.Editors
{
@@ -13,7 +15,11 @@ namespace FlaxEditor.CustomEditors.Editors
/// </summary>
public sealed class ActorLayerEditor : CustomEditor
{
private const string AddOrEditLayersOption = "Add or Edit Layers...";
private ComboBoxElement element;
private int _layerCount;
private bool _updatingItems;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
@@ -22,14 +28,63 @@ namespace FlaxEditor.CustomEditors.Editors
public override void Initialize(LayoutElementsContainer layout)
{
element = layout.ComboBox();
element.ComboBox.SetItems(LayersAndTagsSettings.GetCurrentLayers());
element.ComboBox.SelectedIndex = (int)Values[0];
UpdateLayerItems((int)Values[0]);
element.ComboBox.PopupShowing += OnPopupShowing;
element.ComboBox.PopupShown += OnPopupShown;
element.ComboBox.SelectedIndexChanged += OnSelectedIndexChanged;
}
private void OnPopupShowing(ComboBox comboBox)
{
UpdateLayerItems(HasDifferentValues ? -1 : (int)Values[0]);
}
private void OnPopupShown(ComboBox comboBox)
{
var addOrEditLayersOption = (ContextMenuButton)comboBox.Popup.Items.FirstOrDefault(x => x is FlaxEditor.GUI.ContextMenu.ContextMenuButton b && b.Text == AddOrEditLayersOption);
addOrEditLayersOption?.Icon = Editor.Instance.Icons.Settings12;
}
private void UpdateLayerItems(int selectedIndex)
{
_updatingItems = true;
var layers = LayersAndTagsSettings.GetCurrentLayers();
_layerCount = layers.Length;
element.ComboBox.SetItems(layers);
element.ComboBox.AddItem(AddOrEditLayersOption);
element.ComboBox.SelectedIndex = selectedIndex >= 0 && selectedIndex < _layerCount ? selectedIndex : -1;
_updatingItems = false;
}
private void SelectCurrentLayer()
{
UpdateLayerItems(HasDifferentValues ? -1 : (int)Values[0]);
}
private void OpenLayersAndTagsSettings()
{
var asset = GameSettings.LoadAsset<LayersAndTagsSettings>();
if (!asset)
{
GameSettings.Save(new LayersAndTagsSettings());
asset = GameSettings.LoadAsset<LayersAndTagsSettings>();
}
if (asset)
Editor.Instance.ContentEditing.Open(asset);
}
private void OnSelectedIndexChanged(ComboBox comboBox)
{
if (_updatingItems)
return;
int value = comboBox.SelectedIndex;
if (value == _layerCount)
{
OpenLayersAndTagsSettings();
SelectCurrentLayer();
return;
}
if (value == -1)
value = 0;
@@ -87,7 +142,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
element.ComboBox.SelectedIndex = (int)Values[0];
UpdateLayerItems((int)Values[0]);
}
}
}
@@ -271,6 +271,11 @@ namespace FlaxEditor.CustomEditors.Editors
for (int i = 0; i < properties.Length; i++)
{
var p = properties[i];
// Indexed properties require arguments and cannot be represented by a normal property row (eg. IList.Item[index])
if (p.Type is PropertyInfo managedProperty && managedProperty.GetIndexParameters().Length != 0)
continue;
var attributes = p.GetAttributes(true);
var showInEditor = attributes.Any(x => x is ShowInEditorAttribute);
+7
View File
@@ -172,6 +172,11 @@ namespace FlaxEditor.GUI
/// </summary>
public event Action<ComboBox> PopupShowing;
/// <summary>
/// Occurs when popup is shown (after event). Can be used to customize item controls collection after creation.
/// </summary>
public event Action<ComboBox> PopupShown;
/// <summary>
/// Custom popup creation function.
/// </summary>
@@ -435,6 +440,8 @@ namespace FlaxEditor.GUI
var position = _popupMenu.RootWindow.Window.Position;
_popupMenu.RootWindow.Window.Position = new Float2(position.X, position.Y - Height);
}
PopupShown?.Invoke(this);
}
}
@@ -299,7 +299,9 @@ namespace FlaxEditor.GUI.ContextMenu
PerformLayout();
if (UseVisibilityControl)
{
#if !PLATFORM_SDL
_previouslyFocused = parentWin.FocusedControl;
#endif
Focus();
OnShow();
}
@@ -287,6 +287,7 @@ namespace FlaxEditor.Modules
case Options.InterfaceOptions.PlayModeFocus.None: break;
case Options.InterfaceOptions.PlayModeFocus.GameWindow:
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestoreEditor:
gameWin.FocusGameViewport();
break;
@@ -320,6 +321,11 @@ namespace FlaxEditor.Modules
_previousWindow.Focus();
}
break;
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestoreEditor:
var editorWin = Editor.Windows.EditWin;
if (editorWin != null && !editorWin.IsDisposing)
editorWin.Focus();
break;
}
}
+7 -2
View File
@@ -179,6 +179,11 @@ namespace FlaxEditor.Options
/// Focus the Game Window. On play mode end restore focus to the previous window.
/// </summary>
GameWindowThenRestore,
/// <summary>
/// Focus the Game Window. On play mode end restore focus to the editor window.
/// </summary>
GameWindowThenRestoreEditor
}
/// <summary>
@@ -520,9 +525,9 @@ namespace FlaxEditor.Options
/// <summary>
/// Gets or sets a value indicating what panel should be focused when play mode start.
/// </summary>
[DefaultValue(PlayModeFocus.GameWindow)]
[DefaultValue(PlayModeFocus.GameWindowThenRestoreEditor)]
[EditorDisplay("Play In-Editor", "Focus On Play"), EditorOrder(500), Tooltip("Set what panel to focus on play mode start.")]
public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GameWindow;
public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GameWindowThenRestoreEditor;
/// <summary>
/// Gets or sets a value indicating what action should be taken upon pressing the play button.
@@ -809,10 +809,12 @@ namespace FlaxEditor.Viewport
/// <inheritdoc />
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
{
DragHandlers.ClearDragEffects();
var result = base.OnDragMove(ref location, data);
if (result != DragDropEffect.None)
{
DragHandlers.ClearDragEffects();
return result;
}
return DragHandlers.DragEnter(ref location, data);
}
@@ -647,10 +647,12 @@ namespace FlaxEditor.Viewport
/// <inheritdoc />
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
{
DragHandlers.ClearDragEffects();
var result = base.OnDragMove(ref location, data);
if (result != DragDropEffect.None)
{
DragHandlers.ClearDragEffects();
return result;
}
return DragHandlers.DragEnter(ref location, data);
}
@@ -65,7 +65,7 @@ namespace FlaxEditor.Viewport
{
if (_previewStaticModel)
debugDrawData.HighlightModel(_previewStaticModel, _previewModelEntryIndex);
if (_previewBrushSurface.Brush != null)
if (_previewBrushSurface.Brush)
debugDrawData.HighlightBrushSurface(_previewBrushSurface);
}
@@ -120,10 +120,12 @@ namespace FlaxEditor.Viewport
if (_dragAssets.HasValidDrag && _dragAssets.Objects[0].IsOfType<MaterialBase>())
{
GetHitLocation(ref location, out var hit, out _, out _);
ClearDragEffects();
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(_dragAssets.Objects[0].ID);
if (material.IsDecal)
if (material && material.IsDecal)
{
ClearDragEffects();
return;
}
if (hit is StaticModelNode staticModelNode)
{
@@ -135,6 +137,14 @@ namespace FlaxEditor.Viewport
{
_previewBrushSurface = brushSurfaceNode.Surface;
}
else
{
ClearDragEffects();
}
}
else
{
ClearDragEffects();
}
}
+2
View File
@@ -80,6 +80,8 @@ namespace FlaxEditor
/// <param name="surface">The surface.</param>
public void HighlightBrushSurface(BrushSurface surface)
{
if (surface.Brush == null)
return;
surface.Brush.GetVertices(surface.Index, out var vertices);
if (vertices.Length > 0)
{
+2
View File
@@ -768,9 +768,11 @@ namespace FlaxEditor.Windows
_newElement.Dispose();
_newElement = null;
#if !PLATFORM_SDL
// Focus content window
Focus();
RootWindow?.Focus();
#endif
}
// Refresh database and view now
+9 -3
View File
@@ -147,21 +147,27 @@ namespace FlaxEditor.Windows
new PlayModeFocusOptions
{
Name = "None",
Tooltip = "Don't change focus.",
Tooltip = "Don't change window focus when entering play mode.",
FocusOption = InterfaceOptions.PlayModeFocus.None,
},
new PlayModeFocusOptions
{
Name = "Game Window",
Tooltip = "Focus the Game Window.",
Tooltip = "Focus the Game Window when entering play mode.",
FocusOption = InterfaceOptions.PlayModeFocus.GameWindow,
},
new PlayModeFocusOptions
{
Name = "Game Window Then Restore",
Tooltip = "Focus the Game Window. On play mode end restore focus to the previous window.",
Tooltip = "Focus the Game Window when entering play mode. Restore focus to the previous window when exiting play mode.",
FocusOption = InterfaceOptions.PlayModeFocus.GameWindowThenRestore,
},
new PlayModeFocusOptions
{
Name = "Game Window Then Restore Editor",
Tooltip = "Focus the Game Window when entering play mode and then restore the focus to the editor window when exiting play mode.",
FocusOption = InterfaceOptions.PlayModeFocus.GameWindowThenRestoreEditor
}
};
/// <summary>
+2 -2
View File
@@ -148,13 +148,13 @@ public:
Quality GIQuality = Quality::High;
/// <summary>
/// The Global Illumination probes spacing distance (in world units). Defines the quality of the GI resolution. Adjust to 200-500 to improve performance and lower frequency GI data.
/// The global spacing between Global Illumination probes (in world units). Smaller values improve interior detail at a higher GPU cost. Values around 100-150 are a useful starting point for mixed interiors and exteriors; adjust to 200-500 for mostly outdoor scenes and lower-frequency GI. Changing this value recreates the DDGI probe resources and can change the automatic cascade layout.
/// </summary>
API_FIELD(Attributes="EditorOrder(2120), Limit(50, 1000), EditorDisplay(\"Global Illumination\"), ValueCategory(Utils.ValueCategory.Distance)")
float GIProbesSpacing = 100;
/// <summary>
/// Enables cascades splits blending for Global Illumination.
/// Enables smooth blending between Global Illumination cascade splits. If disabled, the transition uses dithering intended for temporal anti-aliasing. Smooth blending can expose rounded cascade boundaries when adjacent cascades contain significantly different lighting.
/// </summary>
API_FIELD(Attributes="EditorOrder(2125), EditorDisplay(\"Global Illumination\", \"GI Cascades Blending\")")
bool GICascadesBlending = false;
+5 -3
View File
@@ -217,8 +217,6 @@ void Screen::SetGameWindowMode(GameWindowMode windowMode)
switch (windowMode)
{
case GameWindowMode::Windowed:
if (GetIsFullscreen())
SetIsFullscreen(false);
win->SetBorderless(false, false);
break;
case GameWindowMode::Fullscreen:
@@ -279,7 +277,11 @@ void ScreenService::Draw()
auto win = Engine::MainWindow;
if (win)
{
win->SetClientSize(Size.GetValue());
Float2 sizeDelta = Size.GetValue() - win->GetClientSize();
Rectangle newBiunds(win->GetClientPosition(), Size.GetValue());
if (!win->IsMaximized())
newBiunds -= sizeDelta * 0.5f;
win->SetClientBounds(newBiunds);
}
Size.Reset();
@@ -112,6 +112,7 @@ bool DeformableMaterialShader::Load()
auto psDesc = GPUPipelineState::Description::Default;
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
psDesc.VS = _shader->GetVS("VS_SplineModel");
#if GPU_ALLOW_TESSELLATION_SHADERS
// Check if use tessellation (both material and runtime supports it)
@@ -127,7 +128,6 @@ bool DeformableMaterialShader::Load()
if (_shader->HasShader("PS_QuadOverdraw"))
{
// Quad Overdraw
psDesc.VS = _shader->GetVS("VS_SplineModel");
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
_cache.QuadOverdraw.Init(psDesc);
}
@@ -142,7 +142,6 @@ bool DeformableMaterialShader::Load()
psDesc.StencilPassOp = StencilOperation::Replace;
// GBuffer Pass
psDesc.VS = _shader->GetVS("VS_SplineModel");
psDesc.PS = _shader->GetPS("PS_GBuffer");
_cache.Default.Init(psDesc);
@@ -154,7 +153,6 @@ bool DeformableMaterialShader::Load()
_drawModes |= DrawPass::Forward;
// Forward Pass
psDesc.VS = _shader->GetVS("VS_SplineModel");
psDesc.PS = _shader->GetPS("PS_Forward");
psDesc.DepthWriteEnable = false;
psDesc.BlendMode = BlendingMode::AlphaBlend;
@@ -171,6 +169,18 @@ bool DeformableMaterialShader::Load()
break;
}
_cache.Default.Init(psDesc);
// Check if use transparent distortion pass
if (_shader->HasShader("PS_Distortion"))
{
_drawModes |= DrawPass::Distortion;
// Accumulate Distortion Pass
psDesc.PS = _shader->GetPS("PS_Distortion");
psDesc.BlendMode = BlendingMode::Add;
psDesc.DepthWriteEnable = false;
_cache.Distortion.Init(psDesc);
}
}
// Depth Pass
@@ -14,6 +14,7 @@ private:
{
PipelineStateCache Default;
PipelineStateCache Depth;
PipelineStateCache Distortion;
#if GPU_ENABLE_DEVELOPMENT
PipelineStateCache QuadOverdraw;
#endif
@@ -29,6 +30,8 @@ private:
case DrawPass::GlobalSurfaceAtlas:
case DrawPass::Forward:
return &Default;
case DrawPass::Distortion:
return &Distortion;
#if GPU_ENABLE_DEVELOPMENT
case DrawPass::QuadOverdraw:
return &QuadOverdraw;
@@ -42,6 +45,7 @@ private:
{
Default.Release();
Depth.Release();
Distortion.Release();
#if GPU_ENABLE_DEVELOPMENT
QuadOverdraw.Release();
#endif
+1 -1
View File
@@ -416,7 +416,7 @@ API_STRUCT() struct FLAXENGINE_API GlobalIlluminationSettings : ISerializable
float TemporalResponse = 0.9f;
/// <summary>
/// Draw distance of the Global Illumination effect. Scene outside the range will use fallback irradiance.
/// Camera-centered draw distance of the Global Illumination effect. Scene outside the range will use fallback irradiance. DDGI automatically derives its cascade layout from this distance and the global probe spacing, so continuously blending this value can recreate probe resources and cause a visible lighting reset.
/// </summary>
API_FIELD(Attributes="EditorOrder(30), Limit(1000), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Distance), ValueCategory(Utils.ValueCategory.Distance)")
float Distance = 20000.0f;
@@ -589,7 +589,18 @@ bool GPUDeviceDX11::Init()
else
#endif
{
VALIDATE_DIRECTX_CALL(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
HRESULT createResult = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext);
#if GPU_ENABLE_DEBUG_LAYER
if (createResult == DXGI_ERROR_SDK_COMPONENT_MISSING)
{
// The Direct3D debug layer is an optional Windows component
flags &= ~D3D11_CREATE_DEVICE_DEBUG;
createResult = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext);
if (SUCCEEDED(createResult))
LOG(Warning, "Direct3D SDK debug layers were requested, but not available. Continuing without them.");
}
#endif
VALIDATE_DIRECTX_CALL(createResult);
}
if (!_device || !_imContext)
return true;
@@ -162,11 +162,8 @@ void GPUSwapChainDX11::Present(bool vsync)
bool GPUSwapChainDX11::Resize(int32 width, int32 height)
{
// Check if size won't change
if (width == _width && height == _height)
{
return false;
}
_device->WaitForGPU();
GPUDeviceLock lock(_device);
@@ -174,6 +171,10 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
_allowTearing = _device->_allowTearing;
#endif
_format = GPU_BACK_BUFFER_PIXEL_FORMAT;
if (_memoryUsage != 0)
{
PROFILE_MEM_DEC(Graphics, _memoryUsage);
}
#if PLATFORM_WINDOWS
DXGI_SWAP_CHAIN_DESC swapChainDesc;
@@ -1802,7 +1802,11 @@ const String& LinuxPlatform::GetHomeDirectory()
String LinuxPlatform::GetDisplayServer()
{
#if PLATFORM_SDL
return SDLPlatform::GetDisplayServer();
#else
return xDisplay ? TEXT("X11") : TEXT("");
#endif
}
bool LinuxPlatform::Is64BitPlatform()
@@ -297,12 +297,10 @@ namespace WaylandImpl
textData.Text = *DraggingData;
wl_data_source_add_listener(dataSource, &DataSourceListener, &textData);
// Begin dragging operation
auto draggedWindow = Window->GetSDLWindow();
auto dragStartWindow = DragSourceWindow != nullptr ? DragSourceWindow->GetSDLWindow() : draggedWindow;
wl_surface* originSurface = static_cast<wl_surface*>(SDL_GetPointerProperty(SDL_GetWindowProperties(dragStartWindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr));
wl_surface* iconSurface = nullptr;
wl_data_device_start_drag(WrappedDataDevice, dataSource, originSurface, iconSurface, DragSerial);
Platform::AtomicStore(&StartFlag, 1);
@@ -321,11 +319,13 @@ namespace WaylandImpl
if (Platform::AtomicRead(&DragOverFlag) == 1 || Platform::AtomicRead(&Serial) != DragSerial)
break;
// Attach the window to the ongoing drag operation
// Begin dragging operation
wrappedToplevel = static_cast<xdg_toplevel*>(wl_proxy_create_wrapper(toplevel));
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(wrappedToplevel), EventQueue);
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
wl_data_device_start_drag(WrappedDataDevice, dataSource, originSurface, iconSurface, DragSerial);
// Attach the window to the ongoing drag operation
Float2 scaledOffset = DragOffset / Window->GetDpiScale();
xdg_toplevel_drag_v1_attach(toplevelDrag, wrappedToplevel, static_cast<int32>(scaledOffset.X), static_cast<int32>(scaledOffset.Y));
}
@@ -5,7 +5,7 @@
#include "WindowsWindow.h"
#include "WindowsPlatform.h"
#include "WindowsInput.h"
#include "Engine/Core/Log.h"
#include "Engine/Engine/Engine.h"
#include "Engine/Core/Math/Math.h"
#include "Engine/Core/Math/Color32.h"
#include "Engine/Graphics/GPUSwapChain.h"
@@ -267,8 +267,13 @@ void WindowsWindow::SetBorderless(bool isBorderless, bool maximized)
{
ASSERT(HasHWND());
Float2 preserveSize(0, 0);
if (IsFullscreen())
{
if (_swapChain && !maximized)
preserveSize = _swapChain->GetSize();
SetIsFullscreen(false);
}
// Fixes issue of borderless window not going full screen
if (IsMaximized())
@@ -303,6 +308,16 @@ void WindowsWindow::SetBorderless(bool isBorderless, bool maximized)
{
ShowWindow(_handle, SW_SHOW);
}
// Maintain resolution when going out the fullscreen
if (preserveSize != Float2::Zero)
{
Int4 monitorBounds;
GetScreenInfo(monitorBounds.X, monitorBounds.Y, monitorBounds.Z, monitorBounds.W);
monitorBounds.X += (monitorBounds.Z - (int32)preserveSize.X) / 2;
monitorBounds.Y += (monitorBounds.W - (int32)preserveSize.Y) / 2;
SetWindowPos(_handle, nullptr, monitorBounds.X, monitorBounds.Y, (int32)preserveSize.X, (int32)preserveSize.Y, SWP_NOZORDER | SWP_NOACTIVATE);
}
}
else
{
@@ -315,13 +330,22 @@ void WindowsWindow::SetBorderless(bool isBorderless, bool maximized)
if (_settings.HasSizingFrame)
lStyle |= WS_THICKFRAME;
lStyle |= WS_OVERLAPPED | WS_SYSMENU | WS_BORDER | WS_CAPTION;
SetWindowLong(_handle, GWL_STYLE, lStyle);
const Float2 clientSize = GetClientSize();
const Float2 desktopSize = Platform::GetDesktopSize();
// Move window and half size if it is larger than desktop size
if (clientSize.X >= desktopSize.X && clientSize.Y >= desktopSize.Y)
if (preserveSize != Float2::Zero)
{
// Maintain resolution when going out the fullscreen
Int4 monitorBounds;
GetScreenInfo(monitorBounds.X, monitorBounds.Y, monitorBounds.Z, monitorBounds.W);
monitorBounds.X += (monitorBounds.Z - (int32)preserveSize.X) / 2;
monitorBounds.Y += (monitorBounds.W - (int32)preserveSize.Y) / 2;
SetWindowPos(_handle, nullptr, monitorBounds.X, monitorBounds.Y, (int32)preserveSize.X, (int32)preserveSize.Y, SWP_NOZORDER | SWP_NOACTIVATE);
}
else if (clientSize.X >= desktopSize.X && clientSize.Y >= desktopSize.Y)
{
// Move window and half size if it is larger than desktop size
const Float2 halfSize = desktopSize * 0.5f;
const Float2 middlePos = halfSize * 0.5f;
SetWindowPos(_handle, nullptr, (int)middlePos.X, (int)middlePos.Y, (int)halfSize.X, (int)halfSize.Y, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
@@ -411,6 +435,17 @@ void WindowsWindow::SetClientBounds(const Rectangle& clientArea)
int32 width = (int32)clientArea.GetWidth();
int32 height = (int32)clientArea.GetHeight();
// Resize during fullscreen
if (changeSize && _swapChain && _swapChain->IsFullscreen())
{
// Go out fullscreen, resize, and then go back in
_swapChain->SetFullscreen(false);
_clientSize = clientArea.Size;
OnResize(width, height);
_swapChain->SetFullscreen(true);
return;
}
if (changeSize)
{
_clientSize = clientArea.Size;
@@ -763,7 +798,7 @@ void WindowsWindow::DestroyCursorImage(void* image)
::DestroyCursor((HCURSOR)image);
}
void WindowsWindow::CheckForWindowResize()
void WindowsWindow::CheckForWindowResize(bool force)
{
// Skip for minimized window (GetClientRect for minimized window returns 0)
if (_minimized)
@@ -798,7 +833,7 @@ void WindowsWindow::CheckForWindowResize()
_clientSize = Float2(static_cast<float>(width), static_cast<float>(height));
// Check if window size has been changed
if (width > 0 && height > 0 && (_swapChain == nullptr || width != _swapChain->GetWidth() || height != _swapChain->GetHeight()))
if (width > 0 && height > 0 && (force || _swapChain == nullptr || width != _swapChain->GetWidth() || height != _swapChain->GetHeight()))
{
UpdateRegion();
OnResize(width, height);
@@ -926,16 +961,24 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
case WM_PAINT:
{
// Check if window is during resizing
if (_isResizing && _swapChain)
if ((_isResizing || _forceRedrawOnPaint) && _swapChain)
{
// Redraw window backbuffer on DX11
switch (GPUDevice::Instance->GetRendererType())
_forceRedrawOnPaint = false;
if (GPUDevice::Instance && !GPUDevice::Instance->IsRendering() && GPUDevice::Instance->CanDraw())
{
case RendererType::DirectX10:
case RendererType::DirectX10_1:
case RendererType::DirectX11:
_swapChain->Present(false);
break;
Engine::OnDraw();
}
else if (GPUDevice::Instance)
{
// Redraw window backbuffer on DX11
switch (GPUDevice::Instance->GetRendererType())
{
case RendererType::DirectX10:
case RendererType::DirectX10_1:
case RendererType::DirectX11:
_swapChain->Present(false);
break;
}
}
}
break;
@@ -1235,8 +1278,8 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
else if (_isResizing)
{
// If we're neither maximized nor minimized, the window size is changing by the user dragging the window edges.
// In this case, we don't resize yet -- we wait until the user stops dragging, and a WM_EXITSIZEMOVE message comes.
UpdateRegion();
CheckForWindowResize();
RedrawWindow(_handle, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
}
else if (_isSwitchingFullScreen)
{
@@ -1258,6 +1301,10 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
_dpiScale = (float)_dpi / (float)DefaultDPI;
RECT* windowRect = (RECT*)lParam;
SetWindowPos(_handle, nullptr, windowRect->left, windowRect->top, windowRect->right - windowRect->left, windowRect->bottom - windowRect->top, SWP_NOZORDER | SWP_NOACTIVATE);
CheckForWindowResize(true);
UpdateRegion();
_forceRedrawOnPaint = true;
RedrawWindow(_handle, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
// TODO: Recalculate fonts
return 0;
}
@@ -24,6 +24,7 @@ private:
Windows::ULONG _refCount;
#endif
bool _isResizing = false;
bool _forceRedrawOnPaint = false;
bool _isSwitchingFullScreen = false;
bool _trackingMouse = false;
bool _clipCursorSet = false;
@@ -87,7 +88,7 @@ public:
Windows::LRESULT WndProc(Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam);
private:
void CheckForWindowResize();
void CheckForWindowResize(bool force = false);
void UpdateCursor();
void UpdateRegion();
@@ -271,6 +271,7 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
int32 h4 = h2 >> 1;
int32 h8 = h4 >> 1;
int32 bloomMipCount = CalculateBloomMipCount(w1, h1);
useLensFlares &= bloomMipCount > 1;
// Ensure to have valid data and if at least one effect should be applied
if (!(useBloom || useToneMapping || useCameraArtifacts || colorGradingLUT) || checkIfSkipPass() || w8 <= 1 || h8 <= 1)
@@ -451,7 +452,7 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
// Set bloom output
context->UnBindSR(0);
context->UnBindSR(1);
context->BindSR(2, bloomBuffer2->View(0, 0));
context->BindSR(2, (bloomMipCount > 1 ? bloomBuffer2 : bloomBuffer1)->View(0, 0));
}
else
{
@@ -246,7 +246,9 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
ADD_FEATURE(TessellationFeature);
if (isOpaque)
ADD_FEATURE(DeferredShadingFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
if (!isOpaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None)
ADD_FEATURE(DistortionFeature);
if (!isOpaque)
ADD_FEATURE(ForwardShadingFeature);
break;
default:
+4 -2
View File
@@ -383,10 +383,12 @@ void CS_UpdateProbesInitArgs()
{
uint activeProbesCount = ActiveProbes.Load(0); // Counter at 0
activeProbesCount = min(activeProbesCount, ProbesCount);
// The CPU submits every allocated batch, so always overwrite all arguments to avoid
// dispatching stale work left by a previous cascade or frame.
uint arg = 0;
for (uint probesOffset = 0; probesOffset < activeProbesCount; probesOffset += DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT)
for (uint probesOffset = 0; probesOffset < ProbesCount; probesOffset += DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT)
{
uint probesBatchSize = min(activeProbesCount - probesOffset, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT);
uint probesBatchSize = probesOffset < activeProbesCount ? min(activeProbesCount - probesOffset, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT) : 0;
UpdateProbesInitArgs[arg++] = probesBatchSize;
UpdateProbesInitArgs[arg++] = 1;
UpdateProbesInitArgs[arg++] = 1;