diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs index e0affeedc..bf9fb1715 100644 --- a/Source/Editor/Content/GUI/ContentView.cs +++ b/Source/Editor/Content/GUI/ContentView.cs @@ -536,15 +536,6 @@ namespace FlaxEditor.Content.GUI } } - /// - /// Called when user wants to rename item. - /// - /// The item. - public void OnItemDoubleClickName(ContentItem item) - { - OnRename?.Invoke(item); - } - /// /// Called when user wants to open item. /// diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs index d887c304e..1cc6d480e 100644 --- a/Source/Editor/Content/Items/ContentItem.cs +++ b/Source/Editor/Content/Items/ContentItem.cs @@ -690,18 +690,9 @@ namespace FlaxEditor.Content public override bool OnMouseDoubleClick(Float2 location, MouseButton button) { Focus(); - - // Check if clicked on name area (and can be renamed) - if (CanRename && TextRectangle.Contains(ref location)) - { - // Rename - (Parent as ContentView).OnItemDoubleClickName(this); - } - else - { - // Open - (Parent as ContentView).OnItemDoubleClick(this); - } + + // Open + (Parent as ContentView).OnItemDoubleClick(this); return true; } diff --git a/Source/Editor/Content/Tree/ContentTreeNode.cs b/Source/Editor/Content/Tree/ContentTreeNode.cs index 2503cde51..1d70a8252 100644 --- a/Source/Editor/Content/Tree/ContentTreeNode.cs +++ b/Source/Editor/Content/Tree/ContentTreeNode.cs @@ -95,11 +95,19 @@ namespace FlaxEditor.Content { if (!_folder.CanRename) return; - + Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(false); // Start renaming the folder var dialog = RenamePopup.Show(this, HeaderRect, _folder.ShortName, false); dialog.Tag = _folder; - dialog.Renamed += popup => Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text); + dialog.Renamed += popup => + { + Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text); + Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); + }; + dialog.Closed += popup => + { + Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); + }; } /// diff --git a/Source/Editor/CustomEditors/Dedicated/LayersMatrixEditor.cs b/Source/Editor/CustomEditors/Dedicated/LayersMatrixEditor.cs index e6e2338d8..0f6996cc4 100644 --- a/Source/Editor/CustomEditors/Dedicated/LayersMatrixEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/LayersMatrixEditor.cs @@ -24,7 +24,7 @@ namespace FlaxEditor.CustomEditors.Dedicated public override void Initialize(LayoutElementsContainer layout) { string[] layerNames = LayersAndTagsSettings.GetCurrentLayers(); - int layersCount = Math.Max(4, layerNames.Length); + int layersCount = layerNames.Length; _checkBoxes = new List(); _layersCount = layersCount; diff --git a/Source/Editor/CustomEditors/Elements/FloatValueElement.cs b/Source/Editor/CustomEditors/Elements/FloatValueElement.cs index ff2218a9b..6fc10e967 100644 --- a/Source/Editor/CustomEditors/Elements/FloatValueElement.cs +++ b/Source/Editor/CustomEditors/Elements/FloatValueElement.cs @@ -22,7 +22,7 @@ namespace FlaxEditor.CustomEditors.Elements /// /// [Deprecated on 26.05.2022, expires on 26.05.2024] /// - [System.Obsolete("Deprecated in 1.4")] + [System.Obsolete("Deprecated in 1.4, ValueBox instead")] public FloatValueBox FloatValue => ValueBox; /// diff --git a/Source/Editor/GUI/Input/ValueBox.cs b/Source/Editor/GUI/Input/ValueBox.cs index ff824d76c..50cdd529c 100644 --- a/Source/Editor/GUI/Input/ValueBox.cs +++ b/Source/Editor/GUI/Input/ValueBox.cs @@ -56,6 +56,7 @@ namespace FlaxEditor.GUI.Input private Float2 _startSlideLocation; private double _clickStartTime = -1; + private bool _cursorChanged; /// /// Occurs when value gets changed. @@ -172,6 +173,11 @@ namespace FlaxEditor.GUI.Input { _isSliding = false; EndMouseCapture(); + if (_cursorChanged) + { + Cursor = CursorType.Default; + _cursorChanged = false; + } SlidingEnd?.Invoke(); } @@ -222,6 +228,8 @@ namespace FlaxEditor.GUI.Input // Update UpdateText(); } + + Cursor = CursorType.Default; ResetViewOffset(); } @@ -236,6 +244,8 @@ namespace FlaxEditor.GUI.Input _startSlideLocation = location; _startSlideValue = _value; StartMouseCapture(true); + Cursor = CursorType.SizeWE; + _cursorChanged = true; SlidingStart?.Invoke(); return true; } @@ -249,13 +259,25 @@ namespace FlaxEditor.GUI.Input /// public override void OnMouseMove(Float2 location) { - if (_isSliding) + if (_isSliding && !RootWindow.Window.IsMouseFlippingHorizontally) { // Update sliding var slideLocation = location + Root.TrackingMouseOffset; ApplySliding(Mathf.RoundToInt(slideLocation.X - _startSlideLocation.X) * _slideSpeed); return; } + + // Update cursor type so user knows they can slide value + if (CanUseSliding && SlideRect.Contains(location)) + { + Cursor = CursorType.SizeWE; + _cursorChanged = true; + } + else if (_cursorChanged && !_isSliding) + { + Cursor = CursorType.Default; + _cursorChanged = false; + } base.OnMouseMove(location); } @@ -281,6 +303,18 @@ namespace FlaxEditor.GUI.Input return base.OnMouseUp(location, button); } + /// + public override void OnMouseLeave() + { + if (_cursorChanged) + { + Cursor = CursorType.Default; + _cursorChanged = false; + } + + base.OnMouseLeave(); + } + /// protected override void OnEditBegin() { diff --git a/Source/Editor/GUI/Timeline/GUI/TimelineEdge.cs b/Source/Editor/GUI/Timeline/GUI/TimelineEdge.cs index 0f1da6e9b..b74b47c46 100644 --- a/Source/Editor/GUI/Timeline/GUI/TimelineEdge.cs +++ b/Source/Editor/GUI/Timeline/GUI/TimelineEdge.cs @@ -69,10 +69,10 @@ namespace FlaxEditor.GUI.Timeline.GUI /// public override void OnMouseMove(Float2 location) { - if (_isMoving) + if (_isMoving && !_timeline.RootWindow.Window.IsMouseFlippingHorizontally) { var moveLocation = Root.MousePosition; - var moveLocationDelta = moveLocation - _startMoveLocation; + var moveLocationDelta = moveLocation - _startMoveLocation + _timeline.Root.TrackingMouseOffset.X; var moveDelta = (int)(moveLocationDelta.X / (Timeline.UnitsPerSecond * _timeline.Zoom) * _timeline.FramesPerSecond); var durationFrames = _timeline.DurationFrames; @@ -83,6 +83,7 @@ namespace FlaxEditor.GUI.Timeline.GUI else { _timeline.DurationFrames = _startMoveDuration + moveDelta; + _timeline.MediaBackground.HScrollBar.Value = _timeline.MediaBackground.HScrollBar.Maximum; } if (_timeline.DurationFrames != durationFrames) @@ -140,6 +141,7 @@ namespace FlaxEditor.GUI.Timeline.GUI _timeline.DurationFrames = duration; } _isMoving = false; + _timeline.MediaBackground.HScrollBar.Value = _timeline.MediaBackground.HScrollBar.Maximum; EndMouseCapture(); } diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs index 82e9c3c77..63043aa91 100644 --- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs +++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs @@ -273,15 +273,26 @@ namespace FlaxEditor.SceneGraph.GUI Select(); + // Disable scrolling of scene view + Editor.Instance.Windows.SceneWin.ScrollingOnSceneTreeView(false); + // Start renaming the actor var dialog = RenamePopup.Show(this, HeaderRect, _actorNode.Name, false); dialog.Renamed += OnRenamed; + dialog.Closed += popup => + { + // Enable scrolling of scene view + Editor.Instance.Windows.SceneWin.ScrollingOnSceneTreeView(true); + }; } private void OnRenamed(RenamePopup renamePopup) { using (new UndoBlock(ActorNode.Root.Undo, Actor, "Rename")) Actor.Name = renamePopup.Text; + + // Enable scrolling of scene view + Editor.Instance.Windows.SceneWin.ScrollingOnSceneTreeView(true); } /// diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs index ddd4ae565..02fe835f2 100644 --- a/Source/Editor/Surface/VisjectSurface.Input.cs +++ b/Source/Editor/Surface/VisjectSurface.Input.cs @@ -290,9 +290,23 @@ namespace FlaxEditor.Surface // Change scale (disable scaling during selecting nodes) if (IsMouseOver && !_leftMouseDown && !IsPrimaryMenuOpened) { - var viewCenter = ViewCenterPosition; - ViewScale += delta * 0.1f; - ViewCenterPosition = viewCenter; + var nextViewScale = ViewScale + delta * 0.1f; + + if (delta > 0 && !_rightMouseDown) + { + // Scale towards mouse when zooming in + var nextCenterPosition = ViewPosition + location / ViewScale; + ViewScale = nextViewScale; + ViewPosition = nextCenterPosition - (location / ViewScale); + } + else + { + // Scale while keeping center position when zooming out or when dragging view + var viewCenter = ViewCenterPosition; + ViewScale = nextViewScale; + ViewCenterPosition = viewCenter; + } + return true; } diff --git a/Source/Editor/Windows/Assets/SkeletonMaskWindow.cs b/Source/Editor/Windows/Assets/SkeletonMaskWindow.cs index 3627ef70e..301ccf9b4 100644 --- a/Source/Editor/Windows/Assets/SkeletonMaskWindow.cs +++ b/Source/Editor/Windows/Assets/SkeletonMaskWindow.cs @@ -7,6 +7,7 @@ using FlaxEditor.CustomEditors; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.CustomEditors.Elements; using FlaxEditor.GUI; +using FlaxEditor.GUI.Tree; using FlaxEditor.Viewport.Cameras; using FlaxEditor.Viewport.Previews; using FlaxEngine; @@ -166,8 +167,21 @@ namespace FlaxEditor.Windows.Assets var proxy = (PropertiesProxy)Values[0]; int nodeIndex = (int)checkBox.Tag; proxy.NodesMask[nodeIndex] = checkBox.Checked; + if (Input.GetKey(KeyboardKeys.Shift)) + SetTreeChecked(checkBox.Parent as TreeNode, checkBox.Checked); proxy.Window.MarkAsEdited(); } + + private void SetTreeChecked(TreeNode tree, bool state) + { + foreach (var node in tree.Children) + { + if (node is TreeNode treeNode) + SetTreeChecked(treeNode, state); + else if (node is CheckBox checkBox) + checkBox.Checked = state; + } + } } } diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 0f9eba0c0..90cd77d11 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -27,6 +27,8 @@ namespace FlaxEditor.Windows private const string ProjectDataLastViewedFolder = "LastViewedFolder"; private bool _isWorkspaceDirty; private SplitPanel _split; + private Panel _contentViewPanel; + private Panel _contentTreePanel; private ContentView _view; private readonly ToolStrip _toolStrip; @@ -95,7 +97,7 @@ namespace FlaxEditor.Windows }; // Split panel - _split = new SplitPanel(options.Options.Interface.ContentWindowOrientation, ScrollBars.Both, ScrollBars.Vertical) + _split = new SplitPanel(options.Options.Interface.ContentWindowOrientation, ScrollBars.None, ScrollBars.None) { AnchorPreset = AnchorPresets.StretchAll, Offsets = new Margin(0, 0, _toolStrip.Bottom, 0), @@ -120,11 +122,20 @@ namespace FlaxEditor.Windows }; _foldersSearchBox.TextChanged += OnFoldersSearchBoxTextChanged; + // Content tree panel + _contentTreePanel = new Panel + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = new Margin(0, 0, headerPanel.Bottom, 0), + IsScrollable = true, + ScrollBars = ScrollBars.Both, + Parent = _split.Panel1, + }; + // Content structure tree _tree = new Tree(false) { - Y = headerPanel.Bottom, - Parent = _split.Panel1, + Parent = _contentTreePanel, }; _tree.SelectedChanged += OnTreeSelectionChanged; headerPanel.Parent = _split.Panel1; @@ -159,13 +170,23 @@ namespace FlaxEditor.Windows _viewDropdown.Items.Add(((ContentItemSearchFilter)i).ToString()); _viewDropdown.PopupCreate += OnViewDropdownPopupCreate; + // Content view panel + _contentViewPanel = new Panel + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = new Margin(0, 0, contentItemsSearchPanel.Bottom + 4, 0), + IsScrollable = true, + ScrollBars = ScrollBars.Vertical, + Parent = _split.Panel2, + }; + // Content View _view = new ContentView { AnchorPreset = AnchorPresets.HorizontalStretchTop, - Offsets = new Margin(0, 0, contentItemsSearchPanel.Bottom + 4, 0), + Offsets = new Margin(0, 0, 0, 0), IsScrollable = true, - Parent = _split.Panel2, + Parent = _contentViewPanel, }; _view.OnOpen += Open; _view.OnNavigateBack += NavigateBackward; @@ -271,6 +292,30 @@ namespace FlaxEditor.Windows RefreshView(SelectedNode); } + /// + /// Enables or disables vertical and horizontal scrolling on the content tree panel + /// + /// The state to set scrolling to + public void ScrollingOnTreeView(bool enabled) + { + if (_contentTreePanel.VScrollBar != null) + _contentTreePanel.VScrollBar.ThumbEnabled = enabled; + if (_contentTreePanel.HScrollBar != null) + _contentTreePanel.HScrollBar.ThumbEnabled = enabled; + } + + /// + /// Enables or disables vertical and horizontal scrolling on the content view panel + /// + /// The state to set scrolling to + public void ScrollingOnContentView(bool enabled) + { + if (_contentViewPanel.VScrollBar != null) + _contentViewPanel.VScrollBar.ThumbEnabled = enabled; + if (_contentViewPanel.HScrollBar != null) + _contentViewPanel.HScrollBar.ThumbEnabled = enabled; + } + /// /// Shows popup dialog with UI to rename content item. /// @@ -285,6 +330,7 @@ namespace FlaxEditor.Windows _split.Panel2.VScrollBar.ThumbEnabled = false; if (_split.Panel2.HScrollBar != null) _split.Panel2.HScrollBar.ThumbEnabled = false; + ScrollingOnContentView(false); // Show rename popup var popup = RenamePopup.Show(item, item.TextRectangle, item.ShortName, true); @@ -298,6 +344,7 @@ namespace FlaxEditor.Windows _split.Panel2.VScrollBar.ThumbEnabled = true; if (_split.Panel2.HScrollBar != null) _split.Panel2.HScrollBar.ThumbEnabled = true; + ScrollingOnContentView(true); // Check if was creating new element if (_newElement != null) diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index bccba12c2..b0bed2002 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -131,6 +131,7 @@ namespace FlaxEditor.Windows private TextBox _searchBox; private Tree _tree; + private Panel _sceneTreePanel; private bool _isUpdatingSelection; private bool _isMouseDown; @@ -143,10 +144,9 @@ namespace FlaxEditor.Windows /// /// The editor. public SceneTreeWindow(Editor editor) - : base(editor, true, ScrollBars.Both) + : base(editor, true, ScrollBars.None) { Title = "Scene"; - ScrollMargin = new Margin(0, 0, 0, 100.0f); // Scene searching query input box var headerPanel = new ContainerControl @@ -165,19 +165,29 @@ namespace FlaxEditor.Windows }; _searchBox.TextChanged += OnSearchBoxTextChanged; + // Scene tree panel + _sceneTreePanel = new Panel + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = new Margin(0, 0, headerPanel.Bottom, 0), + IsScrollable = true, + ScrollBars = ScrollBars.Both, + Parent = this, + }; + // Create scene structure tree var root = editor.Scene.Root; root.TreeNode.ChildrenIndent = 0; root.TreeNode.Expand(); _tree = new Tree(true) { - Y = headerPanel.Bottom, Margin = new Margin(0.0f, 0.0f, -16.0f, 0.0f), // Hide root node + IsScrollable = true, }; _tree.AddChild(root.TreeNode); _tree.SelectedChanged += Tree_OnSelectedChanged; _tree.RightClick += OnTreeRightClick; - _tree.Parent = this; + _tree.Parent = _sceneTreePanel; headerPanel.Parent = this; // Setup input actions @@ -188,6 +198,18 @@ namespace FlaxEditor.Windows InputActions.Add(options => options.Rename, Rename); } + /// + /// Enables or disables vertical and horizontal scrolling on the scene tree panel. + /// + /// The state to set scrolling to + public void ScrollingOnSceneTreeView(bool enabled) + { + if (_sceneTreePanel.VScrollBar != null) + _sceneTreePanel.VScrollBar.ThumbEnabled = enabled; + if (_sceneTreePanel.HScrollBar != null) + _sceneTreePanel.HScrollBar.ThumbEnabled = enabled; + } + private void OnSearchBoxTextChanged() { // Skip events during setup or init stuff diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h index c05698236..6a85a06b9 100644 --- a/Source/Engine/Core/Config/GraphicsSettings.h +++ b/Source/Engine/Core/Config/GraphicsSettings.h @@ -72,7 +72,7 @@ public: /// If checked, Environment Probes will use HDR texture format. Improves quality in very bright scenes at cost of higher memory usage. /// API_FIELD(Attributes = "EditorOrder(1502), EditorDisplay(\"Quality\")") - bool UeeHDRProbes = false; + bool UseHDRProbes = false; /// /// If checked, enables Global SDF rendering. This can be used in materials, shaders, and particles. @@ -118,6 +118,21 @@ public: API_FIELD(Attributes="EditorOrder(10000), EditorDisplay(\"Post Process Settings\", EditorDisplayAttribute.InlineStyle)") PostProcessSettings PostProcessSettings; +private: + /// + /// Renamed UeeHDRProbes into UseHDRProbes + /// [Deprecated on 12.10.2022, expires on 12.10.2024] + /// + API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") bool GetUeeHDRProbes() const + { + return UseHDRProbes; + } + + API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") void SetUeeHDRProbes(bool value) + { + UseHDRProbes = value; + } + public: /// /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp index a91074ab5..142baa745 100644 --- a/Source/Engine/Level/Actors/Camera.cpp +++ b/Source/Engine/Level/Actors/Camera.cpp @@ -120,6 +120,25 @@ void Camera::ProjectPoint(const Vector3& worldSpaceLocation, Float2& cameraViewp cameraViewportSpaceLocation = Float2(clipSpaceLocation); } +bool Camera::IsPointOnView(const Vector3& worldSpaceLocation) const +{ + Vector3 cameraUp = GetTransform().GetUp(); + Vector3 cameraForward = GetTransform().GetForward(); + Vector3 directionToPosition = (worldSpaceLocation - GetPosition()).GetNormalized(); + if (Vector3::Dot(cameraForward, directionToPosition) < 0) + return false; + + Quaternion lookAt = Quaternion::LookRotation(directionToPosition, cameraUp); + Vector3 lookAtDirection = lookAt * Vector3::Forward; + Vector3 newWorldLocation = GetPosition() + lookAtDirection; + + Float2 windowSpace; + const Viewport viewport = GetViewport(); + ProjectPoint(newWorldLocation, windowSpace, viewport); + + return windowSpace.X >= 0 && windowSpace.X <= viewport.Size.X && windowSpace.Y >= 0 && windowSpace.Y <= viewport.Size.Y; +} + Ray Camera::ConvertMouseToRay(const Float2& mousePosition) const { return ConvertMouseToRay(mousePosition, GetViewport()); diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h index 2b59ab323..465130110 100644 --- a/Source/Engine/Level/Actors/Camera.h +++ b/Source/Engine/Level/Actors/Camera.h @@ -168,6 +168,13 @@ public: /// The viewport. API_FUNCTION() void ProjectPoint(const Vector3& worldSpaceLocation, API_PARAM(Out) Float2& cameraViewportSpaceLocation, API_PARAM(Ref) const Viewport& viewport) const; + /// + /// Checks if the 3d point of the world is in the camera's field of view. + /// + /// World Position (XYZ). + /// Returns true if the point is within the field of view. + API_FUNCTION() bool IsPointOnView(const Vector3& worldSpaceLocation) const; + /// /// Converts the mouse position to 3D ray. /// diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h index 9782f40bb..ebeeb6b45 100644 --- a/Source/Engine/Platform/Base/WindowBase.h +++ b/Source/Engine/Platform/Base/WindowBase.h @@ -287,6 +287,8 @@ protected: bool _isUsingMouseOffset; Rectangle _mouseOffsetScreenSize; bool _isTrackingMouse; + bool _isHorizontalFlippingMouse; + bool _isVerticalFlippingMouse; bool _isClippingCursor; explicit WindowBase(const CreateWindowSettings& settings); @@ -680,6 +682,22 @@ public: return _isTrackingMouse; } + /// + /// Gets the value indicating if the mouse flipped to the other screen edge horizontally + /// + API_PROPERTY() bool IsMouseFlippingHorizontally() const + { + return _isHorizontalFlippingMouse; + } + + /// + /// Gets the value indicating if the mouse flipped to the other screen edge vertically + /// + API_PROPERTY() bool IsMouseFlippingVertically() const + { + return _isVerticalFlippingMouse; + } + /// /// Ends the mouse tracking. /// diff --git a/Source/Engine/Platform/SettingsBase.cs b/Source/Engine/Platform/SettingsBase.cs index 505195819..ab25592a5 100644 --- a/Source/Engine/Platform/SettingsBase.cs +++ b/Source/Engine/Platform/SettingsBase.cs @@ -1,5 +1,8 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. +using System; +using FlaxEngine; + namespace FlaxEditor.Content.Settings { /// @@ -11,13 +14,24 @@ namespace FlaxEditor.Content.Settings partial class GraphicsSettings { + /// + /// Renamed UeeHDRProbes into UseHDRProbes + /// [Deprecated on 12.10.2022, expires on 12.10.2024] + /// + [Serialize, Obsolete, NoUndo] + private bool UeeHDRProbes + { + get => UseHDRProbes; + set => UseHDRProbes = value; + } + /// /// Initializes a new instance of the . /// public GraphicsSettings() { // Initialize PostFx settings with default options (C# structs don't support it) - PostProcessSettings = FlaxEngine.PostProcessSettings.Default; + PostProcessSettings = PostProcessSettings.Default; } } } diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp index 0cd6aab95..da7692eeb 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp @@ -544,6 +544,8 @@ void WindowsWindow::StartTrackingMouse(bool useMouseScreenOffset) _isTrackingMouse = true; _trackingMouseOffset = Float2::Zero; _isUsingMouseOffset = useMouseScreenOffset; + _isHorizontalFlippingMouse = false; + _isVerticalFlippingMouse = false; int32 x = 0, y = 0, width = 0, height = 0; GetScreenInfo(x, y, width, height); @@ -558,6 +560,8 @@ void WindowsWindow::EndTrackingMouse() if (_isTrackingMouse) { _isTrackingMouse = false; + _isHorizontalFlippingMouse = false; + _isVerticalFlippingMouse = false; ReleaseCapture(); } @@ -824,14 +828,14 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) const Float2 mousePos(static_cast(WINDOWS_GET_X_LPARAM(lParam)), static_cast(WINDOWS_GET_Y_LPARAM(lParam))); Float2 mousePosition = ClientToScreen(mousePos); Float2 newMousePosition = mousePosition; - if (mousePosition.X <= desktopLocation.X + 2) - newMousePosition.X = desktopSize.X - 2; - else if (mousePosition.X >= desktopSize.X - 1) - newMousePosition.X = desktopLocation.X + 2; - if (mousePosition.Y <= desktopLocation.Y + 2) - newMousePosition.Y = desktopSize.Y - 2; - else if (mousePosition.Y >= desktopSize.Y - 1) - newMousePosition.Y = desktopLocation.Y + 2; + if (_isHorizontalFlippingMouse = mousePosition.X <= desktopLocation.X + 2) + newMousePosition.X = desktopSize.X - 3; + else if (_isHorizontalFlippingMouse = mousePosition.X >= desktopSize.X - 1) + newMousePosition.X = desktopLocation.X + 3; + if (_isVerticalFlippingMouse = mousePosition.Y <= desktopLocation.Y + 2) + newMousePosition.Y = desktopSize.Y - 3; + else if (_isVerticalFlippingMouse = mousePosition.Y >= desktopSize.Y - 1) + newMousePosition.Y = desktopLocation.Y + 3; if (!Float2::NearEqual(mousePosition, newMousePosition)) { _trackingMouseOffset -= newMousePosition - mousePosition; diff --git a/Source/Engine/Renderer/ProbesRenderer.cpp b/Source/Engine/Renderer/ProbesRenderer.cpp index 51791edd3..c1c273de8 100644 --- a/Source/Engine/Renderer/ProbesRenderer.cpp +++ b/Source/Engine/Renderer/ProbesRenderer.cpp @@ -204,7 +204,7 @@ int32 ProbesRenderer::Entry::GetResolution() const PixelFormat ProbesRenderer::Entry::GetFormat() const { - return GraphicsSettings::Get()->UeeHDRProbes ? PixelFormat::R11G11B10_Float : PixelFormat::R8G8B8A8_UNorm; + return GraphicsSettings::Get()->UseHDRProbes ? PixelFormat::R11G11B10_Float : PixelFormat::R8G8B8A8_UNorm; } int32 ProbesRenderer::GetBakeQueueSize() diff --git a/Source/Engine/UI/GUI/Control.cs b/Source/Engine/UI/GUI/Control.cs index 8384741bc..86c242609 100644 --- a/Source/Engine/UI/GUI/Control.cs +++ b/Source/Engine/UI/GUI/Control.cs @@ -948,6 +948,10 @@ namespace FlaxEngine.GUI { // Set flag _isDragOver = true; + + // Hide tooltip + Tooltip?.Hide(); + return DragDropEffect.None; } diff --git a/Source/Engine/UI/GUI/Panels/SplitPanel.cs b/Source/Engine/UI/GUI/Panels/SplitPanel.cs index 8772c78e6..2a46846e8 100644 --- a/Source/Engine/UI/GUI/Panels/SplitPanel.cs +++ b/Source/Engine/UI/GUI/Panels/SplitPanel.cs @@ -23,6 +23,7 @@ namespace FlaxEngine.GUI private float _splitterValue; private Rectangle _splitterRect; private bool _splitterClicked, _mouseOverSplitter; + private bool _cursorChanged; /// /// The first panel (left or upper based on Orientation). @@ -161,6 +162,18 @@ namespace FlaxEngine.GUI if (_splitterClicked) { SplitterValue = _orientation == Orientation.Horizontal ? location.X / Width : location.Y / Height; + Cursor = _orientation == Orientation.Horizontal ? CursorType.SizeWE : CursorType.SizeNS; + _cursorChanged = true; + } + else if (_mouseOverSplitter) + { + Cursor = _orientation == Orientation.Horizontal ? CursorType.SizeWE : CursorType.SizeNS; + _cursorChanged = true; + } + else if (_cursorChanged) + { + Cursor = CursorType.Default; + _cursorChanged = false; } base.OnMouseMove(location); @@ -197,6 +210,11 @@ namespace FlaxEngine.GUI { // Clear flag _mouseOverSplitter = false; + if (_cursorChanged) + { + Cursor = CursorType.Default; + _cursorChanged = false; + } base.OnMouseLeave(); } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 549e55d2d..53165cac3 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -922,10 +922,8 @@ namespace Flax.Build.Bindings // Properties foreach (var propertyInfo in classInfo.Properties) { - if (propertyInfo.IsHidden) + if (propertyInfo.IsHidden || !useUnmanaged) continue; - if (!useUnmanaged) - throw new NotImplementedException("TODO: support properties inside non-static and non-scripting API class types."); contents.AppendLine(); GenerateCSharpComment(contents, indent, propertyInfo.Comment, true); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index 1f6fcfb04..f178af64b 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -1446,6 +1446,11 @@ namespace Flax.Build.Bindings continue; if (GenerateCppAutoSerializationSkip(buildData, typeInfo, propertyInfo, propertyInfo.Type)) continue; + CppAutoSerializeProperties.Add(propertyInfo); + + // Skip writing deprecated properties (read-only deserialization to allow reading old data) + if (propertyInfo.HasAttribute("Obsolete")) + continue; contents.Append(" {"); contents.Append(" const auto"); @@ -1462,7 +1467,6 @@ namespace Flax.Build.Bindings contents.Append($"stream.JKEY(\"{propertyInfo.Name}\"); Serialization::Serialize(stream, value, nullptr);"); contents.Append(" }"); contents.Append('}').AppendLine(); - CppAutoSerializeProperties.Add(propertyInfo); } } else if (structureInfo != null) @@ -1494,14 +1498,14 @@ namespace Flax.Build.Bindings foreach (var propertyInfo in CppAutoSerializeProperties) { - contents.Append(" {"); - contents.Append($" const auto e = SERIALIZE_FIND_MEMBER(stream, \"{propertyInfo.Name}\");"); - contents.Append(" if (e != stream.MemberEnd()) {"); - contents.Append($" auto p = {propertyInfo.Getter.Name}();"); - contents.Append(" Serialization::Deserialize(e->value, p, modifier);"); - contents.Append($" {propertyInfo.Setter.Name}(p);"); - contents.Append(" }"); - contents.Append('}').AppendLine(); + contents.AppendLine(" {"); + contents.AppendLine($" const auto e = SERIALIZE_FIND_MEMBER(stream, \"{propertyInfo.Name}\");"); + contents.AppendLine(" if (e != stream.MemberEnd()) {"); + contents.AppendLine($" auto p = {propertyInfo.Getter.Name}();"); + contents.AppendLine(" Serialization::Deserialize(e->value, p, modifier);"); + contents.AppendLine($" {propertyInfo.Setter.Name}(p);"); + contents.AppendLine(" }"); + contents.AppendLine(" }"); } contents.Append('}').AppendLine(); diff --git a/Source/Tools/Flax.Build/Build/Builder.Projects.cs b/Source/Tools/Flax.Build/Build/Builder.Projects.cs index bb645a940..1772cb444 100644 --- a/Source/Tools/Flax.Build/Build/Builder.Projects.cs +++ b/Source/Tools/Flax.Build/Build/Builder.Projects.cs @@ -435,7 +435,7 @@ namespace Flax.Build else if (dependencyModule.BinaryModuleName == "FlaxEngine") { // TODO: instead of this hack find a way to reference the prebuilt target bindings binary (example: game C# project references FlaxEngine C# prebuilt dll) - project.CSharp.FileReferences.Add(Path.Combine(Globals.EngineRoot, "Binaries/Editor/Win64/Development/FlaxEngine.CSharp.dll")); + project.CSharp.FileReferences.Add(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), "Development/FlaxEngine.CSharp.dll")); } } } diff --git a/Source/Tools/Flax.Build/Build/Platform.cs b/Source/Tools/Flax.Build/Build/Platform.cs index 72e6454a4..99edc7889 100644 --- a/Source/Tools/Flax.Build/Build/Platform.cs +++ b/Source/Tools/Flax.Build/Build/Platform.cs @@ -245,6 +245,24 @@ namespace Flax.Build return toolchain; } + /// + /// Gets path to the current platform binary directory + /// + public static string GetEditorBinaryDirectory() + { + var subdir = "Binaries/Editor/"; + switch (Platform.BuildTargetPlatform) + { + case TargetPlatform.Windows: + return subdir + "Win64"; + case TargetPlatform.Linux: + return subdir + "Linux"; + case TargetPlatform.Mac: + return subdir + "Mac"; + } + throw new NotImplementedException(); + } + /// /// Creates the project files generator for the specified project format. /// diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index 55f3d138d..4c3f63b0c 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -39,6 +39,12 @@ namespace Flax.Build [CommandLine("deploy", "Runs the deploy tool.")] public static bool Deploy = false; + /// + /// Compresses deployed files. + /// + [CommandLine("deployDontCompress", "Skips compressing deployed files, and keeps files.")] + public static bool DontCompress = false; + /// /// Builds the targets. Builds all the targets, use to select a custom set of targets for the build. /// diff --git a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs index ad94da918..c4ca880f7 100644 --- a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs +++ b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using Flax.Build; +using Flax.Build.Platforms; namespace Flax.Deploy { @@ -126,21 +127,24 @@ namespace Flax.Deploy DeployFile(RootPath, OutputPath, "Flax.flaxproj"); // Compress + if (Configuration.DontCompress) + return; + Log.Info(string.Empty); Log.Info("Compressing editor files..."); string editorPackageZipPath; - if (Platform.BuildTargetPlatform == TargetPlatform.Linux) + var unix = Platform.BuildTargetPlatform == TargetPlatform.Linux || Platform.BuildTargetPlatform == TargetPlatform.Mac; + if (unix) { - // Use system tool (preserves executable file attributes and link files) - editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "FlaxEditorLinux.zip"); - Utilities.FileDelete(editorPackageZipPath); - Utilities.Run("zip", "Editor.zip -r .", null, OutputPath, Utilities.RunOptions.ThrowExceptionOnError); - File.Move(Path.Combine(OutputPath, "Editor.zip"), editorPackageZipPath); + var zipEofPath = UnixPlatform.Which("zip"); + unix = File.Exists(zipEofPath); + if (!unix) + Log.Verbose("Using .NET compressing"); } - else if (Platform.BuildTargetPlatform == TargetPlatform.Mac) + if (unix) { // Use system tool (preserves executable file attributes and link files) - editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "FlaxEditorMac.zip"); + editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, $"FlaxEditor{Enum.GetName(typeof(TargetPlatform), Platform.BuildTargetPlatform)}.zip"); Utilities.FileDelete(editorPackageZipPath); Utilities.Run("zip", "Editor.zip -r .", null, OutputPath, Utilities.RunOptions.ThrowExceptionOnError); File.Move(Path.Combine(OutputPath, "Editor.zip"), editorPackageZipPath); @@ -189,13 +193,14 @@ namespace Flax.Deploy private static void DeployEditorBinaries(TargetConfiguration configuration) { + var binariesSubDir = Path.Combine(Platform.GetEditorBinaryDirectory(), configuration.ToString()); + var src = Path.Combine(RootPath, binariesSubDir); + var dst = Path.Combine(OutputPath, binariesSubDir); + Directory.CreateDirectory(dst); + if (Platform.BuildTargetPlatform == TargetPlatform.Windows) { - var binariesSubDir = "Binaries/Editor/Win64/" + configuration; - var src = Path.Combine(RootPath, binariesSubDir); - var dst = Path.Combine(OutputPath, binariesSubDir); var dstDebug = Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols/Win64/" + configuration); - Directory.CreateDirectory(dst); Directory.CreateDirectory(dstDebug); // Validate that build editor app has a valid version number @@ -229,11 +234,6 @@ namespace Flax.Deploy } else if (Platform.BuildTargetPlatform == TargetPlatform.Linux) { - var binariesSubDir = "Binaries/Editor/Linux/" + configuration; - var src = Path.Combine(RootPath, binariesSubDir); - var dst = Path.Combine(OutputPath, binariesSubDir); - Directory.CreateDirectory(dst); - // Deploy binaries DeployFile(src, dst, "FlaxEditor"); DeployFile(src, dst, "FlaxEditor.Build.json"); @@ -253,11 +253,6 @@ namespace Flax.Deploy } else if (Platform.BuildTargetPlatform == TargetPlatform.Mac) { - var binariesSubDir = "Binaries/Editor/Mac/" + configuration; - var src = Path.Combine(RootPath, binariesSubDir); - var dst = Path.Combine(OutputPath, binariesSubDir); - Directory.CreateDirectory(dst); - // Deploy binaries DeployFile(src, dst, "FlaxEditor"); DeployFile(src, dst, "FlaxEditor.Build.json"); @@ -274,10 +269,6 @@ namespace Flax.Deploy Utilities.Run("strip", "libmonosgen-2.0.1.dylib", null, dst, Utilities.RunOptions.None); Utilities.Run("strip", "libMoltenVK.dylib", null, dst, Utilities.RunOptions.None); } - else - { - throw new NotImplementedException(); - } } } } diff --git a/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs b/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs index 78e6183bb..9a6d372d2 100644 --- a/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs +++ b/Source/Tools/Flax.Build/Deploy/Deployment.Platforms.cs @@ -63,6 +63,7 @@ namespace Flax.Deploy } // Compress + if (!Configuration.DontCompress) { Log.Info("Compressing platform files..."); @@ -84,10 +85,10 @@ namespace Flax.Deploy #endif Log.Info(string.Format("Compressed {0} package size: {1}", platformName, Utilities.GetFileSize(packageZipPath))); - } - // Remove files (only zip package is used) - Utilities.DirectoryDelete(dst); + // Remove files (only zip package is used) + Utilities.DirectoryDelete(dst); + } Log.Info(string.Empty); } diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs index 1d0433f50..ced516a54 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs @@ -58,7 +58,7 @@ namespace Flax.Build.Platforms if (Compiler != null) { // System compiler - ToolchainRoot = string.Empty; + ToolchainRoot = "/"; Log.Verbose($"Using native Linux toolchain (compiler {Compiler})"); HasRequiredSDKsInstalled = true; } diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index ede17b639..2904b89a7 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -23,9 +23,16 @@ namespace Flax.Build.Platforms : base(platform, architecture, platform.ToolchainRoot, platform.Compiler) { // Setup system paths - SystemIncludePaths.Add(Path.Combine(ToolsetRoot, "usr", "include")); - SystemIncludePaths.Add(Path.Combine(ToolsetRoot, "include", "c++", "5.2.0")); - SystemIncludePaths.Add(Path.Combine(ToolsetRoot, "lib", "clang", ClangVersion.Major.ToString(), "include")); + var includePath = Path.Combine(ToolsetRoot, "usr", "include"); + SystemIncludePaths.Add(includePath); + var cppIncludePath = Path.Combine(includePath, "c++", ClangVersion.ToString()); + if (Directory.Exists(cppIncludePath)) + SystemIncludePaths.Add(cppIncludePath); + var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang"); + var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include"); + if (!Directory.Exists(clangIncludePath)) + clangIncludePath = Path.Combine(clangLibPath, ClangVersion.ToString(), "include"); + SystemIncludePaths.Add(clangIncludePath); } /// diff --git a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs index f218a9a4f..cb0e5311e 100644 --- a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs @@ -138,7 +138,9 @@ namespace Flax.Build.Projects default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } } - case ProjectFormat.VisualStudioCode: return new VisualStudioCodeProjectGenerator(); + case ProjectFormat.VisualStudioCode: return type == TargetType.DotNet + ? (ProjectGenerator)new CSProjectGenerator(VisualStudioVersion.VisualStudio2015) + : (ProjectGenerator)new VisualStudioCodeProjectGenerator(); case ProjectFormat.XCode: return new XCodeProjectGenerator(); case ProjectFormat.Custom: if (CustomProjectTypes.TryGetValue(Configuration.ProjectFormatCustom, out var factory)) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index e925e70ae..872354f22 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -547,6 +547,10 @@ namespace Flax.Build.Projects.VisualStudioCode json.AddField("**/Output", true); json.AddField("**/*.flax", true); json.EndObject(); + + // Extension settings + json.AddField("omnisharp.useModernNet", false); + json.EndRootObject(); json.Save(Path.Combine(vsCodeFolder, "settings.json"));