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

# Conflicts:
#	Content/Shaders/DepthOfField.flax
#	Source/Engine/Content/Asset.cpp
This commit is contained in:
2026-06-30 10:06:55 +02:00
64 changed files with 1222 additions and 423 deletions
+141 -15
View File
@@ -11,10 +11,12 @@
#include "Engine/Platform/Base/DragDropHelper.h"
#endif
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Color32.h"
#include "Engine/Input/Input.h"
#include "Engine/Input/Mouse.h"
#include "Engine/Input/Keyboard.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/Textures/TextureData.h"
#include <Cocoa/Cocoa.h>
#include <AppKit/AppKit.h>
#include <QuartzCore/CAMetalLayer.h>
@@ -200,6 +202,19 @@ Float2 GetMousePosition(MacWindow* window, NSEvent* event)
return Float2(point.x, frame.size.height - point.y) * MacPlatform::ScreenScale - GetWindowTitleSize(window);
}
NSRect GetFrameRectForClientBounds(MacWindow* macWindow, NSWindow* window, const Rectangle& clientArea)
{
const float screenScale = MacPlatform::ScreenScale;
NSRect rect = NSMakeRect(0, 0, clientArea.Size.X / screenScale, clientArea.Size.Y / screenScale);
rect = [window frameRectForContentRect:rect];
Float2 pos = AppleUtils::PosToCoca(clientArea.Location) / screenScale;
Float2 titleSize = GetWindowTitleSize(macWindow);
rect.origin.x = pos.X + titleSize.X;
rect.origin.y = pos.Y - rect.size.height + titleSize.Y;
return rect;
}
class MacDropData : public IGuiData
{
public:
@@ -310,6 +325,12 @@ NSDragOperation GetDragDropOperation(DragDropEffect dragDropEffect)
Window->OnLostFocus();
}
- (void)windowDidMove:(NSNotification*)notification
{
if (IsWindowInvalid(Window)) return;
Window->SyncWindowState();
}
- (void)windowWillClose:(NSNotification*)notification
{
[self setDelegate: nil];
@@ -518,6 +539,28 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r)
if (IsWindowInvalid(Window)) return;
Float2 mousePos = GetMousePosition(Window, event);
mousePos = Window->ClientToScreen(mousePos);
if ([event clickCount] == 1 && !Input::Mouse->IsRelative())
{
WindowHitCodes hit = WindowHitCodes::Client;
bool handled = false;
Window->OnHitTest(mousePos, hit, handled);
if (hit == WindowHitCodes::Caption)
{
bool consumed = false;
Window->OnLeftButtonHit(hit, consumed);
if (!consumed)
{
[(NSWindow*)Window->GetNativePtr() performWindowDragWithEvent:event];
Window->SyncWindowState();
}
return;
}
}
MouseButton mouseButton = MouseButton::Left;
if ([event clickCount] == 2 && !Input::Mouse->IsRelative())
Input::Mouse->OnMouseDoubleClick(mousePos, mouseButton, Window);
@@ -835,15 +878,28 @@ MacWindow::MacWindow(const CreateWindowSettings& settings)
MacWindow::~MacWindow()
{
NSWindow* window = (NSWindow*)_window;
[window close];
[window release];
if (NSWindow* window = (NSWindow*)_window)
{
[window close];
[window release];
}
_window = nullptr;
_view = nullptr;
}
void MacWindow::SyncWindowState()
{
NSWindow* window = (NSWindow*)_window;
if (window)
{
_minimized = window.miniaturized;
_maximized = window.zoomed;
}
}
void MacWindow::CheckForResize(float width, float height)
{
SyncWindowState();
const Float2 clientSize(width, height);
if (clientSize != _clientSize)
{
@@ -940,7 +996,7 @@ void MacWindow::Hide()
[window orderOut:nil];
// Transfer focus back to the parent when hiding popup
if (_settings.Parent && wasKey)
if (_settings.Parent && wasKey && _settings.Type != WindowType::Popup && _settings.Type != WindowType::Tooltip)
{
NSWindow* parent = (NSWindow*)_settings.Parent->GetNativePtr();
[parent makeKeyAndOrderFront:nil];
@@ -951,6 +1007,27 @@ void MacWindow::Hide()
}
}
void MacWindow::Close(ClosingReason reason)
{
const BOOL wasKey = _window && [(NSWindow*)_window isKeyWindow];
WindowBase::Close(reason);
// Closing can be cancelled by managed Window.Closing handlers.
if (!IsClosed())
return;
if (NSWindow* window = (NSWindow*)_window)
{
[window close];
}
if (_settings.Parent && wasKey && _settings.Type != WindowType::Popup && _settings.Type != WindowType::Tooltip)
{
NSWindow* parent = (NSWindow*)_settings.Parent->GetNativePtr();
[parent makeKeyAndOrderFront:nil];
}
}
void MacWindow::Minimize()
{
if (!_settings.AllowMinimize)
@@ -967,17 +1044,43 @@ void MacWindow::Maximize()
if (!_settings.AllowMaximize)
return;
NSWindow* window = (NSWindow*)_window;
if (!window)
return;
if (!window.zoomed)
{
if (!_maximized)
{
_restoreClientBounds = GetClientBounds();
_hasRestoreClientBounds = true;
}
[window zoom:nil];
}
SyncWindowState();
}
void MacWindow::Restore()
{
NSWindow* window = (NSWindow*)_window;
if (!window)
return;
if (window.miniaturized)
{
[window deminiaturize:nil];
SyncWindowState();
}
else if (_maximized && _hasRestoreClientBounds)
{
const Rectangle restoreClientBounds = _restoreClientBounds;
_hasRestoreClientBounds = false;
NSRect restoreFrame = GetFrameRectForClientBounds(this, window, restoreClientBounds);
[window setFrame:restoreFrame display:YES animate:YES];
_maximized = false;
}
else if (window.zoomed)
{
[window zoom:nil];
SyncWindowState();
}
}
bool MacWindow::IsForegroundWindow() const
@@ -1001,17 +1104,7 @@ void MacWindow::SetClientBounds(const Rectangle& clientArea)
NSWindow* window = (NSWindow*)_window;
if (!window)
return;
const float screenScale = MacPlatform::ScreenScale;
NSRect oldRect = [window frame];
NSRect newRect = NSMakeRect(0, 0, clientArea.Size.X / screenScale, clientArea.Size.Y / screenScale);
newRect = [window frameRectForContentRect:newRect];
Float2 pos = AppleUtils::PosToCoca(clientArea.Location) / screenScale;
Float2 titleSize = GetWindowTitleSize(this);
newRect.origin.x = pos.X + titleSize.X;
newRect.origin.y = pos.Y - newRect.size.height + titleSize.Y;
NSRect newRect = GetFrameRectForClientBounds(this, window, clientArea);
[window setFrame:newRect display:YES];
}
@@ -1213,4 +1306,37 @@ void MacWindow::SetCursor(CursorType type)
}
}
void MacWindow::SetIcon(TextureData& icon)
{
// Get pixels
Array<Color32> colorData;
icon.GetPixels(colorData);
// Convert to Cocoa image
NSImage* image = [[NSImage alloc] initWithSize:NSMakeSize(icon.Width, icon.Height)];
if (image == nil)
return;
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:icon.Width
pixelsHigh:icon.Height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:icon.Width * 4
bitsPerPixel:32];
if (rep == nil)
return;
// Copy the pixels
Platform::MemoryCopy([rep bitmapData], colorData.Get(), colorData.Count() * sizeof(Color32));
// Add the image representation
[image addRepresentation:rep];
// Set app icon
[NSApp setApplicationIconImage:image];
}
#endif