From 21083f89057b4d14e6358ce5048d271417366acc Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Thu, 17 Oct 2024 19:24:38 +0200 Subject: [PATCH 01/50] expand play mode game panel focus options --- Source/Editor/Modules/SimulationModule.cs | 39 ++++++++-- Source/Editor/Options/InterfaceOptions.cs | 29 ++++++- Source/Editor/Windows/GameWindow.cs | 93 +++++++++++++++++++++-- 3 files changed, 143 insertions(+), 18 deletions(-) diff --git a/Source/Editor/Modules/SimulationModule.cs b/Source/Editor/Modules/SimulationModule.cs index 6f54ab10d..dd83d7553 100644 --- a/Source/Editor/Modules/SimulationModule.cs +++ b/Source/Editor/Modules/SimulationModule.cs @@ -2,6 +2,7 @@ using System; using System.Threading; +using FlaxEditor.GUI.Docking; using FlaxEditor.States; using FlaxEditor.Windows; using FlaxEngine; @@ -20,6 +21,7 @@ namespace FlaxEditor.Modules private bool _updateOrFixedUpdateWasCalled; private long _breakpointHangFlag; private EditorWindow _enterPlayFocusedWindow; + private DockWindow _previousWindow; private Guid[] _scenesToReload; internal SimulationModule(Editor editor) @@ -272,23 +274,46 @@ namespace FlaxEditor.Modules // Show Game widow if hidden if (gameWin != null) { - if (gameWin.FocusOnPlay) - gameWin.FocusGameViewport(); + switch (gameWin.FocusOnPlayOption) + { + case Options.InterfaceOptions.PlayModeFocus.None: + break; + + case Options.InterfaceOptions.PlayModeFocus.GamePanel: + gameWin.FocusGameViewport(); + break; + + case Options.InterfaceOptions.PlayModeFocus.GamePanelThenBack: + _previousWindow = gameWin.ParentDockPanel.SelectedTab; + gameWin.FocusGameViewport(); + break; + } + gameWin.SetWindowMode(Editor.Options.Options.Interface.DefaultGameWindowMode); } - Editor.Log("[PlayMode] Enter"); } /// public override void OnPlayEnd() { - // Restore focused window before play mode - if (_enterPlayFocusedWindow != null) + var gameWin = Editor.Windows.GameWin; + + switch (gameWin.FocusOnPlayOption) { - _enterPlayFocusedWindow.FocusOrShow(); - _enterPlayFocusedWindow = null; + case Options.InterfaceOptions.PlayModeFocus.None: + break; + + case Options.InterfaceOptions.PlayModeFocus.GamePanel: + break; + + case Options.InterfaceOptions.PlayModeFocus.GamePanelThenBack: + if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow)) + break; + + _previousWindow.Focus(); + break; } Editor.UI.UncheckPauseButton(); diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index d8493a70a..315853041 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -138,6 +138,27 @@ namespace FlaxEditor.Options AutoUnit, } + /// + /// Options for on play mode start panel focus. + /// + public enum PlayModeFocus + { + /// + /// Don't change any focus. + /// + None, + + /// + /// Focus the Game panel. + /// + GamePanel, + + /// + /// Focus the Game panel. On play mode end focus the previous panel again. + /// + GamePanelThenBack, + } + /// /// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required. /// @@ -341,11 +362,11 @@ namespace FlaxEditor.Options public bool OutputLogScrollToBottom { get; set; } = true; /// - /// Gets or sets a value indicating whether auto-focus game window on play mode start. + /// Gets or sets a value indicating what panel should be focused when play mode start. /// - [DefaultValue(true)] - [EditorDisplay("Play In-Editor", "Focus Game Window On Play"), EditorOrder(500), Tooltip("Determines whether auto-focus game window on play mode start.")] - public bool FocusGameWinOnPlay { get; set; } = true; + [DefaultValue(PlayModeFocus.GamePanel)] + [EditorDisplay("Play In-Editor", "Focus On Play"), EditorOrder(500), Tooltip("Set what panel to focus on play mode start.")] + public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GamePanel; /// /// Gets or sets a value indicating what action should be taken upon pressing the play button. diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 56e4c4380..a2e831576 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -39,6 +39,28 @@ namespace FlaxEditor.Windows private bool _useAspect = false; private bool _freeAspect = true; + private List _focusOptions = new List() + { + new PlayModeFocusOptions + { + Name = "None", + Tooltip = "Don't change focus.", + FocusOption = InterfaceOptions.PlayModeFocus.None, + }, + new PlayModeFocusOptions + { + Name = "Game Panel", + Tooltip = "Focus the Game panel.", + FocusOption = InterfaceOptions.PlayModeFocus.GamePanel, + }, + new PlayModeFocusOptions + { + Name = "Game Panel Then Back", + Tooltip = "Focus the Game panel. On play mode end focus the previous panel again.", + FocusOption = InterfaceOptions.PlayModeFocus.GamePanelThenBack, + }, + }; + /// /// Gets the viewport. /// @@ -162,9 +184,9 @@ namespace FlaxEditor.Windows public bool CenterMouseOnFocus { get; set; } /// - /// Gets or sets a value indicating whether auto-focus game window on play mode start. + /// Gets or sets a value indicating what panel should be focused when play mode start. /// - public bool FocusOnPlay { get; set; } + public InterfaceOptions.PlayModeFocus FocusOnPlayOption { get; set; } private enum ViewportScaleType { @@ -195,6 +217,29 @@ namespace FlaxEditor.Windows public bool Active; } + private class PlayModeFocusOptions + { + /// + /// The name. + /// + public string Name; + + /// + /// The tooltip. + /// + public string Tooltip; + + /// + /// The type of focus. + /// + public InterfaceOptions.PlayModeFocus FocusOption; + + /// + /// If the option is active. + /// + public bool Active; + } + /// /// Root control for game UI preview in Editor. Supports basic UI editing via . /// @@ -430,7 +475,7 @@ namespace FlaxEditor.Windows private void OnOptionsChanged(EditorOptions options) { CenterMouseOnFocus = options.Interface.CenterMouseOnGameWinFocus; - FocusOnPlay = options.Interface.FocusGameWinOnPlay; + FocusOnPlayOption = options.Interface.FocusOnPlayMode; } private void PlayingStateOnSceneDuplicating() @@ -488,6 +533,41 @@ namespace FlaxEditor.Windows } } + // TODO: Move this to other generate method + private void GenerateFocusOptionsContextMenu(ContextMenu pfMenu) + { + foreach (PlayModeFocusOptions f in _focusOptions) + { + f.Active = f.FocusOption == FocusOnPlayOption; + + var button = pfMenu.AddButton(f.Name); + button.CloseMenuOnClick = false; + button.Tag = f; + button.TooltipText = f.Tooltip; + button.Icon = f.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + button.Clicked += () => + { + foreach (var child in pfMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is PlayModeFocusOptions p) + { + if (cmb == button) + { + p.Active = true; + button.Icon = Style.Current.CheckBoxTick; + FocusOnPlayOption = p.FocusOption; + } + else if (p.Active) + { + cmb.Icon = SpriteHandle.Invalid; + p.Active = false; + } + } + } + }; + } + } + /// public override void OnShowContextMenu(ContextMenu menu) { @@ -495,10 +575,9 @@ namespace FlaxEditor.Windows // Focus on play { - var focus = menu.AddButton("Start Focused"); - focus.CloseMenuOnClick = false; - var checkbox = new CheckBox(140, 2, FocusOnPlay) { Parent = focus }; - checkbox.StateChanged += state => FocusOnPlay = state.Checked; + var pfMenu = menu.AddChildMenu("Play Mode Focus Override").ContextMenu; + + GenerateFocusOptionsContextMenu(pfMenu); } menu.AddSeparator(); From a810288e2e0cfe206e362b5649daeb8befe0ddcc Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Thu, 17 Oct 2024 22:04:53 +0200 Subject: [PATCH 02/50] do todo --- Source/Editor/Windows/GameWindow.cs | 69 ++++++++++++++--------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index a2e831576..b6b95867e 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -533,41 +533,6 @@ namespace FlaxEditor.Windows } } - // TODO: Move this to other generate method - private void GenerateFocusOptionsContextMenu(ContextMenu pfMenu) - { - foreach (PlayModeFocusOptions f in _focusOptions) - { - f.Active = f.FocusOption == FocusOnPlayOption; - - var button = pfMenu.AddButton(f.Name); - button.CloseMenuOnClick = false; - button.Tag = f; - button.TooltipText = f.Tooltip; - button.Icon = f.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - button.Clicked += () => - { - foreach (var child in pfMenu.Items) - { - if (child is ContextMenuButton cmb && cmb.Tag is PlayModeFocusOptions p) - { - if (cmb == button) - { - p.Active = true; - button.Icon = Style.Current.CheckBoxTick; - FocusOnPlayOption = p.FocusOption; - } - else if (p.Active) - { - cmb.Icon = SpriteHandle.Invalid; - p.Active = false; - } - } - } - }; - } - } - /// public override void OnShowContextMenu(ContextMenu menu) { @@ -679,6 +644,40 @@ namespace FlaxEditor.Windows menu.AddSeparator(); } + private void GenerateFocusOptionsContextMenu(ContextMenu pfMenu) + { + foreach (PlayModeFocusOptions f in _focusOptions) + { + f.Active = f.FocusOption == FocusOnPlayOption; + + var button = pfMenu.AddButton(f.Name); + button.CloseMenuOnClick = false; + button.Tag = f; + button.TooltipText = f.Tooltip; + button.Icon = f.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + button.Clicked += () => + { + foreach (var child in pfMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is PlayModeFocusOptions p) + { + if (cmb == button) + { + p.Active = true; + button.Icon = Style.Current.CheckBoxTick; + FocusOnPlayOption = p.FocusOption; + } + else if (p.Active) + { + cmb.Icon = SpriteHandle.Invalid; + p.Active = false; + } + } + } + }; + } + } + private void CreateViewportSizingContextMenu(ContextMenu vsMenu) { // Add default viewport sizing options From af79a3284748529eb82af1ca2b4599773e6f09d5 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Thu, 17 Oct 2024 22:06:07 +0200 Subject: [PATCH 03/50] make naming more consistent --- Source/Editor/Windows/GameWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index b6b95867e..886b11d11 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -540,7 +540,7 @@ namespace FlaxEditor.Windows // Focus on play { - var pfMenu = menu.AddChildMenu("Play Mode Focus Override").ContextMenu; + var pfMenu = menu.AddChildMenu("Focus On Play Override").ContextMenu; GenerateFocusOptionsContextMenu(pfMenu); } From dddd5b83d07bf812dab0ddb27041ae1e7e4d1f49 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 18 Oct 2024 16:58:49 +0200 Subject: [PATCH 04/50] add button to remove override --- Source/Editor/Windows/GameWindow.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 886b11d11..c10c27913 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -543,6 +543,12 @@ namespace FlaxEditor.Windows var pfMenu = menu.AddChildMenu("Focus On Play Override").ContextMenu; GenerateFocusOptionsContextMenu(pfMenu); + + pfMenu.AddSeparator(); + + var button = pfMenu.AddButton("Remove override"); + button.TooltipText = "Reset the override to the value set in the editor options."; + button.Clicked += () => FocusOnPlayOption = Editor.Instance.Options.Options.Interface.FocusOnPlayMode; } menu.AddSeparator(); From 6830e4f22b1442389d881bd96f28a537827edb00 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 18 Oct 2024 22:13:06 +0200 Subject: [PATCH 05/50] add hotkey for parent to new actor ctrl + g by default --- Source/Editor/Modules/UIModule.cs | 2 +- Source/Editor/Options/InputOptions.cs | 4 ++++ Source/Editor/Utilities/Utils.cs | 1 + Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index 6a197c62f..f6d140e0e 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -556,7 +556,7 @@ namespace FlaxEditor.Modules cm.AddSeparator(); _menuEditSelectAll = cm.AddButton("Select all", inputOptions.SelectAll, Editor.SceneEditing.SelectAllScenes); _menuEditDeselectAll = cm.AddButton("Deselect all", inputOptions.DeselectAll, Editor.SceneEditing.DeselectAllScenes); - _menuCreateParentForSelectedActors = cm.AddButton("Create parent for selected actors", Editor.SceneEditing.CreateParentForSelectedActors); + _menuCreateParentForSelectedActors = cm.AddButton("Parent to new Actor", inputOptions.GroupSelectedActors, Editor.SceneEditing.CreateParentForSelectedActors); _menuEditFind = cm.AddButton("Find", inputOptions.Search, Editor.Windows.SceneWin.Search); cm.AddSeparator(); cm.AddButton("Game Settings", () => diff --git a/Source/Editor/Options/InputOptions.cs b/Source/Editor/Options/InputOptions.cs index 211e8e54f..76610f675 100644 --- a/Source/Editor/Options/InputOptions.cs +++ b/Source/Editor/Options/InputOptions.cs @@ -160,6 +160,10 @@ namespace FlaxEditor.Options [EditorDisplay("Scene"), EditorOrder(573)] public InputBinding PilotActor = new InputBinding(KeyboardKeys.None); + [DefaultValue(typeof(InputBinding), "Ctrl+G")] + [EditorDisplay("Scene"), EditorOrder(574)] + public InputBinding GroupSelectedActors = new InputBinding(KeyboardKeys.G, KeyboardKeys.Control); + #endregion #region Tools diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 1487f1a59..7afe9ad0c 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1432,6 +1432,7 @@ namespace FlaxEditor.Utilities inputActions.Add(options => options.SelectAll, Editor.Instance.SceneEditing.SelectAllScenes); inputActions.Add(options => options.DeselectAll, Editor.Instance.SceneEditing.DeselectAllScenes); inputActions.Add(options => options.Delete, Editor.Instance.SceneEditing.Delete); + inputActions.Add(options => options.GroupSelectedActors, Editor.Instance.SceneEditing.CreateParentForSelectedActors); inputActions.Add(options => options.Search, () => Editor.Instance.Windows.SceneWin.Search()); inputActions.Add(options => options.MoveActorToViewport, Editor.Instance.UI.MoveActorToViewport); inputActions.Add(options => options.AlignActorWithViewport, Editor.Instance.UI.AlignActorWithViewport); diff --git a/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs b/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs index 8d31b2744..2cbe56a27 100644 --- a/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs +++ b/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs @@ -133,7 +133,7 @@ namespace FlaxEditor.Windows contextMenu.AddSeparator(); - b = contextMenu.AddButton("Create parent for selected actors", Editor.SceneEditing.CreateParentForSelectedActors); + b = contextMenu.AddButton("Parent to new Actor", inputOptions.GroupSelectedActors, Editor.SceneEditing.CreateParentForSelectedActors); b.Enabled = canEditScene && hasSthSelected; b = contextMenu.AddButton("Create Prefab", Editor.Prefabs.CreatePrefab); From 0b52a579c7db433e305db27d19400ebd361b1377 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Tue, 22 Oct 2024 13:18:22 -0500 Subject: [PATCH 06/50] Change when wheels are ordered. --- .../Physics/PhysX/PhysicsBackendPhysX.cpp | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index d88031a01..6baac7310 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -3440,39 +3440,13 @@ PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle:: return antiRollBar; } -bool SortWheelsFrontToBack(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b) +bool SortWheelsFrontToBack(WheeledVehicle::Wheel* const& a, WheeledVehicle::Wheel* const& b) { - return a.Collider && b.Collider && a.Collider->GetLocalPosition().Z > b.Collider->GetLocalPosition().Z; + return a->Collider && b->Collider && a->Collider->GetLocalPosition().Z > b->Collider->GetLocalPosition().Z; } void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) { - // Physx vehicles needs to have all wheels sorted to apply controls correctly. - // Its needs to know what wheels are on front to turn wheel to correctly side - // and needs to know wheel side to apply throttle to correctly direction for each track when using tanks. - // Anti roll bars needs to have all wheels sorted to get correctly wheel index too. - if (actor->_driveType != WheeledVehicle::DriveTypes::NoDrive) - { - Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack); - - // Sort wheels by side - if (actor->_driveType == WheeledVehicle::DriveTypes::Tank) - { - for (int32 i = 0; i < actor->_wheels.Count() - 1; i += 2) - { - auto a = actor->_wheels[i]; - auto b = actor->_wheels[i + 1]; - if (!a.Collider || !b.Collider) - continue; - if (a.Collider->GetLocalPosition().X > b.Collider->GetLocalPosition().X) - { - actor->_wheels[i] = b; - actor->_wheels[i + 1] = a; - } - } - } - } - // Get wheels Array> wheels; for (auto& wheel : actor->_wheels) @@ -3503,6 +3477,33 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) // No woman, no cry return nullptr; } + + // Physx vehicles needs to have all wheels sorted to apply controls correctly. + // Its needs to know what wheels are on front to turn wheel to correctly side + // and needs to know wheel side to apply throttle to correctly direction for each track when using tanks. + // Anti roll bars needs to have all wheels sorted to get correctly wheel index too. + if (actor->_driveType != WheeledVehicle::DriveTypes::NoDrive) + { + Sorting::QuickSort(wheels.Get(), wheels.Count(), SortWheelsFrontToBack); + + // Sort wheels by side + if (actor->_driveType == WheeledVehicle::DriveTypes::Tank) + { + for (int32 i = 0; i < wheels.Count() - 1; i += 2) + { + auto a = wheels[i]; + auto b = wheels[i + 1]; + if (!a->Collider || !b->Collider) + continue; + if (a->Collider->GetLocalPosition().X > b->Collider->GetLocalPosition().X) + { + wheels[i] = b; + wheels[i + 1] = a; + } + } + } + } + actor->_wheelsData.Resize(wheels.Count()); auto actorPhysX = (PxRigidDynamic*)actor->GetPhysicsActor(); From ca9b041f540575d55ea4cff0b44dae5547e70b97 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 24 Oct 2024 22:32:02 +0200 Subject: [PATCH 07/50] Fix regression --- Source/Editor/Options/InterfaceOptions.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index ca053dcab..30cb64aa8 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -223,11 +223,15 @@ namespace FlaxEditor.Options /// [DefaultValue(TextAlignment.Center)] [EditorDisplay("Interface"), EditorOrder(321)] - public TextAlignment TooltipTextAlignment { get => _tooltipTextAlignment; + public TextAlignment TooltipTextAlignment + { + get => _tooltipTextAlignment; set { _tooltipTextAlignment = value; - Style.Current.SharedTooltip.HorizontalTextAlignment = value; + var tooltip = Style.Current?.SharedTooltip; + if (tooltip != null) + tooltip.HorizontalTextAlignment = value; } } From 1181deb5df008cf26fbea4d515ccb11be84a9d45 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 24 Oct 2024 23:38:25 +0200 Subject: [PATCH 08/50] Fix crash when using attributes cache after hot-reload in editor --- .../Engine/Scripting/ManagedCLR/MAssembly.h | 1 + Source/Engine/Scripting/ManagedCLR/MEvent.h | 1 + Source/Engine/Scripting/ManagedCLR/MField.h | 1 + Source/Engine/Scripting/ManagedCLR/MMethod.h | 1 + .../Engine/Scripting/ManagedCLR/MProperty.h | 1 + Source/Engine/Scripting/Runtime/DotNet.cpp | 39 +++++++++++++++++++ 6 files changed, 44 insertions(+) diff --git a/Source/Engine/Scripting/ManagedCLR/MAssembly.h b/Source/Engine/Scripting/ManagedCLR/MAssembly.h index 169cfd7e3..8e9b21509 100644 --- a/Source/Engine/Scripting/ManagedCLR/MAssembly.h +++ b/Source/Engine/Scripting/ManagedCLR/MAssembly.h @@ -14,6 +14,7 @@ /// class FLAXENGINE_API MAssembly { + friend MCore; friend MDomain; friend Scripting; diff --git a/Source/Engine/Scripting/ManagedCLR/MEvent.h b/Source/Engine/Scripting/ManagedCLR/MEvent.h index 5692f3dc6..5fe4da1a1 100644 --- a/Source/Engine/Scripting/ManagedCLR/MEvent.h +++ b/Source/Engine/Scripting/ManagedCLR/MEvent.h @@ -10,6 +10,7 @@ class FLAXENGINE_API MEvent { friend MClass; + friend MCore; protected: #if USE_MONO diff --git a/Source/Engine/Scripting/ManagedCLR/MField.h b/Source/Engine/Scripting/ManagedCLR/MField.h index 5475f4535..7c0d89287 100644 --- a/Source/Engine/Scripting/ManagedCLR/MField.h +++ b/Source/Engine/Scripting/ManagedCLR/MField.h @@ -11,6 +11,7 @@ class FLAXENGINE_API MField { friend MClass; + friend MCore; protected: #if USE_MONO diff --git a/Source/Engine/Scripting/ManagedCLR/MMethod.h b/Source/Engine/Scripting/ManagedCLR/MMethod.h index f2b127871..4731e0723 100644 --- a/Source/Engine/Scripting/ManagedCLR/MMethod.h +++ b/Source/Engine/Scripting/ManagedCLR/MMethod.h @@ -16,6 +16,7 @@ class FLAXENGINE_API MMethod friend MClass; friend MProperty; friend MEvent; + friend MCore; protected: #if USE_MONO diff --git a/Source/Engine/Scripting/ManagedCLR/MProperty.h b/Source/Engine/Scripting/ManagedCLR/MProperty.h index dbbed8ab3..975d62b8c 100644 --- a/Source/Engine/Scripting/ManagedCLR/MProperty.h +++ b/Source/Engine/Scripting/ManagedCLR/MProperty.h @@ -12,6 +12,7 @@ class FLAXENGINE_API MProperty { friend MClass; + friend MCore; protected: #if USE_MONO diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp index 4a71e9c2f..38df5c16f 100644 --- a/Source/Engine/Scripting/Runtime/DotNet.cpp +++ b/Source/Engine/Scripting/Runtime/DotNet.cpp @@ -336,7 +336,46 @@ void MCore::ReloadScriptingAssemblyLoadContext() { // Clear any cached class attributes (see https://github.com/FlaxEngine/FlaxEngine/issues/1108) for (auto e : CachedClassHandles) + { + e.Value->_hasCachedAttributes = false; e.Value->_attributes.Clear(); + } + for (auto e : CachedAssemblyHandles) + { + MAssembly* a = e.Value; + if (!a->IsLoaded() || !a->_hasCachedClasses) + continue; + for (auto q : a->GetClasses()) + { + MClass* c = q.Value; + c->_hasCachedAttributes = false; + c->_attributes.Clear(); + if (c->_hasCachedMethods) + { + for (MMethod* m : c->GetMethods()) + { + m->_hasCachedAttributes = false; + m->_attributes.Clear(); + } + } + if (c->_hasCachedFields) + { + for (MField* f : c->GetFields()) + { + f->_hasCachedAttributes = false; + f->_attributes.Clear(); + } + } + if (c->_hasCachedProperties) + { + for (MProperty* p : c->GetProperties()) + { + p->_hasCachedAttributes = false; + p->_attributes.Clear(); + } + } + } + } static void* ReloadScriptingAssemblyLoadContextPtr = GetStaticMethodPointer(TEXT("ReloadScriptingAssemblyLoadContext")); CallStaticMethod(ReloadScriptingAssemblyLoadContextPtr); From 5a873ad606957833fce94971fe6612f1f0da55a0 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 13:21:40 +0200 Subject: [PATCH 09/50] Fix crash when boxing native non-POD structure into managed data --- Source/Engine/Engine/NativeInterop.cs | 52 +++++++++++++++---- .../Bindings/BindingsGenerator.CSharp.cs | 1 - 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 3591df299..35fe70221 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -55,6 +55,9 @@ namespace FlaxEngine.Interop private static Dictionary assemblyOwnedNativeLibraries = new(); internal static AssemblyLoadContext scriptingAssemblyLoadContext; + private delegate TInternal ToNativeDelegate(T value); + private delegate T ToManagedDelegate(TInternal value); + [System.Diagnostics.DebuggerStepThrough] private static IntPtr NativeLibraryImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? dllImportSearchPath) { @@ -490,6 +493,7 @@ namespace FlaxEngine.Interop internal delegate void MarshalFieldTypedDelegate(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize); internal delegate void* GetBasePointer(ref T fieldOwner); + internal static Delegate toManagedDelegate; internal static FieldInfo[] marshallableFields; internal static int[] marshallableFieldOffsets; internal static MarshalFieldTypedDelegate[] toManagedFieldMarshallers; @@ -612,16 +616,32 @@ namespace FlaxEngine.Interop MethodInfo toManagedMethod; if (type.IsValueType) { - string methodName; - if (type == typeof(IntPtr)) - methodName = nameof(MarshalHelperValueType.ToManagedPointer); - else if (type == typeof(ManagedHandle)) - methodName = nameof(MarshalHelperValueType.ToManagedHandle); - else if (marshallableFields != null) - methodName = nameof(MarshalHelperValueType.ToManagedWithMarshallableFields); + // Non-POD structures use internal layout (eg. SpriteHandleManaged in C++ with SpriteHandleMarshaller.SpriteHandleInternal in C#) so convert C++ data into C# data + var attr = type.GetCustomAttribute(); + toManagedMethod = attr?.NativeType.GetMethod("ToManaged", BindingFlags.Static | BindingFlags.NonPublic); + if (toManagedMethod != null) + { + // TODO: optimize via delegate call rather than method invoke + var internalType = toManagedMethod.GetParameters()[0].ParameterType; + var types = new Type[] { type, internalType }; + toManagedDelegate = toManagedMethod.CreateDelegate(typeof(ToManagedDelegate<,>).MakeGenericType(types)); + //toManagedDelegate = toManagedMethod.CreateDelegate();//.CreateDelegate(typeof(ToManagedDelegate<,>).MakeGenericType(type, toManagedMethod.GetParameters()[0].ParameterType)); + string methodName = nameof(MarshalInternalHelper.ToManagedMarshaller); + toManagedMethod = typeof(MarshalInternalHelper<,>).MakeGenericType(types).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic); + } else - methodName = nameof(MarshalHelperValueType.ToManaged); - toManagedMethod = typeof(MarshalHelperValueType<>).MakeGenericType(type).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic); + { + string methodName; + if (type == typeof(IntPtr)) + methodName = nameof(MarshalHelperValueType.ToManagedPointer); + else if (type == typeof(ManagedHandle)) + methodName = nameof(MarshalHelperValueType.ToManagedHandle); + else if (marshallableFields != null) + methodName = nameof(MarshalHelperValueType.ToManagedWithMarshallableFields); + else + methodName = nameof(MarshalHelperValueType.ToManaged); + toManagedMethod = typeof(MarshalHelperValueType<>).MakeGenericType(type).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic); + } } else if (type.IsArray) { @@ -1065,6 +1085,17 @@ namespace FlaxEngine.Interop } } + internal static class MarshalInternalHelper where T : struct + where TInternal : struct + { + internal static void ToManagedMarshaller(ref T managedValue, IntPtr nativePtr, bool byRef) + { + ToManagedDelegate toManaged = Unsafe.As>(MarshalHelper.toManagedDelegate); + TInternal intern = Unsafe.Read(nativePtr.ToPointer()); + managedValue = toManaged(Unsafe.Read(nativePtr.ToPointer())); + } + } + internal static class MarshalHelperValueType where T : struct { internal static void ToNativeWrapper(object managedObject, IntPtr nativePtr) @@ -1504,8 +1535,6 @@ namespace FlaxEngine.Interop private static (IntPtr ptr, int size)[] pinnedAllocations = new (IntPtr ptr, int size)[256]; private static uint pinnedAllocationsPointer = 0; - private delegate TInternal ToNativeDelegate(T value); - private delegate IntPtr UnboxerDelegate(object value, object converter); private static ConcurrentDictionary unboxers = new(1, 3); @@ -1683,6 +1712,7 @@ namespace FlaxEngine.Interop internal static class TypeHelpers { public static readonly int MarshalSize; + static TypeHelpers() { Type type = typeof(T); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 9642c8b02..551417ebf 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -1855,7 +1855,6 @@ namespace Flax.Build.Bindings {{structureInfo.Name}}Internal unmanaged; public void FromManaged({{structureInfo.Name}} managed) => this.managed = managed; public {{structureInfo.Name}}Internal ToUnmanaged() { unmanaged = {{marshallerFullName}}.ToNative(managed); return unmanaged; } - //public void FromUnmanaged({{structureInfo.Name}}Internal unmanaged) { {{marshallerFullName}}.Free(this.unmanaged.Value); this.unmanaged = unmanaged; } public void FromUnmanaged({{structureInfo.Name}}Internal unmanaged) => this.unmanaged = unmanaged; public {{structureInfo.Name}} ToManaged() { managed = {{marshallerFullName}}.ToManaged(unmanaged); return managed; } public void Free() => NativeToManaged.Free(unmanaged); From 1f71a5a2e55adc5f8f9ee81e1e0e36017ec40868 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 16:16:33 +0200 Subject: [PATCH 10/50] Update `Microsoft.VisualStudio.Setup.Configuration.Interop.dll` from `3.4.2244` to the latest `3.11.2177` https://forum.flaxengine.com/t/project-not-loaded-after-installing-1-9/1923 --- .../Microsoft.VisualStudio.Setup.Configuration.Interop.dll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll b/Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll index fbbba57a5..c589d05c1 100644 --- a/Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll +++ b/Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f1e8f9f551bd39474ab7bc25b5c78d2cb9acaf4869d79da6ffd0f0f458e6bde -size 21888 +oid sha256:0f12e6ea9bc8aa0d069c29176c5d248b9f3f5c1ed2d3aaf0d9cc1e83f21f56a1 +size 22544 From 6af788b20c57cf57ea5a61c66e6c41d6cb3ff2b0 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 17:27:28 +0200 Subject: [PATCH 11/50] Fix logging missing ref duplicates #3018 --- Source/Engine/Core/LogContext.cpp | 7 ++++++- Source/Engine/Core/LogContext.h | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Core/LogContext.cpp b/Source/Engine/Core/LogContext.cpp index 9df4bce99..6916fd7de 100644 --- a/Source/Engine/Core/LogContext.cpp +++ b/Source/Engine/Core/LogContext.cpp @@ -54,12 +54,17 @@ void LogContext::Print(LogType verbosity) StringBuilder msg; for (int32 index = (int32)stack.Count - 1; index >= 0; index--) { + LogContextData& context = stack.Ptr[index]; + + // Skip duplicates + if (index < stack.Count - 1 && stack.Ptr[stack.Count - 1] == context) + continue; + // Build call hierarchy via indentation msg.Clear(); for (uint32 i = index; i < stack.Count; i++) msg.Append(indentation); - LogContextData& context = stack.Ptr[index]; if (context.ObjectID != Guid::Empty) { // Object reference context diff --git a/Source/Engine/Core/LogContext.h b/Source/Engine/Core/LogContext.h index 7a851a6c9..59a0c537c 100644 --- a/Source/Engine/Core/LogContext.h +++ b/Source/Engine/Core/LogContext.h @@ -20,6 +20,11 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API LogContextData /// A GUID for an object which this context applies to. /// API_FIELD() Guid ObjectID; + + friend bool operator==(const LogContextData& lhs, const LogContextData& rhs) + { + return lhs.ObjectID == rhs.ObjectID; + } }; template<> From 3c64d57e3dfa48e2626276d2b9b1e508b8bbd7f7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 17:51:29 +0200 Subject: [PATCH 12/50] Another blind attempt to fix issue #3018 --- .../VisualStudioCode/VisualStudioCodeProjectGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 88b7a8df5..68faf3178 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -301,7 +301,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.BeginArray("configurations"); { var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name); - var mainProjectModule = solution.MainProject?.Targets.Length != 0 ? solution.MainProject.Targets[0].Modules[0] : null; + var mainProjectModule = solution.MainProject?.Targets?.Length != 0 ? solution.MainProject.Targets[0].Modules[0] : null; var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null; if (cppProject != null) From f37a595bc3954d0bb2518d9cee5f7806393c04ff Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 18:24:14 +0200 Subject: [PATCH 13/50] Fix actors grouping to make shared parent at the cenetr of the group #2996 --- Source/Editor/Modules/SceneEditingModule.cs | 24 +++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Modules/SceneEditingModule.cs b/Source/Editor/Modules/SceneEditingModule.cs index 13a920fa3..841f2b5dd 100644 --- a/Source/Editor/Modules/SceneEditingModule.cs +++ b/Source/Editor/Modules/SceneEditingModule.cs @@ -555,10 +555,20 @@ namespace FlaxEditor.Modules /// public void CreateParentForSelectedActors() { - Actor actor = new EmptyActor(); - Editor.SceneEditing.Spawn(actor, null, false); List selection = Editor.SceneEditing.Selection; var actors = selection.Where(x => x is ActorNode).Select(x => ((ActorNode)x).Actor); + var actorsCount = actors.Count(); + if (actorsCount == 0) + return; + Vector3 center = Vector3.Zero; + foreach (var actor in actors) + center += actor.Position; + center /= actorsCount; + Actor parent = new EmptyActor + { + Position = center, + }; + Editor.SceneEditing.Spawn(parent, null, false); using (new UndoMultiBlock(Undo, actors, "Reparent actors")) { for (int i = 0; i < selection.Count; i++) @@ -574,15 +584,15 @@ namespace FlaxEditor.Modules // Put created node as child of the Parent Node of node int parentOrder = node.Actor.OrderInParent; - actor.Parent = node.Actor.Parent; - actor.OrderInParent = parentOrder; + parent.SetParent(node.Actor.Parent, true, true); + parent.OrderInParent = parentOrder; } - node.Actor.Parent = actor; + node.Actor.SetParent(parent, true, false); } } } - Editor.SceneEditing.Select(actor); - Editor.Scene.GetActorNode(actor).TreeNode.StartRenaming(Editor.Windows.SceneWin, Editor.Windows.SceneWin.SceneTreePanel); + Editor.SceneEditing.Select(parent); + Editor.Scene.GetActorNode(parent).TreeNode.StartRenaming(Editor.Windows.SceneWin, Editor.Windows.SceneWin.SceneTreePanel); } /// From 12af7f6cc971c95d6ed9e0feb17acd0c75d577ed Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 18:53:10 +0200 Subject: [PATCH 14/50] Add cache to asset references graph for faster displaying data #3013 --- .../Windows/AssetReferencesGraphWindow.cs | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Windows/AssetReferencesGraphWindow.cs b/Source/Editor/Windows/AssetReferencesGraphWindow.cs index 64eef8224..5d0eee183 100644 --- a/Source/Editor/Windows/AssetReferencesGraphWindow.cs +++ b/Source/Editor/Windows/AssetReferencesGraphWindow.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using FlaxEditor.Content; @@ -137,6 +139,7 @@ namespace FlaxEditor.Windows } } + private string _cacheFolder; private Guid _assetId; private Surface _surface; private Label _loadingLabel; @@ -161,6 +164,9 @@ namespace FlaxEditor.Windows { Title = assetItem.ShortName + " References"; + _cacheFolder = Path.Combine(Globals.ProjectCacheFolder, "References"); + if (!Directory.Exists(_cacheFolder)) + Directory.CreateDirectory(_cacheFolder); _assetId = assetItem.ID; _surface = new Surface(this) { @@ -189,7 +195,7 @@ namespace FlaxEditor.Windows return node; } - private void SearchRefs(Guid assetId) + private unsafe void SearchRefs(Guid assetId) { // Skip assets that never contain references to prevent loading them if (FlaxEngine.Content.GetAssetInfo(assetId, out var assetInfo) && @@ -202,8 +208,24 @@ namespace FlaxEditor.Windows if (_refs.ContainsKey(assetId)) return; + // Try to load cached references form previous run + var cachePath = Path.Combine(_cacheFolder, $"{FlaxEngine.Json.JsonSerializer.GetStringID(assetId)}.1.cache"); + var hasInfo = FlaxEngine.Content.GetAssetInfo(assetId, out var info); + if (hasInfo && File.Exists(cachePath) && File.GetLastWriteTime(cachePath) > File.GetLastWriteTime(info.Path)) + { + byte[] rawData = File.ReadAllBytes(cachePath); + Guid[] loadedRefs = new Guid[rawData.Length / sizeof(Guid)]; + if (rawData.Length != 0) + { + fixed (byte* rawDataPtr = rawData) + fixed (Guid* loadedRefsPtr = loadedRefs) + Unsafe.CopyBlock(loadedRefsPtr, rawDataPtr, (uint)rawData.Length); + } + _refs[assetId] = loadedRefs; + return; + } + // Load asset (with cancel support) - //Debug.Log("Searching refs for " + assetInfo.Path); var obj = FlaxEngine.Object.TryFind(ref assetId); if (obj is Scene scene) { @@ -226,7 +248,21 @@ namespace FlaxEditor.Windows return; // Get direct references - _refs[assetId] = asset.GetReferences(); + var references = asset.GetReferences(); + _refs[assetId] = references; + + // Save reference to the cache + if (hasInfo) + { + byte[] rawData = new byte[references.Length * sizeof(Guid)]; + if (rawData.Length != 0) + { + fixed (byte* rawDataPtr = rawData) + fixed (Guid* referencesPtr = references) + Unsafe.CopyBlock(rawDataPtr, referencesPtr, (uint)rawData.Length); + } + File.WriteAllBytes(cachePath, rawData); + } } private void BuildGraph(AssetNode node, int level, bool reverse) From 9f9564895e158cf07bb9fcddc945a3939430c928 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Oct 2024 19:02:31 +0200 Subject: [PATCH 15/50] Fix collecting referenced asses from `Animation` asset #3013 --- Source/Engine/Content/Assets/Animation.cpp | 30 ++++++++++++++++++++++ Source/Engine/Content/Assets/Animation.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/Source/Engine/Content/Assets/Animation.cpp b/Source/Engine/Content/Assets/Animation.cpp index f65a1c3ba..261394441 100644 --- a/Source/Engine/Content/Assets/Animation.cpp +++ b/Source/Engine/Content/Assets/Animation.cpp @@ -12,6 +12,8 @@ #include "Engine/Serialization/MemoryReadStream.h" #if USE_EDITOR #include "Engine/Serialization/MemoryWriteStream.h" +#include "Engine/Serialization/JsonWriters.h" +#include "Engine/Content/JsonAsset.h" #include "Engine/Level/Level.h" #endif @@ -486,6 +488,34 @@ bool Animation::Save(const StringView& path) return false; } +void Animation::GetReferences(Array& assets, Array& files) const +{ + BinaryAsset::GetReferences(assets, files); + + for (const auto& e : Events) + { + for (const auto& k : e.Second.GetKeyframes()) + { + if (k.Value.Instance) + { + // Collect refs from Anim Event data (as Json) + rapidjson_flax::StringBuffer buffer; + CompactJsonWriter writer(buffer); + writer.StartObject(); + k.Value.Instance->Serialize(writer, nullptr); + writer.EndObject(); + JsonAssetBase::GetReferences(StringAnsiView((char*)buffer.GetString(), buffer.GetSize()), assets); + } + } + } + + // Add nested animations + for (const auto& e : NestedAnims) + { + assets.Add(e.Second.Anim.GetID()); + } +} + #endif uint64 Animation::GetMemoryUsage() const diff --git a/Source/Engine/Content/Assets/Animation.h b/Source/Engine/Content/Assets/Animation.h index b90fbdb73..f287fbd72 100644 --- a/Source/Engine/Content/Assets/Animation.h +++ b/Source/Engine/Content/Assets/Animation.h @@ -153,6 +153,9 @@ public: public: // [BinaryAsset] +#if USE_EDITOR + void GetReferences(Array& assets, Array& files) const override; +#endif uint64 GetMemoryUsage() const override; void OnScriptingDispose() override; From 145933dd1118c2e895b502c0f11c7933a6db95cb Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 25 Oct 2024 19:29:48 +0200 Subject: [PATCH 16/50] Remove unnecessary using --- Source/Editor/Options/InterfaceOptions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 315853041..75ce94ea3 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -2,7 +2,6 @@ using System.ComponentModel; using FlaxEditor.GUI.Docking; -using FlaxEditor.Utilities; using FlaxEngine; namespace FlaxEditor.Options From 2721364df6be1c5d38ebcf1055ebbc2beda5863e Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 25 Oct 2024 19:30:53 +0200 Subject: [PATCH 17/50] improve naming --- Source/Editor/Modules/SimulationModule.cs | 8 ++++---- Source/Editor/Options/InterfaceOptions.cs | 17 +++++++++-------- Source/Editor/Windows/GameWindow.cs | 12 ++++++------ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Source/Editor/Modules/SimulationModule.cs b/Source/Editor/Modules/SimulationModule.cs index dd83d7553..155372a7a 100644 --- a/Source/Editor/Modules/SimulationModule.cs +++ b/Source/Editor/Modules/SimulationModule.cs @@ -279,11 +279,11 @@ namespace FlaxEditor.Modules case Options.InterfaceOptions.PlayModeFocus.None: break; - case Options.InterfaceOptions.PlayModeFocus.GamePanel: + case Options.InterfaceOptions.PlayModeFocus.GameWindow: gameWin.FocusGameViewport(); break; - case Options.InterfaceOptions.PlayModeFocus.GamePanelThenBack: + case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: _previousWindow = gameWin.ParentDockPanel.SelectedTab; gameWin.FocusGameViewport(); break; @@ -305,10 +305,10 @@ namespace FlaxEditor.Modules case Options.InterfaceOptions.PlayModeFocus.None: break; - case Options.InterfaceOptions.PlayModeFocus.GamePanel: + case Options.InterfaceOptions.PlayModeFocus.GameWindow: break; - case Options.InterfaceOptions.PlayModeFocus.GamePanelThenBack: + case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow)) break; diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 75ce94ea3..5b01b88ba 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -1,5 +1,6 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. +using System; using System.ComponentModel; using FlaxEditor.GUI.Docking; using FlaxEngine; @@ -138,24 +139,24 @@ namespace FlaxEditor.Options } /// - /// Options for on play mode start panel focus. + /// Options focus Game Window behaviour when play mode is entered. /// public enum PlayModeFocus { /// - /// Don't change any focus. + /// Don't change focus. /// None, /// - /// Focus the Game panel. + /// Focus the Game Window. /// - GamePanel, + GameWindow, /// - /// Focus the Game panel. On play mode end focus the previous panel again. + /// Focus the Game Window. On play mode end restore focus to the previous window. /// - GamePanelThenBack, + GameWindowThenRestore, } /// @@ -363,9 +364,9 @@ namespace FlaxEditor.Options /// /// Gets or sets a value indicating what panel should be focused when play mode start. /// - [DefaultValue(PlayModeFocus.GamePanel)] + [DefaultValue(PlayModeFocus.GameWindow)] [EditorDisplay("Play In-Editor", "Focus On Play"), EditorOrder(500), Tooltip("Set what panel to focus on play mode start.")] - public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GamePanel; + public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GameWindow; /// /// Gets or sets a value indicating what action should be taken upon pressing the play button. diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index c10c27913..d73facfd2 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -49,15 +49,15 @@ namespace FlaxEditor.Windows }, new PlayModeFocusOptions { - Name = "Game Panel", - Tooltip = "Focus the Game panel.", - FocusOption = InterfaceOptions.PlayModeFocus.GamePanel, + Name = "Game Window", + Tooltip = "Focus the Game Window.", + FocusOption = InterfaceOptions.PlayModeFocus.GameWindow, }, new PlayModeFocusOptions { - Name = "Game Panel Then Back", - Tooltip = "Focus the Game panel. On play mode end focus the previous panel again.", - FocusOption = InterfaceOptions.PlayModeFocus.GamePanelThenBack, + Name = "Game Window Then Back", + Tooltip = "Focus the Game Window. On play mode end restore focus to the previous window.", + FocusOption = InterfaceOptions.PlayModeFocus.GameWindowThenRestore, }, }; From 88215ca3f0e3e54ce8a29db1b5bfdde2c476f494 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 25 Oct 2024 19:31:55 +0200 Subject: [PATCH 18/50] add auto-upgrader for old focus option --- Source/Editor/Options/InterfaceOptions.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 5b01b88ba..70ebe139f 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -340,6 +340,18 @@ namespace FlaxEditor.Options [EditorDisplay("Output Log", "Text Shadow Offset"), EditorOrder(445), Tooltip("The output log text shadow offset. Set to 0 to disable this feature.")] public Float2 OutputLogTextShadowOffset { get; set; } = new Float2(1); + // [Deprecated in v1.10] + [Serialize, Obsolete, NoUndo] + private bool FocusGameWinOnPlay + { + get => throw new Exception(); + set + { + // Upgrade value + FocusOnPlayMode = value ? PlayModeFocus.GameWindow : PlayModeFocus.None; + } + } + /// /// Gets or sets a value indicating whether auto-focus output log window on code compilation error. /// From 6c6a557ffb65ae28cff307c519c12e96bcabbb6e Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 25 Oct 2024 23:00:05 +0200 Subject: [PATCH 19/50] make naming more consistent --- Source/Editor/Windows/GameWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index d73facfd2..0366cef8f 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -55,7 +55,7 @@ namespace FlaxEditor.Windows }, new PlayModeFocusOptions { - Name = "Game Window Then Back", + Name = "Game Window Then Restore", Tooltip = "Focus the Game Window. On play mode end restore focus to the previous window.", FocusOption = InterfaceOptions.PlayModeFocus.GameWindowThenRestore, }, From 4d1541aa1d0561839e751d8b36637843be2fdcea Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Oct 2024 23:27:10 +0100 Subject: [PATCH 20/50] Another blind fix #3018 --- .../VisualStudioCode/VisualStudioCodeProjectGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 68faf3178..8adde26b3 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -301,7 +301,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.BeginArray("configurations"); { var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name); - var mainProjectModule = solution.MainProject?.Targets?.Length != 0 ? solution.MainProject.Targets[0].Modules[0] : null; + var mainProjectModule = solution.MainProject?.Targets?.Length != 0 ? solution.MainProject.Targets[0]?.Modules[0] : null; var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null; if (cppProject != null) From 04ac3160e4041a6053c03ed08447d1286e342385 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 28 Oct 2024 20:41:34 +0100 Subject: [PATCH 21/50] Another blind fix attempt #3018 --- .../VisualStudioCodeProjectGenerator.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 8adde26b3..4e6eadc24 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -143,6 +143,7 @@ namespace Flax.Build.Projects.VisualStudioCode var buildToolWorkspace = Environment.CurrentDirectory; var buildToolPath = Path.ChangeExtension(Utilities.MakePathRelativeTo(typeof(Builder).Assembly.Location, solution.WorkspaceRootPath), null); var rules = Builder.GenerateRulesAssembly(); + var mainProject = solution.MainProject ?? solution.Projects.FirstOrDefault(x => x.Name == Globals.Project.Name); // Create tasks file using (var json = new JsonWriter()) @@ -159,10 +160,10 @@ namespace Flax.Build.Projects.VisualStudioCode continue; // Skip duplicate build tasks - if (project.Name == "FlaxEngine" || (solution.MainProject.Name != "Flax" && solution.MainProject != project)) + if (project.Name == "FlaxEngine" || (mainProject != null && mainProject.Name != "Flax" && mainProject != project)) continue; - bool defaultTask = project == solution.MainProject; + bool defaultTask = project == mainProject; foreach (var configuration in project.Configurations) { var target = configuration.Target; @@ -301,7 +302,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.BeginArray("configurations"); { var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name); - var mainProjectModule = solution.MainProject?.Targets?.Length != 0 ? solution.MainProject.Targets[0]?.Modules[0] : null; + var mainProjectModule = mainProject?.Targets?.Length != 0 ? mainProject.Targets[0]?.Modules[0] : null; var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null; if (cppProject != null) @@ -533,10 +534,9 @@ namespace Flax.Build.Projects.VisualStudioCode json.BeginRootObject(); json.BeginArray("configurations"); json.BeginObject(); - var project = solution.MainProject ?? solution.Projects.FirstOrDefault(x => x.Name == Globals.Project.Name); - if (project != null) + if (mainProject != null) { - json.AddField("name", project.Name); + json.AddField("name", mainProject.Name); var targetPlatform = Platform.BuildPlatform.Target; var configuration = TargetConfiguration.Development; @@ -544,10 +544,10 @@ namespace Flax.Build.Projects.VisualStudioCode var includePaths = new HashSet(); var preprocessorDefinitions = new HashSet(); - foreach (var e in project.Defines) + foreach (var e in mainProject.Defines) preprocessorDefinitions.Add(e); - foreach (var target in project.Targets) + foreach (var target in mainProject.Targets) { var platform = Platform.GetPlatform(targetPlatform); if (platform.HasRequiredSDKsInstalled && target.Platforms.Contains(targetPlatform)) From ae4a4a8e571b4b7215336cc6789b4450213e321c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 28 Oct 2024 20:47:53 +0100 Subject: [PATCH 22/50] Fix `ComputeShapeSqrDistanceToPoint` on PhysX with Large Worlds #3023 --- Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index d88031a01..e4335e318 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -2801,7 +2801,14 @@ float PhysicsBackend::ComputeShapeSqrDistanceToPoint(void* shape, const Vector3& { auto shapePhysX = (PxShape*)shape; const PxTransform trans(C2P(position), C2P(orientation)); +#if USE_LARGE_WORLDS + PxVec3 closestPointPx; + float result = PxGeometryQuery::pointDistance(C2P(point), shapePhysX->getGeometry(), trans, &closestPointPx); + *closestPoint = P2C(closestPointPx); + return result; +#else return PxGeometryQuery::pointDistance(C2P(point), shapePhysX->getGeometry(), trans, (PxVec3*)closestPoint); +#endif } bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Quaternion& orientation, const Vector3& origin, const Vector3& direction, float& resultHitDistance, float maxDistance) From a1c7132e48b4b98ed47ed30378663cb541f4898f Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 28 Oct 2024 22:11:47 -0500 Subject: [PATCH 23/50] Add support for trailing return types for c# generation. --- .../Flax.Build/Bindings/BindingsGenerator.Parsing.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index d99fa8b92..e0fa8572d 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -831,6 +831,7 @@ namespace Flax.Build.Bindings } // Read return type + // Handle if "auto" later desc.ReturnType = ParseType(ref context); // Read name @@ -841,15 +842,21 @@ namespace Flax.Build.Bindings // Read parameters desc.Parameters.AddRange(ParseFunctionParameters(ref context)); - // Read ';' or 'const' or 'override' or '= 0' or '{' + // Read ';' or 'const' or 'override' or '= 0' or '{' or '-' while (true) { - var token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.LeftCurlyBrace, TokenType.Equal, TokenType.Identifier }); + var token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.LeftCurlyBrace, TokenType.Equal, TokenType.Sub, TokenType.Identifier }); if (token.Type == TokenType.Equal) { context.Tokenizer.SkipUntil(TokenType.SemiColon); break; } + // Support auto FunctionName() -> Type + else if (token.Type == TokenType.Sub && desc.ReturnType.ToString() == "auto") + { + context.Tokenizer.SkipUntil(TokenType.GreaterThan); + desc.ReturnType = ParseType(ref context); + } else if (token.Type == TokenType.Identifier) { switch (token.Value) From 8a31d1b54f27fdcdc279e51bbf6cbb7291a95786 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 28 Oct 2024 22:15:34 -0500 Subject: [PATCH 24/50] Add test for trailing return. --- Source/Engine/Tests/TestScripting.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Engine/Tests/TestScripting.h b/Source/Engine/Tests/TestScripting.h index dc05750e1..476060b0b 100644 --- a/Source/Engine/Tests/TestScripting.h +++ b/Source/Engine/Tests/TestScripting.h @@ -172,6 +172,12 @@ public: return str.Length(); } + // Test trailing return type + API_FUNCTION() auto TestTrailingReturn(int32 number) -> float + { + return static_cast(number); + } + int32 TestInterfaceMethod(const String& str) override { return str.Length(); From 4153024c21c2628805c3456b7541959427e955fd Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 29 Oct 2024 16:22:05 +0100 Subject: [PATCH 25/50] Final fix for vscode proj gen issue #3018 --- .../VisualStudioCode/VisualStudioCodeProjectGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 4e6eadc24..27092b219 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -302,7 +302,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.BeginArray("configurations"); { var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name); - var mainProjectModule = mainProject?.Targets?.Length != 0 ? mainProject.Targets[0]?.Modules[0] : null; + var mainProjectModule = mainProject != null && mainProject.Targets?.Length != 0 ? mainProject.Targets[0]?.Modules[0] : null; var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null; if (cppProject != null) From 2715df7cf2c049257c082fe3e194df240bb76a3d Mon Sep 17 00:00:00 2001 From: ldkuba Date: Wed, 30 Oct 2024 15:16:45 +0100 Subject: [PATCH 26/50] Fix NetworkManager not resetting LastUpdateTime NetworkManager did not reset the LastUpdateTime variable to 0 when stopping. This lead to wrong behaviour in Update when Stopped and Started multiple times. --- Source/Engine/Networking/NetworkManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index b9bb0125a..db1ba5cac 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -364,6 +364,8 @@ void NetworkManager::Stop() State = NetworkConnectionState::Disconnected; Mode = NetworkManagerMode::Offline; + LastUpdateTime = 0; + StateChanged(); } From 379bccc4212f5978cb486c45d0b8e43411b7fd6a Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Wed, 30 Oct 2024 12:18:03 -0500 Subject: [PATCH 27/50] Support C++ nameless function arguments for C# gen. --- .../Bindings/BindingsGenerator.Parsing.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index e0fa8572d..fd2fff04a 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -390,7 +390,22 @@ namespace Flax.Build.Bindings // Read parameter type and name currentParam.Type = ParseType(ref context); - currentParam.Name = context.Tokenizer.ExpectToken(TokenType.Identifier).Value; + token = context.Tokenizer.NextToken(); + if (token.Type == TokenType.Identifier) + { + currentParam.Name = token.Value; + } + // Support nameless arguments. assume optional usage + else + { + context.Tokenizer.PreviousToken(); + if (string.IsNullOrEmpty(currentParam.Attributes)) + currentParam.Attributes = "Optional"; + else + currentParam.Attributes += ", Optional"; + currentParam.Name = $"namelessArg{parameters.Count}"; + } + if (currentParam.IsOut && (currentParam.Type.IsPtr || currentParam.Type.IsRef) && currentParam.Type.Type.EndsWith("*")) { // Pointer to value passed as output pointer From 2f4e673be3e980f91bd5829b5f8b47cd8ee2838f Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Wed, 30 Oct 2024 12:20:37 -0500 Subject: [PATCH 28/50] Add test for nameless function arguments --- Source/Engine/Tests/TestScripting.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Engine/Tests/TestScripting.h b/Source/Engine/Tests/TestScripting.h index 476060b0b..cf158fded 100644 --- a/Source/Engine/Tests/TestScripting.h +++ b/Source/Engine/Tests/TestScripting.h @@ -178,6 +178,9 @@ public: return static_cast(number); } + // Test nameless arguments + API_FUNCTION() void TestNamelessArguments(int32, float, bool){} + int32 TestInterfaceMethod(const String& str) override { return str.Length(); From 02db7d02f270469137590dc29ac9ae5b551d9436 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:06:16 +0100 Subject: [PATCH 29/50] Collections const-correctness fix --- Source/Engine/Core/Collections/BitArray.h | 20 ++++++++++---------- Source/Engine/Core/Collections/Dictionary.h | 6 +++--- Source/Engine/Core/Collections/HashSet.h | 6 +++--- Source/Engine/Core/Collections/RingBuffer.h | 4 ++-- Source/Engine/Core/Memory/Allocation.h | 12 ++++++------ Source/Engine/Renderer/RenderListBuffer.h | 4 ++-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index c7853b989..267885438 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -22,12 +22,12 @@ private: int32 _capacity; AllocationData _allocation; - FORCE_INLINE static int32 ToItemCount(int32 size) + FORCE_INLINE static int32 ToItemCount(const int32 size) { return Math::DivideAndRoundUp(size, sizeof(ItemType)); } - FORCE_INLINE static int32 ToItemCapacity(int32 size) + FORCE_INLINE static int32 ToItemCapacity(const int32 size) { return Math::Max(Math::DivideAndRoundUp(size, sizeof(ItemType)), 1); } @@ -46,7 +46,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - BitArray(int32 capacity) + BitArray(const int32 capacity) : _count(0) , _capacity(capacity) { @@ -200,7 +200,7 @@ public: /// /// The index of the item. /// The value of the item. - FORCE_INLINE bool operator[](int32 index) const + FORCE_INLINE bool operator[](const int32 index) const { return Get(index); } @@ -210,7 +210,7 @@ public: /// /// The index of the item. /// The value of the item. - bool Get(int32 index) const + bool Get(const int32 index) const { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); @@ -224,7 +224,7 @@ public: /// /// The index of the item. /// The value to set. - void Set(int32 index, bool value) + void Set(const int32 index, const bool value) { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); @@ -250,7 +250,7 @@ public: /// /// The new capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void SetCapacity(const int32 capacity, bool preserveContents = true) + void SetCapacity(const int32 capacity, const bool preserveContents = true) { if (capacity == _capacity) return; @@ -266,7 +266,7 @@ public: /// /// The new collection size. /// True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data. - void Resize(int32 size, bool preserveContents = true) + void Resize(const int32 size, const bool preserveContents = true) { if (_count <= size) EnsureCapacity(size, preserveContents); @@ -278,7 +278,7 @@ public: /// /// The minimum capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, bool preserveContents = true) + void EnsureCapacity(int32 minCapacity, const bool preserveContents = true) { if (_capacity < minCapacity) { @@ -313,7 +313,7 @@ public: /// /// The items to add. /// The items count. - void Add(const bool* items, int32 count) + void Add(const bool* items, const int32 count) { EnsureCapacity(_count + count); for (int32 i = 0; i < count; i++) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 9e516dae7..1ce1db21b 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -149,7 +149,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - Dictionary(int32 capacity) + Dictionary(const int32 capacity) { SetCapacity(capacity); } @@ -538,7 +538,7 @@ public: /// /// The new capacity. /// Enables preserving collection contents during resizing. - void SetCapacity(int32 capacity, bool preserveContents = true) + void SetCapacity(int32 capacity, const bool preserveContents = true) { if (capacity == Capacity()) return; @@ -598,7 +598,7 @@ public: /// /// The minimum required capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, bool preserveContents = true) + void EnsureCapacity(int32 minCapacity, const bool preserveContents = true) { if (_size >= minCapacity) return; diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index b53225044..1bfcc75eb 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -130,7 +130,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - HashSet(int32 capacity) + HashSet(const int32 capacity) { SetCapacity(capacity); } @@ -415,7 +415,7 @@ public: /// /// New capacity /// Enable/disable preserving collection contents during resizing - void SetCapacity(int32 capacity, bool preserveContents = true) + void SetCapacity(int32 capacity, const bool preserveContents = true) { if (capacity == Capacity()) return; @@ -474,7 +474,7 @@ public: /// /// The minimum required capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, bool preserveContents = true) + void EnsureCapacity(int32 minCapacity, const bool preserveContents = true) { if (_size >= minCapacity) return; diff --git a/Source/Engine/Core/Collections/RingBuffer.h b/Source/Engine/Core/Collections/RingBuffer.h index 4dcc75e33..1bc0ae5f4 100644 --- a/Source/Engine/Core/Collections/RingBuffer.h +++ b/Source/Engine/Core/Collections/RingBuffer.h @@ -75,13 +75,13 @@ public: return _allocation.Get()[_front]; } - FORCE_INLINE T& operator[](int32 index) + FORCE_INLINE T& operator[](const int32 index) { ASSERT(index >= 0 && index < _count); return _allocation.Get()[(_front + index) % _capacity]; } - FORCE_INLINE const T& operator[](int32 index) const + FORCE_INLINE const T& operator[](const int32 index) const { ASSERT(index >= 0 && index < _count); return _allocation.Get()[(_front + index) % _capacity]; diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index 7d28c70cb..6e8342515 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -39,20 +39,20 @@ public: return (T*)_data; } - FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const + FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, const int32 minCapacity) const { ASSERT(minCapacity <= Capacity); return Capacity; } - FORCE_INLINE void Allocate(int32 capacity) + FORCE_INLINE void Allocate(const int32 capacity) { #if ENABLE_ASSERTION_LOW_LAYERS ASSERT(capacity <= Capacity); #endif } - FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount) + FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount) { #if ENABLE_ASSERTION_LOW_LAYERS ASSERT(capacity <= Capacity); @@ -104,7 +104,7 @@ public: return _data; } - FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const + FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, const int32 minCapacity) const { if (capacity < minCapacity) capacity = minCapacity; @@ -129,7 +129,7 @@ public: return capacity; } - FORCE_INLINE void Allocate(int32 capacity) + FORCE_INLINE void Allocate(const int32 capacity) { #if ENABLE_ASSERTION_LOW_LAYERS ASSERT(!_data); @@ -141,7 +141,7 @@ public: #endif } - FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount) + FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount) { T* newData = capacity != 0 ? (T*)Allocator::Allocate(capacity * sizeof(T)) : nullptr; #if !BUILD_RELEASE diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index e4f8ab19e..486b1715b 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -242,7 +242,7 @@ public: /// /// The new capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void SetCapacity(const int32 capacity, bool preserveContents = true) + void SetCapacity(const int32 capacity, const bool preserveContents = true) { if (capacity == Capacity()) return; @@ -365,7 +365,7 @@ private: return (int32)Platform::InterlockedIncrement(&_count) - 1; } - FORCE_INLINE static int32 GetMinCapacity(int32 count) + FORCE_INLINE static int32 GetMinCapacity(const int32 count) { // Ensure there is a slack for others threads to reduce resize counts in highly multi-threaded environment constexpr int32 slack = PLATFORM_THREADS_LIMIT * 8; From f37804ac497f4a083973f3b6545601605fb36ee8 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Wed, 30 Oct 2024 15:46:16 -0500 Subject: [PATCH 30/50] Check and warn user if asset is being moved from content to source folders snd from source to content folders. --- .../Editor/Modules/ContentDatabaseModule.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs index 2cbd9cd85..c42bd9d86 100644 --- a/Source/Editor/Modules/ContentDatabaseModule.cs +++ b/Source/Editor/Modules/ContentDatabaseModule.cs @@ -490,6 +490,60 @@ namespace FlaxEditor.Modules return; } + var projects = Editor.ContentDatabase.Projects; + var contentPaths = new List(); + var sourcePaths = new List(); + foreach (var project in projects) + { + if (project.Content != null) + contentPaths.Add(project.Content.Path); + if (project.Source != null) + sourcePaths.Add(project.Source.Path); + } + + // Check if moving from content to source folder. Item may lose reference in Asset Database. Warn user. + foreach (var contentPath in contentPaths) + { + if (item.Path.Contains(contentPath, StringComparison.Ordinal)) + { + bool isFound = false; + foreach (var sourcePath in sourcePaths) + { + if (newParent.Path.Contains(sourcePath, StringComparison.Ordinal)) + { + isFound = true; + var result = MessageBox.Show(Editor.Windows.MainWindow, "Moving item from \"Content\" to \"Source\" folder may lose asset database reference.\nDo you want to continue?", "Moving item", MessageBoxButtons.OKCancel); + if (result == DialogResult.Cancel) + return; + break; + } + } + if (isFound) + break; + } + } + // Check if moving from source to content folder. Item may lose reference in Asset Database. Warn user. + foreach (var sourcePath in sourcePaths) + { + if (item.Path.Contains(sourcePath, StringComparison.Ordinal)) + { + bool isFound = false; + foreach (var contentPath in contentPaths) + { + if (newParent.Path.Contains(contentPath, StringComparison.Ordinal)) + { + isFound = true; + var result = MessageBox.Show(Editor.Windows.MainWindow, "Moving item from \"Source\" to \"Content\" folder may lose asset database reference.\nDo you want to continue?", "Moving item", MessageBoxButtons.OKCancel); + if (result == DialogResult.Cancel) + return; + break; + } + } + if (isFound) + break; + } + } + // Perform renaming { string oldPath = item.Path; From a55866d5589ee3fee14edf50aff319c1a66e9657 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:18:47 +0100 Subject: [PATCH 31/50] Collections casts fix --- Source/Engine/Core/Collections/Array.h | 6 ++-- Source/Engine/Core/Collections/BitArray.h | 8 ++--- Source/Engine/Core/Collections/Dictionary.h | 2 +- Source/Engine/Core/Memory/Allocation.h | 20 ++++++----- Source/Engine/Renderer/RenderListBuffer.h | 38 ++++++++++----------- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index a17d8f686..8f73cfba7 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -66,7 +66,7 @@ public: /// The initial values defined in the array. Array(std::initializer_list initList) { - _count = _capacity = (int32)initList.size(); + _count = _capacity = static_cast(initList.size()); if (_count > 0) { _allocation.Allocate(_count); @@ -160,8 +160,8 @@ public: Clear(); if (initList.size() > 0) { - EnsureCapacity((int32)initList.size()); - _count = (int32)initList.size(); + EnsureCapacity(static_cast(initList.size())); + _count = static_cast(initList.size()); Memory::ConstructItems(_allocation.Get(), initList.begin(), _count); } return *this; diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 267885438..97674974c 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -214,8 +214,8 @@ public: { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); - const ItemType bitMask = (ItemType)(int32)(1 << (index & ((int32)sizeof(ItemType) - 1))); - const ItemType item = ((ItemType*)_allocation.Get())[offset]; + const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); + const ItemType item = static_cast(_allocation.Get())[offset]; return (item & bitMask) != 0; } @@ -228,8 +228,8 @@ public: { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); - const ItemType bitMask = (ItemType)(int32)(1 << (index & ((int32)sizeof(ItemType) - 1))); - ItemType& item = ((ItemType*)_allocation.Get())[offset]; + const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); + ItemType& item = reinterpret_cast(_allocation.Get())[offset]; if (value) item |= bitMask; else diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 1ce1db21b..438e1bb75 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -498,7 +498,7 @@ public: FindPosition(key, pos); if (pos.ObjectIndex == -1) return nullptr; - return (ValueType*)&_allocation.Get()[pos.ObjectIndex].Value; + return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); } public: diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index 6e8342515..bdf30a16d 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -31,12 +31,12 @@ public: FORCE_INLINE T* Get() { - return (T*)_data; + return reinterpret_cast(_data); } FORCE_INLINE const T* Get() const { - return (T*)_data; + return reinterpret_cast(_data); } FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, const int32 minCapacity) const @@ -134,7 +134,7 @@ public: #if ENABLE_ASSERTION_LOW_LAYERS ASSERT(!_data); #endif - _data = (T*)Allocator::Allocate(capacity * sizeof(T)); + _data = static_cast(Allocator::Allocate(capacity * sizeof(T))); #if !BUILD_RELEASE if (!_data) OUT_OF_MEMORY; @@ -143,7 +143,7 @@ public: FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount) { - T* newData = capacity != 0 ? (T*)Allocator::Allocate(capacity * sizeof(T)) : nullptr; + T* newData = capacity != 0 ? static_cast(Allocator::Allocate(capacity * sizeof(T))) : nullptr; #if !BUILD_RELEASE if (!newData && capacity != 0) OUT_OF_MEMORY; @@ -203,12 +203,12 @@ public: FORCE_INLINE T* Get() { - return _useOther ? _other.Get() : (T*)_data; + return _useOther ? _other.Get() : reinterpret_cast(_data); } FORCE_INLINE const T* Get() const { - return _useOther ? _other.Get() : (T*)_data; + return _useOther ? _other.Get() : reinterpret_cast(_data); } FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const @@ -227,13 +227,15 @@ public: FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount) { + T* data = reinterpret_cast(_data); + // Check if the new allocation will fit into inlined storage if (capacity <= Capacity) { if (_useOther) { // Move the items from other allocation to the inlined storage - Memory::MoveItems((T*)_data, _other.Get(), newCount); + Memory::MoveItems(data, _other.Get(), newCount); // Free the other allocation Memory::DestructItems(_other.Get(), oldCount); @@ -255,8 +257,8 @@ public: _useOther = true; // Move the items from the inlined storage to the other allocation - Memory::MoveItems(_other.Get(), (T*)_data, newCount); - Memory::DestructItems((T*)_data, oldCount); + Memory::MoveItems(_other.Get(), data, newCount); + Memory::DestructItems(data, oldCount); } } } diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index 486b1715b..bbe087e6e 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -76,7 +76,7 @@ public: if (_capacity > 0) { _allocation.Allocate(_capacity); - Memory::ConstructItems(_allocation.Get(), other.Get(), (int32)other._count); + Memory::ConstructItems(_allocation.Get(), other.Get(), static_cast(other._count)); } } @@ -102,7 +102,7 @@ public: { if (this != &other) { - Memory::DestructItems(_allocation.Get(), (int32)_count); + Memory::DestructItems(_allocation.Get(), static_cast(_count)); if (_capacity < other.Count()) { _allocation.Free(); @@ -110,7 +110,7 @@ public: _allocation.Allocate(_capacity); } _count = other.Count(); - Memory::ConstructItems(_allocation.Get(), other.Get(), (int32)_count); + Memory::ConstructItems(_allocation.Get(), other.Get(), static_cast(_count)); } return *this; } @@ -124,7 +124,7 @@ public: { if (this != &other) { - Memory::DestructItems(_allocation.Get(), (int32)_count); + Memory::DestructItems(_allocation.Get(), static_cast(_count)); _allocation.Free(); _count = other._count; _capacity = other._capacity; @@ -140,7 +140,7 @@ public: /// ~RenderListBuffer() { - Memory::DestructItems(_allocation.Get(), (int32)_count); + Memory::DestructItems(_allocation.Get(), static_cast(_count)); } public: @@ -149,7 +149,7 @@ public: /// FORCE_INLINE int32 Count() const { - return (int32)Platform::AtomicRead((volatile int64*)&_count); + return static_cast(Platform::AtomicRead((volatile int64*)&_count)); } /// @@ -157,7 +157,7 @@ public: /// FORCE_INLINE int32 Capacity() const { - return (int32)Platform::AtomicRead((volatile int64*)&_capacity); + return static_cast(Platform::AtomicRead((volatile int64*)&_capacity)); } /// @@ -232,7 +232,7 @@ public: void Clear() { _locker.Lock(); - Memory::DestructItems(_allocation.Get(), (int32)_count); + Memory::DestructItems(_allocation.Get(), static_cast(_count)); _count = 0; _locker.Unlock(); } @@ -248,8 +248,8 @@ public: return; _locker.Lock(); ASSERT(capacity >= 0); - const int32 count = preserveContents ? ((int32)_count < capacity ? (int32)_count : capacity) : 0; - _allocation.Relocate(capacity, (int32)_count, count); + const int32 count = preserveContents ? (static_cast(_count) < capacity ? static_cast(_count) : capacity) : 0; + _allocation.Relocate(capacity, static_cast(_count), count); Platform::AtomicStore(&_capacity, capacity); Platform::AtomicStore(&_count, count); _locker.Unlock(); @@ -265,12 +265,12 @@ public: _locker.Lock(); if (_count > size) { - Memory::DestructItems(_allocation.Get() + size, (int32)_count - size); + Memory::DestructItems(_allocation.Get() + size, static_cast(_count) - size); } else { EnsureCapacity(size, preserveContents); - Memory::ConstructItems(_allocation.Get() + _count, size - (int32)_count); + Memory::ConstructItems(_allocation.Get() + _count, size - static_cast(_count)); } _count = size; _locker.Unlock(); @@ -283,11 +283,11 @@ public: void EnsureCapacity(int32 minCapacity) { _locker.Lock(); - int32 capacity = (int32)Platform::AtomicRead(&_capacity); + int32 capacity = static_cast(Platform::AtomicRead(&_capacity)); if (capacity < minCapacity) { capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity); - const int32 count = (int32)_count; + const int32 count = static_cast(_count); _allocation.Relocate(capacity, count, count); Platform::AtomicStore(&_capacity, capacity); } @@ -324,8 +324,8 @@ private: int32 AddOne() { Platform::InterlockedIncrement(&_threadsAdding); - int32 count = (int32)Platform::AtomicRead(&_count); - int32 capacity = (int32)Platform::AtomicRead(&_capacity); + int32 count = static_cast(Platform::AtomicRead(&_count)); + int32 capacity = static_cast(Platform::AtomicRead(&_capacity)); const int32 minCapacity = GetMinCapacity(count); if (minCapacity > capacity || Platform::AtomicRead(&_threadsResizing)) // Resize if not enough space or someone else is already doing it (don't add mid-resizing) { @@ -340,7 +340,7 @@ private: // Thread-safe resizing _locker.Lock(); - capacity = (int32)Platform::AtomicRead(&_capacity); + capacity = static_cast(Platform::AtomicRead(&_capacity)); if (capacity < minCapacity) { if (Platform::AtomicRead(&_threadsAdding)) @@ -350,7 +350,7 @@ private: goto RETRY; } capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity); - count = (int32)Platform::AtomicRead(&_count); + count = static_cast(Platform::AtomicRead(&_count)); _allocation.Relocate(capacity, count, count); Platform::AtomicStore(&_capacity, capacity); } @@ -362,7 +362,7 @@ private: // Let other thread enter resizing-area _locker.Unlock(); } - return (int32)Platform::InterlockedIncrement(&_count) - 1; + return static_cast(Platform::InterlockedIncrement(&_count)) - 1; } FORCE_INLINE static int32 GetMinCapacity(const int32 count) From f77f551b72f88b4fdd9161dd91cce58be344a75d Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:22:56 +0100 Subject: [PATCH 32/50] Collections type aliasing fix This one is debatable. It follows modern C++. --- Source/Engine/Core/Collections/Array.h | 4 ++-- Source/Engine/Core/Collections/BitArray.h | 4 ++-- Source/Engine/Core/Collections/Dictionary.h | 2 +- Source/Engine/Core/Collections/HashSet.h | 2 +- Source/Engine/Core/Collections/RingBuffer.h | 4 ++-- Source/Engine/Core/Memory/Allocation.h | 2 +- Source/Engine/Renderer/RenderListBuffer.h | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index 8f73cfba7..f60d0dec1 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -17,8 +17,8 @@ API_CLASS(InBuild) class Array { friend Array; public: - typedef T ItemType; - typedef typename AllocationType::template Data AllocationData; + using ItemType = T; + using AllocationData = typename AllocationType::template Data; private: int32 _count; diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 97674974c..c62362780 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -14,8 +14,8 @@ API_CLASS(InBuild) class BitArray { friend BitArray; public: - typedef uint64 ItemType; - typedef typename AllocationType::template Data AllocationData; + using ItemType = uint64; + using AllocationData = typename AllocationType::template Data; private: int32 _count; diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 438e1bb75..468025ffe 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -102,7 +102,7 @@ public: } }; - typedef typename AllocationType::template Data AllocationData; + using AllocationData = typename AllocationType::template Data; private: int32 _elementsCount = 0; diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 1bfcc75eb..0be793d96 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -85,7 +85,7 @@ public: } }; - typedef typename AllocationType::template Data AllocationData; + using AllocationData = typename AllocationType::template Data; private: int32 _elementsCount = 0; diff --git a/Source/Engine/Core/Collections/RingBuffer.h b/Source/Engine/Core/Collections/RingBuffer.h index 1bc0ae5f4..9d1c16483 100644 --- a/Source/Engine/Core/Collections/RingBuffer.h +++ b/Source/Engine/Core/Collections/RingBuffer.h @@ -14,8 +14,8 @@ template class RingBuffer { public: - typedef T ItemType; - typedef typename AllocationType::template Data AllocationData; + using ItemType = T; + using AllocationData = typename AllocationType::template Data; private: int32 _front = 0, _back = 0, _count = 0, _capacity = 0; diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index bdf30a16d..5fce2ad73 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -279,4 +279,4 @@ public: }; }; -typedef HeapAllocation DefaultAllocation; +using DefaultAllocation = HeapAllocation; diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index bbe087e6e..d12c430f1 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -17,8 +17,8 @@ class RenderListBuffer { friend RenderListBuffer; public: - typedef T ItemType; - typedef typename AllocationType::template Data AllocationData; + using ItemType = T; + using AllocationData = typename AllocationType::template Data; private: volatile int64 _count; From 5439efc5591e1ef1813ceff5c79cb71da7d64989 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:29:26 +0100 Subject: [PATCH 33/50] Collections implicit cast constructor fix This one prohibits annoying casts. It is also important for future context injection and follows STL practice. --- Source/Engine/Core/Collections/Array.h | 2 +- Source/Engine/Core/Collections/BitArray.h | 2 +- Source/Engine/Core/Collections/Dictionary.h | 2 +- Source/Engine/Core/Collections/HashSet.h | 2 +- Source/Engine/Renderer/RenderListBuffer.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index f60d0dec1..e096992f8 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -52,7 +52,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - Array(int32 capacity) + explicit Array(int32 capacity) : _count(0) , _capacity(capacity) { diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index c62362780..70d51bac0 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -46,7 +46,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - BitArray(const int32 capacity) + explicit BitArray(const int32 capacity) : _count(0) , _capacity(capacity) { diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 468025ffe..ad8793d36 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -149,7 +149,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - Dictionary(const int32 capacity) + explicit Dictionary(const int32 capacity) { SetCapacity(capacity); } diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 0be793d96..1c31eaef4 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -130,7 +130,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - HashSet(const int32 capacity) + explicit HashSet(const int32 capacity) { SetCapacity(capacity); } diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index d12c430f1..50f6ed519 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -42,7 +42,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - RenderListBuffer(int32 capacity) + explicit RenderListBuffer(int32 capacity) : _count(0) , _capacity(capacity) { From 8cb7fb48ceb817f2c15d0cff95f093a94c7e7111 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:35:36 +0100 Subject: [PATCH 34/50] Dictionary returning const item fix Returning const object does not prevent from using mutable by triggering copy constructor. --- Source/Engine/Core/Collections/Dictionary.h | 4 ++-- Source/Engine/Core/Collections/HashSet.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index ad8793d36..fd035e6f4 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -862,14 +862,14 @@ public: return Iterator(this, _size); } - const Iterator begin() const + Iterator begin() const { Iterator i(this, -1); ++i; return i; } - FORCE_INLINE const Iterator end() const + FORCE_INLINE Iterator end() const { return Iterator(this, _size); } diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 1c31eaef4..af9e59566 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -656,14 +656,14 @@ public: return Iterator(this, _size); } - const Iterator begin() const + Iterator begin() const { Iterator i(this, -1); ++i; return i; } - FORCE_INLINE const Iterator end() const + FORCE_INLINE Iterator end() const { return Iterator(this, _size); } From 66b6a29ed405846821b583069a26859665828116 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:19:12 +0100 Subject: [PATCH 35/50] Collections iterator move noexcept fix --- Source/Engine/Core/Collections/Dictionary.h | 4 ++-- Source/Engine/Core/Collections/HashSet.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index fd035e6f4..32f61a30c 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -289,7 +289,7 @@ public: { } - Iterator(Iterator&& i) + Iterator(Iterator&& i) noexcept : _collection(i._collection) , _index(i._index) { @@ -348,7 +348,7 @@ public: return *this; } - Iterator& operator=(Iterator&& v) + Iterator& operator=(Iterator&& v) noexcept { _collection = v._collection; _index = v._index; diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index af9e59566..a5bf8ae3e 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -270,7 +270,7 @@ public: { } - Iterator(Iterator&& i) + Iterator(Iterator&& i) noexcept : _collection(i._collection) , _index(i._index) { @@ -329,7 +329,7 @@ public: return *this; } - Iterator& operator=(Iterator&& v) + Iterator& operator=(Iterator&& v) noexcept { _collection = v._collection; _index = v._index; From 9c448f75d8c13acfdbd4d05ba42b2af597a7c7da Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:29:38 +0100 Subject: [PATCH 36/50] Collections const correctness fix (style) --- Source/Engine/Core/Collections/Array.h | 44 ++++++++++----------- Source/Engine/Core/Collections/BitArray.h | 2 +- Source/Engine/Core/Collections/Dictionary.h | 2 +- Source/Engine/Core/Collections/HashSet.h | 8 ++-- Source/Engine/Renderer/RenderListBuffer.h | 12 +++--- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index e096992f8..3006d045e 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -25,7 +25,7 @@ private: int32 _capacity; AllocationData _allocation; - FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromCount, int32 fromCapacity) + FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromCount, const int32 fromCapacity) { if IF_CONSTEXPR (AllocationType::HasSwap) to.Swap(from); @@ -52,7 +52,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - explicit Array(int32 capacity) + explicit Array(const int32 capacity) : _count(0) , _capacity(capacity) { @@ -79,7 +79,7 @@ public: /// /// The initial data. /// The amount of items. - Array(const T* data, int32 length) + Array(const T* data, const int32 length) { ASSERT(length >= 0); _count = _capacity = length; @@ -255,7 +255,7 @@ public: /// /// The index. /// true if is valid a index; otherwise, false. - bool IsValidIndex(int32 index) const + bool IsValidIndex(const int32 index) const { return index < _count && index >= 0; } @@ -280,7 +280,7 @@ public: /// Gets item at the given index. /// /// The reference to the item. - FORCE_INLINE T& At(int32 index) + FORCE_INLINE T& At(const int32 index) { ASSERT(index >= 0 && index < _count); return _allocation.Get()[index]; @@ -290,7 +290,7 @@ public: /// Gets item at the given index. /// /// The reference to the item. - FORCE_INLINE const T& At(int32 index) const + FORCE_INLINE const T& At(const int32 index) const { ASSERT(index >= 0 && index < _count); return _allocation.Get()[index]; @@ -300,7 +300,7 @@ public: /// Gets or sets the item at the given index. /// /// The reference to the item. - FORCE_INLINE T& operator[](int32 index) + FORCE_INLINE T& operator[](const int32 index) { ASSERT(index >= 0 && index < _count); return _allocation.Get()[index]; @@ -310,7 +310,7 @@ public: /// Gets the item at the given index. /// /// The reference to the item. - FORCE_INLINE const T& operator[](int32 index) const + FORCE_INLINE const T& operator[](const int32 index) const { ASSERT(index >= 0 && index < _count); return _allocation.Get()[index]; @@ -406,7 +406,7 @@ public: /// /// The new capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void SetCapacity(const int32 capacity, bool preserveContents = true) + void SetCapacity(const int32 capacity, const bool preserveContents = true) { if (capacity == _capacity) return; @@ -422,7 +422,7 @@ public: /// /// The new collection size. /// True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data. - void Resize(int32 size, bool preserveContents = true) + void Resize(const int32 size, const bool preserveContents = true) { if (_count > size) { @@ -441,7 +441,7 @@ public: /// /// The minimum capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, bool preserveContents = true) + void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true) { if (_capacity < minCapacity) { @@ -466,7 +466,7 @@ public: /// /// The data. /// The amount of items. - void Set(const T* data, int32 count) + void Set(const T* data, const int32 count) { EnsureCapacity(count, false); Memory::DestructItems(_allocation.Get(), _count); @@ -501,7 +501,7 @@ public: /// /// The items to add. /// The items count. - void Add(const T* items, int32 count) + void Add(const T* items, const int32 count) { EnsureCapacity(_count + count); Memory::ConstructItems(_allocation.Get() + _count, items, count); @@ -532,7 +532,7 @@ public: /// Adds the given amount of items to the collection. /// /// The items count. - FORCE_INLINE void AddDefault(int32 count = 1) + FORCE_INLINE void AddDefault(const int32 count = 1) { EnsureCapacity(_count + count); Memory::ConstructItems(_allocation.Get() + _count, count); @@ -543,7 +543,7 @@ public: /// Adds the given amount of uninitialized items to the collection without calling the constructor. /// /// The items count. - FORCE_INLINE void AddUninitialized(int32 count = 1) + FORCE_INLINE void AddUninitialized(const int32 count = 1) { EnsureCapacity(_count + count); _count += count; @@ -568,7 +568,7 @@ public: /// Warning! AddZeroed() will create items without calling the constructor and this is not appropriate for item types that require a constructor to function properly. /// /// The number of new items to add. - void AddZeroed(int32 count = 1) + void AddZeroed(const int32 count = 1) { EnsureCapacity(_count + count); Platform::MemoryClear(_allocation.Get() + _count, count * sizeof(T)); @@ -580,7 +580,7 @@ public: /// /// The zero-based index at which item should be inserted. /// The item to be inserted by copying. - void Insert(int32 index, const T& item) + void Insert(const int32 index, const T& item) { ASSERT(index >= 0 && index <= _count); EnsureCapacity(_count + 1); @@ -597,7 +597,7 @@ public: /// /// The zero-based index at which item should be inserted. /// The item to inserted by moving. - void Insert(int32 index, T&& item) + void Insert(const int32 index, T&& item) { ASSERT(index >= 0 && index <= _count); EnsureCapacity(_count + 1); @@ -613,7 +613,7 @@ public: /// Insert the given item at specified index with keeping items order. /// /// The zero-based index at which item should be inserted. - void Insert(int32 index) + void Insert(const int32 index) { ASSERT(index >= 0 && index <= _count); EnsureCapacity(_count + 1); @@ -954,7 +954,7 @@ public: { } - Iterator(Array const* array, const int32 index) + Iterator(const Array* array, const int32 index) : _array(const_cast(array)) , _index(index) { @@ -1084,7 +1084,7 @@ public: }; template -void* operator new(size_t size, Array& array) +void* operator new(const size_t size, Array& array) { ASSERT(size == sizeof(T)); const int32 index = array.Count(); @@ -1093,7 +1093,7 @@ void* operator new(size_t size, Array& array) } template -void* operator new(size_t size, Array& array, int32 index) +void* operator new(const size_t size, Array& array, const int32 index) { ASSERT(size == sizeof(T)); array.Insert(index); diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 70d51bac0..bc101f4ae 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -278,7 +278,7 @@ public: /// /// The minimum capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, const bool preserveContents = true) + void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true) { if (_capacity < minCapacity) { diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 32f61a30c..2b1bb8916 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -110,7 +110,7 @@ private: int32 _size = 0; AllocationData _allocation; - FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize) + FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromSize) { if IF_CONSTEXPR (AllocationType::HasSwap) to.Swap(from); diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index a5bf8ae3e..1974051e5 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -93,7 +93,7 @@ private: int32 _size = 0; AllocationData _allocation; - FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize) + FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromSize) { if IF_CONSTEXPR (AllocationType::HasSwap) to.Swap(from); @@ -252,7 +252,7 @@ public: { } - Iterator(HashSet const* collection, const int32 index) + Iterator(const HashSet* collection, const int32 index) : _collection(const_cast(collection)) , _index(index) { @@ -307,7 +307,7 @@ public: return _index >= 0 && _index < _collection->_size; } - FORCE_INLINE bool operator !() const + FORCE_INLINE bool operator!() const { return !(bool)*this; } @@ -474,7 +474,7 @@ public: /// /// The minimum required capacity. /// True if preserve collection data when changing its size, otherwise collection after resize will be empty. - void EnsureCapacity(int32 minCapacity, const bool preserveContents = true) + void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true) { if (_size >= minCapacity) return; diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index 50f6ed519..e6a22949a 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -42,7 +42,7 @@ public: /// Initializes a new instance of the class. /// /// The initial capacity. - explicit RenderListBuffer(int32 capacity) + explicit RenderListBuffer(const int32 capacity) : _count(0) , _capacity(capacity) { @@ -55,7 +55,7 @@ public: /// /// The initial data. /// The amount of items. - RenderListBuffer(const T* data, int32 length) + RenderListBuffer(const T* data, const int32 length) { ASSERT(length >= 0); _count = _capacity = length; @@ -188,7 +188,7 @@ public: /// Gets or sets the item at the given index. /// /// The reference to the item. - FORCE_INLINE T& operator[](int32 index) + FORCE_INLINE T& operator[](const int32 index) { ASSERT(index >= 0 && index < Count()); return _allocation.Get()[index]; @@ -198,7 +198,7 @@ public: /// Gets the item at the given index. /// /// The reference to the item. - FORCE_INLINE const T& operator[](int32 index) const + FORCE_INLINE const T& operator[](const int32 index) const { ASSERT(index >= 0 && index < Count()); return _allocation.Get()[index]; @@ -260,7 +260,7 @@ public: /// /// The new collection size. /// True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data. - void Resize(int32 size, bool preserveContents = true) + void Resize(const int32 size, const bool preserveContents = true) { _locker.Lock(); if (_count > size) @@ -280,7 +280,7 @@ public: /// Ensures the collection has given capacity (or more). /// /// The minimum capacity. - void EnsureCapacity(int32 minCapacity) + void EnsureCapacity(const int32 minCapacity) { _locker.Lock(); int32 capacity = static_cast(Platform::AtomicRead(&_capacity)); From fbb840dff341096cab6646812264de4a80afa41e Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:45:00 +0100 Subject: [PATCH 37/50] Collections de/increment operations fix This one is more stylistic but is consistent with practice of using pre- operations for iterators. --- Source/Engine/Core/Collections/Array.h | 28 +++++++++---------- Source/Engine/Core/Collections/BitArray.h | 6 ++--- Source/Engine/Core/Collections/Dictionary.h | 30 +++++++++++---------- Source/Engine/Core/Collections/HashSet.h | 30 +++++++++++---------- Source/Engine/Core/Collections/RingBuffer.h | 4 +-- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index 3006d045e..ec2d28f49 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -482,7 +482,7 @@ public: { EnsureCapacity(_count + 1); Memory::ConstructItems(_allocation.Get() + _count, &item, 1); - _count++; + ++_count; } /// @@ -493,7 +493,7 @@ public: { EnsureCapacity(_count + 1); Memory::MoveItems(_allocation.Get() + _count, &item, 1); - _count++; + ++_count; } /// @@ -557,7 +557,7 @@ public: { EnsureCapacity(_count + 1); Memory::ConstructItems(_allocation.Get() + _count, 1); - _count++; + ++_count; return _allocation.Get()[_count - 1]; } @@ -605,7 +605,7 @@ public: Memory::ConstructItems(data + _count, 1); for (int32 i = _count - 1; i >= index; i--) data[i + 1] = MoveTemp(data[i]); - _count++; + ++_count; data[index] = MoveTemp(item); } @@ -621,7 +621,7 @@ public: Memory::ConstructItems(data + _count, 1); for (int32 i = _count - 1; i >= index; i--) data[i + 1] = data[i]; - _count++; + ++_count; } /// @@ -661,7 +661,7 @@ public: /// The item to remove. void RemoveAllKeepOrder(const T& item) { - for (int32 i = Count() - 1; i >= 0; i--) + for (int32 i = Count() - 1; i >= 0; --i) { if (_allocation.Get()[i] == item) { @@ -679,14 +679,14 @@ public: void RemoveAtKeepOrder(const int32 index) { ASSERT(index < _count && index >= 0); - _count--; + --_count; T* data = _allocation.Get(); if (index < _count) { T* dst = data + index; T* src = data + (index + 1); const int32 count = _count - index; - for (int32 i = 0; i < count; i++) + for (int32 i = 0; i < count; ++i) dst[i] = MoveTemp(src[i]); } Memory::DestructItems(data + _count, 1); @@ -712,7 +712,7 @@ public: /// The item to remove. void RemoveAll(const T& item) { - for (int32 i = Count() - 1; i >= 0; i--) + for (int32 i = Count() - 1; i >= 0; --i) { if (_allocation.Get()[i] == item) { @@ -730,7 +730,7 @@ public: void RemoveAt(const int32 index) { ASSERT(index < _count && index >= 0); - _count--; + --_count; T* data = _allocation.Get(); if (_count) data[index] = data[_count]; @@ -743,7 +743,7 @@ public: void RemoveLast() { ASSERT(_count > 0); - _count--; + --_count; Memory::DestructItems(_allocation.Get() + _count, 1); } @@ -772,7 +772,7 @@ public: { T* data = _allocation.Get(); const int32 count = _count / 2; - for (int32 i = 0; i < count; i++) + for (int32 i = 0; i < count; ++i) ::Swap(data[i], data[_count - i - 1]); } @@ -1052,7 +1052,7 @@ public: Iterator& operator--() { if (_index > 0) - _index--; + --_index; return *this; } @@ -1060,7 +1060,7 @@ public: { Iterator temp = *this; if (_index > 0) - _index--; + --_index; return temp; } }; diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index bc101f4ae..f0a08d8e2 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -304,7 +304,7 @@ public: void Add(const bool item) { EnsureCapacity(_count + 1); - _count++; + ++_count; Set(_count - 1, item); } @@ -316,7 +316,7 @@ public: void Add(const bool* items, const int32 count) { EnsureCapacity(_count + count); - for (int32 i = 0; i < count; i++) + for (int32 i = 0; i < count; ++i) Add(items[i]); } @@ -327,7 +327,7 @@ public: void Add(const BitArray& other) { EnsureCapacity(_count, other.Count()); - for (int32 i = 0; i < other.Count(); i++) + for (int32 i = 0; i < other.Count(); ++i) Add(other[i]); } diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 2b1bb8916..e9dc8f582 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -363,8 +363,9 @@ public: const Bucket* data = _collection->_allocation.Get(); do { - _index++; - } while (_index != capacity && data[_index].IsNotOccupied()); + ++_index; + } + while (_index != capacity && data[_index].IsNotOccupied()); } return *this; } @@ -383,8 +384,9 @@ public: const Bucket* data = _collection->_allocation.Get(); do { - _index--; - } while (_index > 0 && data[_index].IsNotOccupied()); + --_index; + } + while (_index > 0 && data[_index].IsNotOccupied()); } return *this; } @@ -423,7 +425,7 @@ public: // Insert ASSERT(pos.FreeSlotIndex != -1); - _elementsCount++; + ++_elementsCount; Bucket& bucket = _allocation.Get()[pos.FreeSlotIndex]; bucket.Occupy(key); return bucket.Value; @@ -582,7 +584,7 @@ public: Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1); Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1); bucket->_state = Bucket::Occupied; - _elementsCount++; + ++_elementsCount; } } } @@ -682,8 +684,8 @@ public: if (pos.ObjectIndex != -1) { _allocation.Get()[pos.ObjectIndex].Delete(); - _elementsCount--; - _deletedCount++; + --_elementsCount; + ++_deletedCount; return true; } return false; @@ -701,8 +703,8 @@ public: { ASSERT(_allocation.Get()[i._index].IsOccupied()); _allocation.Get()[i._index].Delete(); - _elementsCount--; - _deletedCount++; + --_elementsCount; + ++_deletedCount; return true; } return false; @@ -721,7 +723,7 @@ public: if (i->Value == value) { Remove(i); - result++; + ++result; } } return result; @@ -768,7 +770,7 @@ public: if (HasItems()) { const Bucket* data = _allocation.Get(); - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) { if (data[i].IsOccupied() && data[i].Value == value) return true; @@ -788,7 +790,7 @@ public: if (HasItems()) { const Bucket* data = _allocation.Get(); - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) { if (data[i].IsOccupied() && data[i].Value == value) { @@ -928,7 +930,7 @@ private: result.ObjectIndex = bucketIndex; return; } - checksCount++; + ++checksCount; bucketIndex = (bucketIndex + DICTIONARY_PROB_FUNC(_size, checksCount)) & tableSizeMinusOne; } result.ObjectIndex = -1; diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 1974051e5..2e90dae4b 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -102,7 +102,7 @@ private: to.Allocate(fromSize); Bucket* toData = to.Get(); Bucket* fromData = from.Get(); - for (int32 i = 0; i < fromSize; i++) + for (int32 i = 0; i < fromSize; ++i) { Bucket& fromBucket = fromData[i]; if (fromBucket.IsOccupied()) @@ -344,8 +344,9 @@ public: const Bucket* data = _collection->_allocation.Get(); do { - _index++; - } while (_index != capacity && data[_index].IsNotOccupied()); + ++_index; + } + while (_index != capacity && data[_index].IsNotOccupied()); } return *this; } @@ -364,8 +365,9 @@ public: const Bucket* data = _collection->_allocation.Get(); do { - _index--; - } while (_index > 0 && data[_index].IsNotOccupied()); + --_index; + } + while (_index > 0 && data[_index].IsNotOccupied()); } return *this; } @@ -559,8 +561,8 @@ public: if (pos.ObjectIndex != -1) { _allocation.Get()[pos.ObjectIndex].Delete(); - _elementsCount--; - _deletedCount++; + --_elementsCount; + ++_deletedCount; return true; } return false; @@ -578,8 +580,8 @@ public: { ASSERT(_allocation.Get()[i._index].IsOccupied()); _allocation.Get()[i._index].Delete(); - _elementsCount--; - _deletedCount++; + --_elementsCount; + ++_deletedCount; return true; } return false; @@ -750,7 +752,7 @@ private: // Insert ASSERT(pos.FreeSlotIndex != -1); - _elementsCount++; + ++_elementsCount; return &_allocation.Get()[pos.FreeSlotIndex]; } @@ -760,7 +762,7 @@ private: { // Fast path if it's empty Bucket* data = _allocation.Get(); - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) data[i]._state = Bucket::Empty; } else @@ -770,11 +772,11 @@ private: MoveToEmpty(oldAllocation, _allocation, _size); _allocation.Allocate(_size); Bucket* data = _allocation.Get(); - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) data[i]._state = Bucket::Empty; Bucket* oldData = oldAllocation.Get(); FindPositionResult pos; - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) { Bucket& oldBucket = oldData[i]; if (oldBucket.IsOccupied()) @@ -786,7 +788,7 @@ private: bucket->_state = Bucket::Occupied; } } - for (int32 i = 0; i < _size; i++) + for (int32 i = 0; i < _size; ++i) oldData[i].Free(); } _deletedCount = 0; diff --git a/Source/Engine/Core/Collections/RingBuffer.h b/Source/Engine/Core/Collections/RingBuffer.h index 9d1c16483..c46f13031 100644 --- a/Source/Engine/Core/Collections/RingBuffer.h +++ b/Source/Engine/Core/Collections/RingBuffer.h @@ -62,7 +62,7 @@ public: } Memory::ConstructItems(_allocation.Get() + _back, &data, 1); _back = (_back + 1) % _capacity; - _count++; + ++_count; } FORCE_INLINE T& PeekFront() @@ -91,7 +91,7 @@ public: { Memory::DestructItems(_allocation.Get() + _front, 1); _front = (_front + 1) % _capacity; - _count--; + --_count; } void Clear() From 5d32ed7f8eb6ff7e237c5b7a5d824d8fea33514a Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:49:59 +0100 Subject: [PATCH 38/50] Collections casts constiness fix --- Source/Engine/Core/Collections/BitArray.h | 4 ++-- Source/Engine/Core/Collections/Dictionary.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index f0a08d8e2..3ae573df6 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -215,7 +215,7 @@ public: ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); - const ItemType item = static_cast(_allocation.Get())[offset]; + const ItemType item = static_cast(_allocation.Get())[offset]; return (item & bitMask) != 0; } @@ -229,7 +229,7 @@ public: ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); - ItemType& item = reinterpret_cast(_allocation.Get())[offset]; + ItemType& item = reinterpret_cast(_allocation.Get())[offset]; if (value) item |= bitMask; else diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index e9dc8f582..169b7bc3f 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -500,7 +500,7 @@ public: FindPosition(key, pos); if (pos.ObjectIndex == -1) return nullptr; - return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); + return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); } public: From 2ae3932fcc60fb76f2bb2cf3a91144d217a60c3c Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 01:06:04 +0100 Subject: [PATCH 39/50] Revert BitArray changes --- Source/Engine/Core/Collections/BitArray.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Core/Collections/BitArray.h b/Source/Engine/Core/Collections/BitArray.h index 3ae573df6..1b601c72f 100644 --- a/Source/Engine/Core/Collections/BitArray.h +++ b/Source/Engine/Core/Collections/BitArray.h @@ -214,8 +214,8 @@ public: { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); - const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); - const ItemType item = static_cast(_allocation.Get())[offset]; + const ItemType bitMask = (ItemType)(int32)(1 << (index & ((int32)sizeof(ItemType) - 1))); + const ItemType item = ((ItemType*)_allocation.Get())[offset]; return (item & bitMask) != 0; } @@ -228,12 +228,12 @@ public: { ASSERT(index >= 0 && index < _count); const ItemType offset = index / sizeof(ItemType); - const ItemType bitMask = static_cast((int32)(1 << (index & (static_cast(sizeof(ItemType)) - 1)))); - ItemType& item = reinterpret_cast(_allocation.Get())[offset]; + const ItemType bitMask = (ItemType)(int32)(1 << (index & ((int32)sizeof(ItemType) - 1))); + ItemType& item = ((ItemType*)_allocation.Get())[offset]; if (value) item |= bitMask; else - item &= ~bitMask; + item &= ~bitMask; // Clear the bit } public: From 7cca26bb97274cff0c7f4d48b774aac768cd34be Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 01:08:44 +0100 Subject: [PATCH 40/50] Dictionary cast constiness fix --- Source/Engine/Core/Collections/Dictionary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 169b7bc3f..e9dc8f582 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -500,7 +500,7 @@ public: FindPosition(key, pos); if (pos.ObjectIndex == -1) return nullptr; - return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); + return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); } public: From 26309a0d4108aa378b08a0ca337303c5b86a713f Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 01:15:05 +0100 Subject: [PATCH 41/50] Dictionary mutable key access for const accessor hack --- Source/Engine/Core/Collections/Dictionary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index e9dc8f582..794cfc455 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -500,7 +500,7 @@ public: FindPosition(key, pos); if (pos.ObjectIndex == -1) return nullptr; - return static_cast(&_allocation.Get()[pos.ObjectIndex].Value); + return const_cast(&_allocation.Get()[pos.ObjectIndex].Value); //TODO This one is problematic. I think this entire method should be removed. } public: From dca48b335a87da5afb2e03ed0297013610329428 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 02:41:51 +0100 Subject: [PATCH 42/50] Hash collections bucket state enum extracted This is a small compilation time optimization by reducing total number of generated types. Should not change runtime behavior. --- Source/Engine/Core/Collections/BucketState.h | 15 +++++++ Source/Engine/Core/Collections/Dictionary.h | 44 +++++++++----------- Source/Engine/Core/Collections/HashSet.h | 42 ++++++++----------- 3 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 Source/Engine/Core/Collections/BucketState.h diff --git a/Source/Engine/Core/Collections/BucketState.h b/Source/Engine/Core/Collections/BucketState.h new file mode 100644 index 000000000..16cbdb845 --- /dev/null +++ b/Source/Engine/Core/Collections/BucketState.h @@ -0,0 +1,15 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Core/Types/BaseTypes.h" + +/// +/// Tells if the object is occupied, and if not, if the bucket is a subject of compaction. +/// +enum class BucketState : byte +{ + Empty = 0, + Deleted = 1, + Occupied = 2, +}; diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 794cfc455..efb7bafcf 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -4,6 +4,7 @@ #include "Engine/Core/Memory/Memory.h" #include "Engine/Core/Memory/Allocation.h" +#include "Engine/Core/Collections/BucketState.h" #include "Engine/Core/Collections/HashFunctions.h" #include "Engine/Core/Collections/Config.h" @@ -25,34 +26,27 @@ public: { friend Dictionary; - enum State : byte - { - Empty = 0, - Deleted = 1, - Occupied = 2, - }; - /// The key. KeyType Key; /// The value. ValueType Value; private: - State _state; + BucketState _state; FORCE_INLINE void Free() { - if (_state == Occupied) + if (_state == BucketState::Occupied) { Memory::DestructItem(&Key); Memory::DestructItem(&Value); } - _state = Empty; + _state = BucketState::Empty; } FORCE_INLINE void Delete() { - _state = Deleted; + _state = BucketState::Deleted; Memory::DestructItem(&Key); Memory::DestructItem(&Value); } @@ -62,7 +56,7 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::ConstructItem(&Value); - _state = Occupied; + _state = BucketState::Occupied; } template @@ -70,7 +64,7 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::ConstructItems(&Value, &value, 1); - _state = Occupied; + _state = BucketState::Occupied; } template @@ -78,27 +72,27 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::MoveItems(&Value, &value, 1); - _state = Occupied; + _state = BucketState::Occupied; } FORCE_INLINE bool IsEmpty() const { - return _state == Empty; + return _state == BucketState::Empty; } FORCE_INLINE bool IsDeleted() const { - return _state == Deleted; + return _state == BucketState::Deleted; } FORCE_INLINE bool IsOccupied() const { - return _state == Occupied; + return _state == BucketState::Occupied; } FORCE_INLINE bool IsNotOccupied() const { - return _state != Occupied; + return _state != BucketState::Occupied; } }; @@ -127,10 +121,10 @@ private: Bucket& toBucket = toData[i]; Memory::MoveItems(&toBucket.Key, &fromBucket.Key, 1); Memory::MoveItems(&toBucket.Value, &fromBucket.Value, 1); - toBucket._state = Bucket::Occupied; + toBucket._state = BucketState::Occupied; Memory::DestructItem(&fromBucket.Key); Memory::DestructItem(&fromBucket.Value); - fromBucket._state = Bucket::Empty; + fromBucket._state = BucketState::Empty; } } from.Free(); @@ -566,7 +560,7 @@ public: _allocation.Allocate(capacity); Bucket* data = _allocation.Get(); for (int32 i = 0; i < capacity; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } _size = capacity; Bucket* oldData = oldAllocation.Get(); @@ -583,7 +577,7 @@ public: Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1); Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; ++_elementsCount; } } @@ -967,7 +961,7 @@ private: // Fast path if it's empty Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } else { @@ -977,7 +971,7 @@ private: _allocation.Allocate(_size); Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; Bucket* oldData = oldAllocation.Get(); FindPositionResult pos; for (int32 i = 0; i < _size; i++) @@ -990,7 +984,7 @@ private: Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1); Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; } } for (int32 i = 0; i < _size; i++) diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 2e90dae4b..aa61354fd 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -4,6 +4,7 @@ #include "Engine/Core/Memory/Memory.h" #include "Engine/Core/Memory/Allocation.h" +#include "Engine/Core/Collections/BucketState.h" #include "Engine/Core/Collections/HashFunctions.h" #include "Engine/Core/Collections/Config.h" @@ -24,29 +25,22 @@ public: { friend HashSet; - enum State : byte - { - Empty, - Deleted, - Occupied, - }; - /// The item. T Item; private: - State _state; + BucketState _state; FORCE_INLINE void Free() { - if (_state == Occupied) + if (_state == BucketState::Occupied) Memory::DestructItem(&Item); - _state = Empty; + _state = BucketState::Empty; } FORCE_INLINE void Delete() { - _state = Deleted; + _state = BucketState::Deleted; Memory::DestructItem(&Item); } @@ -54,34 +48,34 @@ public: FORCE_INLINE void Occupy(const ItemType& item) { Memory::ConstructItems(&Item, &item, 1); - _state = Occupied; + _state = BucketState::Occupied; } template FORCE_INLINE void Occupy(ItemType&& item) { Memory::MoveItems(&Item, &item, 1); - _state = Occupied; + _state = BucketState::Occupied; } FORCE_INLINE bool IsEmpty() const { - return _state == Empty; + return _state == BucketState::Empty; } FORCE_INLINE bool IsDeleted() const { - return _state == Deleted; + return _state == BucketState::Deleted; } FORCE_INLINE bool IsOccupied() const { - return _state == Occupied; + return _state == BucketState::Occupied; } FORCE_INLINE bool IsNotOccupied() const { - return _state != Occupied; + return _state != BucketState::Occupied; } }; @@ -109,9 +103,9 @@ private: { Bucket& toBucket = toData[i]; Memory::MoveItems(&toBucket.Item, &fromBucket.Item, 1); - toBucket._state = Bucket::Occupied; + toBucket._state = BucketState::Occupied; Memory::DestructItem(&fromBucket.Item); - fromBucket._state = Bucket::Empty; + fromBucket._state = BucketState::Empty; } } from.Free(); @@ -443,7 +437,7 @@ public: _allocation.Allocate(capacity); Bucket* data = _allocation.Get(); for (int32 i = 0; i < capacity; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } _size = capacity; Bucket* oldData = oldAllocation.Get(); @@ -459,7 +453,7 @@ public: ASSERT(pos.FreeSlotIndex != -1); Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; _elementsCount++; } } @@ -763,7 +757,7 @@ private: // Fast path if it's empty Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; ++i) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } else { @@ -773,7 +767,7 @@ private: _allocation.Allocate(_size); Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; ++i) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; Bucket* oldData = oldAllocation.Get(); FindPositionResult pos; for (int32 i = 0; i < _size; ++i) @@ -785,7 +779,7 @@ private: ASSERT(pos.FreeSlotIndex != -1); Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; } } for (int32 i = 0; i < _size; ++i) From 313263e54167c259e5547bd2ec5b8cc342e9170f Mon Sep 17 00:00:00 2001 From: Amir Alizadeh Date: Thu, 31 Oct 2024 23:30:40 +0330 Subject: [PATCH 43/50] Fix output log scroll reset on new log entries addition bug --- Source/Editor/Windows/OutputLogWindow.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs index f8c4ea9b5..1ce17218e 100644 --- a/Source/Editor/Windows/OutputLogWindow.cs +++ b/Source/Editor/Windows/OutputLogWindow.cs @@ -600,8 +600,10 @@ namespace FlaxEditor.Windows // Update the output var cachedScrollValue = _vScroll.Value; var cachedSelection = _output.SelectionRange; - var isBottomScroll = _vScroll.Value >= _vScroll.Maximum - 20.0f || wasEmpty; + var cachedOutputTargetViewOffset = _output.TargetViewOffset; + var isBottomScroll = _vScroll.Value >= _vScroll.Maximum - (_scrollSize*2) || wasEmpty; _output.Text = _textBuffer.ToString(); + _output.TargetViewOffset = cachedOutputTargetViewOffset; _textBufferCount = _entries.Count; if (!_vScroll.IsThumbClicked) _vScroll.TargetValue = isBottomScroll ? _vScroll.Maximum : cachedScrollValue; From 9f8989b96993a5dcca6e8c5ae4f8dd357f9121ef Mon Sep 17 00:00:00 2001 From: Paul Adrian <67833935+alcoranpaul@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:26:02 -0500 Subject: [PATCH 44/50] Set minimum resolution and resolution curve - Set minimum resolution to (1,1) and minimum keyframe of the Resolution Curve to (0,0) - Also added float literals --- Source/Engine/UI/GUI/CanvasScaler.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Engine/UI/GUI/CanvasScaler.cs b/Source/Engine/UI/GUI/CanvasScaler.cs index abcd97a38..5b7ec9c27 100644 --- a/Source/Engine/UI/GUI/CanvasScaler.cs +++ b/Source/Engine/UI/GUI/CanvasScaler.cs @@ -99,7 +99,7 @@ namespace FlaxEngine.GUI private float _scale = 1.0f; private float _scaleFactor = 1.0f; private float _physicalUnitSize = 1.0f; - private Float2 _resolutionMin = new Float2(640, 480); + private Float2 _resolutionMin = new Float2(1, 1); private Float2 _resolutionMax = new Float2(7680, 4320); /// @@ -246,10 +246,11 @@ namespace FlaxEngine.GUI #endif public LinearCurve ResolutionCurve = new LinearCurve(new[] { - new LinearCurve.Keyframe(480, 0.444f), // 480p - new LinearCurve.Keyframe(720, 0.666f), // 720p - new LinearCurve.Keyframe(1080, 1.0f), // 1080p - new LinearCurve.Keyframe(8640, 8.0f), // 8640p + new LinearCurve.Keyframe(0f, 0f), // 0p + new LinearCurve.Keyframe(480f, 0.444f), // 480p + new LinearCurve.Keyframe(720f, 0.666f), // 720p + new LinearCurve.Keyframe(1080f, 1.0f), // 1080p + new LinearCurve.Keyframe(8640f, 8.0f), // 8640p }); /// From c4c40874e34139189827c7c94ceae26bccfa327b Mon Sep 17 00:00:00 2001 From: Paul Adrian <67833935+alcoranpaul@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:32:01 -0500 Subject: [PATCH 45/50] added more float literals --- Source/Engine/UI/GUI/CanvasScaler.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Engine/UI/GUI/CanvasScaler.cs b/Source/Engine/UI/GUI/CanvasScaler.cs index 5b7ec9c27..f27f906b2 100644 --- a/Source/Engine/UI/GUI/CanvasScaler.cs +++ b/Source/Engine/UI/GUI/CanvasScaler.cs @@ -99,8 +99,8 @@ namespace FlaxEngine.GUI private float _scale = 1.0f; private float _scaleFactor = 1.0f; private float _physicalUnitSize = 1.0f; - private Float2 _resolutionMin = new Float2(1, 1); - private Float2 _resolutionMax = new Float2(7680, 4320); + private Float2 _resolutionMin = new Float2(1f, 1f); + private Float2 _resolutionMax = new Float2(7680f, 4320f); /// /// Gets the current UI scale. Computed based on the setup when performing layout. @@ -336,7 +336,7 @@ namespace FlaxEngine.GUI scale = min / value; else if (value > max) scale = max / value; - if (ResolutionCurve != null && ResolutionCurve.Keyframes?.Length != 0) + if (ResolutionCurve != null && ResolutionCurve.Keyframes?.Length != 0f) { ResolutionCurve.Evaluate(out var curveScale, value, false); scale *= curveScale; @@ -365,13 +365,13 @@ namespace FlaxEngine.GUI dpi = 25.4f; break; case PhysicalUnitMode.Inches: - dpi = 1; + dpi = 1f; break; case PhysicalUnitMode.Points: - dpi = 72; + dpi = 72f; break; case PhysicalUnitMode.Picas: - dpi = 6; + dpi = 6f; break; } return dpi; From bd344e8137b130c3b14d2e519de772f96f6e16b2 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Thu, 31 Oct 2024 22:19:13 -0500 Subject: [PATCH 46/50] Reload existing scene if opened again. --- Source/Editor/States/ChangingScenesState.cs | 45 +++++++++++++-------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Source/Editor/States/ChangingScenesState.cs b/Source/Editor/States/ChangingScenesState.cs index 4fe543153..17fa30ff7 100644 --- a/Source/Editor/States/ChangingScenesState.cs +++ b/Source/Editor/States/ChangingScenesState.cs @@ -109,29 +109,42 @@ namespace FlaxEditor.States private void TryEnter() { - // Remove redundant scene changes - for (int i = 0; i < _scenesToUnload.Count; i++) + // Reload existing scene if only 1 scene exists + bool reloadExistingScene = false; + if (Level.Scenes.Length == 1 && _scenesToLoad.Count == 1) { - var id = _scenesToUnload[i].ID; - for (int j = 0; j < _scenesToLoad.Count; j++) + if (Level.FindScene(_scenesToLoad[0])) { - if (_scenesToLoad[j] == id) - { - _scenesToLoad.RemoveAt(j--); - _scenesToUnload.RemoveAt(i); - break; - } + reloadExistingScene = true; } } - // Skip already loaded scenes - for (int j = 0; j < _scenesToLoad.Count; j++) + if (!reloadExistingScene) { - if (Level.FindScene(_scenesToLoad[j])) + // Remove redundant scene changes + for (int i = 0; i < _scenesToUnload.Count; i++) { - _scenesToLoad.RemoveAt(j--); - if (_scenesToLoad.Count == 0) - break; + var id = _scenesToUnload[i].ID; + for (int j = 0; j < _scenesToLoad.Count; j++) + { + if (_scenesToLoad[j] == id) + { + _scenesToLoad.RemoveAt(j--); + _scenesToUnload.RemoveAt(i); + break; + } + } + } + + // Skip already loaded scenes + for (int j = 0; j < _scenesToLoad.Count; j++) + { + if (Level.FindScene(_scenesToLoad[j])) + { + _scenesToLoad.RemoveAt(j--); + if (_scenesToLoad.Count == 0) + break; + } } } From 576639148f564a1a3453f45135c2e4e8e6607ee3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 5 Nov 2024 11:32:40 +0100 Subject: [PATCH 47/50] Format code and fix error if `_previousWindow` has been closed #2994 --- Source/Editor/Modules/SimulationModule.cs | 33 +++++++++++------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/Source/Editor/Modules/SimulationModule.cs b/Source/Editor/Modules/SimulationModule.cs index 155372a7a..bb9df0950 100644 --- a/Source/Editor/Modules/SimulationModule.cs +++ b/Source/Editor/Modules/SimulationModule.cs @@ -276,17 +276,16 @@ namespace FlaxEditor.Modules { switch (gameWin.FocusOnPlayOption) { - case Options.InterfaceOptions.PlayModeFocus.None: - break; + case Options.InterfaceOptions.PlayModeFocus.None: break; - case Options.InterfaceOptions.PlayModeFocus.GameWindow: - gameWin.FocusGameViewport(); - break; + case Options.InterfaceOptions.PlayModeFocus.GameWindow: + gameWin.FocusGameViewport(); + break; - case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: - _previousWindow = gameWin.ParentDockPanel.SelectedTab; - gameWin.FocusGameViewport(); - break; + case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: + _previousWindow = gameWin.ParentDockPanel.SelectedTab; + gameWin.FocusGameViewport(); + break; } gameWin.SetWindowMode(Editor.Options.Options.Interface.DefaultGameWindowMode); @@ -302,18 +301,16 @@ namespace FlaxEditor.Modules switch (gameWin.FocusOnPlayOption) { - case Options.InterfaceOptions.PlayModeFocus.None: - break; - - case Options.InterfaceOptions.PlayModeFocus.GameWindow: - break; - - case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: + case Options.InterfaceOptions.PlayModeFocus.None: break; + case Options.InterfaceOptions.PlayModeFocus.GameWindow: break; + case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore: + if (_previousWindow != null && !_previousWindow.IsDisposing) + { if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow)) break; - _previousWindow.Focus(); - break; + } + break; } Editor.UI.UncheckPauseButton(); From 935e25ab7d70d8b0fc5c5729b1f172b2e2832746 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 5 Nov 2024 11:32:49 +0100 Subject: [PATCH 48/50] Fix compile warnings --- Source/Engine/Content/Assets/Animation.cpp | 2 +- Source/Engine/Core/LogContext.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Content/Assets/Animation.cpp b/Source/Engine/Content/Assets/Animation.cpp index 261394441..6f8b23ec7 100644 --- a/Source/Engine/Content/Assets/Animation.cpp +++ b/Source/Engine/Content/Assets/Animation.cpp @@ -504,7 +504,7 @@ void Animation::GetReferences(Array& assets, Array& files) const writer.StartObject(); k.Value.Instance->Serialize(writer, nullptr); writer.EndObject(); - JsonAssetBase::GetReferences(StringAnsiView((char*)buffer.GetString(), buffer.GetSize()), assets); + JsonAssetBase::GetReferences(StringAnsiView((const char*)buffer.GetString(), (int32)buffer.GetSize()), assets); } } } diff --git a/Source/Engine/Core/LogContext.cpp b/Source/Engine/Core/LogContext.cpp index 6916fd7de..c7ed7ea2e 100644 --- a/Source/Engine/Core/LogContext.cpp +++ b/Source/Engine/Core/LogContext.cpp @@ -57,7 +57,7 @@ void LogContext::Print(LogType verbosity) LogContextData& context = stack.Ptr[index]; // Skip duplicates - if (index < stack.Count - 1 && stack.Ptr[stack.Count - 1] == context) + if (index < (int32)stack.Count - 1 && stack.Ptr[stack.Count - 1] == context) continue; // Build call hierarchy via indentation From 853e7cb6f7c04251c2617f4a08c37eae921a0e8b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 5 Nov 2024 16:37:23 +0100 Subject: [PATCH 49/50] Add `NetworkReplicator.AddObjectIdMapping` for global/custom network objects sync #3042 --- Source/Engine/Networking/NetworkReplicator.cpp | 8 ++++++++ Source/Engine/Networking/NetworkReplicator.h | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 232980f9f..804101eb0 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -1311,6 +1311,14 @@ void NetworkReplicator::MapObjectId(Guid& objectId) } } +void NetworkReplicator::AddObjectIdMapping(const ScriptingObject* obj, const Guid& objectId) +{ + CHECK(obj); + const Guid id = obj->GetID(); + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", objectId, id.ToString(), obj->GetType().ToString()); + IdsRemappingTable[objectId] = id; +} + ScriptingObject* NetworkReplicator::ResolveForeignObject(Guid objectId) { if (const auto& object = ResolveObject(objectId)) diff --git a/Source/Engine/Networking/NetworkReplicator.h b/Source/Engine/Networking/NetworkReplicator.h index 0b9da2c28..9934425e0 100644 --- a/Source/Engine/Networking/NetworkReplicator.h +++ b/Source/Engine/Networking/NetworkReplicator.h @@ -122,6 +122,13 @@ public: /// /// The network object identifier to map. Contains result ID once the method completes. API_FUNCTION() static void MapObjectId(API_PARAM(Ref) Guid& objectId); + + /// + /// Adds a new mapping for object identifier. Can be used to link locally-spawned object with across different clients. + /// + /// The network object. + /// The network object identifier to use (eg. defined by server or global/static). + API_FUNCTION() static void AddObjectIdMapping(const ScriptingObject* obj, API_PARAM(Ref) const Guid& objectId); /// /// Resolves foreign Guid into a local ScriptingObject From 7f571a647f3b07be089c3a458f8797132827080b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 5 Nov 2024 17:13:57 +0100 Subject: [PATCH 50/50] Fix project files generation to skip unsupported platforms/architectures in referenced targets #3018 #3040 --- Source/Tools/Flax.Build/Build/Builder.Projects.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Tools/Flax.Build/Build/Builder.Projects.cs b/Source/Tools/Flax.Build/Build/Builder.Projects.cs index d0ab1dd8a..c3a8cc096 100644 --- a/Source/Tools/Flax.Build/Build/Builder.Projects.cs +++ b/Source/Tools/Flax.Build/Build/Builder.Projects.cs @@ -335,6 +335,12 @@ namespace Flax.Build var referenceTargets = GetProjectTargets(reference.Project); foreach (var referenceTarget in referenceTargets) { + // Skip referenced targets that don't meet this configuration specs (eg. Editor target should skip Android platform) + if (!referenceTarget.Platforms.Contains(configurationData.Platform)) + continue; + if (!referenceTarget.Architectures.Contains(configurationData.Architecture)) + continue; + try { var referenceBuildOptions = GetBuildOptions(referenceTarget, configurationData.TargetBuildOptions.Platform, configurationData.TargetBuildOptions.Toolchain, configurationData.Architecture, configurationData.Configuration, reference.Project.ProjectFolderPath);