diff --git a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs index 1f2211571..b88aeb7ad 100644 --- a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs @@ -71,7 +71,7 @@ namespace FlaxEditor.CustomEditors.Dedicated var panel = layout.CustomContainer(); panel.CustomControl.Height = 20.0f; panel.CustomControl.SlotsVertically = 1; - panel.CustomControl.SlotsHorizontally = 2; + panel.CustomControl.SlotsHorizontally = 3; // Selecting actor prefab asset var selectPrefab = panel.Button("Select Prefab"); @@ -81,6 +81,15 @@ namespace FlaxEditor.CustomEditors.Dedicated Editor.Instance.Windows.ContentWin.Select(prefab); }; + // Edit selected prefab asset + var editPrefab = panel.Button("Edit Prefab"); + editPrefab.Button.Clicked += () => + { + Editor.Instance.Windows.ContentWin.ClearItemsSearch(); + Editor.Instance.Windows.ContentWin.Select(prefab); + Editor.Instance.Windows.ContentWin.Open(Editor.Instance.Windows.ContentWin.View.Selection[0]); + }; + // Viewing changes applied to this actor var viewChanges = panel.Button("View Changes"); viewChanges.Button.Clicked += () => ViewChanges(viewChanges.Button, new Float2(0.0f, 20.0f)); diff --git a/Source/Editor/CustomEditors/Dedicated/ClothEditor.cs b/Source/Editor/CustomEditors/Dedicated/ClothEditor.cs index c9ffaf683..d970c0bd2 100644 --- a/Source/Editor/CustomEditors/Dedicated/ClothEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ClothEditor.cs @@ -38,15 +38,15 @@ namespace FlaxEditor.CustomEditors.Dedicated _gizmoMode = new ClothPaintingGizmoMode(); var projectCache = Editor.Instance.ProjectCache; - if (projectCache.TryGetCustomData("ClothGizmoPaintValue", out var cachedPaintValue)) + if (projectCache.TryGetCustomData("ClothGizmoPaintValue", out string cachedPaintValue)) _gizmoMode.PaintValue = JsonSerializer.Deserialize(cachedPaintValue); - if (projectCache.TryGetCustomData("ClothGizmoContinuousPaint", out var cachedContinuousPaint)) + if (projectCache.TryGetCustomData("ClothGizmoContinuousPaint", out string cachedContinuousPaint)) _gizmoMode.ContinuousPaint = JsonSerializer.Deserialize(cachedContinuousPaint); - if (projectCache.TryGetCustomData("ClothGizmoBrushFalloff", out var cachedBrushFalloff)) + if (projectCache.TryGetCustomData("ClothGizmoBrushFalloff", out string cachedBrushFalloff)) _gizmoMode.BrushFalloff = JsonSerializer.Deserialize(cachedBrushFalloff); - if (projectCache.TryGetCustomData("ClothGizmoBrushSize", out var cachedBrushSize)) + if (projectCache.TryGetCustomData("ClothGizmoBrushSize", out string cachedBrushSize)) _gizmoMode.BrushSize = JsonSerializer.Deserialize(cachedBrushSize); - if (projectCache.TryGetCustomData("ClothGizmoBrushStrength", out var cachedBrushStrength)) + if (projectCache.TryGetCustomData("ClothGizmoBrushStrength", out string cachedBrushStrength)) _gizmoMode.BrushStrength = JsonSerializer.Deserialize(cachedBrushStrength); gizmos.AddMode(_gizmoMode); diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index 9227dac06..852fd99c5 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -880,6 +880,13 @@ namespace FlaxEditor.CustomEditors.Dedicated group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2); group.Object(values, editor); + // Remove drop down arrows and containment lines if no objects in the group + if (group.Children.Count == 0) + { + group.Panel.ArrowImageOpened = null; + group.Panel.ArrowImageClosed = null; + group.Panel.EnableContainmentLines = false; + } // Scripts arrange bar dragBar = layout.Custom(); diff --git a/Source/Editor/CustomEditors/Editors/IntegerEditor.cs b/Source/Editor/CustomEditors/Editors/IntegerEditor.cs index 651310349..4f6c2a9e7 100644 --- a/Source/Editor/CustomEditors/Editors/IntegerEditor.cs +++ b/Source/Editor/CustomEditors/Editors/IntegerEditor.cs @@ -83,6 +83,22 @@ namespace FlaxEditor.CustomEditors.Editors _element.Value = asInt; else if (value is float asFloat) _element.Value = (int)asFloat; + else if (value is double asDouble) + _element.Value = (int)asDouble; + else if (value is uint asUint) + _element.Value = (int)asUint; + else if (value is long asLong) + _element.Value = (int)asLong; + else if (value is ulong asULong) + _element.Value = (int)asULong; + else if (value is short asShort) + _element.Value = asShort; + else if (value is ushort asUshort) + _element.Value = asUshort; + else if (value is byte asByte) + _element.Value = asByte; + else if (value is sbyte asSbyte) + _element.Value = asSbyte; else throw new Exception(string.Format("Invalid value type {0}.", value?.GetType().ToString() ?? "")); } @@ -338,7 +354,7 @@ namespace FlaxEditor.CustomEditors.Editors protected abstract ulong GetValue(object value); /// - /// Gets the value from long. + /// Sets the value from long. /// /// The value from editor. /// The value to object. diff --git a/Source/Editor/CustomEditors/LayoutElementsContainer.cs b/Source/Editor/CustomEditors/LayoutElementsContainer.cs index d1999bb99..0ec88238e 100644 --- a/Source/Editor/CustomEditors/LayoutElementsContainer.cs +++ b/Source/Editor/CustomEditors/LayoutElementsContainer.cs @@ -319,6 +319,8 @@ namespace FlaxEditor.CustomEditors element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize); if (header.Color > 0) element.Label.TextColor = Color.FromRGB(header.Color); + var size = element.Label.Font.GetFont().MeasureText(header.Text); + element.Label.Height = size.Y; return element; } diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 2a768099d..034cecebf 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -331,7 +331,7 @@ namespace FlaxEditor } case GeneralOptions.StartupSceneModes.LastOpened: { - if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) + if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out string lastSceneIdName)) { var lastScenes = JsonSerializer.Deserialize(lastSceneIdName); foreach (var scene in lastScenes) @@ -443,7 +443,7 @@ namespace FlaxEditor } case GeneralOptions.StartupSceneModes.LastOpened: { - if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) + if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out string lastSceneIdName)) { var lastScenes = JsonSerializer.Deserialize(lastSceneIdName); foreach (var sceneId in lastScenes) @@ -460,7 +460,7 @@ namespace FlaxEditor } // Restore view - if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out var lastSceneSpawnName)) + if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out string lastSceneSpawnName)) Windows.EditWin.Viewport.ViewRay = JsonSerializer.Deserialize(lastSceneSpawnName); } break; diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index fc66f284a..b19d7a9f1 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -119,10 +119,8 @@ namespace FlaxEditor.GUI.Dialogs _onClosed = pickerClosed; // Get saved colors if they exist - if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out var savedColors)) - { + if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out string savedColors)) _savedColors = JsonSerializer.Deserialize>(savedColors); - } // Selector _cSelector = new ColorSelectorWithSliders(180, 18) diff --git a/Source/Editor/GUI/Input/SliderControl.cs b/Source/Editor/GUI/Input/SliderControl.cs index c0cec3f56..a80b5e230 100644 --- a/Source/Editor/GUI/Input/SliderControl.cs +++ b/Source/Editor/GUI/Input/SliderControl.cs @@ -132,6 +132,8 @@ namespace FlaxEditor.GUI.Input _isSliding = false; EndMouseCapture(); SlidingEnd?.Invoke(); + Defocus(); + Parent?.Focus(); } /// @@ -183,6 +185,8 @@ namespace FlaxEditor.GUI.Input { // Click change Value += (mousePosition < _thumbCenter ? -1 : 1) * 10; + Defocus(); + Parent?.Focus(); } } @@ -197,6 +201,10 @@ namespace FlaxEditor.GUI.Input // Update sliding var slidePosition = location + Root.TrackingMouseOffset; Value = Mathf.Remap(slidePosition.X, 4, TrackSize - 4, Minimum, Maximum); + if (Mathf.NearEqual(Value, Maximum)) + Value = Maximum; + else if (Mathf.NearEqual(Value, Minimum)) + Value = Minimum; } else { @@ -364,7 +372,7 @@ namespace FlaxEditor.GUI.Input }; _slider.ValueChanged += SliderOnValueChanged; _slider.SlidingStart += SlidingStart; - _slider.SlidingEnd += SlidingEnd; + _slider.SlidingEnd += SliderOnSliderEnd; _textBox = new TextBox(false, split, 0) { Text = _value.ToString(CultureInfo.InvariantCulture), @@ -375,6 +383,13 @@ namespace FlaxEditor.GUI.Input _textBox.EditEnd += OnTextBoxEditEnd; } + private void SliderOnSliderEnd() + { + SlidingEnd?.Invoke(); + Defocus(); + Parent?.Focus(); + } + private void SliderOnValueChanged() { if (_valueIsChanging) @@ -397,6 +412,8 @@ namespace FlaxEditor.GUI.Input { UpdateText(); } + Defocus(); + Parent?.Focus(); } /// diff --git a/Source/Editor/Gizmo/UIEditorGizmo.cs b/Source/Editor/Gizmo/UIEditorGizmo.cs index 26cf02972..3fa574e1b 100644 --- a/Source/Editor/Gizmo/UIEditorGizmo.cs +++ b/Source/Editor/Gizmo/UIEditorGizmo.cs @@ -626,9 +626,6 @@ namespace FlaxEditor var viewScale = ViewScale; if (viewScale < 0.7f) widgetSize *= viewScale; - var controlSize = control.Size.Absolute.MinValue / 50.0f; - if (controlSize < 1.0f) - widgetSize *= Mathf.Clamp(controlSize + 0.1f, 0.1f, 1.0f); var widgetHandleSize = new Float2(widgetSize); DrawControlWidget(uiControl, ref ul, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, -1), CursorType.SizeNWSE); DrawControlWidget(uiControl, ref ur, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, -1), CursorType.SizeNESW); @@ -647,7 +644,7 @@ namespace FlaxEditor } } - private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size,float scale, Float2 resizeAxis, CursorType cursor) + private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size, float scale, Float2 resizeAxis, CursorType cursor) { var style = Style.Current; var rect = new Rectangle((pos + resizeAxis * 10 * scale) - size * 0.5f, size); diff --git a/Source/Editor/Modules/ProjectCacheModule.cs b/Source/Editor/Modules/ProjectCacheModule.cs index ac8bd4a8f..b0ebb6981 100644 --- a/Source/Editor/Modules/ProjectCacheModule.cs +++ b/Source/Editor/Modules/ProjectCacheModule.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Runtime.CompilerServices; using FlaxEngine; namespace FlaxEditor.Modules @@ -119,6 +121,30 @@ namespace FlaxEditor.Modules return _customData.TryGetValue(key, out value); } + /// + /// Tries to get the custom data by the key. + /// + /// The key. + /// When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. + /// The custom data. + public bool TryGetCustomData(string key, out bool value) + { + value = false; + return _customData.TryGetValue(key, out var valueStr) && bool.TryParse(valueStr, out value); + } + + /// + /// Tries to get the custom data by the key. + /// + /// The key. + /// When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. + /// The custom data. + public bool TryGetCustomData(string key, out float value) + { + value = 0.0f; + return _customData.TryGetValue(key, out var valueStr) && float.TryParse(valueStr, out value); + } + /// /// Sets the custom data. /// @@ -130,6 +156,28 @@ namespace FlaxEditor.Modules _isDirty = true; } + /// + /// Sets the custom data. + /// + /// The key. + /// The value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetCustomData(string key, bool value) + { + SetCustomData(key, value.ToString()); + } + + /// + /// Sets the custom data. + /// + /// The key. + /// The value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetCustomData(string key, float value) + { + SetCustomData(key, value.ToString(CultureInfo.InvariantCulture)); + } + /// /// Removes the custom data. /// diff --git a/Source/Editor/Modules/SimulationModule.cs b/Source/Editor/Modules/SimulationModule.cs index c77bc4492..fecfcfdd6 100644 --- a/Source/Editor/Modules/SimulationModule.cs +++ b/Source/Editor/Modules/SimulationModule.cs @@ -127,13 +127,12 @@ namespace FlaxEditor.Modules public void RequestStartPlayGame() { if (!Editor.StateMachine.IsEditMode) - { return; - } var firstScene = Content.Settings.GameSettings.Load().FirstScene; if (firstScene == Guid.Empty) { + Editor.LogWarning("No First Scene assigned in Game Settings."); if (Level.IsAnySceneLoaded) Editor.Simulation.RequestStartPlayScenes(); return; @@ -141,6 +140,9 @@ namespace FlaxEditor.Modules if (!FlaxEngine.Content.GetAssetInfo(firstScene.ID, out var info)) { Editor.LogWarning("Invalid First Scene in Game Settings."); + if (Level.IsAnySceneLoaded) + Editor.Simulation.RequestStartPlayScenes(); + return; } // Load scenes after entering the play mode diff --git a/Source/Editor/Modules/SourceCodeEditing/CodeDocsModule.cs b/Source/Editor/Modules/SourceCodeEditing/CodeDocsModule.cs index 02ca7be20..610368a82 100644 --- a/Source/Editor/Modules/SourceCodeEditing/CodeDocsModule.cs +++ b/Source/Editor/Modules/SourceCodeEditing/CodeDocsModule.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Text.RegularExpressions; using System.Xml; using FlaxEditor.Scripting; @@ -65,7 +66,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing { var key = "T:" + GetXmlKey(type.Type.FullName); if (xml.TryGetValue(key, out var xmlDoc)) - text += '\n' + xmlDoc; + text += '\n' + FilterWhitespaces(xmlDoc); } } @@ -262,6 +263,27 @@ namespace FlaxEditor.Modules.SourceCodeEditing return Regex.Replace(typeFullNameString, @"\[.*\]", string.Empty).Replace('+', '.'); } + private static string FilterWhitespaces(string str) + { + if (str.Contains(" ", StringComparison.Ordinal)) + { + var sb = new StringBuilder(); + var prev = str[0]; + sb.Append(prev); + for (int i = 1; i < str.Length; i++) + { + var c = str[i]; + if (prev != ' ' || c != ' ') + { + sb.Append(c); + } + prev = c; + } + str = sb.ToString(); + } + return str; + } + private Dictionary GetXmlDocs(Assembly assembly) { if (!_xmlCache.TryGetValue(assembly, out var result)) diff --git a/Source/Editor/Modules/WindowsModule.cs b/Source/Editor/Modules/WindowsModule.cs index 3926412a0..02dd6d151 100644 --- a/Source/Editor/Modules/WindowsModule.cs +++ b/Source/Editor/Modules/WindowsModule.cs @@ -511,11 +511,11 @@ namespace FlaxEditor.Modules { var bounds = node["Bounds"]; var isMaximizedText = bounds.GetAttribute("IsMaximized"); - if (!string.IsNullOrEmpty(isMaximizedText)) - isMaximized = bool.Parse(isMaximizedText); + if (!string.IsNullOrEmpty(isMaximizedText) && bool.TryParse(isMaximizedText, out var tmpBool)) + isMaximized = tmpBool; var isMinimizedText = bounds.GetAttribute("IsMinimized"); - if (!string.IsNullOrEmpty(isMinimizedText)) - isMinimized = bool.Parse(isMinimizedText); + if (!string.IsNullOrEmpty(isMinimizedText) && bool.TryParse(isMinimizedText, out tmpBool)) + isMinimized = tmpBool; float x = float.Parse(bounds.GetAttribute("X"), CultureInfo.InvariantCulture); float y = float.Parse(bounds.GetAttribute("Y"), CultureInfo.InvariantCulture); float width = float.Parse(bounds.GetAttribute("Width"), CultureInfo.InvariantCulture); diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 223420191..7fa08cc39 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -312,6 +312,13 @@ namespace FlaxEditor.Options [EditorDisplay("Cook & Run"), EditorOrder(500)] public int NumberOfGameClientsToLaunch = 1; + /// + /// Gets or sets the visject connection curvature. + /// + [DefaultValue(1.0f), Range(0.0f, 2.0f)] + [EditorDisplay("Visject"), EditorOrder(550)] + public float ConnectionCurvature { get; set; } = 1.0f; + private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont); private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont); diff --git a/Source/Editor/States/PlayingState.cs b/Source/Editor/States/PlayingState.cs index 69a11cf1b..9da71a967 100644 --- a/Source/Editor/States/PlayingState.cs +++ b/Source/Editor/States/PlayingState.cs @@ -77,7 +77,6 @@ namespace FlaxEditor.States { if (!IsActive) throw new InvalidOperationException(); - Time.GamePaused = value; } } diff --git a/Source/Editor/Surface/Archetypes/Boolean.cs b/Source/Editor/Surface/Archetypes/Boolean.cs index 0c5d41a60..268d7a360 100644 --- a/Source/Editor/Surface/Archetypes/Boolean.cs +++ b/Source/Editor/Surface/Archetypes/Boolean.cs @@ -60,7 +60,7 @@ namespace FlaxEditor.Surface.Archetypes Op1(1, "Boolean NOT", "Negates the boolean value", new[] { "!", "~" }), Op2(2, "Boolean AND", "Performs a logical conjunction on two values", new[] { "&&" }), Op2(3, "Boolean OR", "Returns true if either (or both) of its operands is true", new[] { "||" }), - Op2(4, "Boolean XOR", "", new [] { "^" } ), + Op2(4, "Boolean XOR", "", new[] { "^" }), Op2(5, "Boolean NOR", ""), Op2(6, "Boolean NAND", ""), }; diff --git a/Source/Editor/Surface/Archetypes/Constants.cs b/Source/Editor/Surface/Archetypes/Constants.cs index 4591459f1..b94bc34cb 100644 --- a/Source/Editor/Surface/Archetypes/Constants.cs +++ b/Source/Editor/Surface/Archetypes/Constants.cs @@ -47,7 +47,8 @@ namespace FlaxEditor.Surface.Archetypes base.OnShowSecondaryContextMenu(menu, location); menu.AddSeparator(); - menu.AddButton("Convert to Parameter", OnConvertToParameter); + var b = menu.AddButton("Convert to Parameter", OnConvertToParameter); + b.Enabled = Surface.Owner is IVisjectSurfaceWindow window && Surface.Owner.SurfaceAsset && window.NewParameterTypes.Contains(_type); } private void OnConvertToParameter() @@ -122,8 +123,7 @@ namespace FlaxEditor.Surface.Archetypes private bool OnParameterRenameValidate(string value) { - if (Surface.Owner is not IVisjectSurfaceWindow window) - throw new Exception("Surface owner is not a Visject Surface Window"); + var window = (IVisjectSurfaceWindow)Surface.Owner; return !string.IsNullOrWhiteSpace(value) && window.VisjectSurface.Parameters.All(x => x.Name != value); } } diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index 5182fdb36..58d1b854d 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -71,20 +71,20 @@ namespace FlaxEditor.Surface.Archetypes // Layered material if (GetBox(MaterialNodeBoxes.Layer).HasAnyConnection) { - GetBox(MaterialNodeBoxes.Color).Enabled = false; - GetBox(MaterialNodeBoxes.Mask).Enabled = false; - GetBox(MaterialNodeBoxes.Emissive).Enabled = false; - GetBox(MaterialNodeBoxes.Metalness).Enabled = false; - GetBox(MaterialNodeBoxes.Specular).Enabled = false; - GetBox(MaterialNodeBoxes.Roughness).Enabled = false; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = false; - GetBox(MaterialNodeBoxes.Normal).Enabled = false; - GetBox(MaterialNodeBoxes.Opacity).Enabled = false; - GetBox(MaterialNodeBoxes.Refraction).Enabled = false; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = false; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = false; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = false; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = false; + GetBox(MaterialNodeBoxes.Color).IsActive = false; + GetBox(MaterialNodeBoxes.Mask).IsActive = false; + GetBox(MaterialNodeBoxes.Emissive).IsActive = false; + GetBox(MaterialNodeBoxes.Metalness).IsActive = false; + GetBox(MaterialNodeBoxes.Specular).IsActive = false; + GetBox(MaterialNodeBoxes.Roughness).IsActive = false; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = false; + GetBox(MaterialNodeBoxes.Normal).IsActive = false; + GetBox(MaterialNodeBoxes.Opacity).IsActive = false; + GetBox(MaterialNodeBoxes.Refraction).IsActive = false; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = false; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = false; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = false; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = false; return; } @@ -102,94 +102,94 @@ namespace FlaxEditor.Surface.Archetypes bool isNotUnlit = info.ShadingModel != MaterialShadingModel.Unlit; bool withTess = info.TessellationMode != TessellationMethod.None; - GetBox(MaterialNodeBoxes.Color).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.Mask).Enabled = true; - GetBox(MaterialNodeBoxes.Emissive).Enabled = true; - GetBox(MaterialNodeBoxes.Metalness).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.Specular).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.Roughness).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.Normal).Enabled = isNotUnlit; - GetBox(MaterialNodeBoxes.Opacity).Enabled = info.ShadingModel == MaterialShadingModel.Subsurface || info.ShadingModel == MaterialShadingModel.Foliage || info.BlendMode != MaterialBlendMode.Opaque; - GetBox(MaterialNodeBoxes.Refraction).Enabled = info.BlendMode != MaterialBlendMode.Opaque; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = true; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = withTess; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = withTess; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = info.ShadingModel == MaterialShadingModel.Subsurface || info.ShadingModel == MaterialShadingModel.Foliage; + GetBox(MaterialNodeBoxes.Color).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.Mask).IsActive = true; + GetBox(MaterialNodeBoxes.Emissive).IsActive = true; + GetBox(MaterialNodeBoxes.Metalness).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.Specular).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.Roughness).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.Normal).IsActive = isNotUnlit; + GetBox(MaterialNodeBoxes.Opacity).IsActive = info.ShadingModel == MaterialShadingModel.Subsurface || info.ShadingModel == MaterialShadingModel.Foliage || info.BlendMode != MaterialBlendMode.Opaque; + GetBox(MaterialNodeBoxes.Refraction).IsActive = info.BlendMode != MaterialBlendMode.Opaque; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = true; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = withTess; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = withTess; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = info.ShadingModel == MaterialShadingModel.Subsurface || info.ShadingModel == MaterialShadingModel.Foliage; break; } case MaterialDomain.PostProcess: { - GetBox(MaterialNodeBoxes.Color).Enabled = false; - GetBox(MaterialNodeBoxes.Mask).Enabled = false; - GetBox(MaterialNodeBoxes.Emissive).Enabled = true; - GetBox(MaterialNodeBoxes.Metalness).Enabled = false; - GetBox(MaterialNodeBoxes.Specular).Enabled = false; - GetBox(MaterialNodeBoxes.Roughness).Enabled = false; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = false; - GetBox(MaterialNodeBoxes.Normal).Enabled = false; - GetBox(MaterialNodeBoxes.Opacity).Enabled = true; - GetBox(MaterialNodeBoxes.Refraction).Enabled = false; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = false; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = false; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = false; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = false; + GetBox(MaterialNodeBoxes.Color).IsActive = false; + GetBox(MaterialNodeBoxes.Mask).IsActive = false; + GetBox(MaterialNodeBoxes.Emissive).IsActive = true; + GetBox(MaterialNodeBoxes.Metalness).IsActive = false; + GetBox(MaterialNodeBoxes.Specular).IsActive = false; + GetBox(MaterialNodeBoxes.Roughness).IsActive = false; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = false; + GetBox(MaterialNodeBoxes.Normal).IsActive = false; + GetBox(MaterialNodeBoxes.Opacity).IsActive = true; + GetBox(MaterialNodeBoxes.Refraction).IsActive = false; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = false; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = false; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = false; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = false; break; } case MaterialDomain.Decal: { var mode = info.DecalBlendingMode; - GetBox(MaterialNodeBoxes.Color).Enabled = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Stain; - GetBox(MaterialNodeBoxes.Mask).Enabled = true; - GetBox(MaterialNodeBoxes.Emissive).Enabled = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Emissive; - GetBox(MaterialNodeBoxes.Metalness).Enabled = mode == MaterialDecalBlendingMode.Translucent; - GetBox(MaterialNodeBoxes.Specular).Enabled = mode == MaterialDecalBlendingMode.Translucent; - GetBox(MaterialNodeBoxes.Roughness).Enabled = mode == MaterialDecalBlendingMode.Translucent; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = false; - GetBox(MaterialNodeBoxes.Normal).Enabled = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Normal; - GetBox(MaterialNodeBoxes.Opacity).Enabled = true; - GetBox(MaterialNodeBoxes.Refraction).Enabled = false; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = false; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = false; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = false; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = false; + GetBox(MaterialNodeBoxes.Color).IsActive = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Stain; + GetBox(MaterialNodeBoxes.Mask).IsActive = true; + GetBox(MaterialNodeBoxes.Emissive).IsActive = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Emissive; + GetBox(MaterialNodeBoxes.Metalness).IsActive = mode == MaterialDecalBlendingMode.Translucent; + GetBox(MaterialNodeBoxes.Specular).IsActive = mode == MaterialDecalBlendingMode.Translucent; + GetBox(MaterialNodeBoxes.Roughness).IsActive = mode == MaterialDecalBlendingMode.Translucent; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = false; + GetBox(MaterialNodeBoxes.Normal).IsActive = mode == MaterialDecalBlendingMode.Translucent || mode == MaterialDecalBlendingMode.Normal; + GetBox(MaterialNodeBoxes.Opacity).IsActive = true; + GetBox(MaterialNodeBoxes.Refraction).IsActive = false; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = false; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = false; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = false; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = false; break; } case MaterialDomain.GUI: { - GetBox(MaterialNodeBoxes.Color).Enabled = false; - GetBox(MaterialNodeBoxes.Mask).Enabled = true; - GetBox(MaterialNodeBoxes.Emissive).Enabled = true; - GetBox(MaterialNodeBoxes.Metalness).Enabled = false; - GetBox(MaterialNodeBoxes.Specular).Enabled = false; - GetBox(MaterialNodeBoxes.Roughness).Enabled = false; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = false; - GetBox(MaterialNodeBoxes.Normal).Enabled = false; - GetBox(MaterialNodeBoxes.Opacity).Enabled = true; - GetBox(MaterialNodeBoxes.Refraction).Enabled = false; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = false; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = false; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = false; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = false; + GetBox(MaterialNodeBoxes.Color).IsActive = false; + GetBox(MaterialNodeBoxes.Mask).IsActive = true; + GetBox(MaterialNodeBoxes.Emissive).IsActive = true; + GetBox(MaterialNodeBoxes.Metalness).IsActive = false; + GetBox(MaterialNodeBoxes.Specular).IsActive = false; + GetBox(MaterialNodeBoxes.Roughness).IsActive = false; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = false; + GetBox(MaterialNodeBoxes.Normal).IsActive = false; + GetBox(MaterialNodeBoxes.Opacity).IsActive = true; + GetBox(MaterialNodeBoxes.Refraction).IsActive = false; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = false; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = false; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = false; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = false; break; } case MaterialDomain.VolumeParticle: { - GetBox(MaterialNodeBoxes.Color).Enabled = true; - GetBox(MaterialNodeBoxes.Mask).Enabled = true; - GetBox(MaterialNodeBoxes.Emissive).Enabled = true; - GetBox(MaterialNodeBoxes.Metalness).Enabled = false; - GetBox(MaterialNodeBoxes.Specular).Enabled = false; - GetBox(MaterialNodeBoxes.Roughness).Enabled = false; - GetBox(MaterialNodeBoxes.AmbientOcclusion).Enabled = false; - GetBox(MaterialNodeBoxes.Normal).Enabled = false; - GetBox(MaterialNodeBoxes.Opacity).Enabled = true; - GetBox(MaterialNodeBoxes.Refraction).Enabled = false; - GetBox(MaterialNodeBoxes.PositionOffset).Enabled = false; - GetBox(MaterialNodeBoxes.TessellationMultiplier).Enabled = false; - GetBox(MaterialNodeBoxes.WorldDisplacement).Enabled = false; - GetBox(MaterialNodeBoxes.SubsurfaceColor).Enabled = false; + GetBox(MaterialNodeBoxes.Color).IsActive = true; + GetBox(MaterialNodeBoxes.Mask).IsActive = true; + GetBox(MaterialNodeBoxes.Emissive).IsActive = true; + GetBox(MaterialNodeBoxes.Metalness).IsActive = false; + GetBox(MaterialNodeBoxes.Specular).IsActive = false; + GetBox(MaterialNodeBoxes.Roughness).IsActive = false; + GetBox(MaterialNodeBoxes.AmbientOcclusion).IsActive = false; + GetBox(MaterialNodeBoxes.Normal).IsActive = false; + GetBox(MaterialNodeBoxes.Opacity).IsActive = true; + GetBox(MaterialNodeBoxes.Refraction).IsActive = false; + GetBox(MaterialNodeBoxes.PositionOffset).IsActive = false; + GetBox(MaterialNodeBoxes.TessellationMultiplier).IsActive = false; + GetBox(MaterialNodeBoxes.WorldDisplacement).IsActive = false; + GetBox(MaterialNodeBoxes.SubsurfaceColor).IsActive = false; break; } default: throw new ArgumentOutOfRangeException(); diff --git a/Source/Editor/Surface/Archetypes/Math.cs b/Source/Editor/Surface/Archetypes/Math.cs index d0284d6fa..cdbcaac03 100644 --- a/Source/Editor/Surface/Archetypes/Math.cs +++ b/Source/Editor/Surface/Archetypes/Math.cs @@ -114,10 +114,10 @@ namespace FlaxEditor.Surface.Archetypes Op1(13, "Round", "Rounds A to the nearest integer"), Op1(14, "Saturate", "Clamps A to the range [0, 1]"), Op1(15, "Sine", "Returns sine of A"), - Op1(16, "Sqrt", "Returns square root of A", new [] { "Square Root", "Square", "Root" }), + Op1(16, "Sqrt", "Returns square root of A", new[] { "Square Root", "Square", "Root" }), Op1(17, "Tangent", "Returns tangent of A"), Op2(18, "Cross", "Returns the cross product of A and B", ConnectionsHint.None, typeof(Float3)), - Op2(19, "Distance", "Returns a distance scalar between A and B", new [] { "Magnitude", "Mag", "Length" }, ConnectionsHint.Vector, null, typeof(float), false), + Op2(19, "Distance", "Returns a distance scalar between A and B", new[] { "Magnitude", "Mag", "Length" }, ConnectionsHint.Vector, null, typeof(float), false), Op2(20, "Dot", "Returns the dot product of A and B", ConnectionsHint.Vector, null, typeof(float), false), Op2(21, "Max", "Selects the greater of A and B"), Op2(22, "Min", "Selects the lesser of A and B"), @@ -192,7 +192,7 @@ namespace FlaxEditor.Surface.Archetypes } }, // - Op1(27, "Negate", "Returns opposite value", new [] { "Invert" }), + Op1(27, "Negate", "Returns opposite value", new[] { "Invert" }), Op1(28, "One Minus", "Returns 1 - value"), // new NodeArchetype @@ -232,7 +232,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 31, Title = "Mad", - AlternativeTitles = new [] { "Multiply", "Add", "*+" }, + AlternativeTitles = new[] { "Multiply", "Add", "*+" }, Description = "Performs value multiplication and addition at once", Flags = NodeFlags.AllGraphs, Size = new Float2(160, 60), diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs index a995009ad..9dbfbce77 100644 --- a/Source/Editor/Surface/Archetypes/ParticleModules.cs +++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs @@ -399,7 +399,7 @@ namespace FlaxEditor.Surface.Archetypes private void UpdateInputBox() { var facingMode = (ParticleSpriteFacingMode)Values[2]; - GetBox(0).Enabled = facingMode == ParticleSpriteFacingMode.CustomFacingVector || facingMode == ParticleSpriteFacingMode.FixedAxis; + GetBox(0).IsActive = facingMode == ParticleSpriteFacingMode.CustomFacingVector || facingMode == ParticleSpriteFacingMode.FixedAxis; } } diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs index 0340eee2f..ee2bf4718 100644 --- a/Source/Editor/Surface/Archetypes/Tools.cs +++ b/Source/Editor/Surface/Archetypes/Tools.cs @@ -1032,7 +1032,8 @@ namespace FlaxEditor.Surface.Archetypes private Rectangle _localBounds; private InputBox _input; private OutputBox _output; - private bool _isMouseDown, _isConnecting; + private bool _isMouseDown, _isConnecting, _isMouseInConnectingBounds; + private const float ConnectingBounds = -12.0f; /// public RerouteNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) @@ -1170,7 +1171,7 @@ namespace FlaxEditor.Surface.Archetypes if (button == MouseButton.Left) { _isMouseDown = true; - _isConnecting = _localBounds.MakeExpanded(-10.0f).Contains(ref location); // Inner area for connecting, outer area for moving + _isConnecting = _isMouseInConnectingBounds; if (_isConnecting) { Focus(); @@ -1189,12 +1190,22 @@ namespace FlaxEditor.Surface.Archetypes if (Surface.CanEdit && _isConnecting) Surface.ConnectingStart(this); } + + _isMouseInConnectingBounds = false; + Cursor = CursorType.Default; + base.OnMouseLeave(); } /// public override void OnMouseMove(Float2 location) { + _isMouseInConnectingBounds = IsMouseOver && _localBounds.MakeExpanded(ConnectingBounds).Contains(ref location); // Inner area for connecting, outer area for moving + if (!_isMouseInConnectingBounds && !_isMouseDown) + Cursor = CursorType.SizeAll; + else + Cursor = CursorType.Default; + Surface.ConnectingOver(this); base.OnMouseMove(location); } @@ -1483,7 +1494,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 11, Title = "Comment", - AlternativeTitles = new[] { "//" , "Group" }, + AlternativeTitles = new[] { "//", "Group" }, TryParseText = (string filterText, out object[] data) => { data = null; @@ -1639,7 +1650,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 22, Title = "As", - AlternativeTitles = new [] { "Cast" }, + AlternativeTitles = new[] { "Cast" }, Create = (id, context, arch, groupArch) => new AsNode(id, context, arch, groupArch), Description = "Casts the object to a different type. Returns null if cast fails.", Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph, diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index 19ddcd294..ae4cef3dc 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -307,7 +307,10 @@ namespace FlaxEditor.Surface.ContextMenu if (!IsLayoutLocked) { group.UnlockChildrenRecursive(); - SortGroups(); + if (_contextSensitiveSearchEnabled && _selectedBox != null) + UpdateFilters(); + else + SortGroups(); if (ShowExpanded) group.Open(false); group.PerformLayout(); @@ -367,7 +370,10 @@ namespace FlaxEditor.Surface.ContextMenu if (!isLayoutLocked) { - SortGroups(); + if (_contextSensitiveSearchEnabled && _selectedBox != null) + UpdateFilters(); + else + SortGroups(); Profiler.BeginEvent("Perform Layout"); UnlockChildrenRecursive(); foreach (var group in groups) @@ -482,10 +488,11 @@ namespace FlaxEditor.Surface.ContextMenu // Update groups LockChildrenRecursive(); + var contextSensitiveSelectedBox = _contextSensitiveSearchEnabled ? _selectedBox : null; for (int i = 0; i < _groups.Count; i++) { - _groups[i].UpdateFilter(_searchBox.Text, _contextSensitiveSearchEnabled ? _selectedBox : null); - _groups[i].UpdateItemSort(_selectedBox); + _groups[i].UpdateFilter(_searchBox.Text, contextSensitiveSelectedBox); + _groups[i].UpdateItemSort(contextSensitiveSelectedBox); } SortGroups(); UnlockChildrenRecursive(); @@ -560,7 +567,10 @@ namespace FlaxEditor.Surface.ContextMenu } UnlockChildrenRecursive(); - SortGroups(); + if (_contextSensitiveSearchEnabled && _selectedBox != null) + UpdateFilters(); + else + SortGroups(); PerformLayout(); Profiler.EndEvent(); diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMGroup.cs b/Source/Editor/Surface/ContextMenu/VisjectCMGroup.cs index 2e82bdf50..d8cf0433f 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMGroup.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMGroup.cs @@ -89,6 +89,25 @@ namespace FlaxEditor.Surface.ContextMenu { Profiler.BeginEvent("VisjectCMGroup.UpdateFilter"); + // Check if a dot is inside the filter text and split the string accordingly. + // Everything in front of the dot is for specifying a class/group name. And everything afterward is the actual item filter text + if (!string.IsNullOrEmpty(filterText)) + { + int dotIndex = filterText.IndexOf('.'); + if (dotIndex != -1) + { + // Early out and make the group invisible if it doesn't start with the specified string + string filterGroupName = filterText.Substring(0, dotIndex); + if (!Name.StartsWith(filterGroupName, StringComparison.InvariantCultureIgnoreCase)) + { + Visible = false; + Profiler.EndEvent(); + return; + } + filterText = filterText.Substring(dotIndex + 1); + } + } + // Update items bool isAnyVisible = false; bool groupHeaderMatches = QueryFilterHelper.Match(filterText, HeaderText); @@ -177,6 +196,13 @@ namespace FlaxEditor.Surface.ContextMenu SortScore = item.SortScore; } } + + if (selectedBox != null) + { + if (string.Equals(Name, selectedBox.CurrentType.Name, StringComparison.InvariantCultureIgnoreCase)) + SortScore += 10; + } + SortChildren(); Profiler.EndEvent(); diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index bffb0e7e3..9d582c491 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -219,7 +219,7 @@ namespace FlaxEditor.Surface.ContextMenu } // Check archetype synonyms - if (_archetype.AlternativeTitles!= null && _archetype.AlternativeTitles.Any(altTitle => QueryFilterHelper.Match(filterText, altTitle, out ranges))) + if (_archetype.AlternativeTitles != null && _archetype.AlternativeTitles.Any(altTitle => QueryFilterHelper.Match(filterText, altTitle, out ranges))) { // Update highlights if (_highlights == null) diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs index 90022f482..eca1e15af 100644 --- a/Source/Editor/Surface/Elements/Box.cs +++ b/Source/Editor/Surface/Elements/Box.cs @@ -41,6 +41,11 @@ namespace FlaxEditor.Surface.Elements /// protected bool _isSelected; + /// + /// The is active flag for the box. Unlike , inactive boxes can still be interacted with, they just will be drawn like disabled boxes + /// + protected bool _isActive = true; + /// /// Unique box ID within single node. /// @@ -180,6 +185,15 @@ namespace FlaxEditor.Surface.Elements } } + /// + /// Gets or sets the active state of the box. Unlike , inactive boxes can still be interacted with, they just will be drawn like disabled boxes + /// + public bool IsActive + { + get => _isActive; + set => _isActive = value; + } + /// protected Box(SurfaceNode parentNode, NodeElementArchetype archetype, Float2 location) : base(parentNode, archetype, location, new Float2(Constants.BoxSize), false) diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs index 555b0ae4e..d60e283f4 100644 --- a/Source/Editor/Surface/Elements/OutputBox.cs +++ b/Source/Editor/Surface/Elements/OutputBox.cs @@ -3,6 +3,7 @@ using FlaxEngine; using FlaxEngine.GUI; using System; +using FlaxEditor.Options; namespace FlaxEditor.Surface.Elements { @@ -57,8 +58,8 @@ namespace FlaxEditor.Surface.Elements private static void CalculateBezierControlPoints(Float2 start, Float2 end, out Float2 control1, out Float2 control2) { // Control points parameters - const float minControlLength = 100f; - const float maxControlLength = 150f; + const float minControlLength = 50f; + const float maxControlLength = 120f; var dst = (end - start).Length; var yDst = Mathf.Abs(start.Y - end.Y); @@ -66,6 +67,7 @@ namespace FlaxEditor.Surface.Elements var minControlDst = dst * 0.5f; var maxControlDst = Mathf.Max(Mathf.Min(maxControlLength, dst), minControlLength); var controlDst = Mathf.Lerp(minControlDst, maxControlDst, Mathf.Clamp(yDst / minControlLength, 0f, 1f)); + controlDst *= Editor.Instance.Options.Options.Interface.ConnectionCurvature; control1 = new Float2(start.X + controlDst, start.Y); control2 = new Float2(end.X - controlDst, end.Y); @@ -152,7 +154,8 @@ namespace FlaxEditor.Surface.Elements Box targetBox = Connections[i]; var endPos = targetBox.ConnectionOrigin; var highlight = 1 + Mathf.Max(startHighlight, targetBox.ConnectionsHighlightIntensity); - var color = _currentTypeColor * highlight; + var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f; + var color = _currentTypeColor * highlight * alpha; // TODO: Figure out how to only draw the topmost connection if (IntersectsConnection(ref startPos, ref endPos, ref mousePosition, mouseOverDistance)) @@ -172,7 +175,9 @@ namespace FlaxEditor.Surface.Elements // Draw all the connections var startPos = ConnectionOrigin; var endPos = targetBox.ConnectionOrigin; - DrawConnection(Surface.Style, ref startPos, ref endPos, ref _currentTypeColor, 2.5f); + var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f; + var color = _currentTypeColor * alpha; + DrawConnection(Surface.Style, ref startPos, ref endPos, ref color, 2.5f); } /// diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs index f5179ba9a..86b68da4e 100644 --- a/Source/Editor/Surface/SurfaceComment.cs +++ b/Source/Editor/Surface/SurfaceComment.cs @@ -20,12 +20,18 @@ namespace FlaxEditor.Surface private Rectangle _colorButtonRect; private Rectangle _resizeButtonRect; private Float2 _startResizingSize; + private readonly TextBox _renameTextBox; /// /// True if sizing tool is in use. /// protected bool _isResizing; + /// + /// True if rename textbox is active in order to rename comment + /// + protected bool _isRenaming; + /// /// Gets or sets the color of the comment. /// @@ -63,6 +69,13 @@ namespace FlaxEditor.Surface public SurfaceComment(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) : base(id, context, nodeArch, groupArch) { + _renameTextBox = new TextBox(false, 0, 0, Width) + { + Height = Constants.NodeHeaderSize, + Visible = false, + Parent = this, + EndEditOnClick = false, // We have to handle this ourselves, otherwise the textbox instantly loses focus when double-clicking the header + }; } /// @@ -83,7 +96,7 @@ namespace FlaxEditor.Surface IndexInParent = 0; OrderValue = IndexInParent; } - else if(OrderValue != -1) + else if (OrderValue != -1) { IndexInParent = OrderValue; } @@ -97,7 +110,7 @@ namespace FlaxEditor.Surface // Randomize color Color = ColorValue = Color.FromHSV(new Random().NextFloat(0, 360), 0.7f, 0.25f, 0.8f); - if(OrderValue == -1) + if (OrderValue == -1) OrderValue = Context.CommentCount - 1; IndexInParent = OrderValue; } @@ -149,6 +162,20 @@ namespace FlaxEditor.Surface _closeButtonRect = new Rectangle(Width - buttonSize - buttonMargin, buttonMargin, buttonSize, buttonSize); _colorButtonRect = new Rectangle(_closeButtonRect.Left - buttonSize - buttonMargin, buttonMargin, buttonSize, buttonSize); _resizeButtonRect = new Rectangle(_closeButtonRect.Left, Height - buttonSize - buttonMargin, buttonSize, buttonSize); + _renameTextBox.Width = Width; + _renameTextBox.Height = headerSize; + } + + /// + public override void Update(float deltaTime) + { + if (_isRenaming && (!_renameTextBox.IsFocused || !RootWindow.IsFocused)) + { + Rename(_renameTextBox.Text); + StopRenaming(); + } + + base.Update(deltaTime); } /// @@ -158,7 +185,7 @@ namespace FlaxEditor.Surface var color = Color; var backgroundRect = new Rectangle(Float2.Zero, Size); var headerColor = new Color(Mathf.Clamp(color.R, 0.1f, 0.3f), Mathf.Clamp(color.G, 0.1f, 0.3f), Mathf.Clamp(color.B, 0.1f, 0.3f), 0.4f); - if (IsSelected) + if (IsSelected && !_isRenaming) headerColor *= 2.0f; // Paint background @@ -169,7 +196,8 @@ namespace FlaxEditor.Surface // Header Render2D.FillRectangle(_headerRect, headerColor); - Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center); + if (!_isRenaming) + Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center); // Close button Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); @@ -213,6 +241,13 @@ namespace FlaxEditor.Surface EndResizing(); } + // Check if was renaming + if (_isRenaming) + { + Rename(_renameTextBox.Text); + StopRenaming(); + } + // Base base.OnLostFocus(); } @@ -294,17 +329,47 @@ namespace FlaxEditor.Surface /// public void StartRenaming() { - Surface.Select(this); - var dialog = RenamePopup.Show(this, _headerRect, Title, false); - dialog.Renamed += OnRenamed; + _isRenaming = true; + _renameTextBox.Visible = true; + _renameTextBox.SetText(Title); + _renameTextBox.Focus(); + _renameTextBox.SelectAll(); } - private void OnRenamed(RenamePopup renamePopup) + private void StopRenaming() { - Title = TitleValue = renamePopup.Text; + _isRenaming = false; + _renameTextBox.Visible = false; + } + + private void Rename(string newTitle) + { + if (string.Equals(Title, newTitle, StringComparison.Ordinal)) + return; + + Title = TitleValue = newTitle; Surface.MarkAsEdited(false); } + /// + public override bool OnKeyDown(KeyboardKeys key) + { + if (key == KeyboardKeys.Return) + { + Rename(_renameTextBox.Text); + StopRenaming(); + return true; + } + + if (key == KeyboardKeys.Escape) + { + StopRenaming(); + return true; + } + + return base.OnKeyDown(key); + } + /// public override bool OnMouseUp(Float2 location, MouseButton button) { @@ -350,18 +415,18 @@ namespace FlaxEditor.Surface { cmOrder.ContextMenu.AddButton("Bring Forward", () => { - if(IndexInParent < Context.CommentCount-1) + if (IndexInParent < Context.CommentCount - 1) IndexInParent++; OrderValue = IndexInParent; }); cmOrder.ContextMenu.AddButton("Bring to Front", () => { - IndexInParent = Context.CommentCount-1; + IndexInParent = Context.CommentCount - 1; OrderValue = IndexInParent; }); cmOrder.ContextMenu.AddButton("Send Backward", () => { - if(IndexInParent > 0) + if (IndexInParent > 0) IndexInParent--; OrderValue = IndexInParent; }); diff --git a/Source/Editor/Surface/SurfaceStyle.cs b/Source/Editor/Surface/SurfaceStyle.cs index d91b81089..f4db6dfa2 100644 --- a/Source/Editor/Surface/SurfaceStyle.cs +++ b/Source/Editor/Surface/SurfaceStyle.cs @@ -228,7 +228,7 @@ namespace FlaxEditor.Surface // Draw icon bool hasConnections = box.HasAnyConnection; - float alpha = box.Enabled ? 1.0f : 0.6f; + float alpha = box.Enabled && box.IsActive ? 1.0f : 0.6f; Color color = box.CurrentTypeColor * alpha; var style = box.Surface.Style; SpriteHandle icon; diff --git a/Source/Editor/Utilities/DuplicateScenes.cs b/Source/Editor/Utilities/DuplicateScenes.cs index dc2d5e4bb..37b5bf824 100644 --- a/Source/Editor/Utilities/DuplicateScenes.cs +++ b/Source/Editor/Utilities/DuplicateScenes.cs @@ -36,7 +36,10 @@ namespace FlaxEditor.Utilities public void GatherSceneData() { if (HasData) - throw new InvalidOperationException("DuplicateScenes has already gathered scene data."); + { + Editor.LogError("DuplicateScenes has already gathered scene data."); + return; + } Profiler.BeginEvent("DuplicateScenes.GatherSceneData"); Editor.Log("Collecting scene data"); @@ -47,7 +50,8 @@ namespace FlaxEditor.Utilities if (scenesCount == 0) { Profiler.EndEvent(); - throw new InvalidOperationException("Cannot gather scene data. No scene loaded."); + Editor.LogWarning("Cannot gather scene data. No scene loaded."); + return; } var sceneIds = new Guid[scenesCount]; for (int i = 0; i < scenesCount; i++) @@ -72,7 +76,8 @@ namespace FlaxEditor.Utilities if (Level.UnloadAllScenes()) { Profiler.EndEvent(); - throw new Exception("Failed to unload scenes."); + Editor.LogError("Failed to unload scenes."); + return; } FlaxEngine.Scripting.FlushRemovedObjects(); @@ -82,7 +87,8 @@ namespace FlaxEditor.Utilities if (noScenes != null && noScenes.Length != 0) { Profiler.EndEvent(); - throw new Exception("Failed to unload scenes."); + Editor.LogError("Failed to unload scenes."); + return; } } @@ -96,7 +102,10 @@ namespace FlaxEditor.Utilities public void CreateScenes() { if (!HasData) - throw new InvalidOperationException("DuplicateScenes has not gathered scene data yet."); + { + Editor.LogError("DuplicateScenes has not gathered scene data yet."); + return; + } Profiler.BeginEvent("DuplicateScenes.CreateScenes"); Editor.Log("Creating scenes"); @@ -110,7 +119,8 @@ namespace FlaxEditor.Utilities if (scene == null) { Profiler.EndEvent(); - throw new Exception("Failed to deserialize scene"); + Editor.LogError("Failed to deserialize scene."); + return; } } @@ -131,7 +141,8 @@ namespace FlaxEditor.Utilities if (Level.UnloadAllScenes()) { Profiler.EndEvent(); - throw new Exception("Failed to unload scenes."); + Editor.LogError("Failed to unload scenes."); + return; } FlaxEngine.Scripting.FlushRemovedObjects(); Editor.WipeOutLeftoverSceneObjects(); @@ -145,7 +156,10 @@ namespace FlaxEditor.Utilities public void RestoreSceneData() { if (!HasData) - throw new InvalidOperationException("DuplicateScenes has not gathered scene data yet."); + { + Editor.LogError("DuplicateScenes has not gathered scene data yet."); + return; + } Profiler.BeginEvent("DuplicateScenes.RestoreSceneData"); // Deserialize old scenes diff --git a/Source/Editor/Viewport/EditorGizmoViewport.cs b/Source/Editor/Viewport/EditorGizmoViewport.cs index df0f7a8ff..f0681e48d 100644 --- a/Source/Editor/Viewport/EditorGizmoViewport.cs +++ b/Source/Editor/Viewport/EditorGizmoViewport.cs @@ -137,19 +137,19 @@ namespace FlaxEditor.Viewport if (useProjectCache) { // Initialize snapping enabled from cached values - if (editor.ProjectCache.TryGetCustomData("TranslateSnapState", out var cachedState)) - transformGizmo.TranslationSnapEnable = bool.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedState)) - transformGizmo.RotationSnapEnabled = bool.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("ScaleSnapState", out cachedState)) - transformGizmo.ScaleSnapEnabled = bool.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("TranslateSnapValue", out cachedState)) - transformGizmo.TranslationSnapValue = float.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("RotationSnapValue", out cachedState)) - transformGizmo.RotationSnapValue = float.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("ScaleSnapValue", out cachedState)) - transformGizmo.ScaleSnapValue = float.Parse(cachedState); - if (editor.ProjectCache.TryGetCustomData("TransformSpaceState", out cachedState) && Enum.TryParse(cachedState, out TransformGizmoBase.TransformSpace space)) + if (editor.ProjectCache.TryGetCustomData("TranslateSnapState", out bool cachedBool)) + transformGizmo.TranslationSnapEnable = cachedBool; + if (editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedBool)) + transformGizmo.RotationSnapEnabled = cachedBool; + if (editor.ProjectCache.TryGetCustomData("ScaleSnapState", out cachedBool)) + transformGizmo.ScaleSnapEnabled = cachedBool; + if (editor.ProjectCache.TryGetCustomData("TranslateSnapValue", out float cachedFloat)) + transformGizmo.TranslationSnapValue = cachedFloat; + if (editor.ProjectCache.TryGetCustomData("RotationSnapValue", out cachedFloat)) + transformGizmo.RotationSnapValue = cachedFloat; + if (editor.ProjectCache.TryGetCustomData("ScaleSnapValue", out cachedFloat)) + transformGizmo.ScaleSnapValue = cachedFloat; + if (editor.ProjectCache.TryGetCustomData("TransformSpaceState", out string cachedText) && Enum.TryParse(cachedText, out TransformGizmoBase.TransformSpace space)) transformGizmo.ActiveTransformSpace = space; } @@ -181,7 +181,7 @@ namespace FlaxEditor.Viewport { transformGizmo.ScaleSnapEnabled = !transformGizmo.ScaleSnapEnabled; if (useProjectCache) - editor.ProjectCache.SetCustomData("ScaleSnapState", transformGizmo.ScaleSnapEnabled.ToString()); + editor.ProjectCache.SetCustomData("ScaleSnapState", transformGizmo.ScaleSnapEnabled); }; var scaleSnappingCM = new ContextMenu(); var scaleSnapping = new ViewportWidgetButton(transformGizmo.ScaleSnapValue.ToString(), SpriteHandle.Invalid, scaleSnappingCM) @@ -200,7 +200,7 @@ namespace FlaxEditor.Viewport transformGizmo.ScaleSnapValue = v; scaleSnapping.Text = v.ToString(); if (useProjectCache) - editor.ProjectCache.SetCustomData("ScaleSnapValue", transformGizmo.ScaleSnapValue.ToString("N")); + editor.ProjectCache.SetCustomData("ScaleSnapValue", transformGizmo.ScaleSnapValue); }; scaleSnappingCM.VisibleChanged += control => { @@ -231,7 +231,7 @@ namespace FlaxEditor.Viewport { transformGizmo.RotationSnapEnabled = !transformGizmo.RotationSnapEnabled; if (useProjectCache) - editor.ProjectCache.SetCustomData("RotationSnapState", transformGizmo.RotationSnapEnabled.ToString()); + editor.ProjectCache.SetCustomData("RotationSnapState", transformGizmo.RotationSnapEnabled); }; var rotateSnappingCM = new ContextMenu(); var rotateSnapping = new ViewportWidgetButton(transformGizmo.RotationSnapValue.ToString(), SpriteHandle.Invalid, rotateSnappingCM) @@ -250,7 +250,7 @@ namespace FlaxEditor.Viewport transformGizmo.RotationSnapValue = v; rotateSnapping.Text = v.ToString(); if (useProjectCache) - editor.ProjectCache.SetCustomData("RotationSnapValue", transformGizmo.RotationSnapValue.ToString("N")); + editor.ProjectCache.SetCustomData("RotationSnapValue", transformGizmo.RotationSnapValue); }; rotateSnappingCM.VisibleChanged += control => { @@ -281,7 +281,7 @@ namespace FlaxEditor.Viewport { transformGizmo.TranslationSnapEnable = !transformGizmo.TranslationSnapEnable; if (useProjectCache) - editor.ProjectCache.SetCustomData("TranslateSnapState", transformGizmo.TranslationSnapEnable.ToString()); + editor.ProjectCache.SetCustomData("TranslateSnapState", transformGizmo.TranslationSnapEnable); }; var translateSnappingCM = new ContextMenu(); var translateSnapping = new ViewportWidgetButton(transformGizmo.TranslationSnapValue.ToString(), SpriteHandle.Invalid, translateSnappingCM) @@ -307,7 +307,7 @@ namespace FlaxEditor.Viewport else translateSnapping.Text = v.ToString(); if (useProjectCache) - editor.ProjectCache.SetCustomData("TranslateSnapValue", transformGizmo.TranslationSnapValue.ToString("N")); + editor.ProjectCache.SetCustomData("TranslateSnapValue", transformGizmo.TranslationSnapValue); }; translateSnappingCM.VisibleChanged += control => { diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index 1e24560d8..c7b845c89 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -540,30 +540,30 @@ namespace FlaxEditor.Viewport } // Initialize camera values from cache - if (_editor.ProjectCache.TryGetCustomData("CameraMovementSpeedValue", out var cachedState)) - MovementSpeed = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraMinMovementSpeedValue", out cachedState)) - _minMovementSpeed = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraMaxMovementSpeedValue", out cachedState)) - _maxMovementSpeed = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("UseCameraEasingState", out cachedState)) - _useCameraEasing = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraPanningSpeedValue", out cachedState)) - _panningSpeed = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraInvertPanningState", out cachedState)) - _invertPanning = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraRelativePanningState", out cachedState)) - _relativePanning = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicState", out cachedState)) - _isOrtho = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicSizeValue", out cachedState)) - _orthoSize = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraFieldOfViewValue", out cachedState)) - _fieldOfView = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraNearPlaneValue", out cachedState)) - _nearPlane = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("CameraFarPlaneValue", out cachedState)) - _farPlane = float.Parse(cachedState); + if (_editor.ProjectCache.TryGetCustomData("CameraMovementSpeedValue", out float cachedFloat)) + MovementSpeed = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraMinMovementSpeedValue", out cachedFloat)) + _minMovementSpeed = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraMaxMovementSpeedValue", out cachedFloat)) + _maxMovementSpeed = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("UseCameraEasingState", out bool cachedBool)) + _useCameraEasing = cachedBool; + if (_editor.ProjectCache.TryGetCustomData("CameraPanningSpeedValue", out cachedFloat)) + _panningSpeed = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraInvertPanningState", out cachedBool)) + _invertPanning = cachedBool; + if (_editor.ProjectCache.TryGetCustomData("CameraRelativePanningState", out cachedBool)) + _relativePanning = cachedBool; + if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicState", out cachedBool)) + _isOrtho = cachedBool; + if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicSizeValue", out cachedFloat)) + _orthoSize = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraFieldOfViewValue", out cachedFloat)) + _fieldOfView = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraNearPlaneValue", out cachedFloat)) + _nearPlane = cachedFloat; + if (_editor.ProjectCache.TryGetCustomData("CameraFarPlaneValue", out cachedFloat)) + _farPlane = cachedFloat; OnCameraMovementProgressChanged(); @@ -1041,7 +1041,7 @@ namespace FlaxEditor.Viewport MovementSpeed = value; OnCameraMovementProgressChanged(); - _editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed.ToString()); + _editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed); } private void OnMinMovementSpeedChanged(FloatValueBox control) @@ -1053,7 +1053,7 @@ namespace FlaxEditor.Viewport MovementSpeed = value; OnCameraMovementProgressChanged(); - _editor.ProjectCache.SetCustomData("CameraMinMovementSpeedValue", _minMovementSpeed.ToString()); + _editor.ProjectCache.SetCustomData("CameraMinMovementSpeedValue", _minMovementSpeed); } private void OnMaxMovementSpeedChanged(FloatValueBox control) @@ -1065,7 +1065,7 @@ namespace FlaxEditor.Viewport MovementSpeed = value; OnCameraMovementProgressChanged(); - _editor.ProjectCache.SetCustomData("CameraMaxMovementSpeedValue", _maxMovementSpeed.ToString()); + _editor.ProjectCache.SetCustomData("CameraMaxMovementSpeedValue", _maxMovementSpeed); } private void OnCameraEasingToggled(Control control) @@ -1073,25 +1073,25 @@ namespace FlaxEditor.Viewport _useCameraEasing = !_useCameraEasing; OnCameraMovementProgressChanged(); - _editor.ProjectCache.SetCustomData("UseCameraEasingState", _useCameraEasing.ToString()); + _editor.ProjectCache.SetCustomData("UseCameraEasingState", _useCameraEasing); } private void OnPanningSpeedChanged(FloatValueBox control) { _panningSpeed = control.Value; - _editor.ProjectCache.SetCustomData("CameraPanningSpeedValue", _panningSpeed.ToString()); + _editor.ProjectCache.SetCustomData("CameraPanningSpeedValue", _panningSpeed); } private void OnRelativePanningToggled(Control control) { _relativePanning = !_relativePanning; - _editor.ProjectCache.SetCustomData("CameraRelativePanningState", _relativePanning.ToString()); + _editor.ProjectCache.SetCustomData("CameraRelativePanningState", _relativePanning); } private void OnInvertPanningToggled(Control control) { _invertPanning = !_invertPanning; - _editor.ProjectCache.SetCustomData("CameraInvertPanningState", _invertPanning.ToString()); + _editor.ProjectCache.SetCustomData("CameraInvertPanningState", _invertPanning); } @@ -1104,7 +1104,7 @@ namespace FlaxEditor.Viewport private void OnFieldOfViewChanged(FloatValueBox control) { _fieldOfView = control.Value; - _editor.ProjectCache.SetCustomData("CameraFieldOfViewValue", _fieldOfView.ToString()); + _editor.ProjectCache.SetCustomData("CameraFieldOfViewValue", _fieldOfView); } private void OnOrthographicModeToggled(Control control) @@ -1120,25 +1120,25 @@ namespace FlaxEditor.Viewport OrientViewport(ref orient); } - _editor.ProjectCache.SetCustomData("CameraOrthographicState", _isOrtho.ToString()); + _editor.ProjectCache.SetCustomData("CameraOrthographicState", _isOrtho); } private void OnOrthographicSizeChanged(FloatValueBox control) { _orthoSize = control.Value; - _editor.ProjectCache.SetCustomData("CameraOrthographicSizeValue", _orthoSize.ToString()); + _editor.ProjectCache.SetCustomData("CameraOrthographicSizeValue", _orthoSize); } private void OnNearPlaneChanged(FloatValueBox control) { _nearPlane = control.Value; - _editor.ProjectCache.SetCustomData("CameraNearPlaneValue", _nearPlane.ToString()); + _editor.ProjectCache.SetCustomData("CameraNearPlaneValue", _nearPlane); } private void OnFarPlaneChanged(FloatValueBox control) { _farPlane = control.Value; - _editor.ProjectCache.SetCustomData("CameraFarPlaneValue", _farPlane.ToString()); + _editor.ProjectCache.SetCustomData("CameraFarPlaneValue", _farPlane); } /// @@ -1217,7 +1217,7 @@ namespace FlaxEditor.Viewport var speed = Mathf.Lerp(_minMovementSpeed, _maxMovementSpeed, progress); MovementSpeed = (float)Math.Round(speed, 3); - _editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed.ToString()); + _editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed); } private void OnEditorOptionsChanged(EditorOptions options) diff --git a/Source/Editor/Windows/Assets/VisualScriptWindow.cs b/Source/Editor/Windows/Assets/VisualScriptWindow.cs index 3c4cce68d..4a2cb74cf 100644 --- a/Source/Editor/Windows/Assets/VisualScriptWindow.cs +++ b/Source/Editor/Windows/Assets/VisualScriptWindow.cs @@ -1027,7 +1027,7 @@ namespace FlaxEditor.Windows.Assets try { // Try to restore the cached breakpoints from the last session - if (Editor.ProjectCache.TryGetCustomData(_asset.ScriptTypeName + ".Breakpoints", out var breakpointsData)) + if (Editor.ProjectCache.TryGetCustomData(_asset.ScriptTypeName + ".Breakpoints", out string breakpointsData)) { var data = JsonSerializer.Deserialize(breakpointsData); if (data != null) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index c147579f9..8d60036cb 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -1068,7 +1068,7 @@ namespace FlaxEditor.Windows PerformLayout(); // Load last viewed folder - if (Editor.ProjectCache.TryGetCustomData(ProjectDataLastViewedFolder, out var lastViewedFolder)) + if (Editor.ProjectCache.TryGetCustomData(ProjectDataLastViewedFolder, out string lastViewedFolder)) { if (Editor.ContentDatabase.Find(lastViewedFolder) is ContentFolder folder) _tree.Select(folder.Node); diff --git a/Source/Editor/Windows/DebugLogWindow.cs b/Source/Editor/Windows/DebugLogWindow.cs index fe26f80aa..12a2553c3 100644 --- a/Source/Editor/Windows/DebugLogWindow.cs +++ b/Source/Editor/Windows/DebugLogWindow.cs @@ -328,7 +328,10 @@ namespace FlaxEditor.Windows }; toolstrip.AddButton("Clear", Clear).LinkTooltip("Clears all log entries"); _clearOnPlayButton = (ToolStripButton)toolstrip.AddButton("Clear on Play").SetAutoCheck(true).SetChecked(true).LinkTooltip("Clears all log entries on enter playmode"); - _collapseLogsButton = (ToolStripButton)toolstrip.AddButton("Collapse").SetAutoCheck(true).SetChecked(true).LinkTooltip("Collapses similar logs."); + bool collapse = true; + if (Editor.ProjectCache.TryGetCustomData("DebugLogCollapse", out bool setCollapse)) + collapse = setCollapse; + _collapseLogsButton = (ToolStripButton)toolstrip.AddButton("Collapse", () => Editor.ProjectCache.SetCustomData("DebugLogCollapse", _collapseLogsButton.Checked.ToString())).SetAutoCheck(true).SetChecked(collapse).LinkTooltip("Collapses similar logs."); _pauseOnErrorButton = (ToolStripButton)toolstrip.AddButton("Pause on Error").SetAutoCheck(true).LinkTooltip("Performs auto pause on error"); toolstrip.AddSeparator(); _groupButtons[0] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Error32, () => UpdateLogTypeVisibility(LogGroup.Error, _groupButtons[0].Checked)).SetAutoCheck(true).SetChecked(true).LinkTooltip("Shows/hides error messages"); diff --git a/Source/Editor/Windows/GraphicsQualityWindow.cs b/Source/Editor/Windows/GraphicsQualityWindow.cs index a1b6b3eab..9c194c17d 100644 --- a/Source/Editor/Windows/GraphicsQualityWindow.cs +++ b/Source/Editor/Windows/GraphicsQualityWindow.cs @@ -168,7 +168,7 @@ namespace FlaxEditor.Windows /// public override void OnInit() { - if (Editor.ProjectCache.TryGetCustomData(_optionsName, out var options) && !string.IsNullOrEmpty(options)) + if (Editor.ProjectCache.TryGetCustomData(_optionsName, out string options) && !string.IsNullOrEmpty(options)) { // Load cached settings JsonSerializer.Deserialize(_viewModel, options); diff --git a/Source/Engine/Debug/DebugDraw.cs b/Source/Engine/Debug/DebugDraw.cs index c3e6f8990..62843428f 100644 --- a/Source/Engine/Debug/DebugDraw.cs +++ b/Source/Engine/Debug/DebugDraw.cs @@ -279,6 +279,64 @@ namespace FlaxEngine public static void DrawBox(OrientedBoundingBox box, Color color, float duration = 0.0f, bool depthTest = true) { } + + /// + /// Draws the arc. + /// + /// The center position. + /// The orientation. + /// The radius. + /// The angle (in radians) of the arc (arc is facing positive Z axis - forward). Use PI*2 for full disc (360 degrees). + /// The color. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawArc(Vector3 position, Quaternion orientation, float radius, float angle, Color color, float duration = 0.0f, bool depthTest = true) + { + } + + /// + /// Draws the wireframe arc. + /// + /// The center position. + /// The orientation. + /// The radius. + /// The angle (in radians) of the arc (arc is facing positive Z axis - forward). Use PI*2 for full disc (360 degrees). + /// The color. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawWireArc(Vector3 position, Quaternion orientation, float radius, float angle, Color color, float duration = 0.0f, bool depthTest = true) + { + } + + /// + /// Draws the cone. + /// + /// The center position. + /// The orientation. + /// The radius. + /// The angle (in radians) of the cone over the XY axis (cone forward is over X). + /// The angle (in radians) of the cone over the XZ axis (cone forward is over X). + /// The color. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawCone(Vector3 position, Quaternion orientation, float radius, float angleXY, float angleXZ, Color color, float duration = 0.0f, bool depthTest = true) + { + } + + /// + /// Draws the wireframe cone. + /// + /// The center position. + /// The orientation. + /// The radius. + /// The angle (in radians) of the cone over the XY axis (cone forward is over X). + /// The angle (in radians) of the cone over the XZ axis (cone forward is over X). + /// The color. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawWireCone(Vector3 position, Quaternion orientation, float radius, float angleXY, float angleXZ, Color color, float duration = 0.0f, bool depthTest = true) + { + } } } #endif diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index cb925a206..4462251c5 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -937,7 +937,7 @@ void Actor::EndPlay() } // Cleanup managed object - DestroyManaged(); + //DestroyManaged(); if (IsRegistered()) UnregisterObject(); } diff --git a/Source/Engine/Scripting/Script.cpp b/Source/Engine/Scripting/Script.cpp index 4f467ef4d..5bee98436 100644 --- a/Source/Engine/Scripting/Script.cpp +++ b/Source/Engine/Scripting/Script.cpp @@ -313,7 +313,7 @@ void Script::EndPlay() Flags &= ~ObjectFlags::IsDuringPlay; // Cleanup managed object - DestroyManaged(); + //DestroyManaged(); if (IsRegistered()) UnregisterObject(); } diff --git a/Source/Engine/UI/GUI/CanvasRootControl.cs b/Source/Engine/UI/GUI/CanvasRootControl.cs index 4cc16bc10..9ec3c0f1a 100644 --- a/Source/Engine/UI/GUI/CanvasRootControl.cs +++ b/Source/Engine/UI/GUI/CanvasRootControl.cs @@ -200,6 +200,8 @@ namespace FlaxEngine.GUI /// public override void Update(float deltaTime) { + base.Update(deltaTime); + // Update navigation if (SkipEvents) { @@ -215,8 +217,6 @@ namespace FlaxEngine.GUI UpdateNavigation(deltaTime, _canvas.NavigateRight.Name, NavDirection.Right, ref _navigationHeldTimeRight, ref _navigationRateTimeRight); UpdateNavigation(deltaTime, _canvas.NavigateSubmit.Name, ref _navigationHeldTimeSubmit, ref _navigationRateTimeSubmit, SubmitFocused); } - - base.Update(deltaTime); } private void ConditionalNavigate(NavDirection direction) diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs index a085fb25f..6c5240977 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs @@ -48,8 +48,8 @@ namespace FlaxEngine.GUI { if (alphaText.Length == 3 && alphaText[0] == '#') style.Color.A = ((StringUtils.HexDigit(alphaText[1]) << 4) + StringUtils.HexDigit(alphaText[2])) / 255.0f; - else if (alphaText.Length > 1 && alphaText[alphaText.Length - 1] == '%') - style.Color.A = float.Parse(alphaText.Substring(0, alphaText.Length - 1)) / 100.0f; + else if (alphaText.Length > 1 && alphaText[alphaText.Length - 1] == '%' && float.TryParse(alphaText.Substring(0, alphaText.Length - 1), out var alpha)) + style.Color.A = alpha / 100.0f; } context.StyleStack.Push(style); } @@ -297,8 +297,8 @@ namespace FlaxEngine.GUI { if (float.TryParse(text, out var width)) output = width; - if (text.Length > 1 && text[text.Length - 1] == '%') - output = input * float.Parse(text.Substring(0, text.Length - 1)) / 100.0f; + if (text.Length > 1 && text[text.Length - 1] == '%' && float.TryParse(text.Substring(0, text.Length - 1), out width)) + output = input * width / 100.0f; used = true; } return used;