From 141555377b8198476880c6ec4f18e07e27c2941e Mon Sep 17 00:00:00 2001 From: Menotdan Date: Sun, 7 May 2023 22:58:57 -0400 Subject: [PATCH 01/14] Begin working on an IconButton class, and demoing the IconButton idea using the scale link icon. --- .../Editors/ActorTransformEditor.cs | 32 +++- Source/Engine/UI/GUI/Common/IconButton.cs | 167 ++++++++++++++++++ 2 files changed, 192 insertions(+), 7 deletions(-) create mode 100644 Source/Engine/UI/GUI/Common/IconButton.cs diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs index 2612440a4..a824076f7 100644 --- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs @@ -78,7 +78,8 @@ namespace FlaxEditor.CustomEditors.Editors /// public class ScaleEditor : Float3Editor { - private Image _linkImage; + private Button _linkButton; + private SpriteBrush _linkBrush; /// public override void Initialize(LayoutElementsContainer layout) @@ -87,18 +88,26 @@ namespace FlaxEditor.CustomEditors.Editors LinkValues = Editor.Instance.Windows.PropertiesWin.ScaleLinked; - _linkImage = new Image + // Add button with the link icon. + _linkBrush = new SpriteBrush(Editor.Instance.Icons.Link32); + _linkButton = new Button { Parent = LinkedLabel, Width = 18, Height = 18, - Brush = LinkValues ? new SpriteBrush(Editor.Instance.Icons.Link32) : new SpriteBrush(), + BackgroundBrush = _linkBrush, AnchorPreset = AnchorPresets.TopLeft, - TooltipText = "Scale values are linked together.", }; + + _linkButton.Clicked += ToggleLink; + _linkButton.BorderColor = Color.Transparent; + _linkButton.BorderColorSelected = Color.Transparent; + _linkButton.BorderColorHighlighted = Color.Transparent; + SetLinkStyle(); + var x = LinkedLabel.Text.Value.Length * 7 + 5; - _linkImage.LocalX += x; - _linkImage.LocalY += 1; + _linkButton.LocalX += x; + _linkButton.LocalY += 1; LinkedLabel.SetupContextMenu += (label, menu, editor) => { @@ -127,7 +136,16 @@ namespace FlaxEditor.CustomEditors.Editors { LinkValues = !LinkValues; Editor.Instance.Windows.PropertiesWin.ScaleLinked = LinkValues; - _linkImage.Brush = LinkValues ? new SpriteBrush(Editor.Instance.Icons.Link32) : new SpriteBrush(); + SetLinkStyle(); + } + + private void SetLinkStyle() + { + Color backgroundColor = LinkValues ? FlaxEngine.GUI.Style.Current.BackgroundSelected : FlaxEngine.GUI.Style.Current.ForegroundDisabled; + _linkButton.BackgroundColor = backgroundColor; + _linkButton.BackgroundColorHighlighted = backgroundColor.RGBMultiplied(0.9f); + _linkButton.BackgroundColorSelected = backgroundColor.RGBMultiplied(0.8f); + _linkButton.TooltipText = (LinkValues ? "Unlink" : "Link") + " values for uniform scaling."; } } } diff --git a/Source/Engine/UI/GUI/Common/IconButton.cs b/Source/Engine/UI/GUI/Common/IconButton.cs new file mode 100644 index 000000000..196b4b9c4 --- /dev/null +++ b/Source/Engine/UI/GUI/Common/IconButton.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +using System; + +namespace FlaxEngine.GUI +{ + /// + /// Button with an icon. + /// + public class IconButton : Button + { + /// + public override void ClearState() + { + base.ClearState(); + + if (_isPressed) + OnPressEnd(); + } + + /// + public override void DrawSelf() + { + // Cache data + Rectangle clientRect = new Rectangle(Float2.Zero, Size); + bool enabled = EnabledInHierarchy; + Color backgroundColor = BackgroundColor; + Color borderColor = BorderColor; + Color textColor = TextColor; + if (!enabled) + { + backgroundColor *= 0.5f; + borderColor *= 0.5f; + textColor *= 0.6f; + } + else if (_isPressed) + { + backgroundColor = BackgroundColorSelected; + borderColor = BorderColorSelected; + } + else if (IsMouseOver || IsNavFocused) + { + backgroundColor = BackgroundColorHighlighted; + borderColor = BorderColorHighlighted; + } + + // Draw background + if (BackgroundBrush != null) + BackgroundBrush.Draw(clientRect, backgroundColor); + else + Render2D.FillRectangle(clientRect, backgroundColor); + Render2D.DrawRectangle(clientRect, borderColor); + + // Draw text + Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center); + } + + /// + public override void OnMouseEnter(Float2 location) + { + base.OnMouseEnter(location); + + HoverBegin?.Invoke(); + } + + /// + public override void OnMouseLeave() + { + if (_isPressed) + { + OnPressEnd(); + } + + HoverEnd?.Invoke(); + + base.OnMouseLeave(); + } + + /// + public override bool OnMouseDown(Float2 location, MouseButton button) + { + if (base.OnMouseDown(location, button)) + return true; + + if (button == MouseButton.Left && !_isPressed) + { + OnPressBegin(); + return true; + } + return false; + } + + /// + public override bool OnMouseUp(Float2 location, MouseButton button) + { + if (base.OnMouseUp(location, button)) + return true; + + if (button == MouseButton.Left && _isPressed) + { + OnPressEnd(); + OnClick(); + return true; + } + return false; + } + + /// + public override bool OnTouchDown(Float2 location, int pointerId) + { + if (base.OnTouchDown(location, pointerId)) + return true; + + if (!_isPressed) + { + OnPressBegin(); + return true; + } + return false; + } + + /// + public override bool OnTouchUp(Float2 location, int pointerId) + { + if (base.OnTouchUp(location, pointerId)) + return true; + + if (_isPressed) + { + OnPressEnd(); + OnClick(); + return true; + } + return false; + } + + /// + public override void OnTouchLeave() + { + if (_isPressed) + { + OnPressEnd(); + } + + base.OnTouchLeave(); + } + + /// + public override void OnLostFocus() + { + if (_isPressed) + { + OnPressEnd(); + } + + base.OnLostFocus(); + } + + /// + public override void OnSubmit() + { + OnClick(); + + base.OnSubmit(); + } + } +} From 296ac0b9404dbff349007aca8d6b348abe7930f1 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Sun, 7 May 2023 23:04:11 -0400 Subject: [PATCH 02/14] Revert "Use shorter, relative path for displaying Asset Tooltips." This reverts commit 4c906f4040880b3a77686f27289800fb6c0cb55a. undo changes from master branch which I don't want for this seperate change. --- Source/Editor/Content/Items/AssetItem.cs | 4 +- Source/Editor/Content/Items/ContentFolder.cs | 9 +-- Source/Editor/Content/Items/ContentItem.cs | 14 +--- Source/Editor/Options/InterfaceOptions.cs | 7 -- Source/Editor/Utilities/Utils.cs | 76 +------------------- 5 files changed, 8 insertions(+), 102 deletions(-) diff --git a/Source/Editor/Content/Items/AssetItem.cs b/Source/Editor/Content/Items/AssetItem.cs index 120d0e416..6697ed27c 100644 --- a/Source/Editor/Content/Items/AssetItem.cs +++ b/Source/Editor/Content/Items/AssetItem.cs @@ -80,9 +80,9 @@ namespace FlaxEditor.Content /// The String Builder. protected virtual void OnBuildTooltipText(StringBuilder sb) { - sb.Append("Type: ").Append(Utilities.Utils.TranslateTypeName(TypeName)).AppendLine(); + sb.Append("Type: ").Append(TypeName).AppendLine(); sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); + sb.Append("Path: ").Append(Path).AppendLine(); } /// diff --git a/Source/Editor/Content/Items/ContentFolder.cs b/Source/Editor/Content/Items/ContentFolder.cs index 974b813ee..cbbc15f24 100644 --- a/Source/Editor/Content/Items/ContentFolder.cs +++ b/Source/Editor/Content/Items/ContentFolder.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; using FlaxEditor.GUI.Drag; using FlaxEngine; using FlaxEngine.GUI; @@ -138,13 +137,7 @@ namespace FlaxEditor.Content /// public override void UpdateTooltipText() { - string fileDescription = "Folder"; - StringBuilder sb = new StringBuilder(); - - sb.Append("Type: ").Append(fileDescription).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); - - TooltipText = sb.ToString(); + TooltipText = Path; } /// diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs index b4a4caa9a..284f3f1b3 100644 --- a/Source/Editor/Content/Items/ContentItem.cs +++ b/Source/Editor/Content/Items/ContentItem.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Text; using FlaxEditor.Content.GUI; using FlaxEditor.GUI.Drag; using FlaxEngine; @@ -355,19 +353,11 @@ namespace FlaxEditor.Content } /// - /// Updates the tooltip text. + /// Updates the tooltip text text. /// public virtual void UpdateTooltipText() { - string fileExtension = System.IO.Path.GetExtension(Path); - string fileDescription = Utilities.Utils.TranslateFileExtension(fileExtension); - StringBuilder sb = new StringBuilder(); - - sb.Append("Type: ").Append(fileDescription).AppendLine(); - sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); - - TooltipText = sb.ToString(); + TooltipText = "Path: " + Path; } /// diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index d8e30d62b..acfb7f5e8 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -134,13 +134,6 @@ namespace FlaxEditor.Options [EditorDisplay("Interface"), EditorOrder(280), Tooltip("Editor content window orientation.")] public FlaxEngine.GUI.Orientation ContentWindowOrientation { get; set; } = FlaxEngine.GUI.Orientation.Horizontal; - /// - /// Gets or sets the option to use type name translations. - /// - [DefaultValue(true)] - [EditorDisplay("Interface"), EditorOrder(290), Tooltip("Attempt to translate asset type names.")] - public bool TranslateTypeNames { get; set; } = true; - /// /// Gets or sets the timestamps prefix mode for output log messages. /// diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 6ef5a8ea0..ade084431 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -20,8 +20,6 @@ using FlaxEditor.SceneGraph; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; -using FlaxEditor.Options; -using System.Linq; namespace FlaxEngine { @@ -1019,76 +1017,6 @@ namespace FlaxEditor.Utilities node.Visible = isThisVisible | isAnyChildVisible; } - /// - /// Gets the asset type, translating if possible, and if enabled in InterfaceOptions.TranslateTypes. - /// - /// The type name. - /// The translated type name. - public static string TranslateTypeName(string typeName) - { - // TODO: Surely there is a better way to get this value. - if (!Editor.Instance.Options.Options.Interface.TranslateTypeNames) - { - return typeName; - } - - string[] typeNamespaces = typeName.Split('.'); - string lastNamespace = typeNamespaces.Last(); - - // TODO: Add better handling for unconventional type names. - try - { - // Adds spaces between capital letters. - return string.Concat(lastNamespace.Select(x => Char.IsUpper(x) ? " " + x : x.ToString())).TrimStart(' '); - } catch { - return typeName; - } - } - - /// - /// Gets a description of a file from it's extension. - /// - /// The file's extension - /// The processed description. - public static string TranslateFileExtension(string fileExtension) - { - string fileDescription = ""; - switch (fileExtension) - { - case ".cs": - fileDescription = "C# Source Code"; - break; - case ".cpp": - fileDescription = "C++ Source Code"; - break; - case ".h": - fileDescription = "C++ Header File"; - break; - case ".json": - fileDescription = "JSON File"; - break; - default: - fileDescription = fileExtension; - break; - } - - return fileDescription; - } - - - /// - /// Gets the asset name relative to the project root folder (with asset file extension) - /// - /// The asset path. - /// The processed name path. - public static string GetAssetNamePathWithExt(string path) - { - var projectFolder = Globals.ProjectFolder; - if (path.StartsWith(projectFolder)) - path = path.Substring(projectFolder.Length + 1); - return path; - } - /// /// Gets the asset name relative to the project root folder (without asset file extension) /// @@ -1096,7 +1024,9 @@ namespace FlaxEditor.Utilities /// The processed name path. public static string GetAssetNamePath(string path) { - path = GetAssetNamePathWithExt(path); + var projectFolder = Globals.ProjectFolder; + if (path.StartsWith(projectFolder)) + path = path.Substring(projectFolder.Length + 1); return StringUtils.GetPathWithoutExtension(path); } From 681564189fe720005470cc54d06af60ae149a499 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Mon, 8 May 2023 00:42:38 -0400 Subject: [PATCH 03/14] Finish implementing IconButton and use that to create a more intuitive scale linking interface. --- .../Editors/ActorTransformEditor.cs | 15 +- Source/Engine/UI/GUI/Common/Button.cs | 4 +- Source/Engine/UI/GUI/Common/IconButton.cs | 191 +++++------------- 3 files changed, 55 insertions(+), 155 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs index a824076f7..fb7a0b29d 100644 --- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs @@ -79,7 +79,6 @@ namespace FlaxEditor.CustomEditors.Editors public class ScaleEditor : Float3Editor { private Button _linkButton; - private SpriteBrush _linkBrush; /// public override void Initialize(LayoutElementsContainer layout) @@ -89,20 +88,16 @@ namespace FlaxEditor.CustomEditors.Editors LinkValues = Editor.Instance.Windows.PropertiesWin.ScaleLinked; // Add button with the link icon. - _linkBrush = new SpriteBrush(Editor.Instance.Icons.Link32); - _linkButton = new Button + //Editor.Instance.Icons.Link32 + _linkButton = new IconButton(Editor.Instance.Icons.Link32) { Parent = LinkedLabel, Width = 18, Height = 18, - BackgroundBrush = _linkBrush, - AnchorPreset = AnchorPresets.TopLeft, + AnchorPreset = AnchorPresets.TopLeft }; _linkButton.Clicked += ToggleLink; - _linkButton.BorderColor = Color.Transparent; - _linkButton.BorderColorSelected = Color.Transparent; - _linkButton.BorderColorHighlighted = Color.Transparent; SetLinkStyle(); var x = LinkedLabel.Text.Value.Length * 7 + 5; @@ -142,9 +137,7 @@ namespace FlaxEditor.CustomEditors.Editors private void SetLinkStyle() { Color backgroundColor = LinkValues ? FlaxEngine.GUI.Style.Current.BackgroundSelected : FlaxEngine.GUI.Style.Current.ForegroundDisabled; - _linkButton.BackgroundColor = backgroundColor; - _linkButton.BackgroundColorHighlighted = backgroundColor.RGBMultiplied(0.9f); - _linkButton.BackgroundColorSelected = backgroundColor.RGBMultiplied(0.8f); + _linkButton.SetColors(backgroundColor); _linkButton.TooltipText = (LinkValues ? "Unlink" : "Link") + " values for uniform scaling."; } } diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs index 0e0d29615..b6ee13e41 100644 --- a/Source/Engine/UI/GUI/Common/Button.cs +++ b/Source/Engine/UI/GUI/Common/Button.cs @@ -10,7 +10,7 @@ namespace FlaxEngine.GUI public class Button : ContainerControl { /// - /// The default height fro the buttons. + /// The default height for the buttons. /// public const float DefaultHeight = 24.0f; @@ -195,7 +195,7 @@ namespace FlaxEngine.GUI /// Sets the button colors palette based on a given main color. /// /// The main color. - public void SetColors(Color color) + public virtual void SetColors(Color color) { BackgroundColor = color; BorderColor = color.RGBMultiplied(0.5f); diff --git a/Source/Engine/UI/GUI/Common/IconButton.cs b/Source/Engine/UI/GUI/Common/IconButton.cs index 196b4b9c4..e2652cd9f 100644 --- a/Source/Engine/UI/GUI/Common/IconButton.cs +++ b/Source/Engine/UI/GUI/Common/IconButton.cs @@ -9,159 +9,66 @@ namespace FlaxEngine.GUI /// public class IconButton : Button { - /// - public override void ClearState() + /// + /// The sprite rendered on the button. + /// + public SpriteHandle ButtonSprite { get; set; } + + /// + /// Whether or not to hide the border of the button. + /// + public bool HideBorder = true; + + /// + /// Initializes a new instance of the class. + /// + /// The sprite used by the button. + public IconButton(SpriteHandle buttonSprite) + : this(0, 0, buttonSprite) { - base.ClearState(); - - if (_isPressed) - OnPressEnd(); } - /// - public override void DrawSelf() + /// + /// Initializes a new instance of the class. + /// + /// Position X coordinate + /// Position Y coordinate + /// The sprite used by the button. + /// Width + /// Height + /// Whether or not to hide the border. + public IconButton(float x, float y, SpriteHandle buttonSprite, float width = 120, float height = DefaultHeight, bool hideBorder = true) + : base(x, y, width, height) { - // Cache data - Rectangle clientRect = new Rectangle(Float2.Zero, Size); - bool enabled = EnabledInHierarchy; - Color backgroundColor = BackgroundColor; - Color borderColor = BorderColor; - Color textColor = TextColor; - if (!enabled) - { - backgroundColor *= 0.5f; - borderColor *= 0.5f; - textColor *= 0.6f; - } - else if (_isPressed) - { - backgroundColor = BackgroundColorSelected; - borderColor = BorderColorSelected; - } - else if (IsMouseOver || IsNavFocused) - { - backgroundColor = BackgroundColorHighlighted; - borderColor = BorderColorHighlighted; - } - - // Draw background - if (BackgroundBrush != null) - BackgroundBrush.Draw(clientRect, backgroundColor); - else - Render2D.FillRectangle(clientRect, backgroundColor); - Render2D.DrawRectangle(clientRect, borderColor); - - // Draw text - Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center); + ButtonSprite = buttonSprite; + BackgroundBrush = new SpriteBrush(ButtonSprite); + HideBorder = hideBorder; } - /// - public override void OnMouseEnter(Float2 location) + /// + /// Initializes a new instance of the class. + /// + /// Position + /// Size + /// The sprite used by the button. + public IconButton(Float2 location, Float2 size, SpriteHandle buttonSprite) + : this(location.X, location.Y, buttonSprite, size.X, size.Y) { - base.OnMouseEnter(location); - - HoverBegin?.Invoke(); } - /// - public override void OnMouseLeave() + /// + /// Sets the colors of the button, taking into account the field.> + /// + /// The color to use. + public override void SetColors(Color color) { - if (_isPressed) - { - OnPressEnd(); - } + BackgroundColor = color; + BackgroundColorSelected = color.RGBMultiplied(0.8f); + BackgroundColorHighlighted = color.RGBMultiplied(1.2f); - HoverEnd?.Invoke(); - - base.OnMouseLeave(); - } - - /// - public override bool OnMouseDown(Float2 location, MouseButton button) - { - if (base.OnMouseDown(location, button)) - return true; - - if (button == MouseButton.Left && !_isPressed) - { - OnPressBegin(); - return true; - } - return false; - } - - /// - public override bool OnMouseUp(Float2 location, MouseButton button) - { - if (base.OnMouseUp(location, button)) - return true; - - if (button == MouseButton.Left && _isPressed) - { - OnPressEnd(); - OnClick(); - return true; - } - return false; - } - - /// - public override bool OnTouchDown(Float2 location, int pointerId) - { - if (base.OnTouchDown(location, pointerId)) - return true; - - if (!_isPressed) - { - OnPressBegin(); - return true; - } - return false; - } - - /// - public override bool OnTouchUp(Float2 location, int pointerId) - { - if (base.OnTouchUp(location, pointerId)) - return true; - - if (_isPressed) - { - OnPressEnd(); - OnClick(); - return true; - } - return false; - } - - /// - public override void OnTouchLeave() - { - if (_isPressed) - { - OnPressEnd(); - } - - base.OnTouchLeave(); - } - - /// - public override void OnLostFocus() - { - if (_isPressed) - { - OnPressEnd(); - } - - base.OnLostFocus(); - } - - /// - public override void OnSubmit() - { - OnClick(); - - base.OnSubmit(); + BorderColor = HideBorder ? Color.Transparent : color.RGBMultiplied(0.5f); + BorderColorSelected = BorderColor; + BorderColorHighlighted = BorderColor; } } } From 627b1cee103b58fe42324d72e6fa69323834f508 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 May 2023 17:49:45 -0400 Subject: [PATCH 04/14] Resolve issues that came through when attempting to merge previously. --- Source/Editor/Content/Items/ContentFolder.cs | 1 + Source/Editor/Content/Items/ContentItem.cs | 2 ++ Source/Editor/Utilities/Utils.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/Source/Editor/Content/Items/ContentFolder.cs b/Source/Editor/Content/Items/ContentFolder.cs index a654ea697..86c374fee 100644 --- a/Source/Editor/Content/Items/ContentFolder.cs +++ b/Source/Editor/Content/Items/ContentFolder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using FlaxEditor.GUI.Drag; using FlaxEngine; using FlaxEngine.GUI; diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs index 60adb1caa..2a0390b30 100644 --- a/Source/Editor/Content/Items/ContentItem.cs +++ b/Source/Editor/Content/Items/ContentItem.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Text; using FlaxEditor.Content.GUI; using FlaxEditor.GUI.Drag; using FlaxEngine; diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 614c4cdc7..acc0cf605 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1030,6 +1030,7 @@ namespace FlaxEditor.Utilities return path; } + /// /// Gets the asset name relative to the project root folder (without asset file extension) /// /// The asset path. From 4482fc0bcfc7242ece25be5679b5b62e127f33a2 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 12:13:23 +0200 Subject: [PATCH 05/14] Cleanup #1086 Reuse text for UI tooltip Remove `IconButton` and use simple button instead Cleanup code style --- .../Editors/ActorTransformEditor.cs | 17 ++++++++--------- Source/Editor/Utilities/Utils.cs | 4 +--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs index fb7a0b29d..076b94b0a 100644 --- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs @@ -87,23 +87,20 @@ namespace FlaxEditor.CustomEditors.Editors LinkValues = Editor.Instance.Windows.PropertiesWin.ScaleLinked; - // Add button with the link icon. - //Editor.Instance.Icons.Link32 - _linkButton = new IconButton(Editor.Instance.Icons.Link32) + // Add button with the link icon + _linkButton = new Button { + BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Link32), Parent = LinkedLabel, Width = 18, Height = 18, - AnchorPreset = AnchorPresets.TopLeft + AnchorPreset = AnchorPresets.TopLeft, }; - _linkButton.Clicked += ToggleLink; SetLinkStyle(); - var x = LinkedLabel.Text.Value.Length * 7 + 5; _linkButton.LocalX += x; _linkButton.LocalY += 1; - LinkedLabel.SetupContextMenu += (label, menu, editor) => { menu.AddSeparator(); @@ -136,9 +133,11 @@ namespace FlaxEditor.CustomEditors.Editors private void SetLinkStyle() { - Color backgroundColor = LinkValues ? FlaxEngine.GUI.Style.Current.BackgroundSelected : FlaxEngine.GUI.Style.Current.ForegroundDisabled; + var style = FlaxEngine.GUI.Style.Current; + var backgroundColor = LinkValues ? style.Foreground : style.ForegroundDisabled; _linkButton.SetColors(backgroundColor); - _linkButton.TooltipText = (LinkValues ? "Unlink" : "Link") + " values for uniform scaling."; + _linkButton.BorderColor = _linkButton.BorderColorSelected = _linkButton.BorderColorHighlighted = Color.Transparent; + _linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling"; } } } diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index acc0cf605..5f836e069 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1037,9 +1037,7 @@ namespace FlaxEditor.Utilities /// The processed name path. public static string GetAssetNamePath(string path) { - var projectFolder = Globals.ProjectFolder; - if (path.StartsWith(projectFolder)) - path = path.Substring(projectFolder.Length + 1); + path = GetAssetNamePathWithExt(path); return StringUtils.GetPathWithoutExtension(path); } From 3fa9f9e9cfc9ea52e7e493dc59d6aa2139f525db Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 12:14:52 +0200 Subject: [PATCH 06/14] Follow up 4482fc0bcfc7242ece25be5679b5b62e127f33a2 #1086 --- Source/Engine/UI/GUI/Common/IconButton.cs | 74 ----------------------- 1 file changed, 74 deletions(-) delete mode 100644 Source/Engine/UI/GUI/Common/IconButton.cs diff --git a/Source/Engine/UI/GUI/Common/IconButton.cs b/Source/Engine/UI/GUI/Common/IconButton.cs deleted file mode 100644 index e2652cd9f..000000000 --- a/Source/Engine/UI/GUI/Common/IconButton.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. - -using System; - -namespace FlaxEngine.GUI -{ - /// - /// Button with an icon. - /// - public class IconButton : Button - { - /// - /// The sprite rendered on the button. - /// - public SpriteHandle ButtonSprite { get; set; } - - /// - /// Whether or not to hide the border of the button. - /// - public bool HideBorder = true; - - /// - /// Initializes a new instance of the class. - /// - /// The sprite used by the button. - public IconButton(SpriteHandle buttonSprite) - : this(0, 0, buttonSprite) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Position X coordinate - /// Position Y coordinate - /// The sprite used by the button. - /// Width - /// Height - /// Whether or not to hide the border. - public IconButton(float x, float y, SpriteHandle buttonSprite, float width = 120, float height = DefaultHeight, bool hideBorder = true) - : base(x, y, width, height) - { - ButtonSprite = buttonSprite; - BackgroundBrush = new SpriteBrush(ButtonSprite); - HideBorder = hideBorder; - } - - /// - /// Initializes a new instance of the class. - /// - /// Position - /// Size - /// The sprite used by the button. - public IconButton(Float2 location, Float2 size, SpriteHandle buttonSprite) - : this(location.X, location.Y, buttonSprite, size.X, size.Y) - { - } - - /// - /// Sets the colors of the button, taking into account the field.> - /// - /// The color to use. - public override void SetColors(Color color) - { - BackgroundColor = color; - BackgroundColorSelected = color.RGBMultiplied(0.8f); - BackgroundColorHighlighted = color.RGBMultiplied(1.2f); - - BorderColor = HideBorder ? Color.Transparent : color.RGBMultiplied(0.5f); - BorderColorSelected = BorderColor; - BorderColorHighlighted = BorderColor; - } - } -} From 64f3f1e9bc38125d1d457ab3d63d92a7b510b67d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 13:08:25 +0200 Subject: [PATCH 07/14] Add network error log for missing network object when accessing ownership #1066 --- Source/Engine/Networking/NetworkReplicator.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index e150b1ea0..2145753fe 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -878,9 +878,16 @@ uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj) { if (item.HasOwnership) id = item.OwnerClientId; +#if USE_NETWORK_REPLICATOR_LOG + return id; +#else break; +#endif } } +#if USE_NETWORK_REPLICATOR_LOG + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to get ownership of unregistered network object {} ({})", obj->GetID(), obj->GetType().ToString()); +#endif } } return id; @@ -903,9 +910,16 @@ NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj) { if (item.HasOwnership) role = item.Role; +#if USE_NETWORK_REPLICATOR_LOG + return role; +#else break; +#endif } } +#if USE_NETWORK_REPLICATOR_LOG + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to get ownership of unregistered network object {} ({})", obj->GetID(), obj->GetType().ToString()); +#endif } } return role; From 953ae3e9bbbfd9d353bd7d2b0b390edbf784b308 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 14:58:16 +0200 Subject: [PATCH 08/14] Fix hierarchical network ownership propagation to sub-objects #1066 --- .../Engine/Networking/NetworkReplicator.cpp | 86 ++++++++++++------- Source/Engine/Networking/NetworkReplicator.h | 6 +- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 2145753fe..3142e54b3 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -745,7 +745,7 @@ bool NetworkReplicator::InvokeSerializer(const ScriptingTypeHandle& typeHandle, return false; } -void NetworkReplicator::AddObject(ScriptingObject* obj, ScriptingObject* parent) +void NetworkReplicator::AddObject(ScriptingObject* obj, const ScriptingObject* parent) { if (!obj || NetworkManager::IsOffline()) return; @@ -774,6 +774,19 @@ void NetworkReplicator::AddObject(ScriptingObject* obj, ScriptingObject* parent) item.OwnerClientId = NetworkManager::ServerClientId; // Server owns objects by default item.Role = NetworkManager::IsClient() ? NetworkObjectRole::Replicated : NetworkObjectRole::OwnedAuthoritative; NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Add new object {}:{}, parent {}:{}", item.ToString(), obj->GetType().ToString(), item.ParentId.ToString(), parent ? parent->GetType().ToString() : String::Empty); + for (const SpawnItem& spawnItem : SpawnQueue) + { + if (spawnItem.HasOwnership && spawnItem.HierarchicalOwnership) + { + if (IsParentOf(obj, spawnItem.Object)) + { + // Inherit ownership + item.Role = spawnItem.Role; + item.OwnerClientId = spawnItem.OwnerClientId; + break; + } + } + } Objects.Add(MoveTemp(item)); } @@ -864,7 +877,7 @@ void NetworkReplicator::DespawnObject(ScriptingObject* obj) uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj) { uint32 id = NetworkManager::ServerClientId; - if (obj) + if (obj && NetworkManager::IsConnected()) { ScopeLock lock(ObjectsLock); const auto it = Objects.Find(obj->GetID()); @@ -896,7 +909,7 @@ uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj) NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj) { NetworkObjectRole role = NetworkObjectRole::None; - if (obj) + if (obj && NetworkManager::IsConnected()) { ScopeLock lock(ObjectsLock); const auto it = Objects.Find(obj->GetID()); @@ -927,10 +940,11 @@ NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj) void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerClientId, NetworkObjectRole localRole, bool hierarchical) { - if (!obj) + if (!obj || NetworkManager::IsOffline()) return; + const Guid objectId = obj->GetID(); ScopeLock lock(ObjectsLock); - const auto it = Objects.Find(obj->GetID()); + const auto it = Objects.Find(objectId); if (it == Objects.End()) { // Special case if we're just spawning this object @@ -958,31 +972,33 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli break; } } - return; - } - auto& item = it->Item; - if (item.Object != obj) - return; - - // Check if this client is object owner - if (item.OwnerClientId == NetworkManager::LocalClientId) - { - // Check if object owner will change - if (item.OwnerClientId != ownerClientId) - { - // Change role locally - CHECK(localRole != NetworkObjectRole::OwnedAuthoritative); - item.OwnerClientId = ownerClientId; - item.LastOwnerFrame = 1; - item.Role = localRole; - SendObjectRoleMessage(item); - } } else { - // Allow to change local role of the object (except ownership) - CHECK(localRole != NetworkObjectRole::OwnedAuthoritative); - item.Role = localRole; + auto& item = it->Item; + if (item.Object != obj) + return; + + // Check if this client is object owner + if (item.OwnerClientId == NetworkManager::LocalClientId) + { + // Check if object owner will change + if (item.OwnerClientId != ownerClientId) + { + // Change role locally + CHECK(localRole != NetworkObjectRole::OwnedAuthoritative); + item.OwnerClientId = ownerClientId; + item.LastOwnerFrame = 1; + item.Role = localRole; + SendObjectRoleMessage(item); + } + } + else + { + // Allow to change local role of the object (except ownership) + CHECK(localRole != NetworkObjectRole::OwnedAuthoritative); + item.Role = localRole; + } } // Go down hierarchy @@ -990,7 +1006,7 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli { for (auto& e : Objects) { - if (e.Item.ParentId == item.ObjectId) + if (e.Item.ParentId == objectId) SetObjectOwnership(e.Item.Object.Get(), ownerClientId, localRole, hierarchical); } } @@ -1196,9 +1212,11 @@ void NetworkInternal::NetworkReplicatorUpdate() { if (!q.HasOwnership && IsParentOf(q.Object, e.Object)) { + // Inherit ownership q.HasOwnership = true; q.Role = e.Role; q.OwnerClientId = e.OwnerClientId; + break; } } } @@ -1637,7 +1655,7 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl } } - // Setup all newly spawned objects + // Add all newly spawned objects for (int32 i = 0; i < msgData.ItemsCount; i++) { auto& msgDataItem = msgDataItems[i]; @@ -1666,6 +1684,16 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl // Boost future lookups by using indirection NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", msgDataItem.ObjectId, item.ToString(), obj->GetType().ToString()); IdsRemappingTable.Add(msgDataItem.ObjectId, item.ObjectId); + } + + // Spawn all newly spawned objects (ensure to have valid ownership hierarchy set before spawning object) + for (int32 i = 0; i < msgData.ItemsCount; i++) + { + auto& msgDataItem = msgDataItems[i]; + ScriptingObject* obj = objects[i]; + auto it = Objects.Find(obj->GetID()); + auto& item = it->Item; + const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId); // Automatic parenting for scene objects auto sceneObject = ScriptingObject::Cast(obj); diff --git a/Source/Engine/Networking/NetworkReplicator.h b/Source/Engine/Networking/NetworkReplicator.h index 389350e5f..84db2797b 100644 --- a/Source/Engine/Networking/NetworkReplicator.h +++ b/Source/Engine/Networking/NetworkReplicator.h @@ -68,7 +68,7 @@ public: /// Does nothing if network is offline. /// The object to replicate. /// The parent of the object (eg. player that spawned it). - API_FUNCTION() static void AddObject(ScriptingObject* obj, ScriptingObject* parent = nullptr); + API_FUNCTION() static void AddObject(ScriptingObject* obj, const ScriptingObject* parent = nullptr); /// /// Removes the object from the network replication system. @@ -80,14 +80,14 @@ public: /// /// Spawns the object to the other clients. Can be spawned by the owner who locally created it (eg. from prefab). /// - /// Does nothing if network is offline. + /// Does nothing if network is offline. Doesn't spawn actor in a level - but in network replication system. /// The object to spawn on other clients. API_FUNCTION() static void SpawnObject(ScriptingObject* obj); /// /// Spawns the object to the other clients. Can be spawned by the owner who locally created it (eg. from prefab). /// - /// Does nothing if network is offline. + /// Does nothing if network is offline. Doesn't spawn actor in a level - but in network replication system. /// The object to spawn on other clients. /// List with network client IDs that should receive network spawn event. Empty to spawn on all clients. API_FUNCTION() static void SpawnObject(ScriptingObject* obj, const DataContainer& clientIds); From 70593177c71d730cc89dd622fc2f11e241fd3b2a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 14:58:47 +0200 Subject: [PATCH 09/14] Add `NetworkReplicator::HasObject` --- Source/Engine/Networking/NetworkReplicator.cpp | 17 +++++++++++++++++ Source/Engine/Networking/NetworkReplicator.h | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 3142e54b3..165d20659 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -874,6 +874,23 @@ void NetworkReplicator::DespawnObject(ScriptingObject* obj) DeleteNetworkObject(obj); } +bool NetworkReplicator::HasObject(const ScriptingObject* obj) +{ + if (obj) + { + ScopeLock lock(ObjectsLock); + const auto it = Objects.Find(obj->GetID()); + if (it != Objects.End()) + return true; + for (const SpawnItem& item : SpawnQueue) + { + if (item.Object == obj) + return true; + } + } + return false; +} + uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj) { uint32 id = NetworkManager::ServerClientId; diff --git a/Source/Engine/Networking/NetworkReplicator.h b/Source/Engine/Networking/NetworkReplicator.h index 84db2797b..0e9a2d0d8 100644 --- a/Source/Engine/Networking/NetworkReplicator.h +++ b/Source/Engine/Networking/NetworkReplicator.h @@ -99,6 +99,13 @@ public: /// The object to despawn on other clients. API_FUNCTION() static void DespawnObject(ScriptingObject* obj); + /// + /// Checks if the network object is spawned or added to the network replication system. + /// + /// The network object. + /// True if object exists in networking, otherwise false. + API_FUNCTION() static bool HasObject(const ScriptingObject* obj); + /// /// Gets the Client Id of the network object owner. /// From e045f096a9dbe635ad02548155b30e61ea842812 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 May 2023 14:59:15 +0200 Subject: [PATCH 10/14] Add network debugging panel to actors and scripts #1066 --- .../Editor/CustomEditors/CustomEditorsUtil.cs | 5 +++- .../CustomEditors/Dedicated/ActorEditor.cs | 2 +- .../Dedicated/ScriptingObjectEditor.cs | 29 +++++++++++++++++++ .../CustomEditors/Dedicated/ScriptsEditor.cs | 1 - 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 Source/Editor/CustomEditors/Dedicated/ScriptingObjectEditor.cs diff --git a/Source/Editor/CustomEditors/CustomEditorsUtil.cs b/Source/Editor/CustomEditors/CustomEditorsUtil.cs index 070ad1fb3..7f653376b 100644 --- a/Source/Editor/CustomEditors/CustomEditorsUtil.cs +++ b/Source/Editor/CustomEditors/CustomEditorsUtil.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; +using FlaxEditor.CustomEditors.Dedicated; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.Scripting; using FlaxEngine; @@ -107,7 +108,7 @@ namespace FlaxEditor.CustomEditors // Select default editor (based on type) if (targetType.IsEnum) return new EnumEditor(); - if (targetType.IsGenericType) + if (targetType.IsGenericType) { if (targetTypeType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) return new DictionaryEditor(); @@ -118,6 +119,8 @@ namespace FlaxEditor.CustomEditors if (customEditorType != null) return (CustomEditor)Activator.CreateInstance(customEditorType); } + if (typeof(FlaxEngine.Object).IsAssignableFrom(targetTypeType)) + return new ScriptingObjectEditor(); // The most generic editor return new GenericEditor(); diff --git a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs index 75e3fff23..a8773a8d7 100644 --- a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs @@ -20,7 +20,7 @@ namespace FlaxEditor.CustomEditors.Dedicated /// /// [CustomEditor(typeof(Actor)), DefaultEditor] - public class ActorEditor : GenericEditor + public class ActorEditor : ScriptingObjectEditor { private Guid _linkedPrefabId; diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptingObjectEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptingObjectEditor.cs new file mode 100644 index 000000000..477deb708 --- /dev/null +++ b/Source/Editor/CustomEditors/Dedicated/ScriptingObjectEditor.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +using FlaxEditor.CustomEditors.Editors; +using FlaxEngine.Networking; + +namespace FlaxEditor.CustomEditors.Dedicated +{ + /// + /// Custom editor for . + /// + public class ScriptingObjectEditor : GenericEditor + { + /// + public override void Initialize(LayoutElementsContainer layout) + { + // Network objects debugging + var obj = Values[0] as FlaxEngine.Object; + if (Editor.IsPlayMode && NetworkManager.IsConnected && NetworkReplicator.HasObject(obj)) + { + var group = layout.Group("Network"); + group.Panel.Open(); + group.Label("Role", Utilities.Utils.GetPropertyNameUI(NetworkReplicator.GetObjectRole(obj).ToString())); + group.Label("Owner Client Id", NetworkReplicator.GetObjectOwnerClientId(obj).ToString()); + } + + base.Initialize(layout); + } + } +} diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index 73a43f1bf..613f5d3b4 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -3,7 +3,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using FlaxEditor.Actions; using FlaxEditor.Content; using FlaxEditor.GUI; From 31fb25a43de10ede8a31cb79a378bde2f0424b6f Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Wed, 17 May 2023 02:28:45 +0300 Subject: [PATCH 11/14] Fix dispatch order regression --- Source/Engine/Networking/NetworkManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index 88a104c3e..373a24c9d 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -318,10 +318,10 @@ bool NetworkManager::StartHost() // Auto-connect host LocalClient->State = NetworkConnectionState::Connected; - ClientConnected(LocalClient); - State = NetworkConnectionState::Connected; StateChanged(); + + ClientConnected(LocalClient); return false; } From f0564e0b066ec0673274b905c223b0ff741e151b Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Wed, 17 May 2023 03:34:03 +0300 Subject: [PATCH 12/14] Fix NetworkReplicator::SetObjectOwnership not considering spawn queue for hierarchical asignment --- Source/Engine/Networking/NetworkReplicator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 165d20659..be7571b80 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -1026,6 +1026,12 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli if (e.Item.ParentId == objectId) SetObjectOwnership(e.Item.Object.Get(), ownerClientId, localRole, hierarchical); } + + for (const SpawnItem& spawnItem : SpawnQueue) + { + if (IsParentOf(spawnItem.Object, obj)) + SetObjectOwnership(spawnItem.Object, ownerClientId, localRole, hierarchical); + } } } From b244ffedd2aafd72c7e1af4d88c744d82000871d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 17 May 2023 12:23:01 +0200 Subject: [PATCH 13/14] Fix output log text ranges to handle line ending --- Source/Editor/Windows/OutputLogWindow.cs | 4 ++-- Source/Engine/Render2D/Font.h | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs index 544253fa5..f2f3b4aff 100644 --- a/Source/Editor/Windows/OutputLogWindow.cs +++ b/Source/Editor/Windows/OutputLogWindow.cs @@ -541,7 +541,7 @@ namespace FlaxEditor.Windows { ref var line = ref lines[j]; textBlock.Range.StartIndex = startIndex + line.FirstCharIndex; - textBlock.Range.EndIndex = startIndex + line.LastCharIndex; + textBlock.Range.EndIndex = startIndex + line.LastCharIndex + 1; textBlock.Bounds = new Rectangle(new Float2(0.0f, prevBlockBottom), line.Size); if (textBlock.Range.Length > 0) @@ -550,7 +550,7 @@ namespace FlaxEditor.Windows var regexStart = line.FirstCharIndex; if (j == 0) regexStart += prefixLength; - var regexLength = line.LastCharIndex - regexStart; + var regexLength = line.LastCharIndex + 1 - regexStart; if (regexLength > 0) { var match = _compileRegex.Match(entryText, regexStart, regexLength); diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h index d3806f0b4..3f42fd396 100644 --- a/Source/Engine/Render2D/Font.h +++ b/Source/Engine/Render2D/Font.h @@ -17,17 +17,17 @@ class FontAsset; /// /// The text range. /// -API_STRUCT() struct TextRange +API_STRUCT(NoDefault) struct TextRange { DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// - /// The start index. + /// The start index (inclusive). /// API_FIELD() int32 StartIndex; /// - /// The end index. + /// The end index (exclusive). /// API_FIELD() int32 EndIndex; @@ -70,7 +70,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// /// Gets the substring from the source text. /// - /// The text. + /// The text. /// The substring of the original text of the defined range. StringView Substring(const StringView& text) const { @@ -87,7 +87,7 @@ struct TIsPODType /// /// The font line info generated during text processing. /// -API_STRUCT() struct FontLineCache +API_STRUCT(NoDefault) struct FontLineCache { DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache); @@ -151,7 +151,7 @@ struct TIsPODType /// /// The cached font character entry (read for rendering and further processing). /// -API_STRUCT() struct FontCharacterEntry +API_STRUCT(NoDefault) struct FontCharacterEntry { DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry); From 0d3bae376157fce471fac7b7fb52b886e482930e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 17 May 2023 21:37:55 +0200 Subject: [PATCH 14/14] Minor adjustment to #1105 so the local client state is reflected as connecting --- Source/Engine/Networking/NetworkManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index 373a24c9d..88c59ad9a 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -317,11 +317,12 @@ bool NetworkManager::StartHost() LocalClient = New(LocalClientId, NetworkConnection{ 0 }); // Auto-connect host - LocalClient->State = NetworkConnectionState::Connected; + LocalClient->State = NetworkConnectionState::Connecting; State = NetworkConnectionState::Connected; StateChanged(); - + LocalClient->State = NetworkConnectionState::Connected; ClientConnected(LocalClient); + return false; }