diff --git a/Source/Editor/Surface/Archetypes/Animation.MultiBlend.cs b/Source/Editor/Surface/Archetypes/Animation.MultiBlend.cs index 450960af7..1d842a7c3 100644 --- a/Source/Editor/Surface/Archetypes/Animation.MultiBlend.cs +++ b/Source/Editor/Surface/Archetypes/Animation.MultiBlend.cs @@ -102,8 +102,14 @@ namespace FlaxEditor.Surface.Archetypes outline = style.BorderHighlighted; else if (_editor._node.SelectedAnimationIndex == _index) outline = style.BackgroundSelected; + + var features = Render2D.Features; + Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping; + Render2D.DrawSprite(icon, rect.MakeExpanded(4.0f), outline); Render2D.DrawSprite(icon, rect, style.Foreground); + + Render2D.Features = features; } /// diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs index e66f38398..b4afff091 100644 --- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs +++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs @@ -79,7 +79,7 @@ namespace FlaxEditor.Surface.Archetypes : base(id, context, nodeArch, groupArch) { var marginX = FlaxEditor.Surface.Constants.NodeMarginX; - var uiStartPosY = FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize; + var uiStartPosY = FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight; var editButton = new Button(marginX, uiStartPosY, 246, 20) { diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs index 9f3112905..c8d45cc5f 100644 --- a/Source/Editor/Surface/Archetypes/Animation.cs +++ b/Source/Editor/Surface/Archetypes/Animation.cs @@ -70,6 +70,9 @@ namespace FlaxEditor.Surface.Archetypes if (box.ID != _assetBox.ID) return; _assetSelect.Visible = !box.HasAnyConnection; + + if (!Archetype.UseFixedSize) + ResizeAuto(); } } @@ -243,8 +246,8 @@ namespace FlaxEditor.Surface.Archetypes { Type = NodeElementType.Input, Position = new Float2( - FlaxEditor.Surface.Constants.NodeMarginX - FlaxEditor.Surface.Constants.BoxOffsetX, - FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize + ylevel * FlaxEditor.Surface.Constants.LayoutOffsetY), + FlaxEditor.Surface.Constants.NodeMarginX, + FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight + ylevel * FlaxEditor.Surface.Constants.LayoutOffsetY), Text = "Pose " + _blendPoses.Count, Single = true, ValueIndex = -1, @@ -263,7 +266,7 @@ namespace FlaxEditor.Surface.Archetypes private void UpdateHeight() { float nodeHeight = 10 + (Mathf.Max(_blendPoses.Count, 1) + 3) * FlaxEditor.Surface.Constants.LayoutOffsetY; - Height = nodeHeight + FlaxEditor.Surface.Constants.NodeMarginY * 2 + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.NodeFooterSize; + Height = nodeHeight + FlaxEditor.Surface.Constants.NodeMarginY * 2 + FlaxEditor.Surface.Constants.NodeHeaderHeight + FlaxEditor.Surface.Constants.NodeFooterSize; } /// @@ -932,6 +935,7 @@ namespace FlaxEditor.Surface.Archetypes Title = "Copy Node", Description = "Copies the skeleton node transformation data (in local space)", Flags = NodeFlags.AnimGraph, + UseFixedSize = true, Size = new Float2(260, 140), DefaultValues = new object[] { diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs index 0b4b3f713..d99fedaee 100644 --- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs +++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs @@ -189,13 +189,70 @@ namespace FlaxEditor.Surface.Archetypes public override void Draw() { - base.Draw(); + var style = Style.Current; + + var backgroundRect = new Rectangle(Float2.Zero, Size); + + // Shadow + if (DrawBasicShadow) + { + var shadowRect = backgroundRect.MakeOffsetted(ShadowOffset); + Render2D.FillRectangle(shadowRect, Color.Black.AlphaMultiplied(0.125f)); + } + + // Background + Render2D.FillRectangle(backgroundRect, ArchetypeColor); + + // Breakpoint hit + if (Breakpoint.Hit) + { + var colorTop = Color.OrangeRed; + var colorBottom = Color.Red; + var time = DateTime.Now - Engine.StartupTime; + Render2D.DrawRectangle(backgroundRect.MakeExpanded(Mathf.Lerp(3.0f, 12.0f, Mathf.Sin((float)time.TotalSeconds * 10.0f) * 0.5f + 0.5f)), colorTop, colorTop, colorBottom, colorBottom, 2.0f); + } + + // Header + var headerColor = style.BackgroundHighlighted; + if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting) + headerColor *= 1.07f; + Render2D.FillRectangle(_headerRect, style.BackgroundHighlighted); + Render2D.DrawText(style.FontLarge, Title, _headerTextRect, style.Foreground, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1f, FlaxEditor.Surface.Constants.NodeHeaderTextScale); + + // Close button + if ((Archetype.Flags & NodeFlags.NoCloseButton) == 0 && Surface.CanEdit) + { + bool highlightClose = _closeButtonRect.Contains(_mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting; + DrawCloseButton(_closeButtonRect, highlightClose ? style.Foreground : style.ForegroundGrey); + } + + DrawChildren(); + + // Selection outline + if (_isSelected) + { + var colorTop = Color.Orange; + var colorBottom = Color.OrangeRed; + Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom, 2.5f); + } + + // Breakpoint dot + if (Breakpoint.Set) + { + var icon = Breakpoint.Enabled ? Surface.Style.Icons.BoxClose : Surface.Style.Icons.BoxOpen; + Render2D.DrawSprite(icon, new Rectangle(-7, -7, 16, 16), new Color(0.9f, 0.9f, 0.9f)); + Render2D.DrawSprite(icon, new Rectangle(-6, -6, 14, 14), new Color(0.894117647f, 0.0784313725f, 0.0f)); + } + + if (highlightBox != null) + Render2D.DrawRectangle(highlightBox.Bounds, style.BorderHighlighted, 2f); // Debug Info if (!string.IsNullOrEmpty(_debugInfo)) { - var style = Style.Current; - Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground); + // Draw an extra background to cover the archetype color colored node background and make text more legible + Render2D.FillRectangle(new Rectangle(0, _headerRect.Bottom + 4, Width, Height - _headerRect.Bottom - 4), style.BackgroundHighlighted); + Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 7, _debugInfoSize), style.Foreground, scale: 0.8f); } // Debug relevancy outline @@ -203,7 +260,7 @@ namespace FlaxEditor.Surface.Archetypes { var colorTop = Color.LightYellow; var colorBottom = Color.Yellow; - var backgroundRect = new Rectangle(Float2.One, Size - new Float2(2.0f)); + backgroundRect = new Rectangle(Float2.One, Size - new Float2(2.0f)); Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom); } } @@ -415,8 +472,8 @@ namespace FlaxEditor.Surface.Archetypes // Setup boxes _input = (InputBox)GetBox(0); _output = (OutputBox)GetBox(1); - _input.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxSize * -0.5f); - _output.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxSize * 0.5f); + _input.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxRowHeight * -0.5f); + _output.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxRowHeight * 0.5f); // Setup node type and data var flagsRoot = NodeFlags.NoRemove | NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaPaste; @@ -515,7 +572,7 @@ namespace FlaxEditor.Surface.Archetypes height += decorator.Height + DecoratorsMarginY; width = Mathf.Max(width, decorator.Width - FlaxEditor.Surface.Constants.NodeCloseButtonSize - 2 * DecoratorsMarginX); } - Size = new Float2(width + FlaxEditor.Surface.Constants.NodeMarginX * 2 + FlaxEditor.Surface.Constants.NodeCloseButtonSize, height + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.NodeFooterSize); + Size = new Float2(width + FlaxEditor.Surface.Constants.NodeMarginX * 2 + FlaxEditor.Surface.Constants.NodeCloseButtonSize, height + FlaxEditor.Surface.Constants.NodeHeaderHeight); UpdateRectangles(); } @@ -536,13 +593,13 @@ namespace FlaxEditor.Surface.Archetypes if (decorator.IndexInParent < indexInParent) decorator.IndexInParent = indexInParent + 1; // Push elements above the node } - const float footerSize = FlaxEditor.Surface.Constants.NodeFooterSize; - const float headerSize = FlaxEditor.Surface.Constants.NodeHeaderSize; + + const float headerHeight = FlaxEditor.Surface.Constants.NodeHeaderHeight; const float closeButtonMargin = FlaxEditor.Surface.Constants.NodeCloseButtonMargin; - const float closeButtonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize; - _headerRect = new Rectangle(0, bounds.Y - Y, bounds.Width, headerSize); + float closeButtonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize * 0.75f; + _headerRect = new Rectangle(0, bounds.Y - Y, bounds.Width, headerHeight); + _headerTextRect = _headerRect with { X = 5f, Width = Width - closeButtonSize - closeButtonMargin * 4f }; _closeButtonRect = new Rectangle(bounds.Width - closeButtonSize - closeButtonMargin, _headerRect.Y + closeButtonMargin, closeButtonSize, closeButtonSize); - _footerRect = new Rectangle(0, bounds.Height - footerSize, bounds.Width, footerSize); if (_output != null && _output.Visible) { _footerRect.Y -= ConnectionAreaHeight; @@ -648,6 +705,8 @@ namespace FlaxEditor.Surface.Archetypes private DragDecorator _dragDecorator; private float _dragLocation = -1; + internal override bool DrawBasicShadow => false; + internal Decorator(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) : base(id, context, nodeArch, groupArch) { @@ -667,7 +726,7 @@ namespace FlaxEditor.Surface.Archetypes } } - protected override Color FooterColor => Color.Transparent; + protected override Color ArchetypeColor => Color.Transparent; protected override Float2 CalculateNodeSize(float width, float height) { @@ -676,7 +735,7 @@ namespace FlaxEditor.Surface.Archetypes width = Mathf.Max(width, _debugInfoSize.X + 8.0f); height += _debugInfoSize.Y + 8.0f; } - return new Float2(width + FlaxEditor.Surface.Constants.NodeCloseButtonSize * 2 + DecoratorsMarginX * 2, height + FlaxEditor.Surface.Constants.NodeHeaderSize); + return new Float2(width + FlaxEditor.Surface.Constants.NodeCloseButtonSize * 2 + DecoratorsMarginX * 2, height + FlaxEditor.Surface.Constants.NodeHeaderHeight); } protected override void UpdateRectangles() @@ -684,8 +743,14 @@ namespace FlaxEditor.Surface.Archetypes base.UpdateRectangles(); _footerRect = Rectangle.Empty; + const float closeButtonMargin = FlaxEditor.Surface.Constants.NodeCloseButtonMargin; + float closeButtonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize * 0.75f; + _closeButtonRect = new Rectangle(Bounds.Width - closeButtonSize - closeButtonMargin, _headerRect.Y + closeButtonMargin, closeButtonSize, closeButtonSize); if (_dragIcon != null) - _dragIcon.Bounds = new Rectangle(_closeButtonRect.X - _closeButtonRect.Width, _closeButtonRect.Y, _closeButtonRect.Size); + { + var dragIconRect = _closeButtonRect.MakeExpanded(5f); + _dragIcon.Bounds = new Rectangle(dragIconRect.X - dragIconRect.Width, dragIconRect.Y, dragIconRect.Size); + } } protected override void UpdateTitle() @@ -764,6 +829,11 @@ namespace FlaxEditor.Surface.Archetypes node.ResizeAuto(); } } + else + { + // Correctly size decorators when surface is loaded + Node.ResizeAuto(); + } } /// diff --git a/Source/Editor/Surface/Archetypes/Comparisons.cs b/Source/Editor/Surface/Archetypes/Comparisons.cs index bcf0159d2..32baadc1c 100644 --- a/Source/Editor/Surface/Archetypes/Comparisons.cs +++ b/Source/Editor/Surface/Archetypes/Comparisons.cs @@ -173,10 +173,10 @@ namespace FlaxEditor.Surface.Archetypes { Op(1, "==", "Determines whether two values are equal", new[] { "equals" }), Op(2, "!=", "Determines whether two values are not equal", new[] { "not equals" }), - Op(3, ">", "Determines whether the first value is greater than the other", new[] { "greater than", "larger than", "bigger than" }), - Op(4, "<", "Determines whether the first value is less than the other", new[] { "less than", "smaller than" }), - Op(5, "<=", "Determines whether the first value is less or equal to the other", new[] { "less equals than", "smaller equals than" }), - Op(6, ">=", "Determines whether the first value is greater or equal to the other", new[] { "greater equals than", "larger equals than", "bigger equals than" }), + Op(3, ">", "Determines whether the first value is greater than the other", new[] { "greater than", "larger than", "bigger than", "more than" }), + Op(4, "<", "Determines whether the first value is less than the other", new[] { "less than", "smaller than", "tinier than" }), + Op(5, "<=", "Determines whether the first value is less or equal to the other", new[] { "less equals than", "smaller equals than", "tinier equals than" }), + Op(6, ">=", "Determines whether the first value is greater or equal to the other", new[] { "greater equals than", "larger equals than", "bigger equals than", "more equals than" }), new NodeArchetype { TypeID = 7, diff --git a/Source/Editor/Surface/Archetypes/Constants.cs b/Source/Editor/Surface/Archetypes/Constants.cs index ad88fa56a..a11213f93 100644 --- a/Source/Editor/Surface/Archetypes/Constants.cs +++ b/Source/Editor/Surface/Archetypes/Constants.cs @@ -166,7 +166,7 @@ namespace FlaxEditor.Surface.Archetypes _picker = new EnumComboBox(type) { EnumTypeValue = Values[0], - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _picker.ValueChanged += () => SetValue(0, _picker.EnumTypeValue); @@ -218,7 +218,7 @@ namespace FlaxEditor.Surface.Archetypes _output = (OutputBox)Elements[0]; _typePicker = new TypePickerControl { - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _typePicker.ValueChanged += () => Set(3); @@ -362,7 +362,7 @@ namespace FlaxEditor.Surface.Archetypes _output = (OutputBox)Elements[0]; _keyTypePicker = new TypePickerControl { - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _keyTypePicker.ValueChanged += OnKeyTypeChanged; @@ -482,7 +482,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(bool))), Description = "Constant boolean value", Flags = NodeFlags.AllGraphs, - Size = new Float2(110, 20), + Size = new Float2(90, 20), DefaultValues = new object[] { false @@ -515,7 +515,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(int))), Description = "Constant integer value", Flags = NodeFlags.AllGraphs, - Size = new Float2(110, 20), + Size = new Float2(120, 20), DefaultValues = new object[] { 0 @@ -543,7 +543,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(float))), Description = "Constant floating point", Flags = NodeFlags.AllGraphs, - Size = new Float2(110, 20), + Size = new Float2(120, 20), DefaultValues = new object[] { 0.0f @@ -750,7 +750,7 @@ namespace FlaxEditor.Surface.Archetypes Title = "PI", Description = "A value specifying the approximation of π which is 180 degrees", Flags = NodeFlags.AllGraphs, - Size = new Float2(50, 20), + Size = new Float2(45, 20), Elements = new[] { NodeElementArchetype.Factory.Output(0, "π", typeof(float), 0), @@ -782,7 +782,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(uint))), Description = "Constant unsigned integer value", Flags = NodeFlags.AllGraphs, - Size = new Float2(170, 20), + Size = new Float2(130, 20), DefaultValues = new object[] { 0u @@ -824,7 +824,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(double))), Description = "Constant floating point", Flags = NodeFlags.AllGraphs, - Size = new Float2(110, 20), + Size = new Float2(120, 20), DefaultValues = new object[] { 0.0d diff --git a/Source/Editor/Surface/Archetypes/Function.cs b/Source/Editor/Surface/Archetypes/Function.cs index 79d3948bf..6410b51e7 100644 --- a/Source/Editor/Surface/Archetypes/Function.cs +++ b/Source/Editor/Surface/Archetypes/Function.cs @@ -631,7 +631,7 @@ namespace FlaxEditor.Surface.Archetypes } /// - protected override Color FooterColor => new Color(200, 11, 112); + protected override Color ArchetypeColor => new Color(200, 11, 112); /// public override void OnLoaded(SurfaceNodeActions action) diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index df89dfc94..d9890f031 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -312,16 +312,17 @@ namespace FlaxEditor.Surface.Archetypes : base(id, context, nodeArch, groupArch) { _sizeValueIndex = Archetype.TypeID == 8 ? 1 : 3; // Index of the Size stored in Values array - Float2 pos = new Float2(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize), size; + Float2 pos = new Float2(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight), size; if (nodeArch.TypeID == 8) { - pos += new Float2(60, 0); - size = new Float2(172, 200); + pos += new Float2(65, 0); + size = new Float2(160, 185); + _sizeMin = new Float2(240, 185); } else { - pos += new Float2(0, 40); - size = new Float2(300, 200); + pos += new Float2(0, 40 + FlaxEditor.Utilities.Constants.UIMargin * 2f); + size = new Float2(300, 180); } _textBox = new CustomCodeTextBox { @@ -506,8 +507,8 @@ namespace FlaxEditor.Surface.Archetypes Size = new Float2(300, 200), DefaultValues = new object[] { - "// Here you can add HLSL code\nOutput0 = Input0;", - new Float2(300, 200), + "// You can add HLSL code here\nOutput0 = Input0;", + new Float2(350, 200), }, Elements = new[] { @@ -972,7 +973,7 @@ namespace FlaxEditor.Surface.Archetypes Size = new Float2(300, 240), DefaultValues = new object[] { - "// Here you can add HLSL code\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}", + "// You can add HLSL code here\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}", true, (int)MaterialTemplateInputsMapping.Utilities, new Float2(300, 240), diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs index 4a68c31e0..e85c87898 100644 --- a/Source/Editor/Surface/Archetypes/ParticleModules.cs +++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs @@ -121,7 +121,7 @@ namespace FlaxEditor.Surface.Archetypes Render2D.DrawRectangle(new Rectangle(1, 0, Width - 2, Height - 1), Colors[idx]); // Close button - Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey); + DrawCloseButton(_closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey); // Arrange button var dragBarColor = _arrangeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey; @@ -138,6 +138,12 @@ namespace FlaxEditor.Surface.Archetypes } } + /// + public override void Resize(float width, float height) + { + // Do nothing so module does not change size + } + private bool ArrangeAreaCheck(out int index, out Rectangle rect) { var barSidesExtend = 20.0f; @@ -261,9 +267,9 @@ namespace FlaxEditor.Surface.Archetypes const float closeButtonMargin = FlaxEditor.Surface.Constants.NodeCloseButtonMargin; const float closeButtonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize; _headerRect = new Rectangle(0, 0, Width, headerSize); - _closeButtonRect = new Rectangle(Width - closeButtonSize - closeButtonMargin, closeButtonMargin, closeButtonSize, closeButtonSize); + _closeButtonRect = new Rectangle(Width - closeButtonSize * 0.75f - closeButtonMargin, closeButtonMargin + 0.25f, closeButtonSize * 0.75f, closeButtonSize * 0.75f); _footerRect = Rectangle.Empty; - _enabled.Location = new Float2(_closeButtonRect.X - _enabled.Width - 2, _closeButtonRect.Y); + _enabled.Location = new Float2(_closeButtonRect.X - _enabled.Width - 2, _closeButtonRect.Y - 0.25f); _arrangeButtonRect = new Rectangle(_enabled.X - closeButtonSize - closeButtonMargin, closeButtonMargin, closeButtonSize, closeButtonSize); } @@ -461,7 +467,7 @@ namespace FlaxEditor.Surface.Archetypes /// /// The particle module node elements offset applied to controls to reduce default surface node header thickness. /// - private const float NodeElementsOffset = 16.0f - Surface.Constants.NodeHeaderSize; + private const float NodeElementsOffset = 16.0f - Surface.Constants.NodeHeaderHeight; private const NodeFlags DefaultModuleFlags = NodeFlags.ParticleEmitterGraph | NodeFlags.NoSpawnViaGUI | NodeFlags.NoMove; diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs index 59af7af5e..d5848a8e4 100644 --- a/Source/Editor/Surface/Archetypes/Particles.cs +++ b/Source/Editor/Surface/Archetypes/Particles.cs @@ -74,7 +74,7 @@ namespace FlaxEditor.Surface.Archetypes /// /// The header height. /// - public const float HeaderHeight = FlaxEditor.Surface.Constants.NodeHeaderSize; + public const float HeaderHeight = FlaxEditor.Surface.Constants.NodeHeaderHeight; /// /// Gets the type of the module. @@ -199,7 +199,7 @@ namespace FlaxEditor.Surface.Archetypes DrawChildren(); // Options border - var optionsAreaStart = FlaxEditor.Surface.Constants.NodeHeaderSize + 3.0f; + var optionsAreaStart = FlaxEditor.Surface.Constants.NodeHeaderHeight + 3.0f; var optionsAreaHeight = 7 * FlaxEditor.Surface.Constants.LayoutOffsetY + 6.0f; Render2D.DrawRectangle(new Rectangle(1, optionsAreaStart, Width - 2, optionsAreaHeight), style.BackgroundSelected); @@ -341,6 +341,7 @@ namespace FlaxEditor.Surface.Archetypes Title = "Particle Emitter", Description = "Main particle emitter node. Contains a set of modules per emitter context. Modules are executed in order from top to bottom of the stack.", Flags = NodeFlags.ParticleEmitterGraph | NodeFlags.NoRemove | NodeFlags.NoSpawnViaGUI | NodeFlags.NoSpawnViaPaste | NodeFlags.NoCloseButton, + UseFixedSize = true, Size = new Float2(300, 600), DefaultValues = new object[] { diff --git a/Source/Editor/Surface/Archetypes/Textures.cs b/Source/Editor/Surface/Archetypes/Textures.cs index f09ee5015..2cc56c8a4 100644 --- a/Source/Editor/Surface/Archetypes/Textures.cs +++ b/Source/Editor/Surface/Archetypes/Textures.cs @@ -57,7 +57,7 @@ namespace FlaxEditor.Surface.Archetypes { _textureGroupPicker = new ComboBox { - Location = new Float2(FlaxEditor.Surface.Constants.NodeMarginX + 50, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.LayoutOffsetY * _level), + Location = new Float2(FlaxEditor.Surface.Constants.NodeMarginX + 50, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight + FlaxEditor.Surface.Constants.LayoutOffsetY * _level), Width = 100, Parent = this, }; @@ -134,7 +134,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Texture))), Description = "Two dimensional texture object", Flags = NodeFlags.MaterialGraph, - Size = new Float2(140, 120), + Size = new Float2(140, 140), DefaultValues = new object[] { Guid.Empty @@ -158,7 +158,7 @@ namespace FlaxEditor.Surface.Archetypes AlternativeTitles = new string[] { "UV", "UVs" }, Description = "Texture coordinates", Flags = NodeFlags.MaterialGraph, - Size = new Float2(150, 30), + Size = new Float2(160, 20), DefaultValues = new object[] { 0u @@ -239,7 +239,7 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.Input(3, "Max Steps", true, typeof(float), 3, 2), NodeElementArchetype.Factory.Input(4, "Heightmap Texture", true, typeof(FlaxEngine.Object), 4), NodeElementArchetype.Factory.Output(0, "Parallax UVs", typeof(Float2), 5), - NodeElementArchetype.Factory.Text(Surface.Constants.BoxSize + 4, 5 * Surface.Constants.LayoutOffsetY, "Channel"), + NodeElementArchetype.Factory.Text(Surface.Constants.BoxRowHeight + 4, 5 * Surface.Constants.LayoutOffsetY, "Channel"), NodeElementArchetype.Factory.ComboBox(70, 5 * Surface.Constants.LayoutOffsetY, 50, 3, new[] { "R", @@ -493,7 +493,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 18, Title = "Lightmap UV", - AlternativeTitles = new string[] { "Lightmap TexCoord" }, + AlternativeTitles = new string[] { "Lightmap TexCoord" }, Description = "Lightmap UVs", Flags = NodeFlags.MaterialGraph, Size = new Float2(110, 20), diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs index 68a733197..ee335d01d 100644 --- a/Source/Editor/Surface/Archetypes/Tools.cs +++ b/Source/Editor/Surface/Archetypes/Tools.cs @@ -467,7 +467,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new CurveNode(id, context, arch, groupArch), Description = "An animation spline represented by a set of keyframes, each representing an endpoint of a Bezier curve.", Flags = NodeFlags.AllGraphs, - Size = new Float2(400, 180), + Size = new Float2(400, 180.0f), DefaultValues = new object[] { // Keyframes count @@ -485,7 +485,7 @@ namespace FlaxEditor.Surface.Archetypes zero, // Tangent In zero, // Tangent Out - // Empty keys zero-6 + // Empty keys 0-6 0.0f, zero, zero, zero, 0.0f, zero, zero, zero, 0.0f, zero, zero, zero, @@ -515,13 +515,12 @@ namespace FlaxEditor.Surface.Archetypes base.OnLoaded(action); // Create curve editor - var upperLeft = GetBox(0).BottomLeft; - var upperRight = GetBox(1).BottomRight; - float curveMargin = 20.0f; + var upperLeft = GetBox(0).BottomRight; + var upperRight = GetBox(1).BottomLeft; _curve = new BezierCurveEditor { MaxKeyframes = 7, - Bounds = new Rectangle(upperLeft + new Float2(curveMargin, 10.0f), upperRight.X - upperLeft.X - curveMargin * 2.0f, 140.0f), + Bounds = new Rectangle(upperLeft + new Float2(0f, 10.0f), upperRight.X - upperLeft.X - 8.0f, 135.0f), Parent = this, AnchorMax = Float2.One, }; @@ -841,7 +840,7 @@ namespace FlaxEditor.Surface.Archetypes _picker = new TypePickerControl { Type = ScriptType.FlaxObject, - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName); @@ -910,7 +909,7 @@ namespace FlaxEditor.Surface.Archetypes _picker = new TypePickerControl { Type = ScriptType.Object, - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 140, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 140, 16), Parent = this, }; _picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName); @@ -961,7 +960,7 @@ namespace FlaxEditor.Surface.Archetypes _picker = new TypePickerControl { Type = ScriptType.FlaxObject, - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName); @@ -1012,7 +1011,7 @@ namespace FlaxEditor.Surface.Archetypes _picker = new TypePickerControl { Type = type, - Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16), + Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight, 160, 16), Parent = this, }; _picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName); @@ -1071,7 +1070,11 @@ namespace FlaxEditor.Surface.Archetypes internal class RerouteNode : SurfaceNode, IConnectionInstigator { - internal static readonly Float2 DefaultSize = new Float2(FlaxEditor.Surface.Constants.BoxSize); + internal static readonly Float2 DefaultSize = new Float2(FlaxEditor.Surface.Constants.BoxRowHeight); + + internal bool DrawDisabled => _input.AllConnectionsDisabled || _output.AllConnectionsDisabled; + internal override bool DrawBasicShadow => false; + private Rectangle _localBounds; private InputBox _input; private OutputBox _output; @@ -1174,9 +1177,18 @@ namespace FlaxEditor.Surface.Archetypes _footerRect = Rectangle.Empty; } + /// + public override void Resize(float width, float height) + { + // Do nothing so the input and output boxes do not change position + } + /// public override void Draw() { + // Update active state of input + _input.IsActive = !_output.AllConnectionsDisabled; + var style = Surface.Style; var connectionColor = style.Colors.Default; var type = ScriptType.Null; @@ -1190,6 +1202,10 @@ namespace FlaxEditor.Surface.Archetypes Surface.Style.GetConnectionColor(type, hints, out connectionColor); } + // Draw the box as disabled if needed + if (DrawDisabled) + connectionColor = connectionColor * 0.6f; + if (!_input.HasAnyConnection) Render2D.FillRectangle(new Rectangle(-barHorizontalOffset - barHeight * 2, (DefaultSize.Y - barHeight) / 2, barHeight * 2, barHeight), connectionColor); if (!_output.HasAnyConnection) @@ -1200,6 +1216,11 @@ namespace FlaxEditor.Surface.Archetypes icon = type.IsVoid ? style.Icons.ArrowClose : style.Icons.BoxClose; else icon = type.IsVoid ? style.Icons.ArrowOpen : style.Icons.BoxOpen; + + // Shadow + var shadowRect = _localBounds.MakeOffsetted(ShadowOffset); + Render2D.DrawSprite(icon, shadowRect, Color.Black.AlphaMultiplied(0.125f)); + Render2D.DrawSprite(icon, _localBounds, connectionColor); base.Draw(); @@ -1507,6 +1528,7 @@ namespace FlaxEditor.Surface.Archetypes Description = "Linear color gradient sampler", Flags = NodeFlags.AllGraphs, Size = new Float2(400, 150.0f), + UseFixedSize = true, DefaultValues = new object[] { // Stops count @@ -1826,6 +1848,7 @@ namespace FlaxEditor.Surface.Archetypes Description = "Reroute a connection.", Flags = NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaGUI | NodeFlags.AllGraphs, Size = RerouteNode.DefaultSize, + UseFixedSize = true, ConnectionsHints = ConnectionsHint.All, IndependentBoxes = new int[] { 0 }, DependentBoxes = new int[] { 1 }, diff --git a/Source/Editor/Surface/Constants.cs b/Source/Editor/Surface/Constants.cs index 0f3dca783..474d3979b 100644 --- a/Source/Editor/Surface/Constants.cs +++ b/Source/Editor/Surface/Constants.cs @@ -13,46 +13,61 @@ namespace FlaxEditor.Surface /// /// The node close button size. /// - public const float NodeCloseButtonSize = 12.0f; + public const float NodeCloseButtonSize = 10.0f; /// /// The node close button margin from the edges. /// - public const float NodeCloseButtonMargin = 2.0f; + public const float NodeCloseButtonMargin = 5.0f; /// /// The node header height. /// - public const float NodeHeaderSize = 28.0f; + public const float NodeHeaderHeight = 25.0f; + + /// + /// The scale of the header text. + /// + public const float NodeHeaderTextScale = 0.8f; /// /// The node footer height. /// - public const float NodeFooterSize = 4.0f; + public const float NodeFooterSize = 2.0f; /// - /// The node left margin. + /// The horizontal node margin. /// - public const float NodeMarginX = 5.0f; + public const float NodeMarginX = 6.0f; /// - /// The node right margin. + /// The vertical node right margin. /// - public const float NodeMarginY = 5.0f; + public const float NodeMarginY = 8.0f; /// - /// The box position offset on the x axis. + /// The width of the row that is started by a box. /// - public const float BoxOffsetX = 2.0f; + public const float BoxRowHeight = 19.0f; /// /// The box size (with and height). /// - public const float BoxSize = 20.0f; + public const float BoxSize = 15.0f; /// /// The node layout offset on the y axis (height of the boxes rows, etc.). It's used to make the design more consistent. /// - public const float LayoutOffsetY = 20.0f; + public const float LayoutOffsetY = 24.0f; + + /// + /// The offset between the box text and the box + /// + public const float BoxTextOffset = 1.65f; + + /// + /// The width of the rectangle used to draw the box text. + /// + public const float BoxTextRectWidth = 500.0f; } } diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs index 964b3cc69..4c86af041 100644 --- a/Source/Editor/Surface/Elements/Box.cs +++ b/Source/Editor/Surface/Elements/Box.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Linq; using FlaxEditor.Scripting; using FlaxEditor.Surface.Undo; using FlaxEngine; @@ -194,9 +195,19 @@ namespace FlaxEditor.Surface.Elements set => _isActive = value; } + /// + /// Gets if the box is disabled (user can still connect, but connections will be ignored). + /// + public bool IsDisabled => !(Enabled && IsActive); + + /// + /// Gets a value indicating whether all connections are disabled. + /// + public bool AllConnectionsDisabled => Connections.All(c => c.IsDisabled); + /// protected Box(SurfaceNode parentNode, NodeElementArchetype archetype, Float2 location) - : base(parentNode, archetype, location, new Float2(Constants.BoxSize), false) + : base(parentNode, archetype, location, new Float2(Constants.BoxRowHeight), false) { _currentType = DefaultType; _isSingle = Archetype.Single; diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs index 9861ebacd..3e2bb4d5c 100644 --- a/Source/Editor/Surface/Elements/InputBox.cs +++ b/Source/Editor/Surface/Elements/InputBox.cs @@ -1442,8 +1442,8 @@ namespace FlaxEditor.Surface.Elements // Draw text var style = Style.Current; - var rect = new Rectangle(Width + 4, 0, 1410, Height); - Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); + var rect = new Rectangle(Width + Constants.BoxTextOffset, 0, Constants.BoxTextRectWidth, Height); + Render2D.DrawText(style.FontMedium, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); } /// diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs index 8836dc0dc..e1ec56a36 100644 --- a/Source/Editor/Surface/Elements/OutputBox.cs +++ b/Source/Editor/Surface/Elements/OutputBox.cs @@ -186,7 +186,7 @@ namespace FlaxEditor.Surface.Elements Box targetBox = Connections[i]; var endPos = targetBox.ConnectionOrigin; var highlight = DefaultConnectionThickness + Mathf.Max(startHighlight, targetBox.ConnectionsHighlightIntensity); - var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f; + var alpha = targetBox.IsDisabled ? 0.6f : 1.0f; // We have to calculate an offset here to preserve the original color for when the default connection thickness is larger than 1 var highlightOffset = (highlight - (DefaultConnectionThickness - 1)); @@ -212,7 +212,7 @@ namespace FlaxEditor.Surface.Elements // Draw all the connections var startPos = ConnectionOrigin; var endPos = targetBox.ConnectionOrigin; - var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f; + var alpha = targetBox.IsDisabled ? 0.6f : 1.0f; var color = _currentTypeColor * alpha; DrawConnection(Surface.Style, ref startPos, ref endPos, ref color, SelectedConnectionThickness); } @@ -230,8 +230,8 @@ namespace FlaxEditor.Surface.Elements // Draw text var style = Style.Current; - var rect = new Rectangle(-100, 0, 100 - 2, Height); - Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center); + var rect = new Rectangle(-Constants.BoxTextRectWidth - Constants.BoxTextOffset * 2f, 0f, Constants.BoxTextRectWidth, Height); + Render2D.DrawText(style.FontMedium, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center); } } } diff --git a/Source/Editor/Surface/NodeArchetype.cs b/Source/Editor/Surface/NodeArchetype.cs index b29dd0956..006bd2fb6 100644 --- a/Source/Editor/Surface/NodeArchetype.cs +++ b/Source/Editor/Surface/NodeArchetype.cs @@ -129,6 +129,11 @@ namespace FlaxEditor.Surface /// public NodeFlags Flags; + /// + /// If the node should use the as node size. If false, the node will auto resize based on its elements. + /// + public bool UseFixedSize = false; + /// /// Title text. /// diff --git a/Source/Editor/Surface/NodeElementArchetype.cs b/Source/Editor/Surface/NodeElementArchetype.cs index f5a23d411..0e3c504ff 100644 --- a/Source/Editor/Surface/NodeElementArchetype.cs +++ b/Source/Editor/Surface/NodeElementArchetype.cs @@ -3,8 +3,9 @@ using System; using System.Collections.Generic; using System.Reflection; -using FlaxEditor.CustomEditors; +using FlaxEditor.GUI.Input; using FlaxEditor.Scripting; +using FlaxEditor.Surface.Elements; using FlaxEngine; namespace FlaxEditor.Surface @@ -78,12 +79,12 @@ namespace FlaxEditor.Surface /// /// Gets the actual element position on the y axis. /// - public float ActualPositionY => Position.Y + Constants.NodeMarginY + Constants.NodeHeaderSize; + public float ActualPositionY => Position.Y + Constants.NodeMarginY + Constants.NodeHeaderHeight; /// /// Gets the actual element position. /// - public Float2 ActualPosition => new Float2(Position.X + Constants.NodeMarginX, Position.Y + Constants.NodeMarginY + Constants.NodeHeaderSize); + public Float2 ActualPosition => new Float2(Position.X + Constants.NodeMarginX, Position.Y + Constants.NodeMarginY + Constants.NodeHeaderHeight); /// /// Node element archetypes factory object. Helps to build surface nodes archetypes. @@ -106,8 +107,8 @@ namespace FlaxEditor.Surface { Type = NodeElementType.Input, Position = new Float2( - Constants.NodeMarginX - Constants.BoxOffsetX, - Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY), + Constants.NodeMarginX, + Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY), Text = text, Single = single, ValueIndex = valueIndex, @@ -132,8 +133,8 @@ namespace FlaxEditor.Surface { Type = NodeElementType.Input, Position = new Float2( - Constants.NodeMarginX - Constants.BoxOffsetX, - Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY), + Constants.NodeMarginX, + Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY), Text = text, Single = single, ValueIndex = valueIndex, @@ -157,8 +158,8 @@ namespace FlaxEditor.Surface { Type = NodeElementType.Output, Position = new Float2( - Constants.NodeMarginX - Constants.BoxSize + Constants.BoxOffsetX, - Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY), + -Constants.NodeMarginX, + Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY), Text = text, Single = single, ValueIndex = -1, @@ -182,8 +183,8 @@ namespace FlaxEditor.Surface { Type = NodeElementType.Output, Position = new Float2( - Constants.NodeMarginX - Constants.BoxSize + Constants.BoxOffsetX, - Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY), + -Constants.NodeMarginX, + Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY), Text = text, Single = single, ValueIndex = -1, @@ -205,6 +206,7 @@ namespace FlaxEditor.Surface { Type = NodeElementType.BoolValue, Position = new Float2(x, y), + Size = new Float2(16f), Text = null, Single = false, ValueIndex = valueIndex, @@ -228,7 +230,8 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.IntegerValue, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), + Size = new Float2(50f, IntegerValue.DefaultHeight), Text = null, Single = false, ValueIndex = valueIndex, @@ -254,7 +257,8 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.UnsignedIntegerValue, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), + Size = new Float2(50f, UnsignedIntegerValue.DefaultHeight), Text = null, Single = false, ValueIndex = valueIndex, @@ -280,7 +284,8 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.FloatValue, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), + Size = new Float2(50f, FloatValueBox.DefaultHeight), Text = null, Single = false, ValueIndex = valueIndex, @@ -359,7 +364,8 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.ColorValue, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), + Size = new Float2(32, 18), Text = null, Single = false, ValueIndex = valueIndex, @@ -382,6 +388,7 @@ namespace FlaxEditor.Surface { Type = NodeElementType.Asset, Position = new Float2(x, y), + Size = new Float2(78f, 90f), Text = type.FullName, Single = false, ValueIndex = valueIndex, @@ -530,7 +537,7 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.TextBox, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), Size = new Float2(width, height), Single = false, ValueIndex = valueIndex, @@ -595,7 +602,7 @@ namespace FlaxEditor.Surface return new NodeElementArchetype { Type = NodeElementType.BoxValue, - Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y), + Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y), Text = null, Single = false, ValueIndex = valueIndex, diff --git a/Source/Editor/Surface/NodeFactory.cs b/Source/Editor/Surface/NodeFactory.cs index 7c85cb449..f787899dc 100644 --- a/Source/Editor/Surface/NodeFactory.cs +++ b/Source/Editor/Surface/NodeFactory.cs @@ -60,84 +60,84 @@ namespace FlaxEditor.Surface { GroupID = 1, Name = "Material", - Color = new Color(231, 76, 60), + Color = new Color(181, 89, 49), Archetypes = Archetypes.Material.Nodes }, new GroupArchetype { GroupID = 2, Name = "Constants", - Color = new Color(243, 156, 18), + Color = new Color(163, 106, 21), Archetypes = Archetypes.Constants.Nodes }, new GroupArchetype { GroupID = 3, Name = "Math", - Color = new Color(52, 152, 219), + Color = new Color(45, 126, 181), Archetypes = Archetypes.Math.Nodes }, new GroupArchetype { GroupID = 4, Name = "Packing", - Color = new Color(155, 89, 182), + Color = new Color(124, 66, 143), Archetypes = Archetypes.Packing.Nodes }, new GroupArchetype { GroupID = 5, Name = "Textures", - Color = new Color(46, 204, 113), + Color = new Color(43, 130, 83), Archetypes = Archetypes.Textures.Nodes }, new GroupArchetype { GroupID = 6, Name = "Parameters", - Color = new Color(52, 73, 94), + Color = new Color(55, 78, 99), Archetypes = Archetypes.Parameters.Nodes }, new GroupArchetype { GroupID = 7, Name = "Tools", - Color = new Color(149, 165, 166), + Color = new Color(88, 96, 97), Archetypes = Archetypes.Tools.Nodes }, new GroupArchetype { GroupID = 8, Name = "Layers", - Color = new Color(249, 105, 116), + Color = new Color(189, 75, 81), Archetypes = Archetypes.Layers.Nodes }, new GroupArchetype { GroupID = 9, Name = "Animations", - Color = new Color(105, 179, 160), + Color = new Color(72, 125, 107), Archetypes = Archetypes.Animation.Nodes }, new GroupArchetype { GroupID = 10, Name = "Boolean", - Color = new Color(237, 28, 36), + Color = new Color(166, 27, 32), Archetypes = Archetypes.Boolean.Nodes }, new GroupArchetype { GroupID = 11, Name = "Bitwise", - Color = new Color(181, 230, 29), + Color = new Color(96, 125, 34), Archetypes = Archetypes.Bitwise.Nodes }, new GroupArchetype { GroupID = 12, Name = "Comparisons", - Color = new Color(148, 30, 34), + Color = new Color(166, 33, 57), Archetypes = Archetypes.Comparisons.Nodes }, // GroupID = 13 -> Custom Nodes provided externally @@ -145,7 +145,7 @@ namespace FlaxEditor.Surface { GroupID = 14, Name = "Particles", - Color = new Color(121, 210, 176), + Color = new Color(72, 125, 107), Archetypes = Archetypes.Particles.Nodes }, new GroupArchetype @@ -166,7 +166,7 @@ namespace FlaxEditor.Surface { GroupID = 17, Name = "Flow", - Color = new Color(237, 136, 64), + Color = new Color(181, 91, 33), Archetypes = Archetypes.Flow.Nodes }, new GroupArchetype diff --git a/Source/Editor/Surface/ParticleEmitterSurface.cs b/Source/Editor/Surface/ParticleEmitterSurface.cs index f332471fb..c61d4365d 100644 --- a/Source/Editor/Surface/ParticleEmitterSurface.cs +++ b/Source/Editor/Surface/ParticleEmitterSurface.cs @@ -59,7 +59,7 @@ namespace FlaxEditor.Surface var width = _rootNode.Width; var rootPos = _rootNode.Location; var pos = rootPos; - pos.Y += Constants.NodeHeaderSize + 1.0f + 7 * Constants.LayoutOffsetY + 6.0f + 4.0f; + pos.Y += Constants.NodeHeaderHeight + 1.0f + 7 * Constants.LayoutOffsetY + 6.0f + 4.0f; for (int i = 0; i < _rootNode.Headers.Length; i++) { @@ -67,7 +67,7 @@ namespace FlaxEditor.Surface var modulesStart = pos - rootPos; var modules = modulesGroups.FirstOrDefault(x => x.Key == header.ModuleType); - pos.Y += Constants.NodeHeaderSize + 2.0f; + pos.Y += Constants.NodeHeaderHeight + 2.0f; if (modules != null) { foreach (var module in modules) diff --git a/Source/Editor/Surface/ResizableSurfaceNode.cs b/Source/Editor/Surface/ResizableSurfaceNode.cs index 259c29836..ee6560a84 100644 --- a/Source/Editor/Surface/ResizableSurfaceNode.cs +++ b/Source/Editor/Surface/ResizableSurfaceNode.cs @@ -74,6 +74,12 @@ namespace FlaxEditor.Surface Resize(size.X, size.Y); } + /// + public override void ResizeAuto() + { + // Do nothing, we want to put full control of node size into the users hands + } + /// public override void Draw() { diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs index a76fa245d..79a285bd8 100644 --- a/Source/Editor/Surface/SurfaceComment.cs +++ b/Source/Editor/Surface/SurfaceComment.cs @@ -56,10 +56,10 @@ namespace FlaxEditor.Surface : base(id, context, nodeArch, groupArch) { _sizeValueIndex = 2; // Index of the Size stored in Values array - _sizeMin = new Float2(140.0f, Constants.NodeHeaderSize); + _sizeMin = new Float2(140.0f, Constants.NodeHeaderHeight); _renameTextBox = new TextBox(false, 0, 0, Width) { - Height = Constants.NodeHeaderSize, + Height = Constants.NodeHeaderHeight, Visible = false, Parent = this, EndEditOnClick = false, // We have to handle this ourselves, otherwise the textbox instantly loses focus when double-clicking the header @@ -124,11 +124,11 @@ namespace FlaxEditor.Surface { base.UpdateRectangles(); - const float headerSize = Constants.NodeHeaderSize; + const float headerSize = Constants.NodeHeaderHeight; const float buttonMargin = Constants.NodeCloseButtonMargin; const float buttonSize = Constants.NodeCloseButtonSize; _headerRect = new Rectangle(0, 0, Width, headerSize); - _closeButtonRect = new Rectangle(Width - buttonSize - buttonMargin, buttonMargin, buttonSize, buttonSize); + _closeButtonRect = new Rectangle(Width - buttonSize * 0.75f - buttonMargin, buttonMargin, buttonSize * 0.75f, buttonSize * 0.75f); _colorButtonRect = new Rectangle(_closeButtonRect.Left - buttonSize - buttonMargin, buttonMargin, buttonSize, buttonSize); _resizeButtonRect = new Rectangle(_closeButtonRect.Left, Height - buttonSize - buttonMargin, buttonSize, buttonSize); _renameTextBox.Width = Width; @@ -183,7 +183,7 @@ namespace FlaxEditor.Surface if (Surface.CanEdit) { // Close button - Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); + DrawCloseButton(_closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); // Color button Render2D.DrawSprite(style.Settings, _colorButtonRect, _colorButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey); diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs index 6312bd68d..2d440160f 100644 --- a/Source/Editor/Surface/SurfaceNode.cs +++ b/Source/Editor/Surface/SurfaceNode.cs @@ -40,6 +40,13 @@ namespace FlaxEditor.Surface [HideInEditor] public class SurfaceNode : SurfaceControl { + internal const float ShadowOffset = 2.25f; + + /// + /// If true, draws a basic rectangle shadow behind the node. Disable to hide shadow or if the node is drawing a custom shadow. + /// + internal virtual bool DrawBasicShadow => true; + /// /// The box to draw a highlight around. Drawing will be skipped if null. /// @@ -55,6 +62,11 @@ namespace FlaxEditor.Surface /// protected Rectangle _headerRect; + /// + /// The header text rectangle (local space). + /// + protected Rectangle _headerTextRect; + /// /// The close button rectangle (local space). /// @@ -123,7 +135,7 @@ namespace FlaxEditor.Surface /// The node archetype. /// The group archetype. public SurfaceNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) - : base(context, nodeArch.Size.X + Constants.NodeMarginX * 2, nodeArch.Size.Y + Constants.NodeMarginY * 2 + Constants.NodeHeaderSize + Constants.NodeFooterSize) + : base(context, nodeArch.Size.X + Constants.NodeMarginX * 2, nodeArch.Size.Y + Constants.NodeMarginY * 2 + Constants.NodeHeaderHeight + Constants.NodeFooterSize) { Title = nodeArch.Title; ID = id; @@ -132,7 +144,7 @@ namespace FlaxEditor.Surface AutoFocus = false; TooltipText = GetTooltip(); CullChildren = false; - BackgroundColor = Style.Current.BackgroundNormal; + BackgroundColor = Color.Lerp(Style.Current.Background, Style.Current.BackgroundHighlighted, 0.55f); if (Archetype.DefaultValues != null) { @@ -147,9 +159,9 @@ namespace FlaxEditor.Surface public virtual string ContentSearchText => null; /// - /// Gets the color of the footer of the node. + /// Gets the color of the header of the node. /// - protected virtual Color FooterColor => GroupArchetype.Color; + protected virtual Color ArchetypeColor => GroupArchetype.Color; private Float2 mouseDownMousePosition; @@ -161,7 +173,7 @@ namespace FlaxEditor.Surface /// The node control total size. protected virtual Float2 CalculateNodeSize(float width, float height) { - return new Float2(width + Constants.NodeMarginX * 2, height + Constants.NodeMarginY * 2 + Constants.NodeHeaderSize + Constants.NodeFooterSize); + return new Float2(width + Constants.NodeMarginX * 2, height + Constants.NodeMarginY * 2 + Constants.NodeHeaderHeight + Constants.NodeFooterSize); } /// @@ -169,7 +181,7 @@ namespace FlaxEditor.Surface /// /// The width. /// The height. - public void Resize(float width, float height) + public virtual void Resize(float width, float height) { if (Surface == null) return; @@ -187,7 +199,7 @@ namespace FlaxEditor.Surface { if (Elements[i] is OutputBox box) { - box.Location = box.Archetype.Position + new Float2(width, 0); + box.Location = box.Archetype.Position + new Float2(width - Constants.NodeMarginX, 0); } } @@ -215,29 +227,39 @@ namespace FlaxEditor.Surface var child = Children[i]; if (!child.Visible) continue; + // Input boxes if (child is InputBox inputBox) { var boxWidth = boxLabelFont.MeasureText(inputBox.Text).X + 20; if (inputBox.DefaultValueEditor != null) boxWidth += inputBox.DefaultValueEditor.Width + 4; leftWidth = Mathf.Max(leftWidth, boxWidth); - leftHeight = Mathf.Max(leftHeight, inputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f); + leftHeight = Mathf.Max(leftHeight, inputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderHeight + 20.0f); } + // Output boxes else if (child is OutputBox outputBox) { rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20); - rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f); + rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderHeight + 20.0f); } + // Elements (Float-, int-, uint- value boxes, asset pickers, etc.) + // These will only ever be on the left side of the node, so we only adjust left width and height + else if (child is SurfaceNodeElementControl elementControl) + { + leftWidth = Mathf.Max(leftWidth, elementControl.Width + 8f); + leftHeight = Mathf.Max(leftHeight, elementControl.Height + 8f); + } + // Other controls in the node else if (child is Control control) { if (control.AnchorPreset == AnchorPresets.TopLeft) { - width = Mathf.Max(width, control.Right + 4 - Constants.NodeMarginX); - height = Mathf.Max(height, control.Bottom + 4 - Constants.NodeMarginY - Constants.NodeHeaderSize); + width = Mathf.Max(width, control.Right + 15 + Constants.NodeMarginX); + height = Mathf.Max(height, control.Bottom + 4 - Constants.NodeMarginY - Constants.NodeHeaderHeight); } else if (!_headerRect.Intersects(control.Bounds)) { - width = Mathf.Max(width, control.Width + 4); + width = Mathf.Max(width, control.Width + 15 + Constants.NodeMarginX); height = Mathf.Max(height, control.Height + 4); } } @@ -325,6 +347,11 @@ namespace FlaxEditor.Surface Elements.Add(element); if (element is Control control) AddChild(control); + + if (!Archetype.UseFixedSize) + ResizeAuto(); + else + Resize(Archetype.Size.X, Archetype.Size.Y); } /// @@ -365,7 +392,7 @@ namespace FlaxEditor.Surface // Sync properties for exiting box box.Text = text; box.CurrentType = type; - box.Y = Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY; + box.Y = Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY; } // Update box @@ -434,7 +461,7 @@ namespace FlaxEditor.Surface private static readonly List UpdateStack = new List(); /// - /// Updates dependant/independent boxes types. + /// Updates dependent/independent boxes types. /// public void UpdateBoxesTypes() { @@ -776,6 +803,24 @@ namespace FlaxEditor.Surface return output; } + /// + /// Draws the close button inside of the . + /// + /// The rectangle to draw the close button in. + /// The color of the close button. + public void DrawCloseButton(Rectangle rect, Color color) + { + // Disable vertex snapping to reduce artefacts at the line ends + var features = Render2D.Features; + Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping; + + rect.Expand(-2f); // Don't overshoot the rectangle because of the thickness + Render2D.DrawLine(rect.TopLeft, rect.BottomRight, color, 2f); + Render2D.DrawLine(rect.BottomLeft, rect.TopRight, color, 2f); + + Render2D.Features = features; + } + /// /// Draws all the connections between surface objects related to this node. /// @@ -919,6 +964,11 @@ namespace FlaxEditor.Surface if (Elements[i] is Box box) box.OnConnectionsChanged(); } + + if (!Archetype.UseFixedSize) + ResizeAuto(); + else + Resize(Archetype.Size.X, Archetype.Size.Y); } /// @@ -956,6 +1006,11 @@ namespace FlaxEditor.Surface Surface.AddBatchedUndoAction(new EditNodeValuesAction(this, before, graphEdited)); _isDuringValuesEditing = false; + + if (!Archetype.UseFixedSize) + ResizeAuto(); + else + Resize(Archetype.Size.X, Archetype.Size.Y); } /// @@ -990,6 +1045,11 @@ namespace FlaxEditor.Surface } _isDuringValuesEditing = false; + + if (!Archetype.UseFixedSize) + ResizeAuto(); + else + Resize(Archetype.Size.X, Archetype.Size.Y); } internal void SetIsDuringValuesEditing(bool value) @@ -998,7 +1058,7 @@ namespace FlaxEditor.Surface } /// - /// Sets teh node values from the given pasted source. Can be overriden to perform validation or custom values processing. + /// Sets teh node values from the given pasted source. Can be overridden to perform validation or custom values processing. /// /// The input values array. public virtual void SetValuesPaste(object[] values) @@ -1022,16 +1082,21 @@ namespace FlaxEditor.Surface public virtual void ConnectionTick(Box box) { UpdateBoxesTypes(); + if (!Archetype.UseFixedSize) + ResizeAuto(); + else + Resize(Archetype.Size.X, Archetype.Size.Y); } /// protected override void UpdateRectangles() { const float footerSize = Constants.NodeFooterSize; - const float headerSize = Constants.NodeHeaderSize; + const float headerSize = Constants.NodeHeaderHeight; const float closeButtonMargin = Constants.NodeCloseButtonMargin; const float closeButtonSize = Constants.NodeCloseButtonSize; _headerRect = new Rectangle(0, 0, Width, headerSize); + _headerTextRect = _headerRect with { X = 5f, Width = Width - closeButtonSize - closeButtonMargin * 4f }; _closeButtonRect = new Rectangle(Width - closeButtonSize - closeButtonMargin, closeButtonMargin, closeButtonSize, closeButtonSize); _footerRect = new Rectangle(0, Height - footerSize, Width, footerSize); } @@ -1041,8 +1106,16 @@ namespace FlaxEditor.Surface { var style = Style.Current; - // Background var backgroundRect = new Rectangle(Float2.Zero, Size); + + // Shadow + if (DrawBasicShadow) + { + var shadowRect = backgroundRect.MakeOffsetted(ShadowOffset); + Render2D.FillRectangle(shadowRect, Color.Black.AlphaMultiplied(0.125f)); + } + + // Background Render2D.FillRectangle(backgroundRect, BackgroundColor); // Breakpoint hit @@ -1058,18 +1131,18 @@ namespace FlaxEditor.Surface var headerColor = style.BackgroundHighlighted; if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting) headerColor *= 1.07f; - Render2D.FillRectangle(_headerRect, headerColor); - Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center); + Render2D.FillRectangle(_headerRect, ArchetypeColor); + Render2D.DrawText(style.FontLarge, Title, _headerTextRect, style.Foreground, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1f, Constants.NodeHeaderTextScale); // Close button if ((Archetype.Flags & NodeFlags.NoCloseButton) == 0 && Surface.CanEdit) { bool highlightClose = _closeButtonRect.Contains(_mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting; - Render2D.DrawSprite(style.Cross, _closeButtonRect, highlightClose ? style.Foreground : style.ForegroundGrey); + DrawCloseButton(_closeButtonRect, highlightClose ? style.Foreground : style.ForegroundGrey); } // Footer - Render2D.FillRectangle(_footerRect, FooterColor); + Render2D.FillRectangle(_footerRect, ArchetypeColor); DrawChildren(); @@ -1078,7 +1151,7 @@ namespace FlaxEditor.Surface { var colorTop = Color.Orange; var colorBottom = Color.OrangeRed; - Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom); + Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom, 2.5f); } // Breakpoint dot diff --git a/Source/Editor/Surface/SurfaceStyle.cs b/Source/Editor/Surface/SurfaceStyle.cs index be09f51be..4fc656823 100644 --- a/Source/Editor/Surface/SurfaceStyle.cs +++ b/Source/Editor/Surface/SurfaceStyle.cs @@ -2,6 +2,7 @@ using System; using FlaxEditor.Scripting; +using FlaxEditor.Surface.Elements; using FlaxEngine; using FlaxEngine.Utilities; @@ -140,6 +141,11 @@ namespace FlaxEditor.Surface /// public Texture Background; + /// + /// The color used as a surface background. + /// + public Color BackgroundColor; + /// /// Boxes drawing callback. /// @@ -216,19 +222,20 @@ namespace FlaxEditor.Surface private static void DefaultDrawBox(Elements.Box box) { - var rect = new Rectangle(Float2.Zero, box.Size); + var rect = new Rectangle(box.Width * 0.5f - Constants.BoxSize * 0.5f, box.Height * 0.5f - Constants.BoxSize * 0.5f, new Float2(Constants.BoxSize)); // Size culling const float minBoxSize = 5.0f; if (rect.Size.LengthSquared < minBoxSize * minBoxSize) return; - // Debugging boxes size + // Debugging boxes size and bounds //Render2D.DrawRectangle(rect, Color.Orange); return; + //Render2D.DrawRectangle(box.Bounds, Color.Green); // Draw icon bool hasConnections = box.HasAnyConnection; - float alpha = box.Enabled && box.IsActive ? 1.0f : 0.6f; + float alpha = box.IsDisabled ? 0.6f : 1.0f; Color color = box.CurrentTypeColor * alpha; var style = box.Surface.Style; SpriteHandle icon; @@ -237,20 +244,37 @@ namespace FlaxEditor.Surface else icon = hasConnections ? style.Icons.BoxClose : style.Icons.BoxOpen; color *= box.ConnectionsHighlightIntensity + 1; + + // Disable vertex snapping to prevent position jitter/ snapping artefacts for the boxes when zooming the surface + var features = Render2D.Features; + Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping; + Render2D.DrawSprite(icon, rect, color); + // Draw connected hint with color from connected output box + if (hasConnections && box.Connections[0] is OutputBox connectedOutputBox) + { + bool connectedSameColor = connectedOutputBox.CurrentTypeColor == box.CurrentTypeColor; + Color innerColor = connectedSameColor ? color.RGBMultiplied(0.4f) : connectedOutputBox.CurrentTypeColor; + innerColor = innerColor * alpha; + Render2D.DrawSprite(icon, rect.MakeExpanded(-5.0f), innerColor); + } + // Draw selection hint if (box.IsSelected) { float outlineAlpha = Mathf.Sin(Time.TimeSinceStartup * 4.0f) * 0.5f + 0.5f; float outlineWidth = Mathf.Lerp(1.5f, 4.0f, outlineAlpha); var outlineRect = new Rectangle(rect.X - outlineWidth, rect.Y - outlineWidth, rect.Width + outlineWidth * 2, rect.Height + outlineWidth * 2); - Render2D.DrawSprite(icon, outlineRect, FlaxEngine.GUI.Style.Current.BorderSelected.RGBMultiplied(1.0f + outlineAlpha * 0.4f)); + Color selectionColor = FlaxEngine.GUI.Style.Current.BorderSelected.RGBMultiplied(1.0f + outlineAlpha * 0.4f); + Render2D.DrawSprite(icon, outlineRect, selectionColor.AlphaMultiplied(0.4f)); } + + Render2D.Features = features; } /// - /// Function used to create style for the given surface type. Can be overriden to provide some customization via user plugin. + /// Function used to create style for the given surface type. Can be overridden to provide some customization via user plugin. /// public static Func CreateStyleHandler = CreateDefault; @@ -293,6 +317,7 @@ namespace FlaxEditor.Surface ArrowClose = editor.Icons.VisjectArrowClosed32, }, Background = editor.UI.VisjectSurfaceBackground, + BackgroundColor = new Color(31, 31, 31), }; } @@ -311,13 +336,11 @@ namespace FlaxEditor.Surface { var dir = sub / length; var arrowRect = new Rectangle(0, 0, 16.0f, 16.0f); - float rotation = Float2.Dot(dir, Float2.UnitY); - if (endPos.X < startPos.X) - rotation = 2 - rotation; + float rotation = Mathf.Atan2(dir.Y, dir.X); var sprite = Editor.Instance.Icons.VisjectArrowClosed32; var arrowTransform = Matrix3x3.Translation2D(-6.5f, -8) * - Matrix3x3.RotationZ(rotation * Mathf.PiOverTwo) * + Matrix3x3.RotationZ(rotation) * Matrix3x3.Translation2D(endPos - dir * 8); Render2D.PushTransform(ref arrowTransform); diff --git a/Source/Editor/Surface/VisjectSurface.Draw.cs b/Source/Editor/Surface/VisjectSurface.Draw.cs index a7d390132..cb7bccae0 100644 --- a/Source/Editor/Surface/VisjectSurface.Draw.cs +++ b/Source/Editor/Surface/VisjectSurface.Draw.cs @@ -65,7 +65,47 @@ namespace FlaxEditor.Surface /// protected virtual void DrawBackground() { - DrawBackgroundDefault(Style.Background, Width, Height); + DrawBackgroundSolidColor(Style.BackgroundColor, Width, Height); + DrawGridBackground(Width, Height); + } + + internal static void DrawBackgroundSolidColor(Color color, float width, float height) + { + Rectangle backgroundRect = new Rectangle(0f, 0f, width, height); + Render2D.FillRectangle(backgroundRect, color); + } + + internal void DrawGridBackground(float width, float height) + { + var viewRect = GetClientArea(); + var upperLeft = _rootControl.PointFromParent(viewRect.Location); + var bottomRight = _rootControl.PointFromParent(viewRect.Size); + var min = Float2.Min(upperLeft, bottomRight); + var max = Float2.Max(upperLeft, bottomRight); + var pixelRange = (max - min) * ViewScale * 2.75f; + Render2D.PushClip(ref viewRect); + DrawAxis(Float2.UnitX, viewRect, min.X, max.X, pixelRange.X); + DrawAxis(Float2.UnitY, viewRect, min.Y, max.Y, pixelRange.Y); + Render2D.PopClip(); + } + + private void DrawAxis(Float2 axis, Rectangle viewRect, float min, float max, float pixelRange) + { + var linesColor = Style.BackgroundColor.RGBMultiplied(1.2f); + float[] _gridTickStrengths = { 0f }; + Utilities.Utils.DrawCurveTicks((decimal tick, double step, float strength) => + { + var p = _rootControl.PointToParent(axis * (float)tick); ; + + // Draw line + var lineRect = new Rectangle + ( + viewRect.Location + (p - 0.5f) * axis, + Float2.Lerp(viewRect.Size, Float2.One, axis) + ); + Render2D.FillRectangle(lineRect, linesColor.AlphaMultiplied(strength)); + + }, Utilities.Utils.CurveTickSteps, ref _gridTickStrengths, min, max, pixelRange); } internal static void DrawBackgroundDefault(Texture background, float width, float height) diff --git a/Source/Editor/Surface/VisjectSurface.cs b/Source/Editor/Surface/VisjectSurface.cs index 9f326f36c..9f0d78bf6 100644 --- a/Source/Editor/Surface/VisjectSurface.cs +++ b/Source/Editor/Surface/VisjectSurface.cs @@ -217,7 +217,7 @@ namespace FlaxEditor.Surface set { // Clamp - value = Mathf.Clamp(value, 0.05f, 1.6f); + value = Mathf.Clamp(value, 0.05f, 1.85f); // Check if value will change if (Mathf.Abs(value - _targetScale) > 0.0001f) diff --git a/Source/Engine/Core/Math/Rectangle.cs b/Source/Engine/Core/Math/Rectangle.cs index 8e3c2b6c4..db34f8f83 100644 --- a/Source/Engine/Core/Math/Rectangle.cs +++ b/Source/Engine/Core/Math/Rectangle.cs @@ -253,6 +253,16 @@ namespace FlaxEngine return new Rectangle(Location + new Float2(x, y), Size); } + /// + /// Make offseted rectangle + /// + /// Offset (will be applied to X- and Y- axis). + /// Offseted rectangle. + public Rectangle MakeOffsetted(float offset) + { + return new Rectangle(Location + new Float2(offset, offset), Size); + } + /// /// Make offseted rectangle ///