Files
FlaxEngine/Source/Editor/Surface/VisjectSurface.Draw.cs
xxSeys1 b44d4107c0 fixes
2025-06-13 22:25:02 +02:00

273 lines
10 KiB
C#

// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.Surface.Elements;
using FlaxEngine;
namespace FlaxEditor.Surface
{
public partial class VisjectSurface
{
/// <inheritdoc />
public override void Update(float deltaTime)
{
// Update scale
var currentScale = _rootControl.Scale.X;
if (Mathf.Abs(_targetScale - currentScale) > 0.001f)
{
var scale = new Float2(Mathf.Lerp(currentScale, _targetScale, deltaTime * 10.0f));
_rootControl.Scale = scale;
}
// Navigate when mouse is near the edge and is doing sth
bool isMovingWithMouse = false;
if (IsMovingSelection || (IsConnecting && !IsPrimaryMenuOpened))
{
var moveVector = Float2.Zero;
float edgeDetectDistance = 22.0f;
if (_mousePos.X < edgeDetectDistance)
{
moveVector.X -= 1;
}
if (_mousePos.Y < edgeDetectDistance)
{
moveVector.Y -= 1;
}
if (_mousePos.X > Width - edgeDetectDistance)
{
moveVector.X += 1;
}
if (_mousePos.Y > Height - edgeDetectDistance)
{
moveVector.Y += 1;
}
moveVector.Normalize();
isMovingWithMouse = moveVector.LengthSquared > Mathf.Epsilon;
if (isMovingWithMouse)
{
_rootControl.Location -= moveVector * _moveViewWithMouseDragSpeed;
}
}
_moveViewWithMouseDragSpeed = isMovingWithMouse ? Mathf.Clamp(_moveViewWithMouseDragSpeed + deltaTime * 20.0f, 1.0f, 8.0f) : 1.0f;
base.Update(deltaTime);
// Batch undo actions
if (_batchedUndoActions != null && _batchedUndoActions.Count != 0)
{
Undo.AddAction(_batchedUndoActions.Count == 1 ? _batchedUndoActions[0] : new MultiUndoAction(_batchedUndoActions));
_batchedUndoActions.Clear();
}
}
/// <summary>
/// Draws the surface background.
/// </summary>
protected virtual void DrawBackground()
{
DrawBackgroundDefault(Style.Background, Width, Height);
}
internal static void DrawBackgroundDefault(Texture background, float width, float height)
{
if (background && background.ResidentMipLevels > 0)
{
var bSize = background.Size;
float bw = bSize.X;
float bh = bSize.Y;
var pos = Float2.Mod(bSize);
if (pos.X > 0)
pos.X -= bw;
if (pos.Y > 0)
pos.Y -= bh;
int maxI = Mathf.CeilToInt(width / bw + 1.0f);
int maxJ = Mathf.CeilToInt(height / bh + 1.0f);
for (int i = 0; i < maxI; i++)
{
for (int j = 0; j < maxJ; j++)
{
Render2D.DrawTexture(background, new Rectangle(pos.X + i * bw, pos.Y + j * bh, bw, bh), Color.White);
}
}
}
}
/// <summary>
/// Draws the selection background.
/// </summary>
/// <remarks>Called only when user is selecting nodes using rectangle tool.</remarks>
protected virtual void DrawSelection()
{
var style = FlaxEngine.GUI.Style.Current;
var selectionRect = Rectangle.FromPoints(_leftMouseDownPos, _mousePos);
Render2D.FillRectangle(selectionRect, style.Selection);
Render2D.DrawRectangle(selectionRect, style.SelectionBorder);
}
/// <summary>
/// Draws all the connections between surface nodes.
/// </summary>
/// <param name="mousePosition">The current mouse position (in surface-space).</param>
protected virtual void DrawConnections(ref Float2 mousePosition)
{
// Draw all connections at once to boost batching process
for (int i = 0; i < Nodes.Count; i++)
{
Nodes[i].DrawConnections(ref mousePosition);
Nodes[i].DrawSelectedConnections(_selectedConnectionIndex);
}
}
/// <summary>
/// Draws the connecting line.
/// </summary>
/// <remarks>Called only when user is connecting nodes.</remarks>
protected virtual void DrawConnectingLine()
{
var cmVisible = _activeVisjectCM != null && _activeVisjectCM.Visible;
var endPos = cmVisible ? _rootControl.PointFromParent(ref _cmStartPos) : _rootControl.PointFromParent(ref _mousePos);
Color lineColor = Style.Colors.Connecting;
List<IConnectionInstigator> instigators = new List<IConnectionInstigator>(_connectionInstigators);
for (int i = 0; i < instigators.Count; i++)
{
IConnectionInstigator currentInstigator = instigators[i];
Float2 currentStartPosition = currentInstigator.ConnectionOrigin;
// Check if mouse is over any of box
if (_lastInstigatorUnderMouse != null && !cmVisible)
{
// Check if can connect objects
bool canConnect = currentInstigator.CanConnectWith(_lastInstigatorUnderMouse);
lineColor = canConnect ? Style.Colors.ConnectingValid : Style.Colors.ConnectingInvalid;
endPos = _lastInstigatorUnderMouse.ConnectionOrigin;
}
Float2 actualStartPos = currentStartPosition;
Float2 actualEndPos = endPos;
if (currentInstigator is Archetypes.Tools.RerouteNode)
{
if (endPos.X < currentStartPosition.X && _lastInstigatorUnderMouse is null or Box { IsOutput: true })
{
actualStartPos = endPos;
actualEndPos = currentStartPosition;
}
}
else if (currentInstigator is Box { IsOutput: false })
{
actualStartPos = endPos;
actualEndPos = currentStartPosition;
}
// Draw connection
currentInstigator.DrawConnectingLine(ref actualStartPos, ref actualEndPos, ref lineColor);
}
}
/// <summary>
/// Draws the brackets and connections
/// </summary>
protected virtual void DrawInputBrackets()
{
var style = FlaxEngine.GUI.Style.Current;
var fadedColor = style.ForegroundGrey;
foreach (var inputBracket in _inputBrackets)
{
// Draw brackets
var upperLeft = _rootControl.PointToParent(inputBracket.Area.UpperLeft);
var bottomRight = _rootControl.PointToParent(inputBracket.Area.BottomRight);
var upperRight = new Float2(bottomRight.X, upperLeft.Y);
var bottomLeft = new Float2(upperLeft.X, bottomRight.Y);
// Calculate control points
float height = bottomLeft.Y - upperLeft.Y;
float offsetX = height / 10f;
var leftControl1 = new Float2(bottomLeft.X - offsetX, bottomLeft.Y);
var leftControl2 = new Float2(upperLeft.X - offsetX, upperLeft.Y);
// Draw left bracket
Render2D.DrawBezier(bottomLeft, leftControl1, leftControl2, upperLeft, style.Foreground, 2.2f);
// Calculate control points
var rightControl1 = new Float2(bottomRight.X + offsetX, bottomRight.Y);
var rightControl2 = new Float2(upperRight.X + offsetX, upperRight.Y);
// Draw right bracket
Render2D.DrawBezier(bottomRight, rightControl1, rightControl2, upperRight, fadedColor, 2.2f);
// Draw connection bezier
// X-offset at 75%
var bezierStartPoint = new Float2(upperRight.X + offsetX * 0.75f, (upperRight.Y + bottomRight.Y) * 0.5f);
var bezierEndPoint = inputBracket.Box.ParentNode.PointToParent(_rootControl.Parent, inputBracket.Box.Center);
Elements.OutputBox.DrawConnection(Style, ref bezierStartPoint, ref bezierEndPoint, ref fadedColor);
// Debug Area
//Rectangle drawRect = Rectangle.FromPoints(upperLeft, bottomRight);
//Render2D.FillRectangle(drawRect, Color.Green * 0.5f);
}
}
/// <summary>
/// Draws the contents of the surface (nodes, connections, comments, etc.).
/// </summary>
protected virtual void DrawContents()
{
base.Draw();
}
/// <inheritdoc />
public override void Draw()
{
var style = FlaxEngine.GUI.Style.Current;
var rect = new Rectangle(Float2.Zero, Size);
DrawBackground();
_rootControl.DrawComments();
if (IsSelecting)
{
DrawSelection();
}
// Push surface view transform (scale and offset)
Render2D.PushTransform(ref _rootControl._cachedTransform);
var features = Render2D.Features;
Render2D.Features = Render2D.RenderingFeatures.None;
var mousePos = _rootControl.PointFromParent(ref _mousePos);
DrawConnections(ref mousePos);
if (IsConnecting)
{
DrawConnectingLine();
}
Render2D.Features = features;
Render2D.PopTransform();
DrawInputBrackets();
DrawContents();
//Render2D.DrawText(style.FontTitle, string.Format("Scale: {0}", _rootControl.Scale), rect, Enabled ? Color.Red : Color.Black);
// Draw border
if (ContainsFocus)
{
Render2D.DrawRectangle(new Rectangle(1, 1, rect.Width - 2, rect.Height - 2), Editor.IsPlayMode ? Color.OrangeRed : style.BackgroundSelected);
}
// Draw disabled overlay
//if (!Enabled)
// Render2D.FillRectangle(rect, new Color(0.2f, 0.2f, 0.2f, 0.5f), true);
}
}
}