From 4d9ffdb0251af90bfa7aed2004cb3f32ff84601b Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 28 Jan 2023 19:43:11 +0200 Subject: [PATCH 01/36] Fix centered window and message box locations on Linux --- .../Engine/Platform/Linux/LinuxPlatform.cpp | 7 +++-- Source/Engine/Platform/Linux/LinuxWindow.cpp | 28 +++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index a5bd099c9..242f8fb4a 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -431,8 +431,11 @@ static int X11_MessageBoxCreateWindow(MessageBoxData* data) } else { - x = (X11_DisplayWidth(display, data->screen) - data->dialog_width) / 2; - y = (X11_DisplayHeight(display, data->screen) - data->dialog_height) / 3; + int screenCount; + X11::XineramaScreenInfo* xsi = X11::XineramaQueryScreens(xDisplay, &screenCount); + ASSERT(data->screen < screenCount); + x = (float)xsi[data->screen].x_org + ((float)xsi[data->screen].width - data->dialog_width) / 2; + y = (float)xsi[data->screen].y_org + ((float)xsi[data->screen].height - data->dialog_height) / 2; } X11::XMoveWindow(display, data->window, x, y); diff --git a/Source/Engine/Platform/Linux/LinuxWindow.cpp b/Source/Engine/Platform/Linux/LinuxWindow.cpp index cbcfca0af..7694836cb 100644 --- a/Source/Engine/Platform/Linux/LinuxWindow.cpp +++ b/Source/Engine/Platform/Linux/LinuxWindow.cpp @@ -47,6 +47,11 @@ static X11::Time MouseLastButtonPressTime = 0; LinuxWindow::LinuxWindow(const CreateWindowSettings& settings) : WindowBase(settings) { + auto display = (X11::Display*)LinuxPlatform::GetXDisplay(); + if (!display) + return; + auto screen = XDefaultScreen(display); + // Cache data int32 width = Math::TruncToInt(settings.Size.X); int32 height = Math::TruncToInt(settings.Size.Y); @@ -64,9 +69,21 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings) break; case WindowStartPosition::CenterScreen: { - Float2 desktopSize = Platform::GetDesktopSize(); - x = Math::TruncToInt((desktopSize.X - _clientSize.X) * 0.5f); - y = Math::TruncToInt((desktopSize.Y - _clientSize.Y) * 0.5f); + Rectangle desktopBounds; + int event, err; + const bool ok = X11::XineramaQueryExtension(display, &event, &err); + if (X11::XineramaQueryExtension(display, &event, &err)) + { + int count; + X11::XineramaScreenInfo* xsi = X11::XineramaQueryScreens(display, &count); + ASSERT(screen < count); + desktopBounds = Rectangle(Float2((float)xsi[screen].x_org, (float)xsi[screen].y_org), Float2((float)xsi[screen].width, (float)xsi[screen].height)); + X11::XFree(xsi); + } + else + desktopBounds = Rectangle(Float2::Zero, Platform::GetDesktopSize()); + x = Math::TruncToInt(desktopBounds.Location.X + (desktopBounds.Size.X - _clientSize.X) * 0.5f); + y = Math::TruncToInt(desktopBounds.Location.Y + (desktopBounds.Size.Y - _clientSize.Y) * 0.5f); } break; case WindowStartPosition::Manual: @@ -76,11 +93,6 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings) } _resizeDisabled = !settings.HasSizingFrame; - auto display = (X11::Display*)LinuxPlatform::GetXDisplay(); - if (!display) - return; - - auto screen = XDefaultScreen(display); auto rootWindow = XRootWindow(display, screen); long visualMask = VisualScreenMask; From 6f8aee0c1cfadbab0436947a9bb3336bf54610ef Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 29 Jan 2023 19:12:24 +0200 Subject: [PATCH 02/36] Use alternative method to query DPI on Linux --- .../Engine/Platform/Linux/LinuxPlatform.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index a5bd099c9..3effd5d03 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -840,17 +840,17 @@ int X11ErrorHandler(X11::Display* display, X11::XErrorEvent* event) int32 CalculateDpi() { - // in X11 a screen is not necessarily identical to a desktop - // so we need to stick to one type for pixel and physical size query + int dpi = 96; + char* resourceString = X11::XResourceManagerString(xDisplay); + if (resourceString == NULL) + return dpi; - int screenIdx = 0; - int widthMM = X11_DisplayWidthMM(xDisplay, screenIdx); - int heightMM = X11_DisplayHeightMM(xDisplay, screenIdx); - double xdpi = (widthMM ? X11_DisplayWidth(xDisplay, screenIdx) / (double)widthMM * 25.4 : 0); - double ydpi = (heightMM ? X11_DisplayHeight(xDisplay, screenIdx) / (double)heightMM * 25.4 : 0); - if (xdpi || ydpi) - return (int32)Math::Ceil((xdpi + ydpi) / (xdpi && ydpi ? 2 : 1)); - return 96; + char* type = NULL; + X11::XrmValue value; + X11::XrmDatabase database = X11::XrmGetStringDatabase(resourceString); + if (X11::XrmGetResource(database, "Xft.dpi", "String", &type, &value) == 1 && value.addr != NULL) + dpi = (int)atof(value.addr); + return dpi; } // Maps Flax key codes to X11 names for physical key locations. @@ -2101,6 +2101,7 @@ bool LinuxPlatform::Init() xAtomWmName = X11::XInternAtom(xDisplay, "_NET_WM_NAME", 0); xAtomClipboard = X11::XInternAtom(xDisplay, "CLIPBOARD", 0); + X11::XrmInitialize(); SystemDpi = CalculateDpi(); int cursorSize = X11::XcursorGetDefaultSize(xDisplay); From b0bc1fa310bd60d45d1744073a8b8523dfe6203e Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 29 Jan 2023 21:25:29 +0200 Subject: [PATCH 03/36] Fix error when joining exited threads The internal thread handles were cleared prematurely when attempting to join them. The handles should be also cleared when trying to kill already exited threads. --- Source/Engine/Content/Loading/ContentLoadingManager.cpp | 3 +-- Source/Engine/Platform/Base/ThreadBase.cpp | 4 +++- Source/Engine/Platform/Unix/UnixThread.cpp | 1 + Source/Engine/Platform/Win32/Win32Thread.cpp | 1 + Source/Engine/Threading/JobSystem.cpp | 3 +-- Source/Engine/Threading/ThreadPool.cpp | 5 +---- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Source/Engine/Content/Loading/ContentLoadingManager.cpp b/Source/Engine/Content/Loading/ContentLoadingManager.cpp index c9680441b..7fd63a217 100644 --- a/Source/Engine/Content/Loading/ContentLoadingManager.cpp +++ b/Source/Engine/Content/Loading/ContentLoadingManager.cpp @@ -55,8 +55,7 @@ LoadingThread::~LoadingThread() // Check if has thread attached if (_thread != nullptr) { - if (_thread->IsRunning()) - _thread->Kill(true); + _thread->Kill(true); Delete(_thread); } } diff --git a/Source/Engine/Platform/Base/ThreadBase.cpp b/Source/Engine/Platform/Base/ThreadBase.cpp index 38e99ceb7..5739dbf3e 100644 --- a/Source/Engine/Platform/Base/ThreadBase.cpp +++ b/Source/Engine/Platform/Base/ThreadBase.cpp @@ -43,7 +43,10 @@ void ThreadBase::SetPriority(ThreadPriority priority) void ThreadBase::Kill(bool waitForJoin) { if (!_isRunning) + { + ClearHandleInternal(); return; + } ASSERT(GetID()); const auto thread = static_cast(this); @@ -105,7 +108,6 @@ int32 ThreadBase::Run() _callAfterWork = false; _runnable->AfterWork(false); } - ClearHandleInternal(); _isRunning = false; ThreadExiting(thread, exitCode); ThreadRegistry::Remove(thread); diff --git a/Source/Engine/Platform/Unix/UnixThread.cpp b/Source/Engine/Platform/Unix/UnixThread.cpp index 4fa532a4b..f662bdba8 100644 --- a/Source/Engine/Platform/Unix/UnixThread.cpp +++ b/Source/Engine/Platform/Unix/UnixThread.cpp @@ -53,6 +53,7 @@ UnixThread* UnixThread::Setup(UnixThread* thread, uint32 stackSize) void UnixThread::Join() { pthread_join(_thread, nullptr); + ClearHandleInternal(); } void UnixThread::ClearHandleInternal() diff --git a/Source/Engine/Platform/Win32/Win32Thread.cpp b/Source/Engine/Platform/Win32/Win32Thread.cpp index 5ede5cfc6..0cd8faaf2 100644 --- a/Source/Engine/Platform/Win32/Win32Thread.cpp +++ b/Source/Engine/Platform/Win32/Win32Thread.cpp @@ -113,6 +113,7 @@ unsigned long Win32Thread::ThreadProc(void* pThis) void Win32Thread::Join() { WaitForSingleObject((HANDLE)_thread, INFINITE); + ClearHandleInternal(); } void Win32Thread::ClearHandleInternal() diff --git a/Source/Engine/Threading/JobSystem.cpp b/Source/Engine/Threading/JobSystem.cpp index 1d4e9762a..396294e56 100644 --- a/Source/Engine/Threading/JobSystem.cpp +++ b/Source/Engine/Threading/JobSystem.cpp @@ -149,8 +149,7 @@ void JobSystemService::Dispose() { if (Threads[i]) { - if (Threads[i]->IsRunning()) - Threads[i]->Kill(true); + Threads[i]->Kill(true); Delete(Threads[i]); Threads[i] = nullptr; } diff --git a/Source/Engine/Threading/ThreadPool.cpp b/Source/Engine/Threading/ThreadPool.cpp index 2dd6176d0..b7db81ffa 100644 --- a/Source/Engine/Threading/ThreadPool.cpp +++ b/Source/Engine/Threading/ThreadPool.cpp @@ -98,10 +98,7 @@ void ThreadPoolService::Dispose() // Delete threads for (int32 i = 0; i < ThreadPoolImpl::Threads.Count(); i++) { - if (ThreadPoolImpl::Threads[i]->IsRunning()) - { - ThreadPoolImpl::Threads[i]->Kill(true); - } + ThreadPoolImpl::Threads[i]->Kill(true); } ThreadPoolImpl::Threads.ClearDelete(); } From d7595f1eccb5e1d7310c56e3ef35da6d069d152c Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 29 Jan 2023 21:27:43 +0200 Subject: [PATCH 04/36] Fix compiler warnings with Clang 15 or later --- Source/Engine/Core/Templates.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Core/Templates.h b/Source/Engine/Core/Templates.h index dbb6388fc..49da8b84a 100644 --- a/Source/Engine/Core/Templates.h +++ b/Source/Engine/Core/Templates.h @@ -21,7 +21,11 @@ namespace THelpers template struct TIsTriviallyDestructibleImpl { - enum { Value = __has_trivial_destructor(T) }; +#if defined(__clang__) && __clang_major__ >= 15 + enum { Value = __is_trivially_destructible(T) }; +#else + enum { Value = __has_trivial_destructor(T) }; +#endif }; } @@ -261,7 +265,11 @@ struct TIsCopyConstructible template struct TIsTriviallyCopyConstructible { - enum { Value = TOrValue<__has_trivial_copy(T), TIsPODType>::Value }; +#if defined(__clang__) && __clang_major__ >= 15 + enum { Value = TOrValue<__is_trivially_copyable(T), TIsPODType>::Value }; +#else + enum { Value = TOrValue<__has_trivial_copy(T), TIsPODType>::Value }; +#endif }; //////////////////////////////////////////////////////////////////////////////////// @@ -289,7 +297,11 @@ struct TIsTriviallyDestructible template struct TIsTriviallyCopyAssignable { - enum { Value = TOrValue<__has_trivial_assign(T), TIsPODType>::Value }; +#if defined(__clang__) && __clang_major__ >= 15 + enum { Value = TOrValue<__is_trivially_assignable(T, const T), TIsPODType>::Value }; +#else + enum { Value = TOrValue<__has_trivial_assign(T), TIsPODType>::Value }; +#endif }; //////////////////////////////////////////////////////////////////////////////////// From f4da98439943b580e66210e8088b056bf5e3cf80 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 3 Feb 2023 13:27:53 -0600 Subject: [PATCH 05/36] Added function to get viewport size of the game window when in editor. This allows for certain functions to behave correctly. --- Source/Editor/Editor.cs | 17 +++++++++++++++++ Source/Editor/Managed/ManagedEditor.cpp | 18 ++++++++++++++++++ Source/Editor/Managed/ManagedEditor.h | 6 ++++++ Source/Engine/Level/Actors/Camera.cpp | 2 +- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index e5a949f3b..29549977e 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -1408,6 +1408,23 @@ namespace FlaxEditor } } + internal void Internal_GetGameWindowViewportSize(out Float2 result) + { + result = new Float2(1280, 720); + var gameWin = Windows.GameWin; + if (gameWin?.Root?.RootWindow is WindowRootControl root) + { + // Handle case when Game window is not selected in tab view + var dockedTo = gameWin.ParentDockPanel; + if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null) + result = dockedTo.SelectedTab.Size * root.DpiScale; + else + result = gameWin.Viewport.Size * root.DpiScale; + + result = Float2.Round(result); + } + } + internal bool Internal_OnAppExit() { // In editor play mode (when main window is not closed) just skip engine exit and leave the play mode diff --git a/Source/Editor/Managed/ManagedEditor.cpp b/Source/Editor/Managed/ManagedEditor.cpp index fdabf9056..5b45ea7d6 100644 --- a/Source/Editor/Managed/ManagedEditor.cpp +++ b/Source/Editor/Managed/ManagedEditor.cpp @@ -457,6 +457,24 @@ Float2 ManagedEditor::GetGameWindowSize() return Float2::Zero; } +Float2 ManagedEditor::GetGameWindowViewportSize() +{ + if (HasManagedInstance()) + { + if (Internal_GetGameWindowSize == nullptr) + { + Internal_GetGameWindowSize = GetClass()->GetMethod("Internal_GetGameWindowViewportSize", 1); + ASSERT(Internal_GetGameWindowSize); + } + Float2 size; + void* params[1]; + params[0] = &size; + Internal_GetGameWindowSize->Invoke(GetManagedInstance(), params, nullptr); + return size; + } + return Float2::Zero; +} + bool ManagedEditor::OnAppExit() { if (!HasManagedInstance()) diff --git a/Source/Editor/Managed/ManagedEditor.h b/Source/Editor/Managed/ManagedEditor.h index 36fc0c234..cfacce2da 100644 --- a/Source/Editor/Managed/ManagedEditor.h +++ b/Source/Editor/Managed/ManagedEditor.h @@ -133,6 +133,12 @@ public: /// The size. Float2 GetGameWindowSize(); + /// + /// Gets the size of the game window viewport output. + /// + /// The size. + Float2 GetGameWindowViewportSize(); + /// /// Called when application code calls exit. Editor may end play mode or exit normally. /// diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp index ea161c38a..3e19403cd 100644 --- a/Source/Engine/Level/Actors/Camera.cpp +++ b/Source/Engine/Level/Actors/Camera.cpp @@ -189,7 +189,7 @@ Viewport Camera::GetViewport() const #if USE_EDITOR // Editor if (Editor::Managed) - result.Size = Editor::Managed->GetGameWindowSize(); + result.Size = Editor::Managed->GetGameWindowViewportSize(); #else // game auto mainWin = Engine::MainWindow; From 2703401f0813753d0fc4eed94826d873cef8dd06 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 28 Jan 2023 19:46:09 +0200 Subject: [PATCH 06/36] Fix process creation on Linux Forked child process did not exit properly, sometimes causing scripting compilation to get stuck and never finish. --- Source/Engine/Platform/Linux/LinuxPlatform.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index a5bd099c9..5dc62a26e 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -2802,6 +2802,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons { close(fildes[0]); // close the reading end of the pipe dup2(fildes[1], STDOUT_FILENO); // redirect stdout to pipe + close(fildes[1]); dup2(STDOUT_FILENO, STDERR_FILENO); // redirect stderr to stdout } @@ -2810,6 +2811,8 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons { LOG(Warning, " failed, errno={}", errno); } + fflush(stdout); + _exit(1); } else { @@ -2822,7 +2825,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons { char lineBuffer[1024]; close(fildes[1]); // close the writing end of the pipe - FILE *stdPipe = fdopen(fildes[0], "r"); + FILE* stdPipe = fdopen(fildes[0], "r"); while (fgets(lineBuffer, sizeof(lineBuffer), stdPipe) != NULL) { char *p = lineBuffer + strlen(lineBuffer)-1; @@ -2857,6 +2860,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons returnCode = EPIPE; } } + close(fildes[0]); } } From 0ac5db45d1beedba0546e8fe7e3bc7481a5cdd2f Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 3 Feb 2023 22:00:50 +0200 Subject: [PATCH 07/36] Improve Linux file dialog support Adds support for multi selection, filtering and initial folder for both zenity and kdialog. kdialog is also preferred over zenity when KDE is detected. --- Source/Engine/Platform/Base/FileSystemBase.h | 14 ++++++- .../Engine/Platform/Base/StringUtilsBase.cpp | 13 ++++++ .../Engine/Platform/Linux/LinuxFileSystem.cpp | 40 ++++++++++++++----- Source/Engine/Platform/StringUtils.h | 7 ++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Platform/Base/FileSystemBase.h b/Source/Engine/Platform/Base/FileSystemBase.h index d0284042b..fc3d75bb1 100644 --- a/Source/Engine/Platform/Base/FileSystemBase.h +++ b/Source/Engine/Platform/Base/FileSystemBase.h @@ -50,11 +50,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase); /// /// The parent window or null. /// The initial directory. - /// The custom filter. + /// The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon. /// True if allow multiple files to be selected, otherwise use single-file mode. /// The dialog title. /// The output names of the files picked by the user. /// True if failed, otherwise false. + /// + /// Example file filters: + /// "All Files\0*.*" + /// "All Files\0*.*\0Image Files\0*.png;*.jpg" + /// API_FUNCTION() static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array& filenames); /// @@ -62,11 +67,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase); /// /// The parent window. /// The initial directory. - /// The filter. + /// The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon. /// True if allow multiple files to be selected, otherwise use single-file mode. /// The title. /// The output names of the files picked by the user. /// True if failed, otherwise false. + /// + /// Example file filters: + /// "All Files\0*.*" + /// "All Files\0*.*\0Image Files\0*.png;*.jpg" + /// API_FUNCTION() static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array& filenames); /// diff --git a/Source/Engine/Platform/Base/StringUtilsBase.cpp b/Source/Engine/Platform/Base/StringUtilsBase.cpp index 6f1d741d5..d005f8a04 100644 --- a/Source/Engine/Platform/Base/StringUtilsBase.cpp +++ b/Source/Engine/Platform/Base/StringUtilsBase.cpp @@ -528,4 +528,17 @@ String StringUtils::ToString(double value) return String::Format(TEXT("{}"), value); } +String StringUtils::GetZZString(const Char* str) +{ + const Char* end = str; + while (*end != '\0') + { + end++; + if (*end == '\0') + end++; + } + const int len = end - str; + return String(str, len); +} + #undef STRING_UTILS_ITOSTR_BUFFER_SIZE diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp index 7291dc8ac..f8ad0d476 100644 --- a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp +++ b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp @@ -4,7 +4,9 @@ #include "LinuxFileSystem.h" #include "Engine/Platform/File.h" +#include "Engine/Platform/StringUtils.h" #include "Engine/Core/Types/String.h" +#include "Engine/Core/Types/StringBuilder.h" #include "Engine/Core/Types/StringView.h" #include "Engine/Core/Types/TimeSpan.h" #include "Engine/Core/Math/Math.h" @@ -27,20 +29,38 @@ bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView& { const StringAsANSI<> initialDirectoryAnsi(*initialDirectory, initialDirectory.Length()); const StringAsANSI<> titleAnsi(*title, title.Length()); + const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : "."; char cmd[2048]; - if (FileSystem::FileExists(TEXT("/usr/bin/zenity"))) + String xdgCurrentDesktop; + StringBuilder fileFilter; + Array fileFilterEntries; + Platform::GetEnvironmentVariable(TEXT("XDG_CURRENT_DESKTOP"), xdgCurrentDesktop); + StringUtils::GetZZString(filter.Get()).Split('\0', fileFilterEntries); + + const bool zenitySupported = FileSystem::FileExists(TEXT("/usr/bin/zenity")); + const bool kdialogSupported = FileSystem::FileExists(TEXT("/usr/bin/kdialog")); + if (zenitySupported && (xdgCurrentDesktop != TEXT("KDE") || !kdialogSupported)) // Prefer kdialog when running on KDE { - // TODO: initialDirectory support - // TODO: multiSelect support - // TODO: filter support - sprintf(cmd, "/usr/bin/zenity --modal --file-selection --title=\"%s\" ", titleAnsi.Get()); + for (int32 i = 1; i < fileFilterEntries.Count(); i += 2) + { + String extensions(fileFilterEntries[i]); + fileFilterEntries[i].Replace(TEXT(";"), TEXT(" ")); + fileFilter.Append(String::Format(TEXT("{0}--file-filter=\"{1}|{2}\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get())); + } + + sprintf(cmd, "/usr/bin/zenity --modal --file-selection %s--filename=\"%s\" --title=\"%s\" %s ", multiSelect ? "--multiple --separator=$'\n' " : " ", initDir, titleAnsi.Get(), fileFilter.ToStringView().ToStringAnsi().GetText()); } - else if (FileSystem::FileExists(TEXT("/usr/bin/kdialog"))) + else if (kdialogSupported) { - // TODO: multiSelect support - // TODO: filter support - const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : "."; - sprintf(cmd, "/usr/bin/kdialog --getopenfilename \"%s\" --title \"%s\" ", initDir, titleAnsi.Get()); + for (int32 i = 1; i < fileFilterEntries.Count(); i += 2) + { + String extensions(fileFilterEntries[i]); + fileFilterEntries[i].Replace(TEXT(";"), TEXT(" ")); + fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get())); + } + fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), TEXT(" "), TEXT("many things"), TEXT("*.png *.jpg"))); + + sprintf(cmd, "/usr/bin/kdialog --getopenfilename %s--title \"%s\" \"%s\" %s ", multiSelect ? "--multiple --separate-output " : " ", titleAnsi.Get(), initDir, fileFilter.ToStringView().ToStringAnsi().GetText()); } else { diff --git a/Source/Engine/Platform/StringUtils.h b/Source/Engine/Platform/StringUtils.h index 6f90bbe92..ea982c2ee 100644 --- a/Source/Engine/Platform/StringUtils.h +++ b/Source/Engine/Platform/StringUtils.h @@ -438,6 +438,13 @@ public: static String ToString(uint64 value); static String ToString(float value); static String ToString(double value); + +public: + + // Returns the String to double null-terminated string + // @param str Double null-terminated string + // @return Double null-terminated String + static String GetZZString(const Char* str); }; inline uint32 GetHash(const char* key) From 19eaec336df5b43a7ab22fd63c06ad22b1fe7b89 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Mon, 4 Jul 2022 23:06:09 +0300 Subject: [PATCH 08/36] Use better linkers to improve linking times on Linux --- .../Platforms/Unix/UnixToolchain.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs index eb4c8f183..373dde534 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs @@ -61,6 +61,11 @@ namespace Flax.Build.Platforms /// protected string LdPath; + /// + /// The type of the linker. + /// + protected string LdKind; + /// /// The clang tool version. /// @@ -91,7 +96,19 @@ namespace Flax.Build.Platforms RanlibPath = UnixPlatform.Which("ranlib"); StripPath = UnixPlatform.Which("strip"); ObjcopyPath = UnixPlatform.Which("objcopy"); - LdPath = UnixPlatform.Which("ld"); + + LdPath = UnixPlatform.Which("ld.lld"); + LdKind = "lld"; + if (LdPath == null) + { + LdPath = UnixPlatform.Which("ld.gold"); + LdKind = "gold"; + } + if (LdPath == null) + { + LdPath = UnixPlatform.Which("ld"); + LdKind = null; + } } else { @@ -478,6 +495,9 @@ namespace Flax.Build.Platforms // TODO: linkEnvironment.LinkTimeCodeGeneration // TODO: linkEnvironment.Optimization // TODO: linkEnvironment.UseIncrementalLinking + + if (!string.IsNullOrEmpty(LdKind)) + args.Add(string.Format("-fuse-ld={0}", LdKind)); } SetupLinkFilesArgs(graph, options, args, outputFilePath); From 591b45d2e8f7d9d411512325dcbc67c7866f330b Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Tue, 5 Jul 2022 05:24:02 +0300 Subject: [PATCH 09/36] Fix linking errors with other linkers --- Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs index 373dde534..53e20db63 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using Flax.Build.Graph; using Flax.Build.NativeCpp; @@ -556,9 +557,10 @@ namespace Flax.Build.Platforms } } - // Input files + // Input files (link static libraries last) task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles); - foreach (var file in linkEnvironment.InputFiles) + foreach (var file in linkEnvironment.InputFiles.Where(x => !x.EndsWith(".a")) + .Concat(linkEnvironment.InputFiles.Where(x => x.EndsWith(".a")))) { args.Add(string.Format("\"{0}\"", file.Replace('\\', '/'))); } From c51a9231602c12d0ad4c1591d5b62ddbff2d4886 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 5 Feb 2023 13:38:29 +0200 Subject: [PATCH 10/36] Only pass --copy-dt-needed-entries with GNU linker --- Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs | 3 ++- Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index 9bc9aab33..96ef470e4 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -75,7 +75,8 @@ namespace Flax.Build.Platforms args.Add("-Wl,-rpath,\"\\$ORIGIN\""); //args.Add("-Wl,--as-needed"); - args.Add("-Wl,--copy-dt-needed-entries"); + if (LdKind == "bfd") + args.Add("-Wl,--copy-dt-needed-entries"); args.Add("-Wl,--hash-style=gnu"); //args.Add("-Wl,--build-id"); diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs index 53e20db63..6bbb8707f 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs @@ -107,8 +107,8 @@ namespace Flax.Build.Platforms } if (LdPath == null) { - LdPath = UnixPlatform.Which("ld"); - LdKind = null; + LdPath = UnixPlatform.Which("ld"); // ld.bfd + LdKind = "bfd"; } } else From 4b9bbfb66306ca5ec674785dc8c64fefc2ea057e Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 5 Feb 2023 20:22:54 -0600 Subject: [PATCH 11/36] Change `GetGameWindowSize` to return game viewport size. --- Source/Editor/Editor.cs | 17 ----------------- Source/Editor/Managed/ManagedEditor.cpp | 18 ------------------ Source/Editor/Managed/ManagedEditor.h | 6 ------ Source/Engine/Level/Actors/Camera.cpp | 2 +- 4 files changed, 1 insertion(+), 42 deletions(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 29549977e..b8df413e1 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -1392,23 +1392,6 @@ namespace FlaxEditor } internal void Internal_GetGameWindowSize(out Float2 result) - { - result = new Float2(1280, 720); - var gameWin = Windows.GameWin; - if (gameWin?.Root?.RootWindow is WindowRootControl root) - { - // Handle case when Game window is not selected in tab view - var dockedTo = gameWin.ParentDockPanel; - if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null) - result = dockedTo.SelectedTab.Size * root.DpiScale; - else - result = gameWin.Size * root.DpiScale; - - result = Float2.Round(result); - } - } - - internal void Internal_GetGameWindowViewportSize(out Float2 result) { result = new Float2(1280, 720); var gameWin = Windows.GameWin; diff --git a/Source/Editor/Managed/ManagedEditor.cpp b/Source/Editor/Managed/ManagedEditor.cpp index 5b45ea7d6..fdabf9056 100644 --- a/Source/Editor/Managed/ManagedEditor.cpp +++ b/Source/Editor/Managed/ManagedEditor.cpp @@ -457,24 +457,6 @@ Float2 ManagedEditor::GetGameWindowSize() return Float2::Zero; } -Float2 ManagedEditor::GetGameWindowViewportSize() -{ - if (HasManagedInstance()) - { - if (Internal_GetGameWindowSize == nullptr) - { - Internal_GetGameWindowSize = GetClass()->GetMethod("Internal_GetGameWindowViewportSize", 1); - ASSERT(Internal_GetGameWindowSize); - } - Float2 size; - void* params[1]; - params[0] = &size; - Internal_GetGameWindowSize->Invoke(GetManagedInstance(), params, nullptr); - return size; - } - return Float2::Zero; -} - bool ManagedEditor::OnAppExit() { if (!HasManagedInstance()) diff --git a/Source/Editor/Managed/ManagedEditor.h b/Source/Editor/Managed/ManagedEditor.h index cfacce2da..36fc0c234 100644 --- a/Source/Editor/Managed/ManagedEditor.h +++ b/Source/Editor/Managed/ManagedEditor.h @@ -133,12 +133,6 @@ public: /// The size. Float2 GetGameWindowSize(); - /// - /// Gets the size of the game window viewport output. - /// - /// The size. - Float2 GetGameWindowViewportSize(); - /// /// Called when application code calls exit. Editor may end play mode or exit normally. /// diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp index 3e19403cd..ea161c38a 100644 --- a/Source/Engine/Level/Actors/Camera.cpp +++ b/Source/Engine/Level/Actors/Camera.cpp @@ -189,7 +189,7 @@ Viewport Camera::GetViewport() const #if USE_EDITOR // Editor if (Editor::Managed) - result.Size = Editor::Managed->GetGameWindowViewportSize(); + result.Size = Editor::Managed->GetGameWindowSize(); #else // game auto mainWin = Engine::MainWindow; From 533a6576b87ee4272cb9056176f28dfd3234031f Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Tue, 7 Feb 2023 22:11:24 +0200 Subject: [PATCH 12/36] Link against zlib --- Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index 96ef470e4..352d6158e 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -96,6 +96,7 @@ namespace Flax.Build.Platforms args.Add("-pthread"); args.Add("-ldl"); args.Add("-lrt"); + args.Add("-lz"); // Link X11 args.Add("-L/usr/X11R6/lib"); From ca81ee39675da6cbb232cdbd36cc848a1a22b4e0 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Tue, 7 Feb 2023 22:27:31 +0200 Subject: [PATCH 13/36] Update Linux build instructions --- README.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4ef31c91c..3cbcfb6fe 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de * Install Windows 8.1 SDK or newer (via Visual Studio Installer) * Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer) * Install .Net Framework 4.5.2 SDK/Targeting Pack (via Visual Studio Installer) +* Install Git with LFS * Clone repo (with LFS) * Run **GenerateProjectFiles.bat** * Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64** @@ -48,12 +49,23 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de ## Linux * Install Visual Studio Code -* Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable)) -* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/)) +* Install Mono + * Ubuntu: see the instructions here: ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable)) + * Arch: `sudo pacman -S mono` +* Install Vulkan SDK + * Ubuntu: see the instructions here: ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/)) + * Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers` * Install Git with LFS -* Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext cmake python libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev` -* Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer) -* Clone repo (with LFS) + * Ubuntu: `sudo apt-get install git git-lfs` + * Arch: `sudo pacman -S git git-lfs` + * `git-lfs install` +* Install the required packages: + * Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev` + * Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib` +* Install Clang compiler (version 6 or later): + * Ubuntu: `sudo apt-get install clang lldb lld` + * Arch: `sudo pacman -S clang lldb lld` +* Clone the repository (with LFS) * Run `./GenerateProjectFiles.sh` * Open workspace with Visual Code * Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`) From b4cce7db009a09fc6f989c6a077b391e7c516155 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 12 Feb 2023 20:51:03 -0600 Subject: [PATCH 14/36] Fix issue with different lengths of text for scale properties. --- Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs index 727575a49..2612440a4 100644 --- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs @@ -96,7 +96,8 @@ namespace FlaxEditor.CustomEditors.Editors AnchorPreset = AnchorPresets.TopLeft, TooltipText = "Scale values are linked together.", }; - _linkImage.LocalX += 40; + var x = LinkedLabel.Text.Value.Length * 7 + 5; + _linkImage.LocalX += x; _linkImage.LocalY += 1; LinkedLabel.SetupContextMenu += (label, menu, editor) => From 4725a834062c42799ee1f93ec728c391b8fee6e1 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 12 Feb 2023 21:29:58 -0600 Subject: [PATCH 15/36] Move the child menu arrow image to accommodatefor the scroll bar showing when the amunt of items exceeds the maximum. --- Source/Editor/GUI/ContextMenu/ContextMenu.cs | 17 +++++++++++++++++ .../GUI/ContextMenu/ContextMenuChildMenu.cs | 7 ++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Source/Editor/GUI/ContextMenu/ContextMenu.cs b/Source/Editor/GUI/ContextMenu/ContextMenu.cs index e652bc98d..f2e5d30e3 100644 --- a/Source/Editor/GUI/ContextMenu/ContextMenu.cs +++ b/Source/Editor/GUI/ContextMenu/ContextMenu.cs @@ -365,6 +365,7 @@ namespace FlaxEditor.GUI.ContextMenu float maxWidth = 0; float height = _itemsAreaMargin.Height; int itemsLeft = MaximumItemsInViewCount; + int overflowItemCount = 0; for (int i = 0; i < _panel.Children.Count; i++) { if (_panel.Children[i] is ContextMenuItem item && item.Visible) @@ -374,11 +375,27 @@ namespace FlaxEditor.GUI.ContextMenu height += item.Height + _itemsMargin.Height; itemsLeft--; } + else + { + overflowItemCount++; + } maxWidth = Mathf.Max(maxWidth, item.MinimumWidth); } } maxWidth = Mathf.Max(maxWidth + 20, MinimumWidth); + // Move child arrows to accommodate scroll bar showing + if (overflowItemCount > 0) + { + foreach (var child in _panel.Children) + { + if (child is ContextMenuChildMenu item && item.Visible) + { + item.AdjustArrowAmount = -_panel.VScrollBar.Width; + } + } + } + // Resize container Size = new Float2(Mathf.Ceil(maxWidth), Mathf.Ceil(height)); diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuChildMenu.cs b/Source/Editor/GUI/ContextMenu/ContextMenuChildMenu.cs index ebf0a3b4a..0256d2bee 100644 --- a/Source/Editor/GUI/ContextMenu/ContextMenuChildMenu.cs +++ b/Source/Editor/GUI/ContextMenu/ContextMenuChildMenu.cs @@ -17,6 +17,11 @@ namespace FlaxEditor.GUI.ContextMenu /// public readonly ContextMenu ContextMenu = new ContextMenu(); + /// + /// The amount to adjust the arrow image by in x coordinates. + /// + public float AdjustArrowAmount = 0; + /// /// Initializes a new instance of the class. /// @@ -44,7 +49,7 @@ namespace FlaxEditor.GUI.ContextMenu // Draw arrow if (ContextMenu.HasChildren) - Render2D.DrawSprite(style.ArrowRight, new Rectangle(Width - 15, (Height - 12) / 2, 12, 12), Enabled ? isCMopened ? style.BackgroundSelected : style.Foreground : style.ForegroundDisabled); + Render2D.DrawSprite(style.ArrowRight, new Rectangle(Width - 15 + AdjustArrowAmount, (Height - 12) / 2, 12, 12), Enabled ? isCMopened ? style.BackgroundSelected : style.Foreground : style.ForegroundDisabled); } /// From 46cfa016225170410c17632f85cb6553208830a6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 16:04:33 +0100 Subject: [PATCH 16/36] Add `this` to `API_PARAM` for static method extension of a type --- .../Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs | 6 ++++++ Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs | 2 +- .../Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs | 3 +++ Source/Tools/Flax.Build/Bindings/FunctionInfo.cs | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index dc3e09b8f..6f7cba455 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -1005,6 +1005,8 @@ namespace Flax.Build.Bindings contents.Append("out "); else if (parameterInfo.IsRef) contents.Append("ref "); + else if (parameterInfo.IsThis) + contents.Append("this "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); @@ -1064,6 +1066,8 @@ namespace Flax.Build.Bindings contents.Append("out "); else if (parameterInfo.IsRef) contents.Append("ref "); + else if (parameterInfo.IsThis) + contents.Append("this "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); @@ -1374,6 +1378,8 @@ namespace Flax.Build.Bindings contents.Append("out "); else if (parameterInfo.IsRef) contents.Append("ref "); + else if (parameterInfo.IsThis) + contents.Append("this "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs index 0f0b011a0..d1aba9162 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs @@ -19,7 +19,7 @@ namespace Flax.Build.Bindings partial class BindingsGenerator { private static readonly Dictionary TypeCache = new Dictionary(); - private const int CacheVersion = 17; + private const int CacheVersion = 18; internal static void Write(BinaryWriter writer, string e) { diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index bca9b2d9d..b09b0c137 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -334,6 +334,9 @@ namespace Flax.Build.Bindings case "out": currentParam.IsOut = true; break; + case "this": + currentParam.IsThis = true; + break; case "attributes": currentParam.Attributes = tag.Value; break; diff --git a/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs b/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs index efadd193e..69ebe8580 100644 --- a/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs +++ b/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs @@ -18,6 +18,7 @@ namespace Flax.Build.Bindings public string Attributes; public bool IsRef; public bool IsOut; + public bool IsThis; public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue); @@ -35,6 +36,7 @@ namespace Flax.Build.Bindings // TODO: convert into flags writer.Write(IsRef); writer.Write(IsOut); + writer.Write(IsThis); } public void Read(BinaryReader reader) @@ -46,6 +48,7 @@ namespace Flax.Build.Bindings // TODO: convert into flags IsRef = reader.ReadBoolean(); IsOut = reader.ReadBoolean(); + IsThis = reader.ReadBoolean(); } public override string ToString() From cb83de47695095d4294055912a2637028ad2af83 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 16:05:14 +0100 Subject: [PATCH 17/36] Fix compilation issues with various C++ scripting cases --- Source/Engine/Content/SceneReference.h | 1 + Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Content/SceneReference.h b/Source/Engine/Content/SceneReference.h index dae02606f..da25b2c73 100644 --- a/Source/Engine/Content/SceneReference.h +++ b/Source/Engine/Content/SceneReference.h @@ -4,6 +4,7 @@ #include "Engine/Core/Types/Guid.h" #include "Engine/Core/ISerializable.h" +#include "Engine/Scripting/ScriptingType.h" /// /// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene. diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index a0184c63e..76ef5d805 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -2302,7 +2302,10 @@ namespace Flax.Build.Bindings separator = true; contents.Append(parameterInfo.Type).Append(' ').Append(parameterInfo.Name); } - contents.Append(") override").AppendLine(); + contents.Append(')'); + if (functionInfo.IsConst) + contents.Append(" const"); + contents.Append(" override").AppendLine(); contents.AppendLine(" {"); // TODO: try to use ScriptVTable for interfaces implementation in scripting to call proper function instead of manually check at runtime if (functionInfo.Parameters.Count != 0) From 19c24e2a4d98892cbd7f31a220451ef7662f05a0 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 17:14:53 +0100 Subject: [PATCH 18/36] Fix missing game scripts types when starting editor from IDE with `-skipCompile` arg --- .../Modules/SourceCodeEditing/CodeEditingModule.cs | 8 ++++++++ Source/Editor/Scripting/ScriptsBuilder.cpp | 8 ++++++++ Source/Editor/Scripting/ScriptsBuilder.cs | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs b/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs index 52302b785..a06e0f658 100644 --- a/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs +++ b/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs @@ -270,6 +270,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing { ScriptsBuilder.ScriptsReload += OnScriptsReload; ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd; + ScriptsBuilder.ScriptsLoaded += OnScriptsLoaded; Editor.Options.OptionsChanged += OnOptionsChanged; // Add default code editors (in-build) @@ -340,6 +341,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing ScriptsBuilder.ScriptsReload -= OnScriptsReload; ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd; + ScriptsBuilder.ScriptsLoaded -= OnScriptsLoaded; } /// @@ -375,6 +377,12 @@ namespace FlaxEditor.Modules.SourceCodeEditing OnTypesChanged(); } + private void OnScriptsLoaded() + { + // Clear any state with engine-only types + ClearTypes(); + } + private static bool IsTypeValidScriptingType(ScriptType t) { return !t.IsGenericType && !t.IsAbstract && !t.HasAttribute(typeof(HideInEditorAttribute), false); diff --git a/Source/Editor/Scripting/ScriptsBuilder.cpp b/Source/Editor/Scripting/ScriptsBuilder.cpp index e268d44c5..1284d2df9 100644 --- a/Source/Editor/Scripting/ScriptsBuilder.cpp +++ b/Source/Editor/Scripting/ScriptsBuilder.cpp @@ -37,6 +37,7 @@ enum class EventType ReloadBegin = 5, Reload = 6, ReloadEnd = 7, + ScriptsLoaded = 8, }; struct EventData @@ -74,6 +75,7 @@ namespace ScriptsBuilderImpl void onScriptsReloadStart(); void onScriptsReload(); void onScriptsReloadEnd(); + void onScriptsLoaded(); void GetClassName(const MString& fullname, MString& className); @@ -203,6 +205,11 @@ void ScriptsBuilderImpl::onScriptsReloadEnd() CallEvent(EventType::ReloadEnd); } +void ScriptsBuilderImpl::onScriptsLoaded() +{ + CallEvent(EventType::ScriptsLoaded); +} + void ScriptsBuilder::Compile() { ScopeLock scopeLock(_locker); @@ -550,6 +557,7 @@ bool ScriptsBuilderService::Init() Level::ScriptsReloadStart.Bind(onScriptsReloadStart); Level::ScriptsReload.Bind(onScriptsReload); Level::ScriptsReloadEnd.Bind(onScriptsReloadEnd); + Scripting::ScriptsLoaded.Bind(onScriptsLoaded); // Listen to code editors manager events CodeEditingManager::AsyncOpenBegin.Bind(onCodeEditorAsyncOpenBegin); diff --git a/Source/Editor/Scripting/ScriptsBuilder.cs b/Source/Editor/Scripting/ScriptsBuilder.cs index 67a43388a..3dacc9a95 100644 --- a/Source/Editor/Scripting/ScriptsBuilder.cs +++ b/Source/Editor/Scripting/ScriptsBuilder.cs @@ -66,6 +66,11 @@ namespace FlaxEditor /// public static event Action ScriptsReloadEnd; + /// + /// Occurs when engine loads game scripts. + /// + public static event Action ScriptsLoaded; + /// /// Occurs when code editor starts asynchronous open a file or a solution. /// @@ -86,6 +91,7 @@ namespace FlaxEditor ReloadBegin = 5, Reload = 6, ReloadEnd = 7, + ScriptsLoaded = 8, } internal static void Internal_OnEvent(EventType type) @@ -118,6 +124,9 @@ namespace FlaxEditor case EventType.ReloadEnd: ScriptsReloadEnd?.Invoke(); break; + case EventType.ScriptsLoaded: + ScriptsLoaded?.Invoke(); + break; } } From 8184d513e35fd2f51c915c732416665a21d6be63 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 20:04:35 +0100 Subject: [PATCH 19/36] Fix performance when using scene search field --- Source/Editor/Windows/Assets/PrefabWindow.cs | 6 +++--- Source/Editor/Windows/SceneTreeWindow.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Editor/Windows/Assets/PrefabWindow.cs b/Source/Editor/Windows/Assets/PrefabWindow.cs index 8879ff904..7a283e52d 100644 --- a/Source/Editor/Windows/Assets/PrefabWindow.cs +++ b/Source/Editor/Windows/Assets/PrefabWindow.cs @@ -235,14 +235,14 @@ namespace FlaxEditor.Windows.Assets if (IsLayoutLocked) return; - var root = Graph.Root; - root.TreeNode.LockChildrenRecursive(); + _tree.LockChildrenRecursive(); // Update tree var query = _searchBox.Text; + var root = Graph.Root; root.TreeNode.UpdateFilter(query); - root.TreeNode.UnlockChildrenRecursive(); + _tree.UnlockChildrenRecursive(); PerformLayout(); PerformLayout(); } diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index a07bdd71f..f46c22ad4 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -123,14 +123,14 @@ namespace FlaxEditor.Windows if (IsLayoutLocked) return; - var root = Editor.Scene.Root; - root.TreeNode.LockChildrenRecursive(); + _tree.LockChildrenRecursive(); // Update tree var query = _searchBox.Text; + var root = Editor.Scene.Root; root.TreeNode.UpdateFilter(query); - root.TreeNode.UnlockChildrenRecursive(); + _tree.UnlockChildrenRecursive(); PerformLayout(); PerformLayout(); } From 705a6350598db62989bbc412385728ff17ff4796 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Mon, 13 Feb 2023 20:06:59 +0200 Subject: [PATCH 20/36] Fix LinuxFileSystemWatcher not working in sub-directories --- .../Platform/Linux/LinuxFileSystemWatcher.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp b/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp index 93457623c..a695d9d3c 100644 --- a/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp +++ b/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp @@ -140,7 +140,7 @@ namespace FileSystemWatchers void AddDirWatcher(const int rootFileDesc, const String& path) { - auto watcher = New(path, false, rootFileDesc); + auto watcher = New(path, true, rootFileDesc); Pair subDir = Pair(path, watcher); } @@ -183,8 +183,16 @@ LinuxFileSystemWatcher::LinuxFileSystemWatcher(const String& directory, bool wit FileSystemWatchers::Watchers[WachedDirectory] = Pair>(rootWatcher, Pair(directory, this)); if (withSubDirs) { - FileSystemWatchers::RootWatchers[WachedDirectory] = this; - FileSystemWatchers::AddSubDirWatcher(WachedDirectory, directory); + if (rootWatcher == -1) + { + FileSystemWatchers::RootWatchers[WachedDirectory] = this; + FileSystemWatchers::AddSubDirWatcher(WachedDirectory, directory); + } + else + { + FileSystemWatchers::RootWatchers[WachedDirectory] = FileSystemWatchers::RootWatchers[rootWatcher]; + FileSystemWatchers::AddSubDirWatcher(rootWatcher, directory); + } } } FileSystemWatchers::Locker.Unlock(); From 0031d9174d2098dab801b062c8303e00cd919e10 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 22:10:45 +0100 Subject: [PATCH 21/36] Fix scroll on selection change --- Source/Editor/Windows/SceneTreeWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index f46c22ad4..532f400a3 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -251,7 +251,7 @@ namespace FlaxEditor.Windows if (nodes.Count == 1) { nodes[0].ExpandAllParents(true); - ScrollViewTo(nodes[0]); + _sceneTreePanel.ScrollViewTo(nodes[0]); } } From aad2ff51fc5d42266876e9db5c21c76f4a819cef Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 22:35:32 +0100 Subject: [PATCH 22/36] Fix default value for `BoxCollider` --- Source/Engine/Physics/Colliders/BoxCollider.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h index c4ee6c2b5..0cc0e7be9 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.h +++ b/Source/Engine/Physics/Colliders/BoxCollider.h @@ -22,7 +22,7 @@ public: /// Gets the size of the box, measured in the object's local space. /// /// The box size will be scaled by the actor's world scale. - API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(typeof(Vector3), \"100,100,100\"), EditorDisplay(\"Collider\")") + API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(typeof(Float3), \"100,100,100\"), EditorDisplay(\"Collider\")") FORCE_INLINE Float3 GetSize() const { return _size; From 1034a15ddc7cfe8df91543d61d30660c739ed4b7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 22:35:49 +0100 Subject: [PATCH 23/36] Fix default `SceneRenderTask` view to have initialized matrices --- Source/Engine/Graphics/RenderTask.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp index e10f4b6f5..48e89f59e 100644 --- a/Source/Engine/Graphics/RenderTask.cpp +++ b/Source/Engine/Graphics/RenderTask.cpp @@ -134,9 +134,15 @@ bool RenderTask::Resize(int32 width, int32 height) SceneRenderTask::SceneRenderTask(const SpawnParams& params) : RenderTask(params) { + Buffers = New(); + + // Initialize view View.Position = Float3::Zero; View.Direction = Float3::Forward; - Buffers = New(); + Matrix::PerspectiveFov(PI_OVER_2, 1.0f, View.Near, View.Far, View.Projection); + View.NonJitteredProjection = View.Projection; + Matrix::Invert(View.Projection, View.IP); + View.SetFace(4); } SceneRenderTask::~SceneRenderTask() From a70234c9b678524c85c697e7b82d5cf676bf496f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Feb 2023 22:45:44 +0100 Subject: [PATCH 24/36] Cleanup comments --- Source/Engine/Level/Actors/PostFxVolume.h | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/Source/Engine/Level/Actors/PostFxVolume.h b/Source/Engine/Level/Actors/PostFxVolume.h index 21ad1a010..577f05e57 100644 --- a/Source/Engine/Level/Actors/PostFxVolume.h +++ b/Source/Engine/Level/Actors/PostFxVolume.h @@ -100,10 +100,8 @@ public: public: /// - /// Gets the order in which multiple volumes are blended together. - /// The volume with the highest priority takes precedence over all other overlapping volumes. + /// Gets the order in which multiple volumes are blended together. The volume with the highest priority takes precedence over all other overlapping volumes. /// - /// The result. API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(60)") FORCE_INLINE int32 GetPriority() const { @@ -111,10 +109,8 @@ public: } /// - /// Sets the order in which multiple volumes are blended together. - /// The volume with the highest priority takes precedence over all other overlapping volumes. + /// Sets the order in which multiple volumes are blended together. The volume with the highest priority takes precedence over all other overlapping volumes. /// - /// The value. API_PROPERTY() FORCE_INLINE void SetPriority(int32 value) { _priority = value; @@ -123,7 +119,6 @@ public: /// /// Gets the distance inside the volume at which blending with the volume's settings occurs. /// - /// The result. API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(70)") FORCE_INLINE float GetBlendRadius() const { @@ -133,7 +128,6 @@ public: /// /// Sets the distance inside the volume at which blending with the volume's settings occurs. /// - /// The value. API_PROPERTY() void SetBlendRadius(float value) { _blendRadius = Math::Clamp(value, 0.0f, 1000.0f); @@ -142,7 +136,6 @@ public: /// /// Gets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect. /// - /// The result. API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(80)") FORCE_INLINE float GetBlendWeight() const { @@ -152,18 +145,14 @@ public: /// /// Sets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect. /// - /// The value. API_PROPERTY() void SetBlendWeight(float value) { _blendWeight = Math::Saturate(value); } /// - /// Gets the value indicating whether the bounds of the volume are taken into account. - /// If false, the volume affects the entire world, regardless of its bounds. - /// If true, the volume only has an effect within its bounds. + /// Gets the value indicating whether the bounds of the volume are taken into account. If false, the volume affects the entire world, regardless of its bounds. If true, the volume only has an effect within its bounds. /// - /// The result. API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(90)") FORCE_INLINE bool GetIsBounded() const { @@ -171,11 +160,8 @@ public: } /// - /// Sets the value indicating whether the bounds of the volume are taken into account. - /// If false, the volume affects the entire world, regardless of its bounds. - /// If true, the volume only has an effect within its bounds. + /// Sets the value indicating whether the bounds of the volume are taken into account. If false, the volume affects the entire world, regardless of its bounds. If true, the volume only has an effect within its bounds. /// - /// The value. API_PROPERTY() FORCE_INLINE void SetIsBounded(bool value) { _isBounded = value; From 77e19e148b37031460b907daf37ff7c3d6cb719b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Feb 2023 09:31:23 +0100 Subject: [PATCH 25/36] Fix missing `TraceMode` blending in PostFx volume for SSR settings --- Source/Engine/Graphics/PostProcessSettings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Engine/Graphics/PostProcessSettings.cpp b/Source/Engine/Graphics/PostProcessSettings.cpp index 3b28107b2..a564bc85f 100644 --- a/Source/Engine/Graphics/PostProcessSettings.cpp +++ b/Source/Engine/Graphics/PostProcessSettings.cpp @@ -172,6 +172,7 @@ void ScreenSpaceReflectionsSettings::BlendWith(ScreenSpaceReflectionsSettings& o const bool isHalf = weight >= 0.5f; BLEND_FLOAT(Intensity); + BLEND_ENUM(TraceMode); BLEND_ENUM(DepthResolution); BLEND_ENUM(RayTracePassResolution); BLEND_FLOAT(BRDFBias); From 835127ac21690d3e896dd12cbecc5f52dce79784 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Feb 2023 12:39:58 +0100 Subject: [PATCH 26/36] Add **Animation Instance Data node to Anim Graph** for caching value per-model --- Source/Editor/Surface/Archetypes/Animation.cs | 13 +++++++++++++ Source/Engine/Animations/Graph/AnimGraph.Base.cpp | 11 +++++++++-- Source/Engine/Animations/Graph/AnimGraph.h | 7 +++++++ .../Animations/Graph/AnimGroup.Animation.cpp | 14 +++++++++++++- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs index dd214e8fc..b951f5f70 100644 --- a/Source/Editor/Surface/Archetypes/Animation.cs +++ b/Source/Editor/Surface/Archetypes/Animation.cs @@ -973,6 +973,19 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.TextBox(30, Surface.Constants.LayoutOffsetY, 140, TextBox.DefaultHeight, 0, false), } }, + new NodeArchetype + { + TypeID = 33, + Title = "Animation Instance Data", + Description = "Caches custom data per-instance and allow sampling it. Can be used to randomize animation play offset to offer randomization for crowds reusing the same graph.", + Flags = NodeFlags.AnimGraph, + Size = new Float2(240, 20), + Elements = new[] + { + NodeElementArchetype.Factory.Output(0, "Get", typeof(Float4), 0), + NodeElementArchetype.Factory.Input(0, "Init", true, typeof(Float4), 1), + } + }, }; } } diff --git a/Source/Engine/Animations/Graph/AnimGraph.Base.cpp b/Source/Engine/Animations/Graph/AnimGraph.Base.cpp index 3205337ad..d7cdbeecd 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.Base.cpp +++ b/Source/Engine/Animations/Graph/AnimGraph.Base.cpp @@ -115,6 +115,11 @@ void SlotBucketInit(AnimGraphInstanceData::Bucket& bucket) bucket.Slot.LoopsLeft = 0; } +void InstanceDataBucketInit(AnimGraphInstanceData::Bucket& bucket) +{ + bucket.InstanceData.Init = true; +} + bool SortMultiBlend1D(const byte& a, const byte& b, AnimGraphNode* n) { // Sort items by X location from the lowest to the highest @@ -432,10 +437,12 @@ bool AnimGraphBase::onNodeLoaded(Node* n) } // Animation Slot case 32: - { ADD_BUCKET(SlotBucketInit); break; - } + // Animation Instance Data + case 33: + ADD_BUCKET(InstanceDataBucketInit); + break; } break; // Custom diff --git a/Source/Engine/Animations/Graph/AnimGraph.h b/Source/Engine/Animations/Graph/AnimGraph.h index 6f469dcb6..aeb91fbd0 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.h +++ b/Source/Engine/Animations/Graph/AnimGraph.h @@ -315,6 +315,12 @@ public: int32 LoopsLeft; }; + struct InstanceDataBucket + { + bool Init; + float Data[4]; + }; + /// /// The single data storage bucket for the instanced animation graph node. Used to store the node state (playback position, state, transition data). /// @@ -327,6 +333,7 @@ public: BlendPoseBucket BlendPose; StateMachineBucket StateMachine; SlotBucket Slot; + InstanceDataBucket InstanceData; }; }; diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp index 9b74ff347..86aa42ff6 100644 --- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp +++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp @@ -2035,10 +2035,22 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu } break; } + // Animation Instance Data + case 33: + { + auto& bucket = context.Data->State[node->BucketIndex].InstanceData; + if (bucket.Init) + { + bucket.Init = false; + *(Float4*)bucket.Data = (Float4)tryGetValue(node->GetBox(1), Value::Zero); + } + value = *(Float4*)bucket.Data; + break; + } default: break; } - context.ValueCache.Add(boxBase, value); + context.ValueCache[boxBase] = value; } void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& value) From 7d6472a1608cd0d9f8c2fa517808bda8bce6e060 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Feb 2023 13:13:35 +0100 Subject: [PATCH 27/36] Fix deadlock in navmesh capacity calculations --- Source/Engine/Navigation/NavMeshRuntime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Navigation/NavMeshRuntime.cpp b/Source/Engine/Navigation/NavMeshRuntime.cpp index 5b229a424..b09f8346a 100644 --- a/Source/Engine/Navigation/NavMeshRuntime.cpp +++ b/Source/Engine/Navigation/NavMeshRuntime.cpp @@ -352,7 +352,7 @@ void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount) // Navmesh tiles capacity growing rule int32 newCapacity = capacity ? capacity : 32; while (newCapacity < newTilesCount) - newCapacity = Math::RoundUpToPowerOf2(newCapacity); + newCapacity = Math::RoundUpToPowerOf2(newCapacity + 1); LOG(Info, "Resizing navmesh {2} from {0} to {1} tiles capacity", capacity, newCapacity, Properties.Name); From 752fa64cc335e1230f084e671e0224512c5f5f85 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Feb 2023 13:14:04 +0100 Subject: [PATCH 28/36] Add support for 32 bit indices for the terrain chunk geometry --- .../Editor/MaterialTemplates/Terrain.shader | 8 --- .../Tools/Terrain/CreateTerrainDialog.cs | 4 +- Source/Engine/Terrain/TerrainManager.cpp | 57 ++++++++++++++----- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index b60ca2a3c..32395d583 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -269,24 +269,16 @@ float CalcLOD(float2 xy, float4 morph) if ((xy.x + xy.y) > 1) { if (xy.x < xy.y) - { lod = lodCalculated.w; - } else - { lod = lodCalculated.z; - } } else { if (xy.x < xy.y) - { lod = lodCalculated.y; - } else - { lod = lodCalculated.x; - } } return lod; diff --git a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs index 537121001..252891d44 100644 --- a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs +++ b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs @@ -26,7 +26,9 @@ namespace FlaxEditor.Tools.Terrain _31 = 31, _63 = 63, _127 = 127, + _254 = 254, _255 = 255, + _511 = 511, } private class Options @@ -34,7 +36,7 @@ namespace FlaxEditor.Tools.Terrain [EditorOrder(100), EditorDisplay("Layout", "Number Of Patches"), DefaultValue(typeof(Int2), "1,1"), Limit(0, 512), Tooltip("Amount of terrain patches in each direction (X and Z). Each terrain patch contains a grid of 16 chunks. Patches can be later added or removed from terrain using a terrain editor tool.")] public Int2 NumberOfPatches = new Int2(1, 1); - [EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD). Must be power of two minus one (eg. 63).")] + [EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD).")] public ChunkSizes ChunkSize = ChunkSizes._127; [EditorOrder(120), EditorDisplay("Layout", "LOD Count"), DefaultValue(6), Limit(1, FlaxEngine.Terrain.MaxLODs), Tooltip("The maximum Level Of Details count. The actual amount of LODs may be lower due to provided chunk size (each LOD has 4 times less quads).")] diff --git a/Source/Engine/Terrain/TerrainManager.cpp b/Source/Engine/Terrain/TerrainManager.cpp index 0980bcc7a..df9b6d706 100644 --- a/Source/Engine/Terrain/TerrainManager.cpp +++ b/Source/Engine/Terrain/TerrainManager.cpp @@ -98,10 +98,12 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32 // Prepare const int32 vertexCount = (chunkSize + 1) >> lodIndex; chunkSize = vertexCount - 1; + const bool indexUse16bits = chunkSize * chunkSize * vertexCount < MAX_uint16; + const int32 indexSize = indexUse16bits ? sizeof(uint16) : sizeof(uint32); const int32 indexCount = chunkSize * chunkSize * 2 * 3; const int32 vertexCount2 = vertexCount * vertexCount; const int32 vbSize = sizeof(TerrainVertex) * vertexCount2; - const int32 ibSize = sizeof(uint16) * indexCount; + const int32 ibSize = indexSize * indexCount; TempData.Clear(); TempData.EnsureCapacity(Math::Max(vbSize, ibSize)); @@ -140,26 +142,51 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32 // Create index buffer auto ib = GPUDevice::Instance->CreateBuffer(TEXT("TerrainChunk.IB")); - auto index = (uint16*)TempData.Get(); - for (int32 z = 0; z < chunkSize; z++) + if (indexUse16bits) { - for (int32 x = 0; x < chunkSize; x++) + auto index = (uint16*)TempData.Get(); + for (int32 z = 0; z < chunkSize; z++) { - const uint16 i00 = (x + 0) + (z + 0) * vertexCount; - const uint16 i10 = (x + 1) + (z + 0) * vertexCount; - const uint16 i11 = (x + 1) + (z + 1) * vertexCount; - const uint16 i01 = (x + 0) + (z + 1) * vertexCount; + for (int32 x = 0; x < chunkSize; x++) + { + const uint16 i00 = (x + 0) + (z + 0) * vertexCount; + const uint16 i10 = (x + 1) + (z + 0) * vertexCount; + const uint16 i11 = (x + 1) + (z + 1) * vertexCount; + const uint16 i01 = (x + 0) + (z + 1) * vertexCount; - *index++ = i00; - *index++ = i11; - *index++ = i10; + *index++ = i00; + *index++ = i11; + *index++ = i10; - *index++ = i00; - *index++ = i01; - *index++ = i11; + *index++ = i00; + *index++ = i01; + *index++ = i11; + } } } - desc = GPUBufferDescription::Index(sizeof(uint16), indexCount, TempData.Get()); + else + { + auto index = (uint32*)TempData.Get(); + for (int32 z = 0; z < chunkSize; z++) + { + for (int32 x = 0; x < chunkSize; x++) + { + const uint32 i00 = (x + 0) + (z + 0) * vertexCount; + const uint32 i10 = (x + 1) + (z + 0) * vertexCount; + const uint32 i11 = (x + 1) + (z + 1) * vertexCount; + const uint32 i01 = (x + 0) + (z + 1) * vertexCount; + + *index++ = i00; + *index++ = i11; + *index++ = i10; + + *index++ = i00; + *index++ = i01; + *index++ = i11; + } + } + } + desc = GPUBufferDescription::Index(indexSize, indexCount, TempData.Get()); if (ib->Init(desc)) { vb->ReleaseGPU(); From 47afc7817f8ffd9dfbfa12014efa0c59a080d7fb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 14 Feb 2023 15:27:13 +0100 Subject: [PATCH 29/36] Improve building for Android --- .../Cooker/Platform/Android/AndroidPlatformTools.cpp | 11 ++++++----- .../Tools/Flax.Build/Platforms/Android/AndroidSdk.cs | 8 ++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp index 11e437d0a..6610f2295 100644 --- a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp @@ -289,13 +289,14 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) return true; } String androidSdk; - if (!envVars.TryGet(TEXT("ANDROID_SDK"), androidSdk) || !FileSystem::DirectoryExists(androidSdk)) + if (!envVars.TryGet(TEXT("ANDROID_HOME"), androidSdk) || !FileSystem::DirectoryExists(androidSdk)) { - LOG(Error, "Missing or invalid ANDROID_SDK env variable. {0}", androidSdk); - return true; + if (!envVars.TryGet(TEXT("ANDROID_SDK"), androidSdk) || !FileSystem::DirectoryExists(androidSdk)) + { + LOG(Error, "Missing or invalid ANDROID_HOME env variable. {0}", androidSdk); + return true; + } } - if (!envVars.ContainsKey(TEXT("ANDROID_SDK_ROOT"))) - envVars[TEXT("ANDROID_SDK_ROOT")] = androidSdk; // Build Gradle project into package LOG(Info, "Building Gradle project into package..."); diff --git a/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs b/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs index 5fa8eae30..a023d33b2 100644 --- a/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs +++ b/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs @@ -33,7 +33,9 @@ namespace Flax.Build.Platforms return; // Find Android SDK folder path - var sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK"); + var sdkPath = Environment.GetEnvironmentVariable("ANDROID_HOME"); + if (string.IsNullOrEmpty(sdkPath)) + sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK"); if (string.IsNullOrEmpty(sdkPath)) { // Look for adb in Android folders of some common locations @@ -53,6 +55,8 @@ namespace Flax.Build.Platforms foreach (string searchDir in searchDirs) { string androidDir = Path.Combine(searchDir, "Android"); + if (!Directory.Exists(androidDir)) + androidDir = Path.Combine(searchDir, "sdk"); if (Directory.Exists(androidDir)) { string[] subDirs = Directory.GetDirectories(androidDir, "*sdk*", SearchOption.TopDirectoryOnly); @@ -72,7 +76,7 @@ namespace Flax.Build.Platforms } else if (!Directory.Exists(sdkPath)) { - Log.Warning(string.Format("Specified Android SDK folder in ANDROID_SDK env variable doesn't exist ({0})", sdkPath)); + Log.Warning(string.Format("Specified Android SDK folder in ANDROID_HOME env variable doesn't exist ({0})", sdkPath)); } if (string.IsNullOrEmpty(sdkPath)) { From c7d6aca2ad2a28aa92ca9dc2750cb3d51aca5b20 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 29 Jan 2023 19:12:24 +0200 Subject: [PATCH 30/36] Use alternative method to query DPI on Linux --- .../Engine/Platform/Linux/LinuxPlatform.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index a5bd099c9..3effd5d03 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -840,17 +840,17 @@ int X11ErrorHandler(X11::Display* display, X11::XErrorEvent* event) int32 CalculateDpi() { - // in X11 a screen is not necessarily identical to a desktop - // so we need to stick to one type for pixel and physical size query + int dpi = 96; + char* resourceString = X11::XResourceManagerString(xDisplay); + if (resourceString == NULL) + return dpi; - int screenIdx = 0; - int widthMM = X11_DisplayWidthMM(xDisplay, screenIdx); - int heightMM = X11_DisplayHeightMM(xDisplay, screenIdx); - double xdpi = (widthMM ? X11_DisplayWidth(xDisplay, screenIdx) / (double)widthMM * 25.4 : 0); - double ydpi = (heightMM ? X11_DisplayHeight(xDisplay, screenIdx) / (double)heightMM * 25.4 : 0); - if (xdpi || ydpi) - return (int32)Math::Ceil((xdpi + ydpi) / (xdpi && ydpi ? 2 : 1)); - return 96; + char* type = NULL; + X11::XrmValue value; + X11::XrmDatabase database = X11::XrmGetStringDatabase(resourceString); + if (X11::XrmGetResource(database, "Xft.dpi", "String", &type, &value) == 1 && value.addr != NULL) + dpi = (int)atof(value.addr); + return dpi; } // Maps Flax key codes to X11 names for physical key locations. @@ -2101,6 +2101,7 @@ bool LinuxPlatform::Init() xAtomWmName = X11::XInternAtom(xDisplay, "_NET_WM_NAME", 0); xAtomClipboard = X11::XInternAtom(xDisplay, "CLIPBOARD", 0); + X11::XrmInitialize(); SystemDpi = CalculateDpi(); int cursorSize = X11::XcursorGetDefaultSize(xDisplay); From e3cfe9f009ff9a92f1cd02aa2017e94a5b8ee686 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 17 Jan 2023 15:34:45 +0100 Subject: [PATCH 31/36] Add support for using system-installed Vulkan SDK on Linux --- .../Vulkan/GraphicsDeviceVulkan.Build.cs | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs b/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs index c56619a0f..b2780f7ca 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs +++ b/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs @@ -40,20 +40,29 @@ public sealed class VulkanSdk : Sdk return; var vulkanSdk = Environment.GetEnvironmentVariable("VULKAN_SDK"); - if (platform == TargetPlatform.Mac && (vulkanSdk == null || !Directory.Exists(vulkanSdk))) + if (vulkanSdk == null || !Directory.Exists(vulkanSdk)) { - // Try to guess install location for the current user - var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "VulkanSDK"); - if (Directory.Exists(path)) + if (platform == TargetPlatform.Mac) { - var subDirs = Directory.GetDirectories(path); - if (subDirs.Length != 0) + // Try to guess install location for the current user + var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "VulkanSDK"); + if (Directory.Exists(path)) { - path = Path.Combine(subDirs[0], "macOS"); - if (Directory.Exists(path)) - vulkanSdk = path; + var subDirs = Directory.GetDirectories(path); + if (subDirs.Length != 0) + { + path = Path.Combine(subDirs[0], "macOS"); + if (Directory.Exists(path)) + vulkanSdk = path; + } } } + else if (platform == TargetPlatform.Linux) + { + // Try to use system-installed Vulkan SDK + if (File.Exists("/usr/include/vulkan/vulkan.h")) + vulkanSdk = "/usr/include"; + } } if (vulkanSdk != null) { @@ -87,13 +96,20 @@ public sealed class VulkanSdk : Sdk { var vulkanSdk = RootPath; + // Use system-installed headers + if (vulkanSdk.EndsWith("/include") && Directory.Exists(vulkanSdk)) + { + includesFolderPath = vulkanSdk; + return true; + } + + // Check potential location with headers var includes = new[] { Path.Combine(vulkanSdk, "include"), Path.Combine(vulkanSdk, "Include"), Path.Combine(vulkanSdk, "x86_64", "include"), }; - foreach (var include in includes) { if (Directory.Exists(include)) From e40f51cfc5908f8fcd36e531da98dde46187c665 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 15 Feb 2023 10:33:49 +0100 Subject: [PATCH 32/36] Add better logging for the Linxu includes search --- .../Platforms/Linux/LinuxToolchain.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index 9bc9aab33..1a0557c94 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -24,14 +24,30 @@ namespace Flax.Build.Platforms { // Setup system paths var includePath = Path.Combine(ToolsetRoot, "usr", "include"); + if (!Directory.Exists(includePath)) + { + var error = $"Missing toolset header files location {includePath}"; + Log.Error(error); + } SystemIncludePaths.Add(includePath); var cppIncludePath = Path.Combine(includePath, "c++", ClangVersion.ToString()); - if (Directory.Exists(cppIncludePath)) - SystemIncludePaths.Add(cppIncludePath); + if (!Directory.Exists(cppIncludePath)) + { + var error = $"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}"; + cppIncludePath = Path.Combine(ToolsetRoot, "usr", "lib", "llvm-" + ClangVersion.Major.ToString(), "include", "c++", "v1"); + if (!Directory.Exists(cppIncludePath)) + Log.Error(error); + } + SystemIncludePaths.Add(cppIncludePath); var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang"); var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include"); if (!Directory.Exists(clangIncludePath)) + { + var error = $"Missing Clang {ClangVersion} header files location {clangIncludePath}"; clangIncludePath = Path.Combine(clangLibPath, ClangVersion.ToString(), "include"); + if (!Directory.Exists(clangIncludePath)) + Log.Error(error); + } SystemIncludePaths.Add(clangIncludePath); } From d48f61ea33a60c58a80f1b3cfb79eda6ea78dfa0 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 15 Feb 2023 11:18:15 +0100 Subject: [PATCH 33/36] Fix regression from e40f51cfc5908f8fcd36e531da98dde46187c665 --- .../Platforms/Linux/LinuxToolchain.cs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index 1a0557c94..f8faa3cc0 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -24,21 +24,15 @@ namespace Flax.Build.Platforms { // Setup system paths var includePath = Path.Combine(ToolsetRoot, "usr", "include"); - if (!Directory.Exists(includePath)) - { - var error = $"Missing toolset header files location {includePath}"; - Log.Error(error); - } - SystemIncludePaths.Add(includePath); + if (Directory.Exists(includePath)) + SystemIncludePaths.Add(includePath); + else + Log.Error($"Missing toolset header files location {includePath}"); var cppIncludePath = Path.Combine(includePath, "c++", ClangVersion.ToString()); - if (!Directory.Exists(cppIncludePath)) - { - var error = $"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}"; - cppIncludePath = Path.Combine(ToolsetRoot, "usr", "lib", "llvm-" + ClangVersion.Major.ToString(), "include", "c++", "v1"); - if (!Directory.Exists(cppIncludePath)) - Log.Error(error); - } - SystemIncludePaths.Add(cppIncludePath); + if (Directory.Exists(cppIncludePath)) + SystemIncludePaths.Add(cppIncludePath); + else + Log.Error($"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}"); var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang"); var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include"); if (!Directory.Exists(clangIncludePath)) From 55ea197d4f789c5e7563e88aa762bba9a06b5497 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 15 Feb 2023 13:53:43 +0100 Subject: [PATCH 34/36] Hide not important log error --- Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index f8faa3cc0..d966cafdf 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -32,7 +32,7 @@ namespace Flax.Build.Platforms if (Directory.Exists(cppIncludePath)) SystemIncludePaths.Add(cppIncludePath); else - Log.Error($"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}"); + Log.Verbose($"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}"); var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang"); var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include"); if (!Directory.Exists(clangIncludePath)) From 3c9d592d8b842aa6ab7754c91caccfd1c9c02091 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 15 Feb 2023 14:19:56 +0100 Subject: [PATCH 35/36] Code style fix --- Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp b/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp index a695d9d3c..2f1f1219c 100644 --- a/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp +++ b/Source/Engine/Platform/Linux/LinuxFileSystemWatcher.cpp @@ -101,7 +101,7 @@ namespace FileSystemWatchers { } else - { + { GetRootWatcher(event->wd)->OnEvent(name, FileSystemAction::Modify); } } From 4fb336bc9e5c3351f193a3cea37ff5c9b7262ea2 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 15 Feb 2023 15:39:01 +0100 Subject: [PATCH 36/36] Add thread object usage docs #917 --- Source/Engine/Platform/Base/ThreadBase.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Engine/Platform/Base/ThreadBase.h b/Source/Engine/Platform/Base/ThreadBase.h index f9e78b555..dffae8005 100644 --- a/Source/Engine/Platform/Base/ThreadBase.h +++ b/Source/Engine/Platform/Base/ThreadBase.h @@ -12,6 +12,7 @@ class IRunnable; /// /// Base class for thread objects. /// +/// Ensure to call Kill or Join before deleting thread object. class FLAXENGINE_API ThreadBase : public Object, public NonCopyable { public: