diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index df6fa97b9..3238ce5c2 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -3,6 +3,24 @@ on: [push, pull_request] jobs: + # Editor + editor-linux: + name: Editor (Linux, Development x64) + runs-on: "ubuntu-20.04" + steps: + - name: Install dependencies + run: | + sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4-gnutls-dev + - name: Checkout repo + uses: actions/checkout@v2 + - name: Checkout LFS + run: | + git lfs version + git lfs pull + - name: Build + run: | + ./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor + # Game game-linux: name: Game (Linux, Release x64) diff --git a/Content/Editor/Particles/Constant Burst.flax b/Content/Editor/Particles/Constant Burst.flax index 6e8dc3057..7a160baae 100644 --- a/Content/Editor/Particles/Constant Burst.flax +++ b/Content/Editor/Particles/Constant Burst.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5c47c264658adc60ba1809e50039dbaa50c3157d678d31edb8328a143f6dd34 -size 2269 +oid sha256:116453e2aa2950832d6ca0300e65591f7ffbbe262dc5b3d41af4ad465eee130c +size 2671 diff --git a/Content/Editor/Particles/Periodic Burst.flax b/Content/Editor/Particles/Periodic Burst.flax index 6bbb5b7d7..b165f1ee9 100644 --- a/Content/Editor/Particles/Periodic Burst.flax +++ b/Content/Editor/Particles/Periodic Burst.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d7266e3179077f26b1a12617cdb9b1733fd753ee557f2d81ea58a48fa4265f4 -size 3039 +oid sha256:43ab024ecfd3b54aecce42f9bdc8d81fe1c35719146996e336c2105540de1594 +size 3621 diff --git a/Content/Editor/Particles/Ribbon Spiral.flax b/Content/Editor/Particles/Ribbon Spiral.flax index bff7f09a9..6cabcdce6 100644 --- a/Content/Editor/Particles/Ribbon Spiral.flax +++ b/Content/Editor/Particles/Ribbon Spiral.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1bbb361118d68c52d4fd8176c01c144f2f3105ac13b80b33ea23101f40589ea -size 1992 +oid sha256:43d743429f984745a3eeb22fa74fe4462e1f0d7b638f65ded06fc6f14dadb175 +size 2365 diff --git a/Content/Editor/Particles/Smoke.flax b/Content/Editor/Particles/Smoke.flax index cb474f3c3..e68821034 100644 --- a/Content/Editor/Particles/Smoke.flax +++ b/Content/Editor/Particles/Smoke.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9787b9b4cc2caf91c65b4d858cfcb11afe0fe4917c0f741f3e0099ba687e4da9 -size 15421 +oid sha256:84c4ea742b6b4775bc518731ecb56d7fe202302b3bdb61f1dcdf8727ade94353 +size 16019 diff --git a/Content/Editor/Particles/Sparks.flax b/Content/Editor/Particles/Sparks.flax index 9a94e1f98..8b076afdc 100644 --- a/Content/Editor/Particles/Sparks.flax +++ b/Content/Editor/Particles/Sparks.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1abf314458e98bd45638abab1092dea374d68c9cb5085f6d3a5de65947f62ea7 -size 14743 +oid sha256:3a6dc75b65f0eb1a66b12fbe4e20091b55aed9143a8574e7a9dfc000413eb2f6 +size 15081 diff --git a/README.md b/README.md index f7f72e5c9..7d836ed55 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de * Install Visual Studio Code * Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable)) * Install Git with LFS -* Install requried packages: `sudo apt-get install nuget autoconf libtool libogg-dev automake build-essential gettext cmake python curl libtool-bin libx11-dev libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4-gnutls-dev` +* Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext cmake python curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4-gnutls-dev` * Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer) * Clone repo (with LFS) * Run `./GenerateProjectFiles.sh` diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index 3d41d0904..293e7d030 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -282,7 +282,13 @@ namespace FlaxEditor.SceneGraph.Actors { // Remove unused points while (srcCount > dstCount) - ActorChildNodes[srcCount-- - 1].Dispose(); + { + var node = ActorChildNodes[srcCount-- - 1]; + // TODO: support selection interface inside SceneGraph nodes (eg. on Root) so prefab editor can handle this too + if (Editor.Instance.SceneEditing.Selection.Contains(node)) + Editor.Instance.SceneEditing.Deselect(); + node.Dispose(); + } // Add new points var id = ID; diff --git a/Source/Editor/Scripting/CodeEditors/VisualStudioCodeEditor.cpp b/Source/Editor/Scripting/CodeEditors/VisualStudioCodeEditor.cpp index ac226fd2c..64f157db0 100644 --- a/Source/Editor/Scripting/CodeEditors/VisualStudioCodeEditor.cpp +++ b/Source/Editor/Scripting/CodeEditors/VisualStudioCodeEditor.cpp @@ -8,6 +8,9 @@ #include "Editor/Scripting/ScriptsBuilder.h" #include "Engine/Engine/Globals.h" #include "Engine/Platform/Win32/IncludeWindowsHeaders.h" +#if PLATFORM_LINUX +#include +#endif VisualStudioCodeEditor::VisualStudioCodeEditor(const String& execPath, const bool isInsiders) : _execPath(execPath) diff --git a/Source/Editor/Scripting/ScriptsBuilder.cpp b/Source/Editor/Scripting/ScriptsBuilder.cpp index 1c489b2a9..00a93b66c 100644 --- a/Source/Editor/Scripting/ScriptsBuilder.cpp +++ b/Source/Editor/Scripting/ScriptsBuilder.cpp @@ -341,7 +341,21 @@ void ScriptsBuilder::GetBinariesConfiguration(const Char*& target, const Char*& target = platform = architecture = configuration = nullptr; return; } - target = Editor::Project->EditorTarget.GetText(); + + // Pick game target + if (Editor::Project->EditorTarget.HasChars()) + { + target = Editor::Project->EditorTarget.Get(); + } + else if (Editor::Project->GameTarget.HasChars()) + { + target = Editor::Project->GameTarget.Get(); + } + else + { + target = TEXT(""); + LOG(Error, "Missing editor/game targets in project. Please specify EditorTarget and GameTarget properties in .flaxproj file."); + } #if PLATFORM_WINDOWS platform = TEXT("Windows"); @@ -551,19 +565,13 @@ bool ScriptsBuilderService::Init() } // Verify project - if (project->EditorTarget.IsEmpty() || project->GameTarget.IsEmpty()) + if (project->EditorTarget.IsEmpty()) { - const String& name = project->Name; - String codeName; - for (int32 i = 0; i < name.Length(); i++) - { - Char c = name[i]; - if (StringUtils::IsAlnum(c) && c != ' ' && c != '.') - codeName += c; - } - project->GameTarget = codeName + TEXT("Target"); - project->EditorTarget = codeName + TEXT("EditorTarget"); - LOG(Warning, "Missing EditorTarget property in opened project, using deducted target name {0}", Editor::Project->EditorTarget); + LOG(Warning, "Missing {0} property in opened project", TEXT("EditorTarget")); + } + if (project->GameTarget.IsEmpty()) + { + LOG(Warning, "Missing {0} property in opened project", TEXT("GameTarget")); } // Remove any remaining files from previous Editor run hot-reloads diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index 555e0cb7a..a1e2df86c 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -1,7 +1,6 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; -using FlaxEditor.Gizmo; using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Input; using FlaxEditor.Options; diff --git a/Source/Engine/Animations/AnimationUtils.h b/Source/Engine/Animations/AnimationUtils.h index 11b6011e8..121eaee57 100644 --- a/Source/Engine/Animations/AnimationUtils.h +++ b/Source/Engine/Animations/AnimationUtils.h @@ -70,7 +70,7 @@ namespace AnimationUtils FORCE_INLINE void GetTangent(const Quaternion& a, const Quaternion& b, float length, Quaternion& result) { const float oneThird = 1.0f / 3.0f; - Quaternion::Slerp(a, b, length * oneThird, result); + Quaternion::Slerp(a, b, oneThird, result); } template<> @@ -79,7 +79,7 @@ namespace AnimationUtils const float oneThird = 1.0f / 3.0f; const float oneThirdLength = length * oneThird; result.Translation = a.Translation + b.Translation * oneThirdLength; - Quaternion::Slerp(a.Orientation, b.Orientation, oneThirdLength, result.Orientation); + Quaternion::Slerp(a.Orientation, b.Orientation, oneThird, result.Orientation); result.Scale = a.Scale + (b.Scale - a.Scale) * oneThirdLength; } diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index 4b1e32f16..493147355 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -408,16 +408,20 @@ Asset* Content::LoadAsync(const StringView& path, MClass* type) Asset* Content::LoadAsync(const StringView& path, const ScriptingTypeHandle& type) { + // Ensure path is in a valid format + String pathNorm(path); + FileSystem::NormalizePath(pathNorm); + #if USE_EDITOR - if (!FileSystem::FileExists(path)) + if (!FileSystem::FileExists(pathNorm)) { - LOG(Error, "Missing file \'{0}\'", path); + LOG(Error, "Missing file \'{0}\'", pathNorm); return nullptr; } #endif AssetInfo assetInfo; - if (GetAssetInfo(path, assetInfo)) + if (GetAssetInfo(pathNorm, assetInfo)) { return LoadAsync(assetInfo.ID, type); } diff --git a/Source/Engine/Content/Storage/FlaxStorage.cpp b/Source/Engine/Content/Storage/FlaxStorage.cpp index d4da1d951..1a3d5c6b0 100644 --- a/Source/Engine/Content/Storage/FlaxStorage.cpp +++ b/Source/Engine/Content/Storage/FlaxStorage.cpp @@ -194,13 +194,13 @@ void FlaxStorage::AddRef() void FlaxStorage::RemoveRef() { - ASSERT(_refCount > 0); - - _refCount--; - - if (_refCount == 0) + if (_refCount > 0) { - _lastRefLostTime = DateTime::NowUTC(); + _refCount--; + if (_refCount == 0) + { + _lastRefLostTime = DateTime::NowUTC(); + } } } diff --git a/Source/Engine/Core/Math/Matrix3x3.cs b/Source/Engine/Core/Math/Matrix3x3.cs index f440eb799..e65d9b036 100644 --- a/Source/Engine/Core/Math/Matrix3x3.cs +++ b/Source/Engine/Core/Math/Matrix3x3.cs @@ -1566,7 +1566,7 @@ namespace FlaxEngine } /// - /// Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + /// Creates a Matrix3x3 that scales along the x-axis, y-axis, and z-axis. /// /// Scaling factor for all three axes. /// The created scaling Matrix3x3. @@ -1577,7 +1577,7 @@ namespace FlaxEngine } /// - /// Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + /// Creates a Matrix3x3 that scales along the x-axis, y-axis, and z-axis. /// /// Scaling factor that is applied along the x-axis. /// Scaling factor that is applied along the y-axis. @@ -1605,9 +1605,9 @@ namespace FlaxEngine } /// - /// Creates a Matrix3x3 that uniformly scales along all three axis. + /// Creates a Matrix3x3 that uniformly scales along all three axes. /// - /// The uniform scale that is applied along all axis. + /// The uniform scale that is applied along all axes. /// When the method completes, contains the created scaling Matrix3x3. public static void Scaling(float scale, out Matrix3x3 result) { @@ -1616,9 +1616,9 @@ namespace FlaxEngine } /// - /// Creates a Matrix3x3 that uniformly scales along all three axis. + /// Creates a Matrix3x3 that uniformly scales along all three axes. /// - /// The uniform scale that is applied along all axis. + /// The uniform scale that is applied along all axes. /// The created scaling Matrix3x3. public static Matrix3x3 Scaling(float scale) { diff --git a/Source/Engine/Main/UWP/main.h b/Source/Engine/Main/UWP/main.h index ab48a0990..254c0fedb 100644 --- a/Source/Engine/Main/UWP/main.h +++ b/Source/Engine/Main/UWP/main.h @@ -189,10 +189,10 @@ public: *height = bounds.Height; } - void GetDpi(float* dpi) override + void GetDpi(int* dpi) override { auto currentDisplayInformation = Windows::Graphics::Display::DisplayInformation::GetForCurrentView(); - *dpi = currentDisplayInformation->LogicalDpi; + *dpi = (int)currentDisplayInformation->LogicalDpi; } void GetTitle(wchar_t* buffer, int bufferLength) override diff --git a/Source/Engine/Navigation/NavMeshRuntime.cpp b/Source/Engine/Navigation/NavMeshRuntime.cpp index af5ad0662..eae20561b 100644 --- a/Source/Engine/Navigation/NavMeshRuntime.cpp +++ b/Source/Engine/Navigation/NavMeshRuntime.cpp @@ -370,18 +370,9 @@ void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount) PROFILE_CPU_NAMED("NavMeshRuntime.EnsureCapacity"); // Navmesh tiles capacity growing rule - int32 newCapacity = 0; - if (capacity) - { - while (newCapacity < newTilesCount) - { - newCapacity = Math::RoundUpToPowerOf2(newCapacity); - } - } - else - { - newCapacity = 32; - } + int32 newCapacity = capacity ? capacity : 32; + while (newCapacity < newTilesCount) + newCapacity = Math::RoundUpToPowerOf2(newCapacity); LOG(Info, "Resizing navmesh {2} from {0} to {1} tiles capacity", capacity, newCapacity, Properties.Name); diff --git a/Source/Engine/Platform/UWP/UWPPlatformImpl.h b/Source/Engine/Platform/UWP/UWPPlatformImpl.h index f636f9983..99d18d67f 100644 --- a/Source/Engine/Platform/UWP/UWPPlatformImpl.h +++ b/Source/Engine/Platform/UWP/UWPPlatformImpl.h @@ -121,7 +121,7 @@ public: virtual void SetMousePosition(float x, float y) = 0; virtual void GetMousePosition(float* x, float* y) = 0; virtual void GetBounds(float* x, float* y, float* width, float* height) = 0; - virtual void GetDpi(float* dpi) = 0; + virtual void GetDpi(int* dpi) = 0; virtual void GetTitle(wchar_t* buffer, int bufferLength) = 0; virtual void SetTitle(const wchar_t* title) = 0; virtual int GetGamepadsCount() = 0; diff --git a/Source/Engine/Platform/Win32/Win32Platform.cpp b/Source/Engine/Platform/Win32/Win32Platform.cpp index e01a8a8e1..b4140163f 100644 --- a/Source/Engine/Platform/Win32/Win32Platform.cpp +++ b/Source/Engine/Platform/Win32/Win32Platform.cpp @@ -320,7 +320,7 @@ void* Win32Platform::AllocatePages(uint64 numPages, uint64 pageSize) const uint64 numBytes = numPages * pageSize; // Use VirtualAlloc to allocate page-aligned memory - return VirtualAlloc(nullptr, numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + return VirtualAlloc(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } void Win32Platform::FreePages(void* ptr) diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 4c3260045..0552fc598 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -87,8 +87,8 @@ bool ShadowsPass::Init() if (!_supportsShadows) { LOG(Warning, "GPU doesn't support shadows rendering"); - LOG(Warning, "Format: {0} features support: {1}", (int32)SHADOW_MAPS_FORMAT, (uint32)formatFeaturesDepth.Support); - LOG(Warning, "Format: {0} features support: {1}", (int32)formatTexture, (uint32)formatFeaturesTexture.Support); + LOG(Warning, "Format: {0}, features support: {1}", (int32)SHADOW_MAPS_FORMAT, (uint32)formatFeaturesDepth.Support); + LOG(Warning, "Format: {0}, features support: {1}", (int32)formatTexture, (uint32)formatFeaturesTexture.Support); } return false; diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 92a8eb092..d37fccbdb 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -298,6 +298,8 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte context->SetViewportAndScissors(_cache.Data.GridSize.X, _cache.Data.GridSize.Y); // Setup data + perLight.SliceToDepth.X = _cache.Data.GridSize.Z; + perLight.SliceToDepth.Y = _cache.Data.VolumetricFogMaxDistance; perLight.MinZ = volumeZBoundsMin; perLight.LocalLightScatteringIntensity = light.VolumetricScatteringIntensity; perLight.ViewSpaceBoundingSphere = Vector4(viewSpaceLightBoundsOrigin, bounds.Radius); @@ -355,6 +357,8 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte bool withShadow = false; // Setup data + perLight.SliceToDepth.X = cache.Data.GridSize.Z; + perLight.SliceToDepth.Y = cache.Data.VolumetricFogMaxDistance; perLight.MinZ = volumeZBoundsMin; perLight.LocalLightScatteringIntensity = light.VolumetricScatteringIntensity; perLight.ViewSpaceBoundingSphere = Vector4(viewSpaceLightBoundsOrigin, bounds.Radius); diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 5541ee3e5..2e4ef51e3 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -812,6 +812,19 @@ namespace FlaxEngine.GUI return spaceLoc; } + private int FindPrevLineBegin() + { + int caretPos = CaretPosition; + if (caretPos - 2 < 0) + return 0; + int newLineLoc = _text.LastIndexOf('\n', caretPos - 2); + if (newLineLoc == -1) + newLineLoc = 0; + else + newLineLoc++; + return newLineLoc; + } + private int FindLineDownChar(int index) { if (!IsMultiline) @@ -1181,7 +1194,6 @@ namespace FlaxEngine.GUI return true; } case KeyboardKeys.Return: - { if (IsMultiline) { // Insert new line @@ -1192,15 +1204,22 @@ namespace FlaxEngine.GUI // End editing Defocus(); } - return true; - } case KeyboardKeys.Home: - { - // Move caret to the first character - SetSelection(0); + if (shiftDown) + { + // Select text from the current cursor point back to the beginning of the line + if (_selectionStart != -1) + { + SetSelection(FindPrevLineBegin(), _selectionStart); + } + } + else + { + // Move caret to the first character + SetSelection(0); + } return true; - } case KeyboardKeys.End: { // Move caret after last character diff --git a/Source/Engine/UI/GUI/Control.Bounds.cs b/Source/Engine/UI/GUI/Control.Bounds.cs index 06bd0499d..e4e2eafcc 100644 --- a/Source/Engine/UI/GUI/Control.Bounds.cs +++ b/Source/Engine/UI/GUI/Control.Bounds.cs @@ -558,6 +558,7 @@ namespace FlaxEngine.GUI } SetBounds(ref bounds); } + _parent?.PerformLayout(); return; } } diff --git a/Source/Engine/UI/GUI/Panels/HorizontalPanel.cs b/Source/Engine/UI/GUI/Panels/HorizontalPanel.cs index 4ff92834d..116fd7c95 100644 --- a/Source/Engine/UI/GUI/Panels/HorizontalPanel.cs +++ b/Source/Engine/UI/GUI/Panels/HorizontalPanel.cs @@ -35,28 +35,39 @@ namespace FlaxEngine.GUI /// protected override void PerformLayoutAfterChildren() { - // Sort controls from left to right - float x = _margin.Left; + // Sort controls horizontally + float left = _margin.Left; + float right = _margin.Right; float h = Height - _margin.Height; - bool hasAnyItem = false; + bool hasAnyLeft = false, hasAnyRight = false; for (int i = 0; i < _children.Count; i++) { Control c = _children[i]; - if (c.Visible && Mathf.IsZero(c.AnchorMax.X)) + if (c.Visible) { var w = c.Width; - c.Bounds = new Rectangle(x + _offset.X, _margin.Top + _offset.Y, w, h); - x = c.Right + _spacing; - hasAnyItem = true; + if (Mathf.IsZero(c.AnchorMin.X) && Mathf.IsZero(c.AnchorMax.X)) + { + c.Bounds = new Rectangle(left + _offset.X, _margin.Top + _offset.Y, w, h); + left = c.Right + _spacing; + hasAnyLeft = true; + } + else if (Mathf.IsOne(c.AnchorMin.X) && Mathf.IsOne(c.AnchorMax.X)) + { + right += w + _spacing; + c.Bounds = new Rectangle(Width - right + _offset.X, _margin.Top + _offset.Y, w, h); + hasAnyRight = true; + } } } - if (hasAnyItem) - x -= _spacing; - x += _margin.Right; + if (hasAnyLeft) + left -= _spacing; + if (hasAnyRight) + right -= _spacing; // Update size if (_autoSize) - Width = x; + Width = left + right; } } } diff --git a/Source/Engine/UI/GUI/Panels/VerticalPanel.cs b/Source/Engine/UI/GUI/Panels/VerticalPanel.cs index b3e51fb86..84974cc96 100644 --- a/Source/Engine/UI/GUI/Panels/VerticalPanel.cs +++ b/Source/Engine/UI/GUI/Panels/VerticalPanel.cs @@ -35,28 +35,39 @@ namespace FlaxEngine.GUI /// protected override void PerformLayoutAfterChildren() { - // Sort controls from top to bottom - float y = _margin.Top; + // Sort controls vertically + float top = _margin.Top; + float bottom = _margin.Bottom; float w = Width - _margin.Width; - bool hasAnyItem = false; + bool hasAnyTop = false, hasAnyBottom = false; for (int i = 0; i < _children.Count; i++) { Control c = _children[i]; - if (c.Visible && Mathf.IsZero(c.AnchorMax.Y)) + if (c.Visible) { var h = c.Height; - c.Bounds = new Rectangle(_margin.Left + _offset.X, y + _offset.Y, w, h); - y = c.Bottom + _spacing; - hasAnyItem = true; + if (Mathf.IsZero(c.AnchorMin.Y) && Mathf.IsZero(c.AnchorMax.Y)) + { + c.Bounds = new Rectangle(_margin.Left + _offset.X, top + _offset.Y, w, h); + top = c.Bottom + _spacing; + hasAnyTop = true; + } + else if (Mathf.IsOne(c.AnchorMin.Y) && Mathf.IsOne(c.AnchorMax.Y)) + { + bottom += h + _spacing; + c.Bounds = new Rectangle(_margin.Left + _offset.X, Height - bottom + _offset.Y, w, h); + hasAnyBottom = true; + } } } - if (hasAnyItem) - y -= _spacing; - y += _margin.Bottom; + if (hasAnyTop) + top -= _spacing; + if (hasAnyBottom) + bottom -= _spacing; // Update size if (_autoSize) - Height = y; + Height = top + bottom; } } } diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libIrrXML.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libIrrXML.a new file mode 100644 index 000000000..92c1baf0b --- /dev/null +++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libIrrXML.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4eb25101716011a5b4c872c5cd303c3292a61e5f661e9296d95502b5705e2e53 +size 181458 diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a new file mode 100644 index 000000000..4dccc7f4b --- /dev/null +++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8cbd73a154e270cc03d3da292b2c3cc73ee473b221f43722d060dc114916d6d5 +size 7996212 diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.so b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.so deleted file mode 100755 index 08aa3b9a2..000000000 --- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.so +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b35cfdc2b6aa4cbdf0a2aad81d5027736f9e92b1d708e3d358c31c03e679b2d1 -size 11877400 diff --git a/Source/ThirdParty/assimp/assimp.Build.cs b/Source/ThirdParty/assimp/assimp.Build.cs index 110007b7f..dd6da9d7c 100644 --- a/Source/ThirdParty/assimp/assimp.Build.cs +++ b/Source/ThirdParty/assimp/assimp.Build.cs @@ -35,8 +35,8 @@ public class assimp : DepsModule options.DelayLoadLibraries.Add("assimp-vc140-md.dll"); break; case TargetPlatform.Linux: - options.DependencyFiles.Add(Path.Combine(depsRoot, "libassimp.so")); - options.Libraries.Add(Path.Combine(depsRoot, "libassimp.so")); + options.OutputFiles.Add(Path.Combine(depsRoot, "libassimp.a")); + options.OutputFiles.Add(Path.Combine(depsRoot, "libIrrXML.a")); break; default: throw new InvalidPlatformException(options.Platform.Target); } diff --git a/Source/Tools/Flax.Build/Build/EngineTarget.cs b/Source/Tools/Flax.Build/Build/EngineTarget.cs index 2dd00f9d2..76191943c 100644 --- a/Source/Tools/Flax.Build/Build/EngineTarget.cs +++ b/Source/Tools/Flax.Build/Build/EngineTarget.cs @@ -101,7 +101,7 @@ namespace Flax.Build } // Mono on Linux is using dynamic linking and needs additional link files - if (buildOptions.Platform.Target == TargetPlatform.Linux) + if (buildOptions.Platform.Target == TargetPlatform.Linux && Platform.BuildTargetPlatform == TargetPlatform.Linux && !IsPreBuilt) { var task = graph.Add(); task.PrerequisiteFiles.Add(Path.Combine(buildOptions.OutputFolder, "libmonosgen-2.0.so")); @@ -120,6 +120,8 @@ namespace Flax.Build private void BuildMainExecutable(TaskGraph graph, BuildOptions buildOptions) { + if (IsPreBuilt) + return; var outputPath = Path.Combine(buildOptions.OutputFolder, buildOptions.Platform.GetLinkOutputFileName(OutputName, LinkerOutput.Executable)); var exeBuildOptions = Builder.GetBuildOptions(this, buildOptions.Platform, buildOptions.Toolchain, buildOptions.Architecture, buildOptions.Configuration, buildOptions.WorkingDirectory); exeBuildOptions.LinkEnv.Output = LinkerOutput.Executable; @@ -139,7 +141,7 @@ namespace Flax.Build // Build Main module var mainModule = rules.GetModule("Main"); var mainModuleOutputPath = Path.Combine(exeBuildOptions.IntermediateFolder, mainModule.Name); - if (!IsPreBuilt && !Directory.Exists(mainModuleOutputPath)) + if (!Directory.Exists(mainModuleOutputPath)) Directory.CreateDirectory(mainModuleOutputPath); var mainModuleOptions = new BuildOptions { diff --git a/Source/Tools/Flax.Build/Build/ProjectTarget.cs b/Source/Tools/Flax.Build/Build/ProjectTarget.cs index 19d23690f..790452b34 100644 --- a/Source/Tools/Flax.Build/Build/ProjectTarget.cs +++ b/Source/Tools/Flax.Build/Build/ProjectTarget.cs @@ -45,7 +45,7 @@ namespace Flax.Build throw new Exception($"Invalid or missing editor target {project.EditorTarget} specified in project {project.Name} (referenced by project {Project.Name})."); return result; } - if (!IsEditor && !string.IsNullOrEmpty(project.GameTarget)) + if (!string.IsNullOrEmpty(project.GameTarget)) { var result = projectTargets.FirstOrDefault(x => x.Name == project.GameTarget); if (result == null) diff --git a/Source/Tools/Flax.Build/Deploy/Configuration.cs b/Source/Tools/Flax.Build/Deploy/Configuration.cs index 387a009d8..7cf30ccd6 100644 --- a/Source/Tools/Flax.Build/Deploy/Configuration.cs +++ b/Source/Tools/Flax.Build/Deploy/Configuration.cs @@ -15,5 +15,17 @@ namespace Flax.Build /// [CommandLine("deployPlatforms", "Builds and packages the platforms data.")] public static bool DeployPlatforms; + + /// + /// Certificate file path for binaries signing. + /// + [CommandLine("deployCert", "Certificate file path for binaries signing.")] + public static string DeployCert; + + /// + /// Certificate file password for binaries signing. + /// + [CommandLine("deployCertPass", "Certificate file password for binaries signing.")] + public static string DeployCertPass; } } diff --git a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs index b98af5dc1..33dbdbb78 100644 --- a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs +++ b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs @@ -12,6 +12,18 @@ namespace Flax.Deploy { partial class Deployment { + private static void CodeSign(string file) + { + if (string.IsNullOrEmpty(Configuration.DeployCert)) + return; + switch (Platform.BuildTargetPlatform) + { + case TargetPlatform.Windows: + VCEnvironment.CodeSign(file, Configuration.DeployCert, Configuration.DeployCertPass); + break; + } + } + public class Editor { private static string RootPath; @@ -37,6 +49,7 @@ namespace Flax.Deploy var dst = Path.Combine(OutputPath, binariesSubDir); DeployFile(src, dst, "Flax.Build.exe"); + CodeSign(Path.Combine(dst, "Flax.Build.exe")); DeployFile(src, dst, "Flax.Build.xml"); DeployFile(src, dst, "Ionic.Zip.Reduced.dll"); DeployFile(src, dst, "Newtonsoft.Json.dll"); @@ -112,15 +125,26 @@ namespace Flax.Deploy // Compress Log.Info(string.Empty); Log.Info("Compressing editor files..."); - var editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "Editor.zip"); - using (ZipFile zip = new ZipFile()) + string editorPackageZipPath; + if (Platform.BuildPlatform.Target == TargetPlatform.Linux) { - zip.AddDirectory(OutputPath); + // Use system tool (preserves executable file attributes and link files) + editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "FlaxEditorLinux.zip"); + Utilities.Run("zip", "Editor.zip -r .", null, OutputPath, Utilities.RunOptions.None); + File.Move(Path.Combine(OutputPath, "Editor.zip"), editorPackageZipPath); + } + else + { + editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "Editor.zip"); + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(OutputPath); - zip.CompressionLevel = CompressionLevel.BestCompression; - zip.Comment = string.Format("Flax Editor {0}.{1}.{2}\nDate: {3}", Deployer.VersionMajor, Deployer.VersionMinor, Deployer.VersionBuild, DateTime.UtcNow); + zip.CompressionLevel = CompressionLevel.BestCompression; + zip.Comment = string.Format("Flax Editor {0}.{1}.{2}\nDate: {3}", Deployer.VersionMajor, Deployer.VersionMinor, Deployer.VersionBuild, DateTime.UtcNow); - zip.Save(editorPackageZipPath); + zip.Save(editorPackageZipPath); + } } Log.Info("Compressed editor package size: " + Utilities.GetFileSize(editorPackageZipPath)); @@ -166,12 +190,14 @@ namespace Flax.Deploy // Deploy binaries DeployFile(src, dst, editorExeName); + CodeSign(Path.Combine(dst, editorExeName)); DeployFile(src, dst, "FlaxEditor.Build.json"); DeployFile(src, dst, "FlaxEditor.lib"); DeployFile(src, dst, "FlaxEngine.CSharp.pdb"); DeployFile(src, dst, "FlaxEngine.CSharp.xml"); DeployFile(src, dst, "Newtonsoft.Json.pdb"); DeployFiles(src, dst, "*.dll"); + CodeSign(Path.Combine(dst, "FlaxEngine.CSharp.dll")); // Deploy debug symbols files DeployFiles(src, dstDebug, "*.pdb"); diff --git a/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs b/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs index 4ff1a3af3..e9fc98acc 100644 --- a/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs +++ b/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs @@ -37,6 +37,22 @@ namespace Flax.Deploy File.Delete(Path.Combine(dst, "Binaries", "Game", "x64", "Release", "FlaxGame.a")); } + // Sign binaries + if (platform == TargetPlatform.Windows && !string.IsNullOrEmpty(Configuration.DeployCert)) + { + var binaries = Path.Combine(dst, "Binaries", "Game", "x64", "Debug"); + CodeSign(Path.Combine(binaries, "FlaxGame.exe")); + CodeSign(Path.Combine(binaries, "FlaxEngine.CSharp.dll")); + + binaries = Path.Combine(dst, "Binaries", "Game", "x64", "Development"); + CodeSign(Path.Combine(binaries, "FlaxGame.exe")); + CodeSign(Path.Combine(binaries, "FlaxEngine.CSharp.dll")); + + binaries = Path.Combine(dst, "Binaries", "Game", "x64", "Release"); + CodeSign(Path.Combine(binaries, "FlaxGame.exe")); + CodeSign(Path.Combine(binaries, "FlaxEngine.CSharp.dll")); + } + // Don't distribute engine deps Utilities.DirectoryDelete(Path.Combine(dst, "Binaries", "ThirdParty")); diff --git a/Source/Tools/Flax.Build/Deploy/FlaxBuild.cs b/Source/Tools/Flax.Build/Deploy/FlaxBuild.cs index c8d01dea9..402e3e144 100644 --- a/Source/Tools/Flax.Build/Deploy/FlaxBuild.cs +++ b/Source/Tools/Flax.Build/Deploy/FlaxBuild.cs @@ -21,6 +21,8 @@ namespace Flax.Deploy format = format.Replace("-", "--"); } var cmdLine = string.Format(format, target, platform, architecture, configuration); + if (!string.IsNullOrEmpty(Configuration.Compiler)) + cmdLine += " -compiler=" + Configuration.Compiler; int result; if (buildPlatform == TargetPlatform.Windows) diff --git a/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs b/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs index 359c571ef..4cb28f221 100644 --- a/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs +++ b/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs @@ -2,6 +2,7 @@ using System; using System.IO; +using System.Linq; using Flax.Build; using Flax.Build.Platforms; using Flax.Build.Projects.VisualStudio; @@ -255,5 +256,22 @@ namespace Flax.Deploy string cmdLine = string.Format("\"{0}\" /t:Clean /verbosity:minimal /nologo", solutionFile); Utilities.Run(msBuild, cmdLine); } + + internal static void CodeSign(string file, string certificatePath, string certificatePass) + { + if (!File.Exists(file)) + throw new FileNotFoundException("Missing file to sign.", file); + if (!File.Exists(certificatePath)) + throw new FileNotFoundException("Missing certificate to sign with.", certificatePath); + var sdks = WindowsPlatformBase.GetSDKs(); + if (sdks.Count == 0) + throw new Exception("No Windows SDK found. Cannot sign file."); + var sdkKeys = sdks.Keys.ToList(); + sdkKeys.Sort(); + var sdk = sdks[sdkKeys.Last()]; + var signtool = Path.Combine(sdk, "bin", "x64", "signtool.exe"); + var cmdLine = string.Format("sign /debug /f \"{0}\" /p \"{1}\" /tr http://timestamp.comodoca.com /td sha256 /fd sha256 \"{2}\"", certificatePath, certificatePass, file); + Utilities.Run(signtool, cmdLine); + } } } diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs index abb8b47f0..1c671f4b4 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs @@ -39,6 +39,46 @@ namespace Flax.Deps.Dependencies { var root = options.IntermediateFolder; var moduleFilename = "assimp.Build.cs"; + var configs = new string[] + { + "-DASSIMP_NO_EXPORT=ON", + "-DASSIMP_BUILD_ASSIMP_TOOLS=OFF", + "-DASSIMP_BUILD_TESTS=OFF", + "-DASSIMP_BUILD_AMF_IMPORTER=FALSE", + "-DASSIMP_BUILD_AC_IMPORTER=FALSE", + "-DASSIMP_BUILD_ASE_IMPORTER=FALSE", + "-DASSIMP_BUILD_ASSBIN_IMPORTER=FALSE", + "-DASSIMP_BUILD_ASSXML_IMPORTER=FALSE", + "-DASSIMP_BUILD_DXF_IMPORTER=FALSE", + "-DASSIMP_BUILD_CSM_IMPORTER=FALSE", + "-DASSIMP_BUILD_HMP_IMPORTER=FALSE", + "-DASSIMP_BUILD_NFF_IMPORTER=FALSE", + "-DASSIMP_BUILD_NDO_IMPORTER=FALSE", + "-DASSIMP_BUILD_IFC_IMPORTER=FALSE", + "-DASSIMP_BUILD_FBX_IMPORTER=FALSE", + "-DASSIMP_BUILD_RAW_IMPORTER=FALSE", + "-DASSIMP_BUILD_TERRAGEN_IMPORTER=FALSE", + "-DASSIMP_BUILD_3MF_IMPORTER=FALSE", + "-DASSIMP_BUILD_STEP_IMPORTER=FALSE", + "-DASSIMP_BUILD_3DS_IMPORTER=FALSE", + "-DASSIMP_BUILD_BVH_IMPORTER=FALSE", + "-DASSIMP_BUILD_IRRMESH_IMPORTER=FALSE", + "-DASSIMP_BUILD_IRR_IMPORTER=FALSE", + "-DASSIMP_BUILD_MD2_IMPORTER=FALSE", + "-DASSIMP_BUILD_MD3_IMPORTER=FALSE", + "-DASSIMP_BUILD_MD5_IMPORTER=FALSE", + "-DASSIMP_BUILD_MDC_IMPORTER=FALSE", + "-DASSIMP_BUILD_MDL_IMPORTER=FALSE", + "-DASSIMP_BUILD_OFF_IMPORTER=FALSE", + "-DASSIMP_BUILD_COB_IMPORTER=FALSE", + "-DASSIMP_BUILD_Q3D_IMPORTER=FALSE", + "-DASSIMP_BUILD_Q3BSP_IMPORTER=FALSE", + "-DASSIMP_BUILD_SIB_IMPORTER=FALSE", + "-DASSIMP_BUILD_SMD_IMPORTER=FALSE", + "-DASSIMP_BUILD_X3D_IMPORTER=FALSE", + "-DASSIMP_BUILD_MMD_IMPORTER=FALSE", + }; + var globalConfig = string.Join(" ", configs); // Get the source CloneGitRepo(root, "https://github.com/FlaxEngine/assimp.git"); @@ -73,13 +113,11 @@ namespace Flax.Deps.Dependencies case TargetPlatform.Linux: { // Build for Linux - RunCmake(root, TargetPlatform.Linux, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DASSIMP_NO_EXPORT=ON -DASSIMP_BUILD_ASSIMP_TOOLS=OFF -DASSIMP_BUILD_TESTS=OFF"); + RunCmake(root, TargetPlatform.Linux, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig); Utilities.Run("make", null, null, root, Utilities.RunOptions.None); var depsFolder = GetThirdPartyFolder(options, TargetPlatform.Linux, TargetArchitecture.x64); - var srcName = "libassimp.so.4.1.0"; - var dstName = "libassimp.so"; - Utilities.FileCopy(Path.Combine(root, "lib", srcName), Path.Combine(depsFolder, dstName)); - Utilities.Run("strip", dstName, null, depsFolder, Utilities.RunOptions.None); + Utilities.FileCopy(Path.Combine(root, "lib", "libassimp.a"), Path.Combine(depsFolder, "libassimp.a")); + Utilities.FileCopy(Path.Combine(root, "lib", "libIrrXML.a"), Path.Combine(depsFolder, "libIrrXML.a")); break; } } diff --git a/Source/Tools/Flax.Build/ProjectInfo.cs b/Source/Tools/Flax.Build/ProjectInfo.cs index 5f144b2fd..c47c87331 100644 --- a/Source/Tools/Flax.Build/ProjectInfo.cs +++ b/Source/Tools/Flax.Build/ProjectInfo.cs @@ -119,6 +119,8 @@ namespace Flax.Build private bool IsTargetCSharpOnly(string name) { + if (string.IsNullOrWhiteSpace(name)) + return true; var rules = Builder.GenerateRulesAssembly(); var target = rules.GetTarget(name); return target == null || target.Modules.TrueForAll(x => !rules.GetModule(x).BuildNativeCode);