diff --git a/Source/Engine/Platform/Base/FileSystemBase.cpp b/Source/Engine/Platform/Base/FileSystemBase.cpp index 1df3970c3..658100446 100644 --- a/Source/Engine/Platform/Base/FileSystemBase.cpp +++ b/Source/Engine/Platform/Base/FileSystemBase.cpp @@ -20,7 +20,7 @@ bool FileSystemBase::ShowSaveFileDialog(Window* parentWindow, const StringView& return true; } -bool FileSystemBase::ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, StringView& path) +bool FileSystemBase::ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, String& path) { // No supported return true; diff --git a/Source/Engine/Platform/Base/FileSystemBase.h b/Source/Engine/Platform/Base/FileSystemBase.h index d2e0af872..c99fd74da 100644 --- a/Source/Engine/Platform/Base/FileSystemBase.h +++ b/Source/Engine/Platform/Base/FileSystemBase.h @@ -76,7 +76,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase); /// The dialog title. /// The output path. /// True if failed, otherwise false. - API_FUNCTION() static bool ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, API_PARAM(Out) StringView& path); + API_FUNCTION() static bool ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, API_PARAM(Out) String& path); /// /// Opens a standard file explorer application and navigates to the given directory. diff --git a/Source/Engine/Platform/Mac/MacFileSystem.cpp b/Source/Engine/Platform/Mac/MacFileSystem.cpp index 7aeb1fcef..b0529e2d1 100644 --- a/Source/Engine/Platform/Mac/MacFileSystem.cpp +++ b/Source/Engine/Platform/Mac/MacFileSystem.cpp @@ -3,6 +3,7 @@ #if PLATFORM_MAC #include "MacFileSystem.h" +#include "MacUtils.h" #include "Engine/Platform/File.h" #include "Engine/Core/Types/String.h" #include "Engine/Core/Types/StringView.h" @@ -19,9 +20,122 @@ #include #include #include +#include const DateTime UnixEpoch(1970, 1, 1); +void InitMacDialog(NSSavePanel* dialog, const StringView& initialDirectory, const StringView& filter, const StringView& title) +{ + if (initialDirectory.HasChars()) + { + [dialog setDirectoryURL:[NSURL fileURLWithPath:(NSString*)MacUtils::ToString(initialDirectory) isDirectory:YES]]; + } + if (filter.HasChars()) + { + // TODO: finish file tpye filter support + /*NSMutableArray* fileTypes = [[NSMutableArray alloc] init]; + Array entries; + String(filter).Split('\0', entries); + for (int32 i = 1; i < entries.Count(); i += 2) + { + String extension = entries[i]; + if (extension.StartsWith(TEXT("*."))) + extension = extension.Substring(2); + [fileTypes addObject:(NSString*)MacUtils::ToString(extension)]; + } + [dialog setAllowedFileTypes:fileTypes];*/ + } + if (title.HasChars()) + { + [dialog setMessage:(NSString*)MacUtils::ToString(title)]; + } +} + +bool MacFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames) +{ + bool result = true; + @autoreleasepool { + NSWindow* focusedWindow = [[NSApplication sharedApplication] keyWindow]; + + NSOpenPanel* dialog = [NSOpenPanel openPanel]; + [dialog setCanChooseFiles:YES]; + [dialog setCanChooseDirectories:NO]; + [dialog setAllowsMultipleSelection:multiSelect ? YES : NO]; + InitMacDialog(dialog, initialDirectory, filter, title); + + if ([dialog runModal] == NSModalResponseOK) + { + if (multiSelect) + { + const NSArray* urls = [dialog URLs]; + for (int32 i = 0; i < [urls count]; i++) + filenames.Add(MacUtils::ToString((CFStringRef)[[urls objectAtIndex:i] path])); + } + else + { + const NSURL* url = [dialog URL]; + filenames.Add(MacUtils::ToString((CFStringRef)[url path])); + } + result = false; + } + + [focusedWindow makeKeyAndOrderFront:nil]; + } + return result; +} + +bool MacFileSystem::ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames) +{ + bool result = true; + @autoreleasepool { + NSWindow* focusedWindow = [[NSApplication sharedApplication] keyWindow]; + + NSSavePanel* dialog = [NSSavePanel savePanel]; + [dialog setExtensionHidden:NO]; + InitMacDialog(dialog, initialDirectory, filter, title); + + if ([dialog runModal] == NSModalResponseOK) + { + const NSURL* url = [dialog URL]; + filenames.Add(MacUtils::ToString((CFStringRef)[url path])); + result = false; + } + + [focusedWindow makeKeyAndOrderFront:nil]; + } + return result; +} + +bool MacFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, String& path) +{ + bool result = true; + @autoreleasepool { + NSWindow* focusedWindow = [[NSApplication sharedApplication] keyWindow]; + + NSOpenPanel* dialog = [NSOpenPanel openPanel]; + [dialog setCanChooseFiles:NO]; + [dialog setCanChooseDirectories:YES]; + [dialog setCanCreateDirectories:YES]; + [dialog setAllowsMultipleSelection:NO]; + InitMacDialog(dialog, initialDirectory, StringView::Empty, title); + + if ([dialog runModal] == NSModalResponseOK) + { + const NSURL* url = [dialog URL]; + path = MacUtils::ToString((CFStringRef)[url path]); + result = false; + } + + [focusedWindow makeKeyAndOrderFront:nil]; + } + return result; +} + +bool MacFileSystem::ShowFileExplorer(const StringView& path) +{ + return Platform::StartProcess(TEXT("open"), String::Format(TEXT("\"{0}\""), path), StringView::Empty) != 0; +} + bool MacFileSystem::CreateDirectory(const StringView& path) { const StringAsANSI<> pathAnsi(*path, path.Length()); diff --git a/Source/Engine/Platform/Mac/MacFileSystem.h b/Source/Engine/Platform/Mac/MacFileSystem.h index 534a387bd..d1ebc6867 100644 --- a/Source/Engine/Platform/Mac/MacFileSystem.h +++ b/Source/Engine/Platform/Mac/MacFileSystem.h @@ -14,6 +14,10 @@ class FLAXENGINE_API MacFileSystem : public FileSystemBase public: // [FileSystemBase] + static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames); + static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames); + static bool ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, String& path); + static bool ShowFileExplorer(const StringView& path); static bool CreateDirectory(const StringView& path); static bool DeleteDirectory(const String& path, bool deleteContents = true); static bool DirectoryExists(const StringView& path); diff --git a/Source/Engine/Platform/Mac/MacPlatform.cpp b/Source/Engine/Platform/Mac/MacPlatform.cpp index ae1e55e5d..0490520d3 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.cpp +++ b/Source/Engine/Platform/Mac/MacPlatform.cpp @@ -67,9 +67,9 @@ String MacUtils::ToString(CFStringRef str) return result; } -CFStringRef MacUtils::ToString(const String& str) +CFStringRef MacUtils::ToString(const StringView& str) { - return CFStringCreateWithBytes(nullptr, (const UInt8*)str.Get(), str.Length() * sizeof(Char), kCFStringEncodingUTF16LE, false); + return CFStringCreateWithBytes(nullptr, (const UInt8*)str.GetNonTerminatedText(), str.Length() * sizeof(Char), kCFStringEncodingUTF16LE, false); } Vector2 MacUtils::PosToCoca(const Vector2& pos) diff --git a/Source/Engine/Platform/Mac/MacUtils.h b/Source/Engine/Platform/Mac/MacUtils.h index 50caba425..59acb655b 100644 --- a/Source/Engine/Platform/Mac/MacUtils.h +++ b/Source/Engine/Platform/Mac/MacUtils.h @@ -9,7 +9,7 @@ class FLAXENGINE_API MacUtils { public: static String ToString(CFStringRef str); - static CFStringRef ToString(const String& str); + static CFStringRef ToString(const StringView& str); static Vector2 PosToCoca(const Vector2& pos); static Vector2 GetScreensOrigin(); }; diff --git a/Source/Engine/Platform/Windows/WindowsFileSystem.cpp b/Source/Engine/Platform/Windows/WindowsFileSystem.cpp index 176197bc6..746566f50 100644 --- a/Source/Engine/Platform/Windows/WindowsFileSystem.cpp +++ b/Source/Engine/Platform/Windows/WindowsFileSystem.cpp @@ -290,7 +290,7 @@ bool WindowsFileSystem::ShowSaveFileDialog(Window* parentWindow, const StringVie return result; } -bool WindowsFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, StringView& path) +bool WindowsFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, String& path) { bool result = true; diff --git a/Source/Engine/Platform/Windows/WindowsFileSystem.h b/Source/Engine/Platform/Windows/WindowsFileSystem.h index a1569fb6e..1e4927442 100644 --- a/Source/Engine/Platform/Windows/WindowsFileSystem.h +++ b/Source/Engine/Platform/Windows/WindowsFileSystem.h @@ -38,7 +38,7 @@ public: // [Win32FileSystem] static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames); static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames); - static bool ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, StringView& path); + static bool ShowBrowseFolderDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& title, String& path); static bool ShowFileExplorer(const StringView& path); };