4 Commits

Author SHA1 Message Date
8cf6979f90 _some prog with dynamic linking perhaps
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2026-03-15 22:45:36 +02:00
1ff4ac0402 _maybe prog, trying static linking 2026-03-14 15:50:15 +02:00
801f0f7432 _some prog, needs aot for corlib 2026-03-14 15:50:15 +02:00
8b605dff89 _baseline emscripten build 2026-03-14 15:49:23 +02:00
351 changed files with 2713 additions and 6939 deletions

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please attach a minimal reproduction project if available!
Thanks for taking the time to fill out this bug report! Please attach any minimal reproduction projects!
- type: textarea
id: description-area
attributes:
@@ -17,19 +17,19 @@ body:
id: steps-area
attributes:
label: Steps to reproduce
description: Please provide reproduction steps if available.
description: Please provide reproduction steps if possible.
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
description: What version of Flax did you experience the bug in?
description: What version of Flax are you running?
options:
- '1.8'
- '1.9'
- '1.10'
- '1.11'
- '1.12'
- master branch
default: 3
validations:

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thank you for taking the time to submit this feature request!
Thanks for taking the time to fill out a feature request!
- type: textarea
id: description-area
attributes:
@@ -17,6 +17,6 @@ body:
id: benefits-area
attributes:
label: Benefits
description: Please list what benefits this feature would provide to the engine!
description: Please provide what benefits this feature would provide to the engine!
validations:
required: true

1
.github/data/bt.sh vendored
View File

@@ -9,7 +9,6 @@ gdb -q --batch \
-ex 'handle SIGUSR1 nostop pass' \
-ex 'handle SIGUSR2 nostop pass' \
-ex 'handle SIGCHLD nostop pass' \
-ex 'handle SIG34 nostop pass' \
-ex 'set print thread-events off' \
-return-child-result \
-ex 'run' \

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -20,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Setup .NET Workload
run: |
dotnet workload install android
@@ -34,7 +33,4 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -20,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -31,9 +30,6 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
# Game
@@ -48,7 +44,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -59,7 +55,4 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame

View File

@@ -7,7 +7,6 @@ on:
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=1 -c lfs.transfer.maxretries=2 -c http.version="HTTP/1.1" -c lfs.activitytimeout=60'
jobs:
@@ -28,16 +27,13 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
dotnet workload --info
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output -dotnet=8
- name: Upload
uses: actions/upload-artifact@v4
@@ -64,16 +60,13 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
dotnet workload --info
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output -dotnet=8
- name: Upload
uses: actions/upload-artifact@v4

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -57,7 +56,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -68,9 +67,6 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs -dotnet=8
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
dotnet msbuild Source\Tools\Flax.Build.Tests\Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server
[lfs]
url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false

Binary file not shown.

View File

@@ -337,6 +337,7 @@ VertexOutput VS_SplineModel(ModelInput input)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset;
output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif

Binary file not shown.

View File

@@ -4,7 +4,7 @@
"Major": 1,
"Minor": 12,
"Revision": 0,
"Build": 6910
"Build": 6908
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
@@ -14,14 +14,6 @@
"UseCSharp": true,
"UseLargeWorlds": false,
"UseDotNet": true,
"Windows": {
"UseSDL": false,
},
"Mac": {
"UseSDL": false,
},
"Linux": {
"UseSDL": true,
},
"UseSDL": true
}
}
}

View File

@@ -19,7 +19,7 @@ namespace FlaxEditor.Content.GUI
/// <summary>
/// Gets the target node.
/// </summary>
public ContentFolderTreeNode TargetNode { get; }
public ContentTreeNode TargetNode { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ContentNavigationButton"/> class.
@@ -28,7 +28,7 @@ namespace FlaxEditor.Content.GUI
/// <param name="x">The x position.</param>
/// <param name="y">The y position.</param>
/// <param name="height">The height.</param>
public ContentNavigationButton(ContentFolderTreeNode targetNode, float x, float y, float height)
public ContentNavigationButton(ContentTreeNode targetNode, float x, float y, float height)
: base(x, y, height)
{
TargetNode = targetNode;
@@ -147,7 +147,7 @@ namespace FlaxEditor.Content.GUI
ClearItems();
foreach (var child in Target.TargetNode.Children)
{
if (child is ContentFolderTreeNode node)
if (child is ContentTreeNode node)
{
if (node.Folder.VisibleInHierarchy) // Respect the filter set by ContentFilterConfig.Filter(...)
AddItem(node.Folder.ShortName);
@@ -180,7 +180,7 @@ namespace FlaxEditor.Content.GUI
var item = _items[index];
foreach (var child in Target.TargetNode.Children)
{
if (child is ContentFolderTreeNode node && node.Folder.ShortName == item)
if (child is ContentTreeNode node && node.Folder.ShortName == item)
{
Editor.Instance.Windows.ContentWin.Navigate(node);
return;

View File

@@ -59,7 +59,7 @@ namespace FlaxEditor.Content
/// <summary>
/// Gets the content node.
/// </summary>
public ContentFolderTreeNode Node { get; }
public ContentTreeNode Node { get; }
/// <summary>
/// The subitems of this folder.
@@ -72,7 +72,7 @@ namespace FlaxEditor.Content
/// <param name="type">The folder type.</param>
/// <param name="path">The path to the item.</param>
/// <param name="node">The folder parent node.</param>
internal ContentFolder(ContentFolderType type, string path, ContentFolderTreeNode node)
internal ContentFolder(ContentFolderType type, string path, ContentTreeNode node)
: base(path)
{
FolderType = type;
@@ -118,7 +118,7 @@ namespace FlaxEditor.Content
get
{
var hasParentFolder = ParentFolder != null;
var isContentFolder = Node is MainContentFolderTreeNode;
var isContentFolder = Node is MainContentTreeNode;
return hasParentFolder && !isContentFolder;
}
}

View File

@@ -1,433 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.SceneGraph;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content;
/// <summary>
/// Content folder tree node.
/// </summary>
/// <seealso cref="TreeNode" />
public class ContentFolderTreeNode : TreeNode
{
private DragItems _dragOverItems;
private DragActors _dragActors;
private List<Rectangle> _highlights;
/// <summary>
/// The folder.
/// </summary>
protected ContentFolder _folder;
/// <summary>
/// Whether this node can be deleted.
/// </summary>
public virtual bool CanDelete => true;
/// <summary>
/// Whether this node can be duplicated.
/// </summary>
public virtual bool CanDuplicate => true;
/// <summary>
/// Gets the content folder item.
/// </summary>
public ContentFolder Folder => _folder;
/// <summary>
/// Gets the type of the folder.
/// </summary>
public ContentFolderType FolderType => _folder.FolderType;
/// <summary>
/// Returns true if that folder can import/manage scripts.
/// </summary>
public bool CanHaveScripts => _folder.CanHaveScripts;
/// <summary>
/// Returns true if that folder can import/manage assets.
/// </summary>
/// <returns>True if can contain assets for project, otherwise false</returns>
public bool CanHaveAssets => _folder.CanHaveAssets;
/// <summary>
/// Gets the parent node.
/// </summary>
public ContentFolderTreeNode ParentNode => Parent as ContentFolderTreeNode;
/// <summary>
/// Gets the folder path.
/// </summary>
public string Path => _folder.Path;
/// <summary>
/// Gets the navigation button label.
/// </summary>
public virtual string NavButtonLabel => _folder.ShortName;
/// <summary>
/// Initializes a new instance of the <see cref="ContentFolderTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="path">The folder path.</param>
public ContentFolderTreeNode(ContentFolderTreeNode parent, string path)
: this(parent, parent?.FolderType ?? ContentFolderType.Other, path)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentFolderTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
protected ContentFolderTreeNode(ContentFolderTreeNode parent, ContentFolderType type, string path)
: base(false, Editor.Instance.Icons.FolderClosed32, Editor.Instance.Icons.FolderOpen32)
{
_folder = new ContentFolder(type, path, this);
Text = _folder.ShortName;
if (parent != null)
{
Folder.ParentFolder = parent.Folder;
Parent = parent;
}
IconColor = Color.Transparent; // Hide default icon, we draw scaled icon manually
UpdateCustomArrowRect();
Editor.Instance?.Windows?.ContentWin?.TryAutoExpandContentNode(this);
}
/// <summary>
/// Updates the custom arrow rectangle so it stays aligned with the current layout.
/// </summary>
private void UpdateCustomArrowRect()
{
var contentWindow = Editor.Instance?.Windows?.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var arrowSize = Mathf.Clamp(12.0f * scale, 10.0f, 20.0f);
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
// Use the current text layout, not just cached values.
var textRect = TextRect;
var iconLeft = textRect.Left - iconSize - 2.0f;
var x = Mathf.Max(iconLeft - arrowSize - 2.0f, 0.0f);
var y = Mathf.Max((HeaderHeight - arrowSize) * 0.5f, 0.0f);
CustomArrowRect = new Rectangle(x, y, arrowSize, arrowSize);
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
base.PerformLayout(force);
UpdateCustomArrowRect();
}
/// <summary>
/// Shows the rename popup for the item.
/// </summary>
public void StartRenaming()
{
if (!_folder.CanRename)
return;
// Start renaming the folder
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(false);
var dialog = RenamePopup.Show(this, TextRect, _folder.ShortName, false);
dialog.Tag = _folder;
dialog.Renamed += popup =>
{
Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text);
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true);
};
dialog.Closed += popup => { Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); };
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
// Update itself
bool isThisVisible;
if (noFilter)
{
// Clear filter
_highlights?.Clear();
isThisVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
}
else
{
// Hide
_highlights?.Clear();
isThisVisible = false;
}
}
// Update children
bool isAnyChildVisible = false;
for (int i = 0; i < _children.Count; i++)
{
if (_children[i] is ContentFolderTreeNode child)
{
child.UpdateFilter(filterText);
isAnyChildVisible |= child.Visible;
}
else if (_children[i] is ContentItemTreeNode itemNode)
{
itemNode.UpdateFilter(filterText);
isAnyChildVisible |= itemNode.Visible;
}
}
if (!noFilter)
{
bool isExpanded = isAnyChildVisible;
if (isExpanded)
Expand(true);
else
Collapse(true);
}
Visible = isThisVisible | isAnyChildVisible;
}
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ContentItemTreeNode)
return -1;
if (other is ContentFolderTreeNode otherNode)
return string.Compare(Text, otherNode.Text, StringComparison.Ordinal);
return base.Compare(other);
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
// Draw all highlights
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
var contentWindow = Editor.Instance.Windows.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var icon = IsExpanded ? Editor.Instance.Icons.FolderOpen32 : Editor.Instance.Icons.FolderClosed32;
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
var iconRect = new Rectangle(TextRect.Left - iconSize - 2.0f, (HeaderHeight - iconSize) * 0.5f, iconSize, iconSize);
Render2D.DrawSprite(icon, iconRect);
}
/// <inheritdoc />
public override void OnDestroy()
{
// Delete folder item
_folder.Dispose();
base.OnDestroy();
}
/// <inheritdoc />
protected override void OnExpandedChanged()
{
base.OnExpandedChanged();
Editor.Instance?.Windows?.ContentWin?.OnContentTreeNodeExpandedChanged(this, IsExpanded);
}
private DragDropEffect GetDragEffect(DragData data)
{
if (_dragActors != null && _dragActors.HasValidDrag)
return DragDropEffect.Move;
if (data is DragDataFiles)
{
if (_folder.CanHaveAssets)
return DragDropEffect.Copy;
}
else
{
if (_dragOverItems != null && _dragOverItems.HasValidDrag)
return DragDropEffect.Move;
}
return DragDropEffect.None;
}
private bool ValidateDragItem(ContentItem item)
{
// Reject itself and any parent
return item != _folder && !item.Find(_folder);
}
private bool ValidateDragActors(ActorNode actor)
{
return actor.CanCreatePrefab && _folder.CanHaveAssets;
}
private void ImportActors(DragActors actors)
{
Select();
foreach (var actorNode in actors.Objects)
{
var actor = actorNode.Actor;
if (actors.Objects.Contains(actorNode.ParentNode as ActorNode))
continue;
Editor.Instance.Prefabs.CreatePrefab(actor, false);
}
Editor.Instance.Windows.ContentWin.RefreshView();
}
/// <inheritdoc />
protected override DragDropEffect OnDragEnterHeader(DragData data)
{
if (data is DragDataFiles)
return _folder.CanHaveAssets ? DragDropEffect.Copy : DragDropEffect.None;
if (_dragActors == null)
_dragActors = new DragActors(ValidateDragActors);
if (_dragActors.OnDragEnter(data))
return DragDropEffect.Move;
if (_dragOverItems == null)
_dragOverItems = new DragItems(ValidateDragItem);
_dragOverItems.OnDragEnter(data);
return GetDragEffect(data);
}
/// <inheritdoc />
protected override DragDropEffect OnDragMoveHeader(DragData data)
{
if (data is DragDataFiles)
return _folder.CanHaveAssets ? DragDropEffect.Copy : DragDropEffect.None;
if (_dragActors != null && _dragActors.HasValidDrag)
return DragDropEffect.Move;
return GetDragEffect(data);
}
/// <inheritdoc />
protected override void OnDragLeaveHeader()
{
_dragOverItems?.OnDragLeave();
_dragActors?.OnDragLeave();
base.OnDragLeaveHeader();
}
/// <inheritdoc />
protected override DragDropEffect OnDragDropHeader(DragData data)
{
var result = DragDropEffect.None;
// Check if drop element or files
if (data is DragDataFiles files)
{
// Import files
Editor.Instance.ContentImporting.Import(files.Files, _folder);
result = DragDropEffect.Copy;
Expand();
}
else if (_dragActors != null && _dragActors.HasValidDrag)
{
ImportActors(_dragActors);
_dragActors.OnDragDrop();
result = DragDropEffect.Move;
Expand();
}
else if (_dragOverItems != null && _dragOverItems.HasValidDrag)
{
// Move items
Editor.Instance.ContentDatabase.Move(_dragOverItems.Objects, _folder);
result = DragDropEffect.Move;
Expand();
}
_dragOverItems?.OnDragDrop();
return result;
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(_folder));
}
/// <inheritdoc />
protected override void OnLongPress()
{
Select();
StartRenaming();
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.F2:
StartRenaming();
return true;
case KeyboardKeys.Delete:
if (Folder.Exists && CanDelete)
Editor.Instance.Windows.ContentWin.Delete(Folder);
return true;
}
if (RootWindow.GetKey(KeyboardKeys.Control))
{
switch (key)
{
case KeyboardKeys.D:
if (Folder.Exists && CanDuplicate)
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
return true;
}
}
}
return base.OnKeyDown(key);
}
}

View File

@@ -1,224 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content;
/// <summary>
/// Tree node for non-folder content items.
/// </summary>
public sealed class ContentItemTreeNode : TreeNode, IContentItemOwner
{
private List<Rectangle> _highlights;
/// <summary>
/// The content item.
/// </summary>
public ContentItem Item { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ContentItemTreeNode"/> class.
/// </summary>
/// <param name="item">The content item.</param>
public ContentItemTreeNode(ContentItem item)
: base(false, Editor.Instance.Icons.Document128, Editor.Instance.Icons.Document128)
{
Item = item ?? throw new ArgumentNullException(nameof(item));
UpdateDisplayedName();
IconColor = Color.Transparent; // Reserve icon space but draw custom thumbnail.
Item.AddReference(this);
}
private static SpriteHandle GetIcon(ContentItem item)
{
if (item == null)
return SpriteHandle.Invalid;
var icon = item.Thumbnail;
if (!icon.IsValid)
icon = item.DefaultThumbnail;
if (!icon.IsValid)
icon = Editor.Instance.Icons.Document128;
return icon;
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
bool isVisible;
if (noFilter)
{
_highlights?.Clear();
isVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isVisible = true;
}
else
{
_highlights?.Clear();
isVisible = false;
}
}
Visible = isVisible;
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
var icon = GetIcon(Item);
if (icon.IsValid)
{
var contentWindow = Editor.Instance.Windows.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
var textRect = TextRect;
var iconRect = new Rectangle(textRect.Left - iconSize - 2.0f, (HeaderHeight - iconSize) * 0.5f, iconSize, iconSize);
Render2D.DrawSprite(icon, iconRect);
}
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
}
/// <inheritdoc />
protected override bool OnMouseDoubleClickHeader(ref Float2 location, MouseButton button)
{
if (button == MouseButton.Left)
{
Editor.Instance.Windows.ContentWin.Open(Item);
return true;
}
return base.OnMouseDoubleClickHeader(ref location, button);
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.Return:
Editor.Instance.Windows.ContentWin.Open(Item);
return true;
case KeyboardKeys.F2:
Editor.Instance.Windows.ContentWin.Rename(Item);
return true;
case KeyboardKeys.Delete:
Editor.Instance.Windows.ContentWin.Delete(Item);
return true;
}
}
return base.OnKeyDown(key);
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(Item));
}
/// <inheritdoc />
public override bool OnShowTooltip(out string text, out Float2 location, out Rectangle area)
{
Item.UpdateTooltipText();
TooltipText = Item.TooltipText;
return base.OnShowTooltip(out text, out location, out area);
}
/// <inheritdoc />
void IContentItemOwner.OnItemDeleted(ContentItem item)
{
}
/// <inheritdoc />
void IContentItemOwner.OnItemRenamed(ContentItem item)
{
UpdateDisplayedName();
}
/// <inheritdoc />
void IContentItemOwner.OnItemReimported(ContentItem item)
{
}
/// <inheritdoc />
void IContentItemOwner.OnItemDispose(ContentItem item)
{
}
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ContentFolderTreeNode)
return 1;
if (other is ContentItemTreeNode otherItem)
return ApplySortOrder(string.Compare(Text, otherItem.Text, StringComparison.InvariantCulture));
return base.Compare(other);
}
/// <inheritdoc />
public override void OnDestroy()
{
Item.RemoveReference(this);
base.OnDestroy();
}
/// <summary>
/// Updates the text of the node.
/// </summary>
public void UpdateDisplayedName()
{
var contentWindow = Editor.Instance?.Windows?.ContentWin;
var showExtensions = contentWindow?.View?.ShowFileExtensions ?? true;
Text = Item.ShowFileExtension || showExtensions ? Item.FileName : Item.ShortName;
}
private static SortType GetSortType()
{
return Editor.Instance?.Windows?.ContentWin?.CurrentSortType ?? SortType.AlphabeticOrder;
}
private static int ApplySortOrder(int result)
{
return GetSortType() == SortType.AlphabeticReverse ? -result : result;
}
}

View File

@@ -0,0 +1,333 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// Content folder tree node.
/// </summary>
/// <seealso cref="TreeNode" />
public class ContentTreeNode : TreeNode
{
private DragItems _dragOverItems;
private List<Rectangle> _highlights;
/// <summary>
/// The folder.
/// </summary>
protected ContentFolder _folder;
/// <summary>
/// Whether this node can be deleted.
/// </summary>
public virtual bool CanDelete => true;
/// <summary>
/// Whether this node can be duplicated.
/// </summary>
public virtual bool CanDuplicate => true;
/// <summary>
/// Gets the content folder item.
/// </summary>
public ContentFolder Folder => _folder;
/// <summary>
/// Gets the type of the folder.
/// </summary>
public ContentFolderType FolderType => _folder.FolderType;
/// <summary>
/// Returns true if that folder can import/manage scripts.
/// </summary>
public bool CanHaveScripts => _folder.CanHaveScripts;
/// <summary>
/// Returns true if that folder can import/manage assets.
/// </summary>
/// <returns>True if can contain assets for project, otherwise false</returns>
public bool CanHaveAssets => _folder.CanHaveAssets;
/// <summary>
/// Gets the parent node.
/// </summary>
public ContentTreeNode ParentNode => Parent as ContentTreeNode;
/// <summary>
/// Gets the folder path.
/// </summary>
public string Path => _folder.Path;
/// <summary>
/// Gets the navigation button label.
/// </summary>
public virtual string NavButtonLabel => _folder.ShortName;
/// <summary>
/// Initializes a new instance of the <see cref="ContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="path">The folder path.</param>
public ContentTreeNode(ContentTreeNode parent, string path)
: this(parent, parent?.FolderType ?? ContentFolderType.Other, path)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
protected ContentTreeNode(ContentTreeNode parent, ContentFolderType type, string path)
: base(false, Editor.Instance.Icons.FolderClosed32, Editor.Instance.Icons.FolderOpen32)
{
_folder = new ContentFolder(type, path, this);
Text = _folder.ShortName;
if (parent != null)
{
Folder.ParentFolder = parent.Folder;
Parent = parent;
}
IconColor = Style.Current.Foreground;
}
/// <summary>
/// Shows the rename popup for the item.
/// </summary>
public void StartRenaming()
{
if (!_folder.CanRename)
return;
// Start renaming the folder
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(false);
var dialog = RenamePopup.Show(this, TextRect, _folder.ShortName, false);
dialog.Tag = _folder;
dialog.Renamed += popup =>
{
Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text);
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true);
};
dialog.Closed += popup => { Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); };
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
// Update itself
bool isThisVisible;
if (noFilter)
{
// Clear filter
_highlights?.Clear();
isThisVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
}
else
{
// Hide
_highlights?.Clear();
isThisVisible = false;
}
}
// Update children
bool isAnyChildVisible = false;
for (int i = 0; i < _children.Count; i++)
{
if (_children[i] is ContentTreeNode child)
{
child.UpdateFilter(filterText);
isAnyChildVisible |= child.Visible;
}
}
bool isExpanded = isAnyChildVisible;
if (isExpanded)
{
Expand(true);
}
else
{
Collapse(true);
}
Visible = isThisVisible | isAnyChildVisible;
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
// Draw all highlights
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
}
/// <inheritdoc />
public override void OnDestroy()
{
// Delete folder item
_folder.Dispose();
base.OnDestroy();
}
private DragDropEffect GetDragEffect(DragData data)
{
if (data is DragDataFiles)
{
if (_folder.CanHaveAssets)
return DragDropEffect.Copy;
}
else
{
if (_dragOverItems.HasValidDrag)
return DragDropEffect.Move;
}
return DragDropEffect.None;
}
private bool ValidateDragItem(ContentItem item)
{
// Reject itself and any parent
return item != _folder && !item.Find(_folder);
}
/// <inheritdoc />
protected override DragDropEffect OnDragEnterHeader(DragData data)
{
if (_dragOverItems == null)
_dragOverItems = new DragItems(ValidateDragItem);
_dragOverItems.OnDragEnter(data);
return GetDragEffect(data);
}
/// <inheritdoc />
protected override DragDropEffect OnDragMoveHeader(DragData data)
{
return GetDragEffect(data);
}
/// <inheritdoc />
protected override void OnDragLeaveHeader()
{
_dragOverItems.OnDragLeave();
base.OnDragLeaveHeader();
}
/// <inheritdoc />
protected override DragDropEffect OnDragDropHeader(DragData data)
{
var result = DragDropEffect.None;
// Check if drop element or files
if (data is DragDataFiles files)
{
// Import files
Editor.Instance.ContentImporting.Import(files.Files, _folder);
result = DragDropEffect.Copy;
Expand();
}
else if (_dragOverItems.HasValidDrag)
{
// Move items
Editor.Instance.ContentDatabase.Move(_dragOverItems.Objects, _folder);
result = DragDropEffect.Move;
Expand();
}
_dragOverItems.OnDragDrop();
return result;
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(_folder));
}
/// <inheritdoc />
protected override void OnLongPress()
{
Select();
StartRenaming();
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.F2:
StartRenaming();
return true;
case KeyboardKeys.Delete:
if (Folder.Exists && CanDelete)
Editor.Instance.Windows.ContentWin.Delete(Folder);
return true;
}
if (RootWindow.GetKey(KeyboardKeys.Control))
{
switch (key)
{
case KeyboardKeys.D:
if (Folder.Exists && CanDuplicate)
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
return true;
}
}
}
return base.OnKeyDown(key);
}
}
}

View File

@@ -7,8 +7,8 @@ namespace FlaxEditor.Content
/// <summary>
/// Content tree node used for main directories.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public class MainContentFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public class MainContentTreeNode : ContentTreeNode
{
private FileSystemWatcher _watcher;
@@ -19,12 +19,12 @@ namespace FlaxEditor.Content
public override bool CanDuplicate => false;
/// <summary>
/// Initializes a new instance of the <see cref="MainContentFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="MainContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent project.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
public MainContentFolderTreeNode(ProjectFolderTreeNode parent, ContentFolderType type, string path)
public MainContentTreeNode(ProjectTreeNode parent, ContentFolderType type, string path)
: base(parent, type, path)
{
_watcher = new FileSystemWatcher(path)

View File

@@ -1,6 +1,5 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
@@ -8,8 +7,8 @@ namespace FlaxEditor.Content
/// <summary>
/// Root tree node for the project workspace.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public sealed class ProjectFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public sealed class ProjectTreeNode : ContentTreeNode
{
/// <summary>
/// The project/
@@ -19,18 +18,18 @@ namespace FlaxEditor.Content
/// <summary>
/// The project content directory.
/// </summary>
public MainContentFolderTreeNode Content;
public MainContentTreeNode Content;
/// <summary>
/// The project source code directory.
/// </summary>
public MainContentFolderTreeNode Source;
public MainContentTreeNode Source;
/// <summary>
/// Initializes a new instance of the <see cref="ProjectFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="ProjectTreeNode"/> class.
/// </summary>
/// <param name="project">The project.</param>
public ProjectFolderTreeNode(ProjectInfo project)
public ProjectTreeNode(ProjectInfo project)
: base(null, project.ProjectFolderPath)
{
Project = project;
@@ -49,29 +48,9 @@ namespace FlaxEditor.Content
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ProjectFolderTreeNode otherProject)
{
var gameProject = Editor.Instance.GameProject;
var engineProject = Editor.Instance.EngineProject;
bool isGame = Project == gameProject;
bool isEngine = Project == engineProject;
bool otherIsGame = otherProject.Project == gameProject;
bool otherIsEngine = otherProject.Project == engineProject;
// Main game project at the top
if (isGame && !otherIsGame)
return -1;
if (!isGame && otherIsGame)
return 1;
// Engine project at the bottom (when distinct)
if (isEngine && !otherIsEngine)
return 1;
if (!isEngine && otherIsEngine)
return -1;
return string.CompareOrdinal(Project.Name, otherProject.Project.Name);
}
// Move the main game project to the top
if (Project.Name == Editor.Instance.GameProject.Name)
return -1;
return base.Compare(other);
}
}

View File

@@ -5,13 +5,13 @@ namespace FlaxEditor.Content
/// <summary>
/// Root tree node for the content workspace.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public sealed class RootContentFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public sealed class RootContentTreeNode : ContentTreeNode
{
/// <summary>
/// Initializes a new instance of the <see cref="RootContentFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="RootContentTreeNode"/> class.
/// </summary>
public RootContentFolderTreeNode()
public RootContentTreeNode()
: base(null, string.Empty)
{
}

View File

@@ -535,8 +535,7 @@ bool GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
{
Function<int32()> f;
f.Bind(ThreadFunction);
uint32 stackSize = 4 * 1024 * 1024; // Larger stack
const auto thread = ThreadSpawner::Start(f, GameCookerServiceInstance.Name, ThreadPriority::Highest, stackSize);
const auto thread = ThreadSpawner::Start(f, GameCookerServiceInstance.Name, ThreadPriority::Highest);
if (thread == nullptr)
{
GameCookerImpl::IsRunning = false;

View File

@@ -49,7 +49,7 @@ ArchitectureType WebPlatformTools::GetArchitecture() const
DotNetAOTModes WebPlatformTools::UseAOT() const
{
return DotNetAOTModes::NoDotnet;
return DotNetAOTModes::MonoAOTDynamic;//MonoAOTStatic;// DotNetAOTModes::None;//DotNetAOTModes::MonoAOTStatic;//DotNetAOTModes::NoDotnet;
}
PixelFormat WebPlatformTools::GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format)
@@ -166,8 +166,9 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
// Move .wasm assemblies into the data files in order for dlopen to work (blocking)
{
Array<String> files;
Array<String> files, files2;
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.wasm"), DirectorySearchOption::AllDirectories);
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.so"), DirectorySearchOption::AllDirectories);
StringView gameWasm = StringUtils::GetFileNameWithoutExtension(gameJs);
for (const String& file : files)
{
@@ -175,6 +176,12 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
for (const String& file : files2)
{
if (StringUtils::GetFileNameWithoutExtension(file) == gameWasm)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
}
// Pack data files into a single file using Emscripten's file_packager tool
@@ -205,15 +212,7 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
FileSystem::CopyFile(dstIcon, platformDataPath / TEXT("favicon.ico"));
}
// Copy custom HTMl template
auto customHtml = platformSettings->CustomHtml.TrimTrailing();
if (customHtml.HasChars())
{
FileSystem::CopyFile(data.OriginalOutputPath / TEXT("FlaxGame.html"), customHtml);
}
// Rename game website main HTML file to match the most common name used by web servers (index.html)
FileSystem::MoveFile(data.OriginalOutputPath / TEXT("index.html"), data.OriginalOutputPath / TEXT("FlaxGame.html"), true);
// TODO: customizable HTML templates
// Insert packaged file system with game data
{
@@ -262,6 +261,8 @@ bool WebPlatformTools::OnPostProcess(CookingData& data)
return false;
GameCooker::PackageFiles();
// TODO: minify/compress output JS files (in Release builds)
LOG(Info, "Output website size: {0} MB", FileSystem::GetDirectorySize(data.OriginalOutputPath) / 1024 / 1024);
return false;

View File

@@ -37,8 +37,8 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
if (cachedData != aotModeCacheValue)
{
LOG(Info, "AOT cache invalidation");
FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache
FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build)
//FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache
//FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build)
}
}
if (!FileSystem::DirectoryExists(data.ManagedCodeOutputPath))

View File

@@ -52,7 +52,6 @@ namespace FlaxEditor.CustomEditors
private readonly List<CustomEditor> _children = new List<CustomEditor>();
private ValueContainer _values;
private bool _isSetBlocked;
private bool _isRebuilding;
private bool _skipChildrenRefresh;
private bool _hasValueDirty;
private bool _rebuildOnRefresh;
@@ -179,7 +178,7 @@ namespace FlaxEditor.CustomEditors
public void RebuildLayout()
{
// Skip rebuilding during init
if (CurrentCustomEditor == this || _isRebuilding)
if (CurrentCustomEditor == this)
return;
// Special case for root objects to run normal layout build
@@ -198,7 +197,6 @@ namespace FlaxEditor.CustomEditors
_parent?.RebuildLayout();
return;
}
_isRebuilding = true;
var control = layout.ContainerControl;
var parent = _parent;
var parentScrollV = (_presenter?.Panel.Parent as Panel)?.VScrollBar?.Value ?? -1;
@@ -218,7 +216,6 @@ namespace FlaxEditor.CustomEditors
// Restore scroll value
if (parentScrollV > -1 && _presenter != null && _presenter.Panel.Parent is Panel panel && panel.VScrollBar != null)
panel.VScrollBar.Value = parentScrollV;
_isRebuilding = false;
}
/// <summary>

View File

@@ -55,8 +55,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
// TODO: consider editing more than one instance of the same prefab asset at once
var prefab = FlaxEngine.Content.Load<Prefab>(actor.PrefabID);
if (prefab)
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(actor.PrefabID);
// TODO: don't stall here?
if (prefab && !prefab.WaitForLoaded())
{
var prefabObjectId = actor.PrefabObjectID;
var prefabInstance = prefab.GetDefaultInstance(ref prefabObjectId);
@@ -202,7 +203,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
//Presenter.BuildLayoutOnUpdate();
// Better way is to just update the reference value using the new default instance of the prefab, created after changes apply
if (Values != null && (Actor)Values[0] && prefab && !prefab.WaitForLoaded())
if (Values != null && prefab && !prefab.WaitForLoaded())
{
var actor = (Actor)Values[0];
var prefabObjectId = actor.PrefabObjectID;

View File

@@ -370,7 +370,7 @@ namespace FlaxEditor.CustomEditors.Editors
SetValue(Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(path)));
else if (value is Asset)
SetValue(FlaxEngine.Content.LoadAsync(path));
else if (value is string || Values.Type == typeof(string))
else if (value is string)
SetValue(path);
}

View File

@@ -61,7 +61,6 @@ public class Editor : EditorModule
options.PrivateDependencies.Add("Renderer");
options.PrivateDependencies.Add("TextureTool");
options.PrivateDependencies.Add("Particles");
options.PrivateDependencies.Add("Terrain");
var platformToolsRoot = Path.Combine(FolderPath, "Cooker", "Platform");
var platformToolsRootExternal = Path.Combine(Globals.EngineRoot, "Source", "Platforms");

View File

@@ -654,7 +654,7 @@ Window* Editor::CreateMainWindow()
PROFILE_MEM(Editor);
Window* window = Managed->GetMainWindow();
#if PLATFORM_LINUX || PLATFORM_MAC
#if PLATFORM_LINUX
// Set window icon
const String iconPath = Globals::BinariesFolder / TEXT("Logo.png");
if (FileSystem::FileExists(iconPath))

View File

@@ -69,11 +69,6 @@ namespace FlaxEditor
/// </summary>
public static string WindowIcon = "Editor/EditorIcon";
/// <summary>
/// The material used for the HS color wheel.
/// </summary>
public static string HSWheelMaterial = "Editor/HSWheel";
/// <summary>
/// The window icons font.
/// </summary>

View File

@@ -1,11 +1,10 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.GUI.Input;
using FlaxEditor.GUI.Tabs;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using System.Collections.Generic;
namespace FlaxEditor.GUI.Dialogs
{
@@ -26,16 +25,15 @@ namespace FlaxEditor.GUI.Dialogs
/// <seealso cref="FlaxEditor.GUI.Dialogs.Dialog" />
public class ColorPickerDialog : Dialog, IColorPickerDialog
{
private const float ButtonsWidth = 60.0f;
private const float PickerMargin = 6.0f;
private const float EyedropperMargin = 8.0f;
private const float RGBAMargin = 12.0f;
private const float HSVMargin = 0.0f;
private const float ChannelsMargin = 4.0f;
private const float ChannelTextWidth = 12.0f;
private const float SavedColorButtonWidth = 20.0f;
private const float SavedColorButtonHeight = 20.0f;
private const float TabHeight = 20;
private const float ValueBoxesWidth = 100.0f;
private const float HSVRGBTextWidth = 15.0f;
private const float ColorPreviewHeight = 50.0f;
private const int SavedColorsAmount = 10;
private Color _initialValue;
private Color _value;
@@ -48,19 +46,16 @@ namespace FlaxEditor.GUI.Dialogs
private ColorValueBox.ColorPickerClosedEvent _onClosed;
private ColorSelectorWithSliders _cSelector;
private Tabs.Tabs _hsvRGBTabs;
private Tab _RGBTab;
private Panel _rgbPanel;
private FloatValueBox _cRed;
private FloatValueBox _cGreen;
private FloatValueBox _cBlue;
private Tab _hsvTab;
private Panel _hsvPanel;
private FloatValueBox _cAlpha;
private FloatValueBox _cHue;
private FloatValueBox _cSaturation;
private FloatValueBox _cValue;
private TextBox _cHex;
private FloatValueBox _cAlpha;
private Button _cCancel;
private Button _cOK;
private Button _cEyedropper;
private Button _cLinearSRGB;
@@ -132,110 +127,97 @@ namespace FlaxEditor.GUI.Dialogs
_savedColors = JsonSerializer.Deserialize<List<Color>>(savedColors);
// Selector
_cSelector = new ColorSelectorWithSliders(180, 21)
_cSelector = new ColorSelectorWithSliders(180, 18)
{
Location = new Float2(PickerMargin, PickerMargin),
Parent = this
};
_cSelector.ColorChanged += x => SelectedColor = x;
_hsvRGBTabs = new Tabs.Tabs
{
Location = new Float2(_cSelector.Right + 30.0f, PickerMargin),
TabsTextHorizontalAlignment = TextAlignment.Center,
Width = ValueBoxesWidth + HSVRGBTextWidth * 2.0f + ChannelsMargin * 2.0f,
Height = (FloatValueBox.DefaultHeight + ChannelsMargin) * 4 + ChannelsMargin,
Parent = this,
};
_hsvRGBTabs.TabsSize = new Float2(_hsvRGBTabs.Width * 0.5f, TabHeight);
_hsvRGBTabs.SelectedTabChanged += SelectedTabChanged;
// RGB Tab
_RGBTab = _hsvRGBTabs.AddTab(new Tab("RGB"));
_rgbPanel = new Panel(ScrollBars.Vertical)
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Parent = _RGBTab,
};
// HSV Tab
_hsvTab = _hsvRGBTabs.AddTab(new Tab("HSV"));
_hsvPanel = new Panel(ScrollBars.Vertical)
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Parent = _hsvTab,
};
// Red
_cRed = new FloatValueBox(0, HSVRGBTextWidth + ChannelsMargin, PickerMargin, ValueBoxesWidth, 0, float.MaxValue, 0.001f)
_cRed = new FloatValueBox(0, _cSelector.Right + PickerMargin + RGBAMargin + ChannelTextWidth, PickerMargin, 100, 0, float.MaxValue, 0.001f)
{
Parent = _rgbPanel,
Parent = this
};
_cRed.ValueChanged += OnRGBAChanged;
// Green
_cGreen = new FloatValueBox(0, _cRed.X, _cRed.Bottom + ChannelsMargin, _cRed.Width, 0, float.MaxValue, 0.001f)
{
Parent = _rgbPanel,
Parent = this
};
_cGreen.ValueChanged += OnRGBAChanged;
// Blue
_cBlue = new FloatValueBox(0, _cRed.X, _cGreen.Bottom + ChannelsMargin, _cRed.Width, 0, float.MaxValue, 0.001f)
{
Parent = _rgbPanel,
Parent = this
};
_cBlue.ValueChanged += OnRGBAChanged;
// Hue
_cHue = new FloatValueBox(0, HSVRGBTextWidth + ChannelsMargin, PickerMargin, ValueBoxesWidth)
// Alpha
_cAlpha = new FloatValueBox(0, _cRed.X, _cBlue.Bottom + ChannelsMargin, _cRed.Width, 0, float.MaxValue, 0.001f)
{
Parent = _hsvPanel,
Category = Utils.ValueCategory.Angle,
Parent = this
};
_cAlpha.ValueChanged += OnRGBAChanged;
// Hue
_cHue = new FloatValueBox(0, PickerMargin + HSVMargin + ChannelTextWidth, _cSelector.Bottom + PickerMargin, 100, 0, 360)
{
Parent = this
};
_cHue.ValueChanged += OnHSVChanged;
// Saturation
_cSaturation = new FloatValueBox(0, _cHue.X, _cHue.Bottom + ChannelsMargin, _cHue.Width, 0, 100.0f, 0.1f)
{
Parent = _hsvPanel,
Parent = this
};
_cSaturation.ValueChanged += OnHSVChanged;
// Value
_cValue = new FloatValueBox(0, _cHue.X, _cSaturation.Bottom + ChannelsMargin, _cHue.Width, 0, float.MaxValue, 0.1f)
{
Parent = _hsvPanel,
Parent = this
};
_cValue.ValueChanged += OnHSVChanged;
// Alpha
_cAlpha = new FloatValueBox(0, _hsvRGBTabs.Left + HSVRGBTextWidth + ChannelsMargin, _hsvRGBTabs.Bottom + ChannelsMargin * 4.0f, ValueBoxesWidth, 0, float.MaxValue, 0.001f)
{
Parent = this,
};
_cAlpha.ValueChanged += OnRGBAChanged;
// Set valid dialog size based on UI content
_dialogSize = Size = new Float2(_cRed.Right + PickerMargin, 300);
// Hex
_cHex = new TextBox(false, _hsvRGBTabs.Left + HSVRGBTextWidth + ChannelsMargin, _cAlpha.Bottom + ChannelsMargin * 2.0f, ValueBoxesWidth)
const float hexTextBoxWidth = 80;
_cHex = new TextBox(false, Width - hexTextBoxWidth - PickerMargin, _cSelector.Bottom + PickerMargin, hexTextBoxWidth)
{
Parent = this,
Parent = this
};
_cHex.EditEnd += OnHexChanged;
// Set valid dialog size based on UI content
_dialogSize = Size = new Float2(_hsvRGBTabs.Right + PickerMargin, _cHex.Bottom + 40.0f + ColorPreviewHeight + PickerMargin);
// Cancel
_cCancel = new Button(Width - ButtonsWidth - PickerMargin, Height - Button.DefaultHeight - PickerMargin, ButtonsWidth)
{
Text = "Cancel",
Parent = this
};
_cCancel.Clicked += OnCancel;
// OK
_cOK = new Button(_cCancel.Left - ButtonsWidth - PickerMargin, _cCancel.Y, ButtonsWidth)
{
Text = "Ok",
Parent = this
};
_cOK.Clicked += OnSubmit;
// Create saved color buttons
CreateAllSavedColorsButtons();
CreateAllSaveButtons();
// Eyedropper button
var style = Style.Current;
_cEyedropper = new Button(_cSelector.BottomLeft.X, _cSelector.BottomLeft.Y - 25.0f, 25.0f, 25.0f)
_cEyedropper = new Button(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin)
{
TooltipText = "Eyedropper tool to pick a color directly from the screen.",
TooltipText = "Eyedropper tool to pick a color directly from the screen",
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Search32),
BackgroundColor = style.Foreground,
BackgroundColorHighlighted = style.Foreground.RGBMultiplied(0.9f),
@@ -244,11 +226,14 @@ namespace FlaxEditor.GUI.Dialogs
Parent = this,
};
_cEyedropper.Clicked += OnEyedropStart;
_cEyedropper.Height = (_cValue.Bottom - _cEyedropper.Y) * 0.5f;
_cEyedropper.Width = _cEyedropper.Height;
_cEyedropper.X -= _cEyedropper.Width;
// Linear/sRGB toggle button
_cLinearSRGB = new Button(_cSelector.X, _cHex.Bottom + PickerMargin)
_cLinearSRGB = new Button(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin)
{
TooltipText = "Toggles between color preview in Linear and sRGB.",
TooltipText = "Toggles between color preview in Linear and sRGB",
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.SplineAligned64),
BackgroundColor = _cEyedropper.BackgroundColor,
BackgroundColorHighlighted = _cEyedropper.BackgroundColorHighlighted,
@@ -276,10 +261,12 @@ namespace FlaxEditor.GUI.Dialogs
foreach (var color in _savedColors)
{
if (color == _value)
{
return;
}
}
// Set color of button to current value
// Set color of button to current value;
button.BackgroundColor = _value;
button.BackgroundColorHighlighted = _value;
button.BackgroundColorSelected = _value.RGBMultiplied(0.8f);
@@ -291,10 +278,10 @@ namespace FlaxEditor.GUI.Dialogs
var savedColors = JsonSerializer.Serialize(_savedColors, typeof(List<Color>));
Editor.Instance.ProjectCache.SetCustomData("ColorPickerSavedColors", savedColors);
// Create new + button
if (_savedColorButtons.Count < SavedColorsAmount)
// create new + button
if (_savedColorButtons.Count < 8)
{
var savedColorButton = new Button(PickerMargin * (_savedColorButtons.Count + 1) + SavedColorButtonWidth * _savedColorButtons.Count, _cHex.Bottom + 40.0f + ColorPreviewHeight * 0.5f, SavedColorButtonWidth, SavedColorButtonHeight)
var savedColorButton = new Button(PickerMargin * (_savedColorButtons.Count + 1) + SavedColorButtonWidth * _savedColorButtons.Count, Height - SavedColorButtonHeight - PickerMargin, SavedColorButtonWidth, SavedColorButtonHeight)
{
Text = "+",
Parent = this,
@@ -311,32 +298,11 @@ namespace FlaxEditor.GUI.Dialogs
}
}
private void SelectedTabChanged(Tabs.Tabs tabs)
{
if (_rgbPanel == null || _hsvPanel == null)
return;
switch (tabs.SelectedTabIndex)
{
// RGB
case 0:
_rgbPanel.Visible = true;
_hsvPanel.Visible = false;
break;
// HSV
case 1:
_rgbPanel.Visible = false;
_hsvPanel.Visible = true;
break;
}
}
private void OnColorPicked(Color32 colorPicked)
{
if (_activeEyedropper)
{
_activeEyedropper = false;
_cEyedropper.BackgroundColor = _cEyedropper.BackgroundColorHighlighted = Style.Current.Foreground;
if (colorPicked != Color.Transparent)
{
Color color = colorPicked;
@@ -351,7 +317,6 @@ namespace FlaxEditor.GUI.Dialogs
private void OnEyedropStart()
{
_activeEyedropper = true;
_cEyedropper.BackgroundColor = _cEyedropper.BackgroundColorHighlighted = Style.Current.BackgroundHighlighted;
Platform.PickScreenColor();
Platform.PickScreenColorDone += OnColorPicked;
}
@@ -369,7 +334,6 @@ namespace FlaxEditor.GUI.Dialogs
if (_disableEvents)
return;
_cHue.Value = Mathf.Wrap(_cHue.Value, 0f, 360f);
SelectedColor = Color.FromHSV(_cHue.Value, _cSaturation.Value / 100.0f, _cValue.Value / 100.0f, _cAlpha.Value);
}
@@ -410,76 +374,64 @@ namespace FlaxEditor.GUI.Dialogs
base.Draw();
switch (_hsvRGBTabs.SelectedTabIndex)
{
// RGB
case 0:
var rgbRect = new Rectangle(_hsvRGBTabs.Left + PickerMargin, _hsvRGBTabs.Top + TabHeight + PickerMargin, 10000, _cRed.Height);
Render2D.DrawText(style.FontMedium, "R", rgbRect, textColor, TextAlignment.Near, TextAlignment.Center);
rgbRect.Location.Y += _cRed.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "G", rgbRect, textColor, TextAlignment.Near, TextAlignment.Center);
rgbRect.Location.Y += _cRed.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "B", rgbRect, textColor, TextAlignment.Near, TextAlignment.Center);
break;
// HSV
case 1:
// Left
var hsvLeftRect = new Rectangle(_hsvRGBTabs.Left + PickerMargin, _hsvRGBTabs.Top + TabHeight + PickerMargin, 10000, _cHue.Height);
Render2D.DrawText(style.FontMedium, "H", hsvLeftRect, textColor, TextAlignment.Near, TextAlignment.Center);
hsvLeftRect.Location.Y += _cHue.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "S", hsvLeftRect, textColor, TextAlignment.Near, TextAlignment.Center);
hsvLeftRect.Location.Y += _cHue.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "V", hsvLeftRect, textColor, TextAlignment.Near, TextAlignment.Center);
// RGBA
var rgbaR = new Rectangle(_cRed.Left - ChannelTextWidth, _cRed.Y, 10000, _cRed.Height);
Render2D.DrawText(style.FontMedium, "R", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cGreen.Y;
Render2D.DrawText(style.FontMedium, "G", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cBlue.Y;
Render2D.DrawText(style.FontMedium, "B", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cAlpha.Y;
Render2D.DrawText(style.FontMedium, "A", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
// Right
var hsvRightRect = new Rectangle(_hsvRGBTabs.Right - HSVRGBTextWidth, _hsvRGBTabs.Top + TabHeight + PickerMargin, ChannelTextWidth, _cHue.Height);
Render2D.DrawText(style.FontMedium, "°", hsvRightRect, textColor, TextAlignment.Near, TextAlignment.Center);
hsvRightRect.Location.Y += _cHue.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "%", hsvRightRect, textColor, TextAlignment.Near, TextAlignment.Center);
hsvRightRect.Location.Y += _cHue.Height + ChannelsMargin;
Render2D.DrawText(style.FontMedium, "%", hsvRightRect, textColor, TextAlignment.Near, TextAlignment.Center);
break;
}
// HSV left
var hsvHl = new Rectangle(_cHue.Left - ChannelTextWidth, _cHue.Y, 10000, _cHue.Height);
Render2D.DrawText(style.FontMedium, "H", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cSaturation.Y;
Render2D.DrawText(style.FontMedium, "S", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cValue.Y;
Render2D.DrawText(style.FontMedium, "V", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
// A
var alphaHexRect = new Rectangle(_hsvRGBTabs.Left + PickerMargin, _cAlpha.Top, ChannelTextWidth, _cAlpha.Height);
Render2D.DrawText(style.FontMedium, "A", alphaHexRect, textColor, TextAlignment.Near, TextAlignment.Center);
// HSV right
var hsvHr = new Rectangle(_cHue.Right + 2, _cHue.Y, 10000, _cHue.Height);
Render2D.DrawText(style.FontMedium, "°", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cSaturation.Y;
Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cValue.Y;
Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
// Hex
alphaHexRect.Y += _cAlpha.Height + ChannelsMargin * 2.0f;
alphaHexRect.X -= 5.0f; // "Hex" is two characters wider than the other labels so we need to adjust for that
Render2D.DrawText(style.FontMedium, "Hex", alphaHexRect, textColor, TextAlignment.Far, TextAlignment.Center);
var hex = new Rectangle(_cHex.Left - 26, _cHex.Y, 10000, _cHex.Height);
Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
// Color difference
var differenceRect = new Rectangle(_hsvRGBTabs.Left, _cHex.Bottom + 40.0f, _hsvRGBTabs.Width, ColorPreviewHeight);
// Draw checkerboard for background of color to help with transparency
Render2D.FillRectangle(differenceRect, Color.White);
var newRect = new Rectangle(_cOK.X - 3, _cHex.Bottom + PickerMargin, 130, 0);
newRect.Size.Y = 50;
Render2D.FillRectangle(newRect, Color.White);
var smallRectSize = 10;
var numHor = Mathf.CeilToInt(differenceRect.Width / smallRectSize);
var numVer = Mathf.CeilToInt(differenceRect.Height / smallRectSize);
Render2D.PushClip(differenceRect);
var numHor = Mathf.FloorToInt(newRect.Width / smallRectSize);
var numVer = Mathf.FloorToInt(newRect.Height / smallRectSize);
// Draw checkerboard for background of color to help with transparency
for (int i = 0; i < numHor; i++)
{
for (int j = 0; j < numVer; j++)
{
if ((i + j) % 2 == 0)
{
var rect = new Rectangle(differenceRect.X + smallRectSize * i, differenceRect.Y + smallRectSize * j, new Float2(smallRectSize));
var rect = new Rectangle(newRect.X + smallRectSize * i, newRect.Y + smallRectSize * j, new Float2(smallRectSize));
Render2D.FillRectangle(rect, Color.Gray);
}
}
}
Render2D.PopClip();
Render2D.FillRectangle(differenceRect, _linear ? _value.ToSRgb() : _value);
Render2D.FillRectangle(newRect, _linear ? _value.ToSRgb() : _value);
}
/// <inheritdoc />
protected override void OnShow()
{
// Apply changes on lost focus
// Auto cancel on lost focus
#if !PLATFORM_LINUX
((WindowRootControl)Root).Window.LostFocus += OnSubmit;
((WindowRootControl)Root).Window.LostFocus += OnWindowLostFocus;
#endif
base.OnShow();
@@ -492,7 +444,6 @@ namespace FlaxEditor.GUI.Dialogs
{
// Cancel eye dropping
_activeEyedropper = false;
_cEyedropper.BackgroundColor = _cEyedropper.BackgroundColorHighlighted = Style.Current.Foreground;
Platform.PickScreenColorDone -= OnColorPicked;
return true;
}
@@ -504,7 +455,9 @@ namespace FlaxEditor.GUI.Dialogs
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (base.OnMouseUp(location, button))
{
return true;
}
var child = GetChildAtRecursive(location);
if (button == MouseButton.Right && child is Button b && b.Tag is Color c)
@@ -566,20 +519,20 @@ namespace FlaxEditor.GUI.Dialogs
}
_savedColorButtons.Clear();
CreateAllSavedColorsButtons();
CreateAllSaveButtons();
// Save new colors
var savedColors = JsonSerializer.Serialize(_savedColors, typeof(List<Color>));
Editor.Instance.ProjectCache.SetCustomData("ColorPickerSavedColors", savedColors);
}
private void CreateAllSavedColorsButtons()
private void CreateAllSaveButtons()
{
// Create saved color buttons
for (int i = 0; i < _savedColors.Count; i++)
{
var savedColor = _savedColors[i];
var savedColorButton = new Button(PickerMargin * (i + 1) + SavedColorButtonWidth * i, _cHex.Bottom + 40.0f + ColorPreviewHeight * 0.5f, SavedColorButtonWidth, SavedColorButtonHeight)
var savedColorButton = new Button(PickerMargin * (i + 1) + SavedColorButtonWidth * i, Height - SavedColorButtonHeight - PickerMargin, SavedColorButtonWidth, SavedColorButtonHeight)
{
Parent = this,
Tag = savedColor,
@@ -590,9 +543,9 @@ namespace FlaxEditor.GUI.Dialogs
savedColorButton.ButtonClicked += OnSavedColorButtonClicked;
_savedColorButtons.Add(savedColorButton);
}
if (_savedColors.Count < SavedColorsAmount)
if (_savedColors.Count < 8)
{
var savedColorButton = new Button(PickerMargin * (_savedColors.Count + 1) + SavedColorButtonWidth * _savedColors.Count, _cHex.Bottom + 40.0f + ColorPreviewHeight * 0.5f, SavedColorButtonWidth, SavedColorButtonHeight)
var savedColorButton = new Button(PickerMargin * (_savedColors.Count + 1) + SavedColorButtonWidth * _savedColors.Count, Height - SavedColorButtonHeight - PickerMargin, SavedColorButtonWidth, SavedColorButtonHeight)
{
Text = "+",
Parent = this,
@@ -604,6 +557,19 @@ namespace FlaxEditor.GUI.Dialogs
}
}
private void OnWindowLostFocus()
{
// Auto apply color on defocus
var autoAcceptColorPickerChange = Editor.Instance.Options.Options.Interface.AutoAcceptColorPickerChange;
if (_useDynamicEditing && _initialValue != _value && _canPassLastChangeEvent && autoAcceptColorPickerChange)
{
_canPassLastChangeEvent = false;
_onChanged?.Invoke(_value, false);
}
OnCancel();
}
/// <inheritdoc />
public override void OnSubmit()
{
@@ -611,9 +577,6 @@ namespace FlaxEditor.GUI.Dialogs
return;
_disableEvents = true;
// Ensure the cursor is restored
Cursor = CursorType.Default;
// Send color event if modified
if (_value != _initialValue)
{
@@ -630,9 +593,6 @@ namespace FlaxEditor.GUI.Dialogs
return;
_disableEvents = true;
// Ensure the cursor is restored
Cursor = CursorType.Default;
// Restore color if modified
if (_useDynamicEditing && _initialValue != _value && _canPassLastChangeEvent)
{

View File

@@ -12,13 +12,6 @@ namespace FlaxEditor.GUI.Dialogs
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
public class ColorSelector : ContainerControl
{
private const String GrayedOutParamName = "GrayedOut";
/// <summary>
/// Offset value applied to mouse cursor position when the user lets go of wheel or sliders.
/// </summary>
protected const float MouseCursorOffset = 6.0f;
/// <summary>
/// The color.
/// </summary>
@@ -29,22 +22,9 @@ namespace FlaxEditor.GUI.Dialogs
/// </summary>
protected Rectangle _wheelRect;
private readonly MaterialBase _hsWheelMaterial;
private readonly SpriteHandle _colorWheelSprite;
private bool _isMouseDownWheel;
private Rectangle wheelDragRect
{
get
{
var hsv = _color.ToHSV();
float hAngle = hsv.X * Mathf.DegreesToRadians;
float hRadius = hsv.Y * _wheelRect.Width * 0.5f;
var hsPos = new Float2(hRadius * Mathf.Cos(hAngle), -hRadius * Mathf.Sin(hAngle));
float wheelBoxSize = IsSliding ? 9.0f : 5.0f;
return new Rectangle(hsPos - (wheelBoxSize * 0.5f) + _wheelRect.Center, new Float2(wheelBoxSize));
}
}
/// <summary>
/// Occurs when selected color gets changed.
/// </summary>
@@ -98,8 +78,7 @@ namespace FlaxEditor.GUI.Dialogs
{
AutoFocus = true;
_hsWheelMaterial = FlaxEngine.Content.LoadAsyncInternal<MaterialBase>(EditorAssets.HSWheelMaterial);
_hsWheelMaterial = _hsWheelMaterial.CreateVirtualInstance();
_colorWheelSprite = Editor.Instance.Icons.ColorWheel128;
_wheelRect = new Rectangle(0, 0, wheelSize, wheelSize);
}
@@ -186,19 +165,17 @@ namespace FlaxEditor.GUI.Dialogs
{
base.Draw();
var hsv = _color.ToHSV();
bool enabled = EnabledInHierarchy;
_hsWheelMaterial.SetParameterValue(GrayedOutParamName, enabled ? 1.0f : 0.5f);
Render2D.DrawMaterial(_hsWheelMaterial, _wheelRect, enabled ? Color.White : Color.Gray);
// Wheel
float boxExpand = (2.0f * 4.0f / 128.0f) * _wheelRect.Width;
Render2D.DrawMaterial(_hsWheelMaterial, _wheelRect, enabled ? Color.White : Color.Gray);
Float3 hsv = _color.ToHSV();
Color hsColor = Color.FromHSV(new Float3(hsv.X, hsv.Y, 1));
Rectangle wheelRect = wheelDragRect;
Render2D.FillRectangle(wheelRect, hsColor);
Render2D.DrawRectangle(wheelRect, Color.Black, _isMouseDownWheel ? 2.0f : 1.0f);
Render2D.DrawSprite(_colorWheelSprite, _wheelRect.MakeExpanded(boxExpand), enabled ? Color.White : Color.Gray);
float hAngle = hsv.X * Mathf.DegreesToRadians;
float hRadius = hsv.Y * _wheelRect.Width * 0.5f;
var hsPos = new Float2(hRadius * Mathf.Cos(hAngle), -hRadius * Mathf.Sin(hAngle));
const float wheelBoxSize = 4.0f;
Render2D.DrawRectangle(new Rectangle(hsPos - (wheelBoxSize * 0.5f) + _wheelRect.Center, new Float2(wheelBoxSize)), _isMouseDownWheel ? Color.Gray : Color.Black);
}
/// <inheritdoc />
@@ -217,15 +194,6 @@ namespace FlaxEditor.GUI.Dialogs
base.OnMouseMove(location);
}
/// <inheritdoc />
public override void OnMouseMoveRelative(Float2 motion)
{
var location = PointFromScreen(FlaxEngine.Input.MouseScreenPosition);
UpdateMouse(ref location);
base.OnMouseMoveRelative(motion);
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
@@ -234,7 +202,6 @@ namespace FlaxEditor.GUI.Dialogs
if (!_isMouseDownWheel)
{
_isMouseDownWheel = true;
Cursor = CursorType.Hidden;
StartMouseCapture();
SlidingStart?.Invoke();
}
@@ -251,10 +218,6 @@ namespace FlaxEditor.GUI.Dialogs
if (button == MouseButton.Left && _isMouseDownWheel)
{
EndMouseCapture();
// Make the cursor appear where the user expects it to be (position of selection rectangle)
Rectangle dragRect = wheelDragRect;
Root.MousePosition = dragRect.Center + MouseCursorOffset;
Cursor = CursorType.Default;
EndSliding();
return true;
}
@@ -283,10 +246,10 @@ namespace FlaxEditor.GUI.Dialogs
/// <seealso cref="ColorSelector" />
public class ColorSelectorWithSliders : ColorSelector
{
private Rectangle _valueSliderRect;
private Rectangle _alphaSliderRect;
private bool _isMouseDownValueSlider;
private bool _isMouseDownAlphaSlider;
private Rectangle _slider1Rect;
private Rectangle _slider2Rect;
private bool _isMouseDownSlider1;
private bool _isMouseDownSlider2;
/// <summary>
/// Initializes a new instance of the <see cref="ColorSelectorWithSliders"/> class.
@@ -297,26 +260,26 @@ namespace FlaxEditor.GUI.Dialogs
: base(wheelSize)
{
// Setup dimensions
const float slidersMargin = 10.0f;
_valueSliderRect = new Rectangle(wheelSize + slidersMargin, 0, slidersThickness, wheelSize);
_alphaSliderRect = new Rectangle(_valueSliderRect.Right + slidersMargin * 1.5f, _valueSliderRect.Y, slidersThickness, _valueSliderRect.Height);
Size = new Float2(_alphaSliderRect.Right, wheelSize);
const float slidersMargin = 8.0f;
_slider1Rect = new Rectangle(wheelSize + slidersMargin, 0, slidersThickness, wheelSize);
_slider2Rect = new Rectangle(_slider1Rect.Right + slidersMargin, _slider1Rect.Y, slidersThickness, _slider1Rect.Height);
Size = new Float2(_slider2Rect.Right, wheelSize);
}
/// <inheritdoc />
protected override void UpdateMouse(ref Float2 location)
{
if (_isMouseDownValueSlider)
if (_isMouseDownSlider1)
{
var hsv = _color.ToHSV();
hsv.Z = 1.0f - Mathf.Saturate((location.Y - _valueSliderRect.Y) / _valueSliderRect.Height);
hsv.Z = 1.0f - Mathf.Saturate((location.Y - _slider1Rect.Y) / _slider1Rect.Height);
Color = Color.FromHSV(hsv, _color.A);
}
else if (_isMouseDownAlphaSlider)
else if (_isMouseDownSlider2)
{
var color = _color;
color.A = 1.0f - Mathf.Saturate((location.Y - _alphaSliderRect.Y) / _alphaSliderRect.Height);
color.A = 1.0f - Mathf.Saturate((location.Y - _slider2Rect.Y) / _slider2Rect.Height);
Color = color;
}
@@ -333,69 +296,56 @@ namespace FlaxEditor.GUI.Dialogs
// Cache data
var style = Style.Current;
var features = Render2D.Features;
Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping;
var hsv = _color.ToHSV();
var hs = hsv;
hs.Z = 1.0f;
Color hsC = Color.FromHSV(hs);
const float slidersOffset = 3.0f;
const float slidersThickness = 4.0f;
// Value slider
float valueKnobExpand = _isMouseDownValueSlider ? 10.0f : 4.0f;
float valueY = _valueSliderRect.Height * (1 - hsv.Z);
float valueKnobWidth = _valueSliderRect.Width + valueKnobExpand;
float valueKnobHeight = _isMouseDownValueSlider ? 7.0f : 4.0f;
float valueKnobX = _valueSliderRect.X - valueKnobExpand * 0.5f;
float valueKnobY = _valueSliderRect.Y + valueY - valueKnobHeight * 0.5f;
Rectangle valueKnobRect = new Rectangle(valueKnobX, valueKnobY, valueKnobWidth, valueKnobHeight);
Render2D.FillRectangle(_valueSliderRect, hsC, hsC, Color.Black, Color.Black);
// Draw one black and one white border to make the knob visible at any saturation level
Render2D.DrawRectangle(valueKnobRect, Color.White, _isMouseDownValueSlider ? 3.0f : 2.0f);
Render2D.DrawRectangle(valueKnobRect, Color.Black, _isMouseDownValueSlider ? 2.0f : 1.0f);
// Value
float valueY = _slider2Rect.Height * (1 - hsv.Z);
var valueR = new Rectangle(_slider1Rect.X - slidersOffset, _slider1Rect.Y + valueY - slidersThickness / 2, _slider1Rect.Width + slidersOffset * 2, slidersThickness);
Render2D.FillRectangle(_slider1Rect, hsC, hsC, Color.Black, Color.Black);
Render2D.DrawRectangle(_slider1Rect, _isMouseDownSlider1 ? style.BackgroundSelected : Color.Black);
Render2D.DrawRectangle(valueR, _isMouseDownSlider1 ? Color.White : Color.Gray);
// Draw checkerboard pattern as background of alpha slider
Render2D.FillRectangle(_alphaSliderRect, Color.White);
var smallRectSize = _alphaSliderRect.Width / 2.0f;
var numHor = Mathf.CeilToInt(_alphaSliderRect.Width / smallRectSize);
var numVer = Mathf.CeilToInt(_alphaSliderRect.Height / smallRectSize);
Render2D.PushClip(_alphaSliderRect);
// Draw checkerboard pattern to part of the alpha slider background
var alphaRect = _slider2Rect;
Render2D.FillRectangle(alphaRect, Color.White);
var smallRectSize = alphaRect.Width * 0.5f;
var numHor = Mathf.CeilToInt(alphaRect.Width / smallRectSize);
var numVer = Mathf.CeilToInt(alphaRect.Height / smallRectSize);
for (int i = 0; i < numHor; i++)
{
for (int j = 0; j < numVer; j++)
{
if ((i + j) % 2 == 0)
{
var rect = new Rectangle(_alphaSliderRect.X + smallRectSize * i, _alphaSliderRect.Y + smallRectSize * j, new Float2(smallRectSize));
var rect = new Rectangle(alphaRect.X + smallRectSize * i, alphaRect.Y + smallRectSize * j, new Float2(smallRectSize));
Render2D.PushClip(alphaRect);
Render2D.FillRectangle(rect, Color.Gray);
Render2D.PopClip();
}
}
}
Render2D.PopClip();
// Alpha slider
float alphaKnobExpand = _isMouseDownAlphaSlider ? 10.0f : 4.0f;
float alphaY = _alphaSliderRect.Height * (1 - _color.A);
float alphaKnobWidth = _alphaSliderRect.Width + alphaKnobExpand;
float alphaKnobHeight = _isMouseDownAlphaSlider ? 7.0f : 4.0f;
float alphaKnobX = _alphaSliderRect.X - alphaKnobExpand * 0.5f;
float alphaKnobY = _alphaSliderRect.Y + alphaY - alphaKnobExpand * 0.5f;
Rectangle alphaKnobRect = new Rectangle(alphaKnobX, alphaKnobY, alphaKnobWidth, alphaKnobHeight);
// Alpha
float alphaY = _slider2Rect.Height * (1 - _color.A);
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
var color = _color;
color.A = 1; // Prevent alpha slider fill from becoming transparent
Render2D.FillRectangle(_alphaSliderRect, color, color, Color.Transparent, Color.Transparent);
// Draw one black and one white border to make the knob visible at any saturation level
Render2D.DrawRectangle(alphaKnobRect, Color.White, _isMouseDownAlphaSlider ? 3.0f : 2.0f);
Render2D.DrawRectangle(alphaKnobRect, Color.Black, _isMouseDownAlphaSlider ? 2.0f : 1.0f);
Render2D.Features = features;
color.A = 1; // Keep slider 2 fill rect from changing color alpha while selecting.
Render2D.FillRectangle(_slider2Rect, color, color, Color.Transparent, Color.Transparent);
Render2D.DrawRectangle(_slider2Rect, _isMouseDownSlider2 ? style.BackgroundSelected : Color.Black);
Render2D.DrawRectangle(alphaR, _isMouseDownSlider2 ? Color.White : Color.Gray);
}
/// <inheritdoc />
public override void OnLostFocus()
{
// Clear flags
_isMouseDownValueSlider = false;
_isMouseDownAlphaSlider = false;
_isMouseDownSlider1 = false;
_isMouseDownSlider2 = false;
base.OnLostFocus();
}
@@ -403,17 +353,15 @@ namespace FlaxEditor.GUI.Dialogs
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (button == MouseButton.Left && _valueSliderRect.Contains(location))
if (button == MouseButton.Left && _slider1Rect.Contains(location))
{
_isMouseDownValueSlider = true;
Cursor = CursorType.Hidden;
_isMouseDownSlider1 = true;
StartMouseCapture();
UpdateMouse(ref location);
}
if (button == MouseButton.Left && _alphaSliderRect.Contains(location))
if (button == MouseButton.Left && _slider2Rect.Contains(location))
{
_isMouseDownAlphaSlider = true;
Cursor = CursorType.Hidden;
_isMouseDownSlider2 = true;
StartMouseCapture();
UpdateMouse(ref location);
}
@@ -424,16 +372,10 @@ namespace FlaxEditor.GUI.Dialogs
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (button == MouseButton.Left && (_isMouseDownValueSlider || _isMouseDownAlphaSlider))
if (button == MouseButton.Left && (_isMouseDownSlider1 || _isMouseDownSlider2))
{
// Make the cursor appear where the user expects it to be (center of slider horizontally and slider knob position vertically)
float sliderCenter = _isMouseDownValueSlider ? _valueSliderRect.Center.X : _alphaSliderRect.Center.X;
// Calculate y position based on the slider knob to avoid incrementing value by a small amount when the user repeatedly clicks the slider (f.e. when moving in small steps)
float mouseSliderPosition = _isMouseDownValueSlider ? _valueSliderRect.Y + _valueSliderRect.Height * (1 - _color.ToHSV().Z) + MouseCursorOffset : _alphaSliderRect.Y + _alphaSliderRect.Height * (1 - _color.A) + MouseCursorOffset;
Root.MousePosition = new Float2(sliderCenter + MouseCursorOffset, Mathf.Clamp(mouseSliderPosition, _valueSliderRect.Top, _valueSliderRect.Bottom));
Cursor = CursorType.Default;
_isMouseDownValueSlider = false;
_isMouseDownAlphaSlider = false;
_isMouseDownSlider1 = false;
_isMouseDownSlider2 = false;
EndMouseCapture();
return true;
}
@@ -445,8 +387,8 @@ namespace FlaxEditor.GUI.Dialogs
public override void OnEndMouseCapture()
{
// Clear flags
_isMouseDownValueSlider = false;
_isMouseDownAlphaSlider = false;
_isMouseDownSlider1 = false;
_isMouseDownSlider2 = false;
base.OnEndMouseCapture();
}

View File

@@ -135,7 +135,11 @@ namespace FlaxEditor.GUI.Docking
settings.MaximumSize = Float2.Zero; // Unlimited size
settings.Fullscreen = false;
settings.HasBorder = true;
#if PLATFORM_SDL
settings.SupportsTransparency = true;
#else
settings.SupportsTransparency = false;
#endif
settings.ActivateWhenFirstShown = true;
settings.AllowInput = true;
settings.AllowMinimize = true;
@@ -207,7 +211,6 @@ namespace FlaxEditor.GUI.Docking
{
if (ChildPanelsCount > 0)
return;
// Close window
_window?.Close();
}

View File

@@ -269,9 +269,8 @@ namespace FlaxEditor.GUI.Docking
if (_toDock == null)
return;
var window = _toDock.RootWindow?.Window;
if (window != null && window != _dragSourceWindow)
window.MouseUp -= OnMouseUp;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
@@ -328,10 +327,10 @@ namespace FlaxEditor.GUI.Docking
_toDock?.RootWindow.Window.BringToFront();
//_toDock?.RootWindow.Window.Focus();
#if PLATFORM_SDL
// Make the dragged window transparent when dock hints are visible
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
#if !PLATFORM_SDL
#else
// Bring the drop source always to the top
if (_dragSourceWindow != null)
_dragSourceWindow.BringToFront();

View File

@@ -76,23 +76,9 @@ namespace FlaxEditor.GUI
toolstrip.IsLayoutLocked = toolstripLocked;
toolstrip.ItemsMargin = toolstripMargin;
var margin = toolstrip.ItemsMargin;
float xOffset = margin.Left;
bool hadChild = false;
for (int i = 0; i < toolstrip.ChildrenCount; i++)
{
var child = toolstrip.GetChild(i);
if (child == this || !child.Visible)
continue;
hadChild = true;
xOffset += child.Width + margin.Width;
}
var right = hadChild ? xOffset - margin.Width : margin.Left;
var lastToolstripButton = toolstrip.LastButton;
var parentSize = Parent.Size;
var x = right + 8.0f;
var width = Mathf.Max(parentSize.X - x - 8.0f, 0.0f);
Bounds = new Rectangle(x, 0, width, toolstrip.Height);
Bounds = new Rectangle(lastToolstripButton.Right + 8.0f, 0, parentSize.X - X - 8.0f, toolstrip.Height);
}
/// <inheritdoc />

View File

@@ -121,7 +121,7 @@ namespace FlaxEditor.GUI
}
// Select the first platform
_selected = platforms[0].PlatformType;
_selected = PlatformType.Web;
((Image)Children[0]).Color = _selectedColor;
((Image)Children[0]).MouseOverColor = _selectedColor;
}

View File

@@ -2148,9 +2148,10 @@ namespace FlaxEditor.GUI.Timeline
/// </summary>
public void ShowWholeTimeline()
{
const float padding = 40f;
Zoom = (_backgroundArea.Width - padding * 2f) / (Duration * UnitsPerSecond);
_backgroundArea.ViewOffset = new Float2(-_leftEdge.X + padding, _backgroundArea.ViewOffset.Y);
var viewWidth = Width;
var timelineWidth = Duration * UnitsPerSecond * Zoom + 8 * StartOffset;
_backgroundArea.ViewOffset = Float2.Zero;
Zoom = viewWidth / timelineWidth;
}
/// <summary>

View File

@@ -1,300 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.Options;
using FlaxEditor.Viewport;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Gizmo;
[HideInEditor]
internal class DirectionGizmo : ContainerControl
{
public const float DefaultGizmoSize = 112.5f;
private const float AxisLength = 71.25f;
private const float SpriteRadius = 10.85f;
private IGizmoOwner _owner;
private ViewportProjection _viewportProjection;
private EditorViewport _viewport;
private Vector3 _gizmoCenter;
private float _gizmoBrightness;
private float _gizmoOpacity;
private float _backgroundOpacity;
private float _axisLength;
private float _spriteRadius;
private AxisData _xAxisData;
private AxisData _yAxisData;
private AxisData _zAxisData;
private AxisData _negXAxisData;
private AxisData _negYAxisData;
private AxisData _negZAxisData;
private List<AxisData> _axisData = new List<AxisData>();
private int _hoveredAxisIndex = -1;
private SpriteHandle _posHandle;
private SpriteHandle _negHandle;
private FontReference _fontReference;
// Store sprite positions for hover detection
private List<(Float2 position, AxisDirection direction)> _spritePositions = new List<(Float2, AxisDirection)>();
private struct ViewportProjection
{
private Matrix _viewProjection;
private BoundingFrustum _frustum;
private FlaxEngine.Viewport _viewport;
private Vector3 _origin;
public void Init(EditorViewport editorViewport)
{
// Inline EditorViewport.ProjectPoint to save on calculation for large set of points
_viewport = new FlaxEngine.Viewport(0, 0, editorViewport.Width, editorViewport.Height);
_frustum = editorViewport.ViewFrustum;
_viewProjection = _frustum.Matrix;
_origin = editorViewport.Task.View.Origin;
}
public void ProjectPoint(Vector3 worldSpaceLocation, out Float2 viewportSpaceLocation)
{
worldSpaceLocation -= _origin;
_viewport.Project(ref worldSpaceLocation, ref _viewProjection, out var projected);
viewportSpaceLocation = new Float2((float)projected.X, (float)projected.Y);
}
}
private struct AxisData
{
public Float2 Delta;
public float Distance;
public string Label;
public Color AxisColor;
public bool Negative;
public AxisDirection Direction;
}
private enum AxisDirection
{
PosX,
PosY,
PosZ,
NegX,
NegY,
NegZ
}
/// <summary>
/// Constructor of the Direction Gizmo
/// </summary>
/// <param name="owner">The owner of this object.</param>
public DirectionGizmo(IGizmoOwner owner)
{
_owner = owner;
_viewport = owner.Viewport;
_viewportProjection.Init(owner.Viewport);
_xAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "X", AxisColor = new Color(1.0f, 0.0f, 0.02745f, 1.0f), Negative = false, Direction = AxisDirection.PosX };
_yAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "Y", AxisColor = new Color(0.239215f, 1.0f, 0.047058f, 1.0f), Negative = false, Direction = AxisDirection.PosY };
_zAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "Z", AxisColor = new Color(0.0f, 0.3607f, 0.9f, 1.0f), Negative = false, Direction = AxisDirection.PosZ };
_negXAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "-X", AxisColor = new Color(1.0f, 0.0f, 0.02745f, 1.0f), Negative = true, Direction = AxisDirection.NegX };
_negYAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "-Y", AxisColor = new Color(0.239215f, 1.0f, 0.047058f, 1.0f), Negative = true, Direction = AxisDirection.NegY };
_negZAxisData = new AxisData { Delta = new Float2(0, 0), Distance = 0, Label = "-Z", AxisColor = new Color(0.0f, 0.3607f, 0.9f, 1.0f), Negative = true, Direction = AxisDirection.NegZ };
_axisData.EnsureCapacity(6);
_spritePositions.EnsureCapacity(6);
var editor = Editor.Instance;
_posHandle = editor.Icons.VisjectBoxClosed32;
_negHandle = editor.Icons.VisjectBoxOpen32;
_fontReference = new FontReference(Style.Current.FontSmall);
editor.Options.OptionsChanged += OnEditorOptionsChanged;
OnEditorOptionsChanged(editor.Options.Options);
}
private void OnEditorOptionsChanged(EditorOptions options)
{
float gizmoScale = options.Viewport.DirectionGizmoScale;
_axisLength = AxisLength * gizmoScale;
_spriteRadius = SpriteRadius * gizmoScale;
_gizmoBrightness = options.Viewport.DirectionGizmoBrightness;
_gizmoOpacity = options.Viewport.DirectionGizmoOpacity;
_backgroundOpacity = options.Viewport.DirectionGizmoBackgroundOpacity;
_fontReference.Size = 8.25f * gizmoScale;
}
private bool IsPointInSprite(Float2 point, Float2 spriteCenter)
{
Float2 delta = point - spriteCenter;
float distanceSq = delta.LengthSquared;
float radiusSq = _spriteRadius * _spriteRadius;
return distanceSq <= radiusSq;
}
/// <inheritdoc />
public override void OnMouseMove(Float2 location)
{
_hoveredAxisIndex = -1;
// Check which axis is being hovered - check from closest to farthest for proper layering
for (int i = _spritePositions.Count - 1; i >= 0; i--)
{
if (IsPointInSprite(location, _spritePositions[i].position))
{
_hoveredAxisIndex = i;
break;
}
}
base.OnMouseMove(location);
}
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (base.OnMouseUp(location, button))
return true;
// Check which axis is being clicked - check from closest to farthest for proper layering
for (int i = _spritePositions.Count - 1; i >= 0; i--)
{
if (IsPointInSprite(location, _spritePositions[i].position))
{
OrientViewToAxis(_spritePositions[i].direction);
return true;
}
}
return false;
}
private void OrientViewToAxis(AxisDirection direction)
{
Quaternion orientation = direction switch
{
AxisDirection.PosX => Quaternion.Euler(0, -90, 0),
AxisDirection.NegX => Quaternion.Euler(0, 90, 0),
AxisDirection.PosY => Quaternion.Euler(90, 0, 0),
AxisDirection.NegY => Quaternion.Euler(-90, 0, 0),
AxisDirection.PosZ => Quaternion.Euler(0, 180, 0),
AxisDirection.NegZ => Quaternion.Euler(0, 0, 0),
_ => Quaternion.Identity
};
_viewport.OrientViewport(ref orientation);
}
/// <summary>
/// Used to Draw the gizmo.
/// </summary>
public override void DrawSelf()
{
base.DrawSelf();
var features = Render2D.Features;
Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping;
_viewportProjection.Init(_owner.Viewport);
_gizmoCenter = _viewport.Task.View.WorldPosition + _viewport.Task.View.Direction * 1500;
_viewportProjection.ProjectPoint(_gizmoCenter, out var gizmoCenterScreen);
var relativeCenter = Size * 0.5f;
// Project unit vectors
_viewportProjection.ProjectPoint(_gizmoCenter + Vector3.Right, out var xProjected);
_viewportProjection.ProjectPoint(_gizmoCenter + Vector3.Up, out var yProjected);
_viewportProjection.ProjectPoint(_gizmoCenter + Vector3.Forward, out var zProjected);
_viewportProjection.ProjectPoint(_gizmoCenter - Vector3.Right, out var negXProjected);
_viewportProjection.ProjectPoint(_gizmoCenter - Vector3.Up, out var negYProjected);
_viewportProjection.ProjectPoint(_gizmoCenter - Vector3.Forward, out var negZProjected);
// Normalize by viewport height to keep size independent of FOV and viewport dimensions
float heightNormalization = _viewport.Height / 720.0f; // 720 = reference height
// Fix in axes distance no matter FOV/OrthoScale to keep consistent size regardless of zoom level
if (_owner.Viewport.UseOrthographicProjection)
heightNormalization /= _owner.Viewport.OrthographicScale * 0.5f;
else
{
// This could be some actual math expression, not that hack
var fov = _owner.Viewport.FieldOfView / 60.0f;
float scaleAt30 = 0.1f, scaleAt60 = 1.0f, scaleAt120 = 1.5f, scaleAt180 = 3.0f;
heightNormalization /= Mathf.Lerp(scaleAt30, scaleAt60, fov);
heightNormalization /= Mathf.Lerp(scaleAt60, scaleAt120, Mathf.Saturate(fov - 1));
heightNormalization /= Mathf.Lerp(scaleAt60, scaleAt180, Mathf.Saturate(fov - 2));
}
Float2 xDelta = (xProjected - gizmoCenterScreen) / heightNormalization;
Float2 yDelta = (yProjected - gizmoCenterScreen) / heightNormalization;
Float2 zDelta = (zProjected - gizmoCenterScreen) / heightNormalization;
Float2 negXDelta = (negXProjected - gizmoCenterScreen) / heightNormalization;
Float2 negYDelta = (negYProjected - gizmoCenterScreen) / heightNormalization;
Float2 negZDelta = (negZProjected - gizmoCenterScreen) / heightNormalization;
// Calculate distances from camera to determine draw order
Vector3 cameraPosition = _viewport.Task.View.Position;
float xDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter + Vector3.Right);
float yDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter + Vector3.Up);
float zDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter + Vector3.Forward);
float negXDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter - Vector3.Right);
float negYDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter - Vector3.Up);
float negZDistance = (float)Vector3.Distance(cameraPosition, _gizmoCenter - Vector3.Forward);
_xAxisData.Delta = xDelta;
_xAxisData.Distance = xDistance;
_yAxisData.Delta = yDelta;
_yAxisData.Distance = yDistance;
_zAxisData.Delta = zDelta;
_zAxisData.Distance = zDistance;
_negXAxisData.Delta = negXDelta;
_negXAxisData.Distance = negXDistance;
_negYAxisData.Delta = negYDelta;
_negYAxisData.Distance = negYDistance;
_negZAxisData.Delta = negZDelta;
_negZAxisData.Distance = negZDistance;
// Sort for correct draw order.
_axisData.Clear();
_axisData.AddRange([_xAxisData, _yAxisData, _zAxisData, _negXAxisData, _negYAxisData, _negZAxisData]);
_axisData.Sort((a, b) => -a.Distance.CompareTo(b.Distance));
// Rebuild sprite positions list for hover detection
_spritePositions.Clear();
Render2D.DrawSprite(_posHandle, new Rectangle(0, 0, Size), Color.Black.AlphaMultiplied(_backgroundOpacity));
// Draw in order from farthest to closest
for (int i = 0; i < _axisData.Count; i++)
{
var axis = _axisData[i];
Float2 tipScreen = relativeCenter + axis.Delta * _axisLength;
bool isHovered = _hoveredAxisIndex == i;
// Store sprite position for hover detection
_spritePositions.Add((tipScreen, axis.Direction));
var axisColor = isHovered ? new Color(1.0f, 0.8980392f, 0.039215688f) : axis.AxisColor;
axisColor = axisColor.RGBMultiplied(_gizmoBrightness).AlphaMultiplied(_gizmoOpacity);
var font = _fontReference.GetFont();
if (!axis.Negative)
{
Render2D.DrawLine(relativeCenter, tipScreen, axisColor, 1.5f);
Render2D.DrawSprite(_posHandle, new Rectangle(tipScreen - new Float2(_spriteRadius), new Float2(_spriteRadius * 2)), axisColor);
Render2D.DrawText(font, axis.Label, Color.Black, tipScreen - font.MeasureText(axis.Label) * 0.5f);
}
else
{
Render2D.DrawSprite(_posHandle, new Rectangle(tipScreen - new Float2(_spriteRadius), new Float2(_spriteRadius * 2)), axisColor.RGBMultiplied(0.85f).AlphaMultiplied(0.8f));
if (isHovered)
Render2D.DrawText(font, axis.Label, Color.Black, tipScreen - font.MeasureText(axis.Label) * 0.5f);
}
}
Render2D.Features = features;
}
}

View File

@@ -57,7 +57,7 @@ namespace FlaxEditor.Gizmo
var height = output.Height;
var desc = GPUTextureDescription.New2D(width, height, format, GPUTextureFlags.RenderTarget | GPUTextureFlags.ShaderResource, 1, 1, msaaLevel);
var target = RenderTargetPool.Get(ref desc);
desc = GPUTextureDescription.New2D(width, height, renderContext.Buffers.DepthBuffer.Format, GPUTextureFlags.DepthStencil, 1, 1, msaaLevel);
desc = GPUTextureDescription.New2D(width, height, PixelFormat.D24_UNorm_S8_UInt, GPUTextureFlags.DepthStencil, 1, 1, msaaLevel);
var targetDepth = RenderTargetPool.Get(ref desc);
// Copy frame and clear depth

View File

@@ -529,7 +529,7 @@ namespace FlaxEditor
if (EnableBackground && _view != null)
{
// Draw background
Surface.VisjectSurface.DrawBackgroundDefault(Editor.Instance.UI.VisjectSurfaceBackground, Size, _view.Location);
Surface.VisjectSurface.DrawBackgroundDefault(Editor.Instance.UI.VisjectSurfaceBackground, Width, Height);
if (ShowGrid)
{

View File

@@ -24,22 +24,22 @@ namespace FlaxEditor.Modules
private bool _rebuildInitFlag;
private int _itemsCreated;
private int _itemsDeleted;
private readonly HashSet<MainContentFolderTreeNode> _dirtyNodes = new HashSet<MainContentFolderTreeNode>();
private readonly HashSet<MainContentTreeNode> _dirtyNodes = new HashSet<MainContentTreeNode>();
/// <summary>
/// The project directory.
/// </summary>
public ProjectFolderTreeNode Game { get; private set; }
public ProjectTreeNode Game { get; private set; }
/// <summary>
/// The engine directory.
/// </summary>
public ProjectFolderTreeNode Engine { get; private set; }
public ProjectTreeNode Engine { get; private set; }
/// <summary>
/// The list of all projects workspace directories (including game, engine and plugins projects).
/// </summary>
public readonly List<ProjectFolderTreeNode> Projects = new List<ProjectFolderTreeNode>();
public readonly List<ProjectTreeNode> Projects = new List<ProjectTreeNode>();
/// <summary>
/// The list with all content items proxy objects. Use <see cref="AddProxy"/> and <see cref="RemoveProxy"/> to modify this or <see cref="Rebuild"/> to refresh database when adding new item proxy types.
@@ -116,7 +116,7 @@ namespace FlaxEditor.Modules
/// </summary>
/// <param name="project">The project.</param>
/// <returns>The project workspace or null if not loaded into database.</returns>
public ProjectFolderTreeNode GetProjectWorkspace(ProjectInfo project)
public ProjectTreeNode GetProjectWorkspace(ProjectInfo project)
{
return Projects.FirstOrDefault(x => x.Project == project);
}
@@ -878,7 +878,7 @@ namespace FlaxEditor.Modules
}
}
private void LoadFolder(ContentFolderTreeNode node, bool checkSubDirs)
private void LoadFolder(ContentTreeNode node, bool checkSubDirs)
{
if (node == null)
return;
@@ -957,7 +957,7 @@ namespace FlaxEditor.Modules
if (childFolderNode == null)
{
// Create node
ContentFolderTreeNode n = new ContentFolderTreeNode(node, childPath);
ContentTreeNode n = new ContentTreeNode(node, childPath);
if (!_isDuringFastSetup)
sortChildren = true;
@@ -982,7 +982,7 @@ namespace FlaxEditor.Modules
node.SortChildren();
// Ignore some special folders
if (node is MainContentFolderTreeNode mainNode && mainNode.Folder.ShortName == "Source")
if (node is MainContentTreeNode mainNode && mainNode.Folder.ShortName == "Source")
{
var mainNodeChild = mainNode.Folder.Find(StringUtils.CombinePaths(mainNode.Path, "obj")) as ContentFolder;
if (mainNodeChild != null)
@@ -999,7 +999,7 @@ namespace FlaxEditor.Modules
}
}
private void LoadScripts(ContentFolderTreeNode parent, string[] files)
private void LoadScripts(ContentTreeNode parent, string[] files)
{
for (int i = 0; i < files.Length; i++)
{
@@ -1045,7 +1045,7 @@ namespace FlaxEditor.Modules
}
}
private void LoadAssets(ContentFolderTreeNode parent, string[] files)
private void LoadAssets(ContentTreeNode parent, string[] files)
{
for (int i = 0; i < files.Length; i++)
{
@@ -1097,20 +1097,20 @@ namespace FlaxEditor.Modules
var workspace = GetProjectWorkspace(project);
if (workspace == null)
{
workspace = new ProjectFolderTreeNode(project);
workspace = new ProjectTreeNode(project);
Projects.Add(workspace);
var contentFolder = StringUtils.CombinePaths(project.ProjectFolderPath, "Content");
if (Directory.Exists(contentFolder))
{
workspace.Content = new MainContentFolderTreeNode(workspace, ContentFolderType.Content, contentFolder);
workspace.Content = new MainContentTreeNode(workspace, ContentFolderType.Content, contentFolder);
workspace.Content.Folder.ParentFolder = workspace.Folder;
}
var sourceFolder = StringUtils.CombinePaths(project.ProjectFolderPath, "Source");
if (Directory.Exists(sourceFolder))
{
workspace.Source = new MainContentFolderTreeNode(workspace, ContentFolderType.Source, sourceFolder);
workspace.Source = new MainContentTreeNode(workspace, ContentFolderType.Source, sourceFolder);
workspace.Source.Folder.ParentFolder = workspace.Folder;
}
}
@@ -1218,16 +1218,16 @@ namespace FlaxEditor.Modules
Proxy.Add(new GenericJsonAssetProxy());
// Create content folders nodes
Engine = new ProjectFolderTreeNode(Editor.EngineProject)
Engine = new ProjectTreeNode(Editor.EngineProject)
{
Content = new MainContentFolderTreeNode(Engine, ContentFolderType.Content, Globals.EngineContentFolder),
Content = new MainContentTreeNode(Engine, ContentFolderType.Content, Globals.EngineContentFolder),
};
if (Editor.GameProject != Editor.EngineProject)
{
Game = new ProjectFolderTreeNode(Editor.GameProject)
Game = new ProjectTreeNode(Editor.GameProject)
{
Content = new MainContentFolderTreeNode(Game, ContentFolderType.Content, Globals.ProjectContentFolder),
Source = new MainContentFolderTreeNode(Game, ContentFolderType.Source, Globals.ProjectSourceFolder),
Content = new MainContentTreeNode(Game, ContentFolderType.Content, Globals.ProjectContentFolder),
Source = new MainContentTreeNode(Game, ContentFolderType.Source, Globals.ProjectSourceFolder),
};
// TODO: why it's required? the code above should work for linking the nodes hierarchy
Game.Content.Folder.ParentFolder = Game.Folder;
@@ -1307,7 +1307,7 @@ namespace FlaxEditor.Modules
}
}
internal void OnDirectoryEvent(MainContentFolderTreeNode node, FileSystemEventArgs e)
internal void OnDirectoryEvent(MainContentTreeNode node, FileSystemEventArgs e)
{
// Ensure to be ready for external events
if (_isDuringFastSetup)

View File

@@ -710,10 +710,6 @@ namespace FlaxEditor.Options
[EditorDisplay("Node Editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.A, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Shift+F")]
[EditorDisplay("Node Editors"), EditorOrder(4590)]
public InputBinding FocusSelectedNodes = new InputBinding(KeyboardKeys.F, KeyboardKeys.Shift);
#endregion
}
}

View File

@@ -253,6 +253,13 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(280), Tooltip("Editor content window orientation.")]
public FlaxEngine.GUI.Orientation ContentWindowOrientation { get; set; } = FlaxEngine.GUI.Orientation.Horizontal;
/// <summary>
/// If checked, color pickers will always modify the color unless 'Cancel' if pressed, otherwise color won't change unless 'Ok' is pressed.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Interface"), EditorOrder(290)]
public bool AutoAcceptColorPickerChange { get; set; } = true;
/// <summary>
/// Gets or sets the formatting option for numeric values in the editor.
/// </summary>

View File

@@ -171,40 +171,5 @@ namespace FlaxEditor.Options
[DefaultValue(1000.0f), Limit(0.0f, 20000.0f, 5.0f)]
[EditorDisplay("Viewport Icons"), EditorOrder(410)]
public float MaxSizeDistance { get; set; } = 1000.0f;
/// <summary>
/// Gets or sets a value that indicates whether the main viewports <see cref="Gizmo.DirectionGizmo"/> is visible.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Direction Gizmo"), EditorOrder(500), Tooltip("Sets the visibility of the direction gizmo in the main editor viewport.")]
public bool ShowDirectionGizmo { get; set; } = true;
/// <summary>
/// Gets or sets a value by which the main viewports <see cref="Gizmo.DirectionGizmo"/> size is multiplied with.
/// </summary>
[DefaultValue(1f), Limit(0.0f, 2.0f)]
[EditorDisplay("Direction Gizmo"), EditorOrder(501), Tooltip("The scale of the direction gizmo in the main viewport.")]
public float DirectionGizmoScale { get; set; } = 1f;
/// <summary>
/// Gets or sets a value for the opacity of the main viewports <see cref="Gizmo.DirectionGizmo"/> background.
/// </summary>
[DefaultValue(0.1f), Limit(0.0f, 1.0f)]
[EditorDisplay("Direction Gizmo"), EditorOrder(502), Tooltip("The background opacity of the of the direction gizmo in the main viewport.")]
public float DirectionGizmoBackgroundOpacity { get; set; } = 0.1f;
/// <summary>
/// Gets or sets a value for the opacity of the main viewports <see cref="Gizmo.DirectionGizmo"/>.
/// </summary>
[DefaultValue(0.6f), Limit(0.0f, 1.0f)]
[EditorDisplay("Direction Gizmo"), EditorOrder(503), Tooltip("The opacity of the of the direction gizmo in the main viewport.")]
public float DirectionGizmoOpacity { get; set; } = 0.6f;
/// <summary>
/// Gets or sets a value for the opacity of the main viewports <see cref="Gizmo.DirectionGizmo"/>.
/// </summary>
[DefaultValue(1f), Limit(0.0f, 2.0f)]
[EditorDisplay("Direction Gizmo"), EditorOrder(504), Tooltip("The brightness of the of the direction gizmo in the main viewport.")]
public float DirectionGizmoBrightness{ get; set; } = 1f;
}
}

View File

@@ -1,29 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors
{
/// <summary>
/// Scene tree node for <see cref="Cloth"/> actor type.
/// </summary>
[HideInEditor]
public sealed class ClothNode : ActorNode
{
/// <inheritdoc />
public ClothNode(Actor actor)
: base(actor)
{
}
/// <inheritdoc />
public override void PostSpawn()
{
base.PostSpawn();
// Snap to the parent
if (!(ParentNode is SceneNode))
Actor.LocalTransform = Transform.Identity;
}
}
}

View File

@@ -1,29 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors
{
/// <summary>
/// Scene tree node for <see cref="RigidBody"/> actor type.
/// </summary>
[HideInEditor]
public sealed class RigidBodyNode : ActorNode
{
/// <inheritdoc />
public RigidBodyNode(Actor actor)
: base(actor)
{
}
/// <inheritdoc />
public override void PostSpawn()
{
base.PostSpawn();
if (HasPrefabLink)
return;
Actor.StaticFlags = StaticFlags.None;
}
}
}

View File

@@ -324,12 +324,13 @@ namespace FlaxEditor.SceneGraph.GUI
isExpanded = Editor.Instance.ProjectCache.IsExpandedActor(ref id);
}
if (!noFilter)
if (isExpanded)
{
if (isExpanded)
Expand(true);
else
Collapse(true);
Expand(true);
}
else
{
Collapse(true);
}
Visible = isThisVisible | isAnyChildVisible;

View File

@@ -51,7 +51,6 @@ namespace FlaxEditor.SceneGraph
CustomNodesTypes.Add(typeof(AudioSource), typeof(AudioSourceNode));
CustomNodesTypes.Add(typeof(BoneSocket), typeof(BoneSocketNode));
CustomNodesTypes.Add(typeof(Decal), typeof(DecalNode));
CustomNodesTypes.Add(typeof(Cloth), typeof(ClothNode));
CustomNodesTypes.Add(typeof(BoxCollider), typeof(BoxColliderNode));
CustomNodesTypes.Add(typeof(SphereCollider), typeof(ColliderNode));
CustomNodesTypes.Add(typeof(CapsuleCollider), typeof(ColliderNode));
@@ -74,7 +73,6 @@ namespace FlaxEditor.SceneGraph
CustomNodesTypes.Add(typeof(NavMesh), typeof(ActorNode));
CustomNodesTypes.Add(typeof(SpriteRender), typeof(SpriteRenderNode));
CustomNodesTypes.Add(typeof(Joint), typeof(JointNode));
CustomNodesTypes.Add(typeof(RigidBody), typeof(RigidBodyNode));
}
/// <summary>

View File

@@ -102,14 +102,8 @@ 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;
}
/// <inheritdoc />
@@ -569,9 +563,6 @@ namespace FlaxEditor.Surface.Archetypes
// Grid
_node.DrawEditorGrid(ref rect);
var features = Render2D.Features;
Render2D.Features = features & ~Render2D.RenderingFeatures.VertexSnapping;
base.Draw();
// Draw debug position
@@ -587,8 +578,6 @@ namespace FlaxEditor.Surface.Archetypes
Render2D.DrawSprite(icon, debugRect, style.ProgressNormal);
}
Render2D.Features = features;
// Frame
var frameColor = containsFocus ? style.BackgroundSelected : (IsMouseOver ? style.ForegroundGrey : style.ForegroundDisabled);
Render2D.DrawRectangle(new Rectangle(1, 1, rect.Width - 2, rect.Height - 2), frameColor);

View File

@@ -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.NodeHeaderHeight;
var uiStartPosY = FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize;
var editButton = new Button(marginX, uiStartPosY, 246, 20)
{

View File

@@ -70,9 +70,6 @@ namespace FlaxEditor.Surface.Archetypes
if (box.ID != _assetBox.ID)
return;
_assetSelect.Visible = !box.HasAnyConnection;
if (!Archetype.Flags.HasFlag(NodeFlags.FixedSize))
ResizeAuto();
}
}
@@ -246,8 +243,8 @@ namespace FlaxEditor.Surface.Archetypes
{
Type = NodeElementType.Input,
Position = new Float2(
FlaxEditor.Surface.Constants.NodeMarginX,
FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderHeight + ylevel * FlaxEditor.Surface.Constants.LayoutOffsetY),
FlaxEditor.Surface.Constants.NodeMarginX - FlaxEditor.Surface.Constants.BoxOffsetX,
FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize + ylevel * FlaxEditor.Surface.Constants.LayoutOffsetY),
Text = "Pose " + _blendPoses.Count,
Single = true,
ValueIndex = -1,
@@ -266,7 +263,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.NodeHeaderHeight + FlaxEditor.Surface.Constants.NodeFooterSize;
Height = nodeHeight + FlaxEditor.Surface.Constants.NodeMarginY * 2 + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.NodeFooterSize;
}
/// <inheritdoc />
@@ -624,8 +621,8 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new MultiBlend1D(id, context, arch, groupArch),
Title = "Multi Blend 1D",
Description = "Animation blending in 1D",
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize | NodeFlags.FixedSize,
Size = new Float2(420, 320),
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize,
Size = new Float2(420, 300),
DefaultValues = new object[]
{
// Node data
@@ -649,9 +646,9 @@ namespace FlaxEditor.Surface.Archetypes
// Axis X
NodeElementArchetype.Factory.Input(3, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Vector_X(60, 3 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Vector_Y(145, 3 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Vector_X(60, 3 * Surface.Constants.LayoutOffsetY + 2, 0),
NodeElementArchetype.Factory.Vector_Y(145, 3 * Surface.Constants.LayoutOffsetY + 2, 0),
}
},
new NodeArchetype
@@ -660,8 +657,8 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new MultiBlend2D(id, context, arch, groupArch),
Title = "Multi Blend 2D",
Description = "Animation blending in 2D",
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize | NodeFlags.FixedSize,
Size = new Float2(420, 640),
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize,
Size = new Float2(420, 620),
DefaultValues = new object[]
{
// Node data
@@ -685,15 +682,15 @@ namespace FlaxEditor.Surface.Archetypes
// Axis X
NodeElementArchetype.Factory.Input(3, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Vector_X(60, 3 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Vector_Y(145, 3 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Vector_X(60, 3 * Surface.Constants.LayoutOffsetY + 2, 0),
NodeElementArchetype.Factory.Vector_Y(145, 3 * Surface.Constants.LayoutOffsetY + 2, 0),
// Axis Y
NodeElementArchetype.Factory.Input(4, "Y", true, typeof(float), 5),
NodeElementArchetype.Factory.Text(30, 4 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Vector_Z(60, 4 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Vector_W(145, 4 * Surface.Constants.LayoutOffsetY, 0),
NodeElementArchetype.Factory.Text(30, 4 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Vector_Z(60, 4 * Surface.Constants.LayoutOffsetY + 2, 0),
NodeElementArchetype.Factory.Vector_W(145, 4 * Surface.Constants.LayoutOffsetY + 2, 0),
}
},
new NodeArchetype
@@ -934,7 +931,7 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 27,
Title = "Copy Node",
Description = "Copies the skeleton node transformation data (in local space)",
Flags = NodeFlags.AnimGraph | NodeFlags.FixedSize,
Flags = NodeFlags.AnimGraph,
Size = new Float2(260, 140),
DefaultValues = new object[]
{

View File

@@ -189,69 +189,13 @@ namespace FlaxEditor.Surface.Archetypes
public override void 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, BackgroundColor);
// 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);
base.Draw();
// Debug Info
if (!string.IsNullOrEmpty(_debugInfo))
{
// 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);
var style = Style.Current;
Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground);
}
// Debug relevancy outline
@@ -259,7 +203,7 @@ namespace FlaxEditor.Surface.Archetypes
{
var colorTop = Color.LightYellow;
var colorBottom = Color.Yellow;
backgroundRect = new Rectangle(Float2.One, Size - new Float2(2.0f));
var backgroundRect = new Rectangle(Float2.One, Size - new Float2(2.0f));
Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom);
}
}
@@ -471,8 +415,8 @@ namespace FlaxEditor.Surface.Archetypes
// Setup boxes
_input = (InputBox)GetBox(0);
_output = (OutputBox)GetBox(1);
_input.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxRowHeight * -0.5f);
_output.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxRowHeight * 0.5f);
_input.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxSize * -0.5f);
_output.ConnectionOffset = new Float2(0, FlaxEditor.Surface.Constants.BoxSize * 0.5f);
// Setup node type and data
var flagsRoot = NodeFlags.NoRemove | NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaPaste;
@@ -571,7 +515,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.NodeHeaderHeight);
Size = new Float2(width + FlaxEditor.Surface.Constants.NodeMarginX * 2 + FlaxEditor.Surface.Constants.NodeCloseButtonSize, height + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.NodeFooterSize);
UpdateRectangles();
}
@@ -592,13 +536,13 @@ namespace FlaxEditor.Surface.Archetypes
if (decorator.IndexInParent < indexInParent)
decorator.IndexInParent = indexInParent + 1; // Push elements above the node
}
const float headerHeight = FlaxEditor.Surface.Constants.NodeHeaderHeight;
const float footerSize = FlaxEditor.Surface.Constants.NodeFooterSize;
const float headerSize = FlaxEditor.Surface.Constants.NodeHeaderSize;
const float closeButtonMargin = FlaxEditor.Surface.Constants.NodeCloseButtonMargin;
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 };
const float closeButtonSize = FlaxEditor.Surface.Constants.NodeCloseButtonSize;
_headerRect = new Rectangle(0, bounds.Y - Y, bounds.Width, headerSize);
_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;
@@ -704,8 +648,6 @@ 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)
{
@@ -725,7 +667,7 @@ namespace FlaxEditor.Surface.Archetypes
}
}
protected override Color ArchetypeColor => Color.Transparent;
protected override Color FooterColor => Color.Transparent;
protected override Float2 CalculateNodeSize(float width, float height)
{
@@ -734,7 +676,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.NodeHeaderHeight);
return new Float2(width + FlaxEditor.Surface.Constants.NodeCloseButtonSize * 2 + DecoratorsMarginX * 2, height + FlaxEditor.Surface.Constants.NodeHeaderSize);
}
protected override void UpdateRectangles()
@@ -742,14 +684,8 @@ 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)
{
var dragIconRect = _closeButtonRect.MakeExpanded(5f);
_dragIcon.Bounds = new Rectangle(dragIconRect.X - dragIconRect.Width, dragIconRect.Y, dragIconRect.Size);
}
_dragIcon.Bounds = new Rectangle(_closeButtonRect.X - _closeButtonRect.Width, _closeButtonRect.Y, _closeButtonRect.Size);
}
protected override void UpdateTitle()
@@ -818,21 +754,16 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded(action);
var node = Node;
if (action == SurfaceNodeActions.Undo)
{
// Update parent node layout when restoring decorator from undo
var node = Node;
if (node != null)
{
node._decorators = null;
node.ResizeAuto();
}
}
else
{
// Correctly size decorators when surface is loaded
node?.ResizeAuto();
}
}
/// <inheritdoc />

View File

@@ -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", "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" }),
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" }),
new NodeArchetype
{
TypeID = 7,

View File

@@ -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.NodeHeaderHeight, 160, FlaxEditor.Surface.Constants.BoxRowHeight),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 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.NodeHeaderHeight, 160, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 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.NodeHeaderHeight, 160, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 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(90, 20),
Size = new Float2(110, 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(120, 20),
Size = new Float2(110, 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(120, 20),
Size = new Float2(110, 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(45, 20),
Size = new Float2(50, 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(130, 20),
Size = new Float2(170, 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(120, 20),
Size = new Float2(110, 20),
DefaultValues = new object[]
{
0.0d

View File

@@ -267,7 +267,7 @@ namespace FlaxEditor.Surface.Archetypes
{
_nameField = new Label
{
Size = new Float2(140, FlaxEditor.Surface.Constants.BoxRowHeight),
Width = 140.0f,
TextColorHighlighted = Style.Current.ForegroundGrey,
HorizontalAlignment = TextAlignment.Near,
Parent = this,
@@ -386,7 +386,8 @@ namespace FlaxEditor.Surface.Archetypes
_types = surface.FunctionTypes;
_typePicker = new ComboBox
{
Bounds = new Rectangle(4, 34, 80, FlaxEditor.Surface.Constants.BoxRowHeight),
Location = new Float2(4, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
@@ -454,7 +455,8 @@ namespace FlaxEditor.Surface.Archetypes
_types = surface.FunctionTypes;
_typePicker = new ComboBox
{
Bounds = new Rectangle(24, 34, 80, FlaxEditor.Surface.Constants.BoxRowHeight),
Location = new Float2(24, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
@@ -629,7 +631,7 @@ namespace FlaxEditor.Surface.Archetypes
}
/// <inheritdoc />
protected override Color ArchetypeColor => new Color(200, 11, 112);
protected override Color FooterColor => new Color(200, 11, 112);
/// <inheritdoc />
public override void OnLoaded(SurfaceNodeActions action)

View File

@@ -52,7 +52,6 @@ namespace FlaxEditor.Surface.Archetypes
},
new NodeArchetype
{
// [Deprecated]
TypeID = 3,
Title = "Pack Material Layer",
Description = "Pack material properties",
@@ -76,7 +75,6 @@ namespace FlaxEditor.Surface.Archetypes
},
new NodeArchetype
{
// [Deprecated]
TypeID = 4,
Title = "Unpack Material Layer",
Description = "Unpack material properties",
@@ -122,7 +120,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 6,
Title = "Pack Material Layer",
Description = "Pack material properties",
AlternativeTitles = new[] { "Make Material Layer", "Construct Material Layer", "Compose Material Layer" },
Flags = NodeFlags.MaterialGraph,
Size = new Float2(200, 280),
Elements = new[]
@@ -149,7 +146,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 7,
Title = "Unpack Material Layer",
Description = "Unpack material properties",
AlternativeTitles = new[] { "Break Material Layer", "Deconstruct Material Layer", "Decompose Material Layer", "Split Material Layer" },
Flags = NodeFlags.MaterialGraph,
Size = new Float2(210, 280),
Elements = new[]

View File

@@ -312,17 +312,16 @@ 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.NodeHeaderHeight), size;
Float2 pos = new Float2(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize), size;
if (nodeArch.TypeID == 8)
{
pos += new Float2(65, 0);
size = new Float2(160, 185);
_sizeMin = new Float2(240, 185);
pos += new Float2(60, 0);
size = new Float2(172, 200);
}
else
{
pos += new Float2(0, 40 + FlaxEditor.Utilities.Constants.UIMargin * 2f);
size = new Float2(300, 180);
pos += new Float2(0, 40);
size = new Float2(300, 200);
}
_textBox = new CustomCodeTextBox
{
@@ -507,8 +506,8 @@ namespace FlaxEditor.Surface.Archetypes
Size = new Float2(300, 200),
DefaultValues = new object[]
{
"// You can add HLSL code here\nOutput0 = Input0;",
new Float2(350, 200),
"// Here you can add HLSL code\nOutput0 = Input0;",
new Float2(300, 200),
},
Elements = new[]
{
@@ -932,7 +931,7 @@ namespace FlaxEditor.Surface.Archetypes
new NodeArchetype
{
TypeID = 36,
Title = "HSV To RGB",
Title = "HSVToRGB",
Description = "Converts a HSV value to linear RGB [X = 0/360, Y = 0/1, Z = 0/1]",
Flags = NodeFlags.MaterialGraph,
Size = new Float2(160, 25),
@@ -949,7 +948,7 @@ namespace FlaxEditor.Surface.Archetypes
new NodeArchetype
{
TypeID = 37,
Title = "RGB To HSV",
Title = "RGBToHSV",
Description = "Converts a linear RGB value to HSV [X = 0/360, Y = 0/1, Z = 0/1]",
Flags = NodeFlags.MaterialGraph,
Size = new Float2(160, 25),
@@ -973,7 +972,7 @@ namespace FlaxEditor.Surface.Archetypes
Size = new Float2(300, 240),
DefaultValues = new object[]
{
"// You can add HLSL code here\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}",
"// Here you can add HLSL code\nfloat4 GetCustomColor()\n{\n\treturn float4(1, 0, 0, 1);\n}",
true,
(int)MaterialTemplateInputsMapping.Utilities,
new Float2(300, 240),

View File

@@ -213,7 +213,7 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 30,
Title = "Vector Transform",
Description = "Transform vector from source space to destination space",
Flags = NodeFlags.MaterialGraph | NodeFlags.FixedSize,
Flags = NodeFlags.MaterialGraph,
Size = new Float2(170, 40),
DefaultValues = new object[]
{

View File

@@ -342,7 +342,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 20,
Title = "Pack Float2",
Description = "Pack components to Float2",
AlternativeTitles = new[] { "Make Float2", "Construct Float2", "Compose Float2" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 40),
DefaultValues = new object[]
@@ -362,7 +361,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 21,
Title = "Pack Float3",
Description = "Pack components to Float3",
AlternativeTitles = new[] { "Make Float3", "Construct Float3", "Compose Float3" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 60),
DefaultValues = new object[]
@@ -384,7 +382,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 22,
Title = "Pack Float4",
Description = "Pack components to Float4",
AlternativeTitles = new[] { "Make Float4", "Construct Float4", "Compose Float4" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 80),
DefaultValues = new object[]
@@ -408,7 +405,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 23,
Title = "Pack Rotation",
Description = "Pack components to Rotation",
AlternativeTitles = new[] { "Make Rotation", "Construct Rotation", "Compose Rotation" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 60),
DefaultValues = new object[]
@@ -430,7 +426,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 24,
Title = "Pack Transform",
Description = "Pack components to Transform",
AlternativeTitles = new[] { "Make Transform", "Construct Transform", "Compose Transform" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 80),
Elements = new[]
@@ -446,7 +441,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 25,
Title = "Pack Box",
Description = "Pack components to BoundingBox",
AlternativeTitles = new[] { "Make Box", "Construct Box", "Compose Box" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 40),
Elements = new[]
@@ -460,7 +454,6 @@ namespace FlaxEditor.Surface.Archetypes
{
TypeID = 26,
Title = "Pack Structure",
AlternativeTitles = new[] { "Make Structure", "Construct Structure", "Compose Structure" },
Create = (id, context, arch, groupArch) => new PackStructureNode(id, context, arch, groupArch),
IsInputCompatible = PackStructureNode.IsInputCompatible,
IsOutputCompatible = PackStructureNode.IsOutputCompatible,
@@ -486,7 +479,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 30,
Title = "Unpack Float2",
Description = "Unpack components from Float2",
AlternativeTitles = new[] { "Break Float2", "Deconstruct Float2", "Decompose Float2", "Split Float2" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 40),
Elements = new[]
@@ -501,7 +493,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 31,
Title = "Unpack Float3",
Description = "Unpack components from Float3",
AlternativeTitles = new[] { "Break Float3", "Deconstruct Float3", "Decompose Float3", "Split Float3" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 60),
Elements = new[]
@@ -517,7 +508,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 32,
Title = "Unpack Float4",
Description = "Unpack components from Float4",
AlternativeTitles = new[] { "Break Float4", "Deconstruct Float4", "Decompose Float4", "Split Float4" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(150, 80),
Elements = new[]
@@ -534,7 +524,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 33,
Title = "Unpack Rotation",
Description = "Unpack components from Rotation",
AlternativeTitles = new[] { "Break Rotation", "Deconstruct Rotation", "Decompose Rotation", "Split Rotation" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(170, 60),
Elements = new[]
@@ -550,7 +539,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 34,
Title = "Unpack Transform",
Description = "Unpack components from Transform",
AlternativeTitles = new[] { "Break Transform", "Deconstruct Transform", "Decompose Transform", "Split Transform" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(170, 60),
Elements = new[]
@@ -566,7 +554,6 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 35,
Title = "Unpack Box",
Description = "Unpack components from BoundingBox",
AlternativeTitles = new[] { "Break BoundingBox", "Deconstruct BoundingBox", "Decompose BoundingBox", "Split BoundingBox" },
Flags = NodeFlags.AllGraphs,
Size = new Float2(170, 40),
Elements = new[]
@@ -585,7 +572,6 @@ namespace FlaxEditor.Surface.Archetypes
IsOutputCompatible = UnpackStructureNode.IsOutputCompatible,
GetInputOutputDescription = UnpackStructureNode.GetInputOutputDescription,
Description = "Breaks the structure data to allow extracting components from it.",
AlternativeTitles = new[] { "Break Structure", "Deconstruct Structure", "Decompose Structure", "Split Structure" },
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
Size = new Float2(180, 20),
DefaultValues = new object[]

View File

@@ -13,7 +13,6 @@ using FlaxEditor.Scripting;
using FlaxEditor.Surface.Elements;
using FlaxEngine;
using FlaxEngine.Utilities;
using FlaxEditor.Surface.Undo;
namespace FlaxEditor.Surface.Archetypes
{
@@ -23,107 +22,15 @@ namespace FlaxEditor.Surface.Archetypes
[HideInEditor]
public static class Parameters
{
/// <summary>
/// Surface node type for parameters group Get/Set nodes.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
public abstract class SurfaceNodeParamsBase : SurfaceNode
{
/// <summary>
/// The combobox for picking parameter.
/// </summary>
protected ComboBoxElement _combobox;
/// <summary>
/// Fag used to block layout updated when updating node.
/// </summary>
protected bool _isUpdateLocked;
/// <inheritdoc />
protected SurfaceNodeParamsBase(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
: base(id, context, nodeArch, groupArch)
{
}
/// <summary>
/// Gets the selected parameter.
/// </summary>
/// <returns>Surface parameter object or null if nothing selected or cannot find it.</returns>
protected SurfaceParameter GetSelected()
{
if (Surface != null)
return Surface.GetParameter(_combobox.SelectedItem);
return Context.GetParameter((Guid)Values[0]);
}
/// <summary>
/// Updates the combo box.
/// </summary>
protected void UpdateCombo()
{
if (_isUpdateLocked)
return;
_isUpdateLocked = true;
if (_combobox == null)
{
_combobox = GetChild<ComboBoxElement>();
_combobox.SelectedIndexChanged += OnSelectedChanged;
}
string toSelect = null;
Guid loadedSelected = (Guid)Values[0];
_combobox.ClearItems();
var parameters = Surface.Parameters;
for (int i = 0; i < parameters.Count; i++)
{
var param = parameters[i];
if (!param.IsPublic && !Surface.CanShowPrivateParameters)
continue;
_combobox.AddItem(param.Name);
if (param.ID == loadedSelected)
toSelect = param.Name;
}
_combobox.SelectedItem = toSelect;
_isUpdateLocked = false;
}
private void OnSelectedChanged(ComboBox cb)
{
if (_isUpdateLocked)
return;
var selected = GetSelected();
var selectedID = selected?.ID ?? Guid.Empty;
if (selectedID != (Guid)Values[0])
{
if (Surface.Undo != null && Surface.Undo.Enabled)
{
// Capture node connections to support undo
var action = new EditNodeConnections(Context, this);
RemoveConnections();
action.End();
Surface.AddBatchedUndoAction(action);
}
Set(selected, ref selectedID);
}
}
/// <summary>
/// Sets the selected parameter.
/// </summary>
/// <param name="selected">Parameter.</param>
/// <param name="selectedID">Parameter identifier.</param>
protected virtual void Set(SurfaceParameter selected, ref Guid selectedID)
{
SetValue(0, selectedID);
}
}
/// <summary>
/// Surface node type for parameters group Get node.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
public class SurfaceNodeParamsGet : SurfaceNodeParamsBase, IParametersDependantNode
public class SurfaceNodeParamsGet : SurfaceNode, IParametersDependantNode
{
private ComboBoxElement _combobox;
private readonly List<ISurfaceNodeElement> _dynamicChildren = new List<ISurfaceNodeElement>();
private bool _isUpdateLocked;
private ScriptType _layoutType;
private NodeElementArchetype[] _layoutElements;
@@ -399,6 +306,49 @@ namespace FlaxEditor.Surface.Archetypes
UpdateTitle();
}
private void UpdateCombo()
{
if (_isUpdateLocked)
return;
_isUpdateLocked = true;
if (_combobox == null)
{
_combobox = (ComboBoxElement)_children[0];
_combobox.SelectedIndexChanged += OnSelectedChanged;
}
int toSelect = -1;
Guid loadedSelected = (Guid)Values[0];
_combobox.ClearItems();
for (int i = 0; i < Surface.Parameters.Count; i++)
{
var param = Surface.Parameters[i];
_combobox.AddItem(param.Name);
if (param.ID == loadedSelected)
toSelect = i;
}
_combobox.SelectedIndex = toSelect;
_isUpdateLocked = false;
}
private void OnSelectedChanged(ComboBox cb)
{
if (_isUpdateLocked)
return;
var selected = GetSelected();
var selectedID = selected?.ID ?? Guid.Empty;
SetValue(0, selectedID);
}
private SurfaceParameter GetSelected()
{
if (Surface != null)
{
var selectedIndex = _combobox.SelectedIndex;
return selectedIndex >= 0 && selectedIndex < Surface.Parameters.Count ? Surface.Parameters[selectedIndex] : null;
}
return Context.GetParameter((Guid)Values[0]);
}
private void ClearDynamicElements()
{
for (int i = 0; i < _dynamicChildren.Count; i++)
@@ -513,19 +463,15 @@ namespace FlaxEditor.Surface.Archetypes
else if (!_isUpdateLocked)
{
_isUpdateLocked = true;
string toSelect = null;
int toSelect = -1;
Guid loadedSelected = (Guid)Values[0];
var parameters = Surface.Parameters;
for (int i = 0; i < parameters.Count; i++)
for (int i = 0; i < Surface.Parameters.Count; i++)
{
var param = parameters[i];
var param = Surface.Parameters[i];
if (param.ID == loadedSelected)
{
toSelect = param.Name;
break;
}
toSelect = i;
}
_combobox.SelectedItem = toSelect;
_combobox.SelectedIndex = toSelect;
_isUpdateLocked = false;
}
UpdateLayout();
@@ -871,23 +817,66 @@ namespace FlaxEditor.Surface.Archetypes
/// Surface node type for parameters group Set node.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
public class SurfaceNodeParamsSet : SurfaceNodeParamsBase, IParametersDependantNode
public class SurfaceNodeParamsSet : SurfaceNode, IParametersDependantNode
{
private ComboBoxElement _combobox;
private bool _isUpdateLocked;
/// <inheritdoc />
public SurfaceNodeParamsSet(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
: base(id, context, nodeArch, groupArch)
{
}
/// <inheritdoc />
protected override void Set(SurfaceParameter selected, ref Guid selectedID)
private void UpdateCombo()
{
SetValues(new[]
if (_isUpdateLocked)
return;
_isUpdateLocked = true;
if (_combobox == null)
{
selectedID,
selected != null ? TypeUtils.GetDefaultValue(selected.Type) : null,
});
UpdateUI();
_combobox = GetChild<ComboBoxElement>();
_combobox.SelectedIndexChanged += OnSelectedChanged;
}
int toSelect = -1;
Guid loadedSelected = (Guid)Values[0];
_combobox.ClearItems();
for (int i = 0; i < Surface.Parameters.Count; i++)
{
var param = Surface.Parameters[i];
_combobox.AddItem(param.Name);
if (param.ID == loadedSelected)
toSelect = i;
}
_combobox.SelectedIndex = toSelect;
_isUpdateLocked = false;
}
private void OnSelectedChanged(ComboBox cb)
{
if (_isUpdateLocked)
return;
var selected = GetSelected();
var selectedID = selected?.ID ?? Guid.Empty;
if (selectedID != (Guid)Values[0])
{
SetValues(new[]
{
selectedID,
selected != null ? TypeUtils.GetDefaultValue(selected.Type) : null,
});
UpdateUI();
}
}
private SurfaceParameter GetSelected()
{
if (Surface != null)
{
var selectedIndex = _combobox.SelectedIndex;
return selectedIndex >= 0 && selectedIndex < Surface.Parameters.Count ? Surface.Parameters[selectedIndex] : null;
}
return Context.GetParameter((Guid)Values[0]);
}
/// <inheritdoc />

View File

@@ -121,7 +121,7 @@ namespace FlaxEditor.Surface.Archetypes
Render2D.DrawRectangle(new Rectangle(1, 0, Width - 2, Height - 1), Colors[idx]);
// Close button
DrawCloseButton(_closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey);
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey);
// Arrange button
var dragBarColor = _arrangeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey;
@@ -138,12 +138,6 @@ namespace FlaxEditor.Surface.Archetypes
}
}
/// <inheritdoc />
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;
@@ -267,9 +261,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 * 0.75f - closeButtonMargin, closeButtonMargin + 0.25f, closeButtonSize * 0.75f, closeButtonSize * 0.75f);
_closeButtonRect = new Rectangle(Width - closeButtonSize - closeButtonMargin, closeButtonMargin, closeButtonSize, closeButtonSize);
_footerRect = Rectangle.Empty;
_enabled.Location = new Float2(_closeButtonRect.X - _enabled.Width - 2, _closeButtonRect.Y - 0.25f);
_enabled.Location = new Float2(_closeButtonRect.X - _enabled.Width - 2, _closeButtonRect.Y);
_arrangeButtonRect = new Rectangle(_enabled.X - closeButtonSize - closeButtonMargin, closeButtonMargin, closeButtonSize, closeButtonSize);
}
@@ -467,7 +461,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <summary>
/// The particle module node elements offset applied to controls to reduce default surface node header thickness.
/// </summary>
private const float NodeElementsOffset = 16.0f - Surface.Constants.NodeHeaderHeight;
private const float NodeElementsOffset = 16.0f - Surface.Constants.NodeHeaderSize;
private const NodeFlags DefaultModuleFlags = NodeFlags.ParticleEmitterGraph | NodeFlags.NoSpawnViaGUI | NodeFlags.NoMove;

View File

@@ -74,7 +74,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <summary>
/// The header height.
/// </summary>
public const float HeaderHeight = FlaxEditor.Surface.Constants.NodeHeaderHeight;
public const float HeaderHeight = FlaxEditor.Surface.Constants.NodeHeaderSize;
/// <summary>
/// Gets the type of the module.
@@ -199,7 +199,7 @@ namespace FlaxEditor.Surface.Archetypes
DrawChildren();
// Options border
var optionsAreaStart = FlaxEditor.Surface.Constants.NodeHeaderHeight + 3.0f;
var optionsAreaStart = FlaxEditor.Surface.Constants.NodeHeaderSize + 3.0f;
var optionsAreaHeight = 7 * FlaxEditor.Surface.Constants.LayoutOffsetY + 6.0f;
Render2D.DrawRectangle(new Rectangle(1, optionsAreaStart, Width - 2, optionsAreaHeight), style.BackgroundSelected);
@@ -340,7 +340,7 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new ParticleEmitterNode(id, context, arch, groupArch),
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 | NodeFlags.FixedSize,
Flags = NodeFlags.ParticleEmitterGraph | NodeFlags.NoRemove | NodeFlags.NoSpawnViaGUI | NodeFlags.NoSpawnViaPaste | NodeFlags.NoCloseButton,
Size = new Float2(300, 600),
DefaultValues = new object[]
{

View File

@@ -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.NodeHeaderHeight + FlaxEditor.Surface.Constants.LayoutOffsetY * _level),
Location = new Float2(FlaxEditor.Surface.Constants.NodeMarginX + 50, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize + FlaxEditor.Surface.Constants.LayoutOffsetY * _level),
Width = 100,
Parent = this,
};
@@ -133,8 +133,8 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Texture",
Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Texture))),
Description = "Two dimensional texture object",
Flags = NodeFlags.MaterialGraph | NodeFlags.FixedSize,
Size = new Float2(140, 140),
Flags = NodeFlags.MaterialGraph,
Size = new Float2(140, 120),
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(160, 20),
Size = new Float2(150, 30),
DefaultValues = new object[]
{
0u
@@ -176,8 +176,8 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Cube Texture",
Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(CubeTexture))),
Description = "Set of 6 textures arranged in a cube",
Flags = NodeFlags.MaterialGraph | NodeFlags.FixedSize,
Size = new Float2(140, 140),
Flags = NodeFlags.MaterialGraph,
Size = new Float2(140, 120),
DefaultValues = new object[]
{
Guid.Empty
@@ -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.BoxRowHeight + 4, 5 * Surface.Constants.LayoutOffsetY, "Channel"),
NodeElementArchetype.Factory.Text(Surface.Constants.BoxSize + 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),

View File

@@ -467,7 +467,7 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new CurveNode<T>(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.0f),
Size = new Float2(400, 180),
DefaultValues = new object[]
{
// Keyframes count
@@ -485,7 +485,7 @@ namespace FlaxEditor.Surface.Archetypes
zero, // Tangent In
zero, // Tangent Out
// Empty keys 0-6
// Empty keys zero-6
0.0f, zero, zero, zero,
0.0f, zero, zero, zero,
0.0f, zero, zero, zero,
@@ -515,12 +515,13 @@ namespace FlaxEditor.Surface.Archetypes
base.OnLoaded(action);
// Create curve editor
var upperLeft = GetBox(0).BottomRight;
var upperRight = GetBox(1).BottomLeft;
var upperLeft = GetBox(0).BottomLeft;
var upperRight = GetBox(1).BottomRight;
float curveMargin = 20.0f;
_curve = new BezierCurveEditor<T>
{
MaxKeyframes = 7,
Bounds = new Rectangle(upperLeft + new Float2(0f, 10.0f), upperRight.X - upperLeft.X - 8.0f, 135.0f),
Bounds = new Rectangle(upperLeft + new Float2(curveMargin, 10.0f), upperRight.X - upperLeft.X - curveMargin * 2.0f, 140.0f),
Parent = this,
AnchorMax = Float2.One,
};
@@ -840,7 +841,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.NodeHeaderHeight, 160, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16),
Parent = this,
};
_picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName);
@@ -909,7 +910,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.NodeHeaderHeight, 140, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 140, 16),
Parent = this,
};
_picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName);
@@ -960,7 +961,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.NodeHeaderHeight, 160, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16),
Parent = this,
};
_picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName);
@@ -1011,7 +1012,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.NodeHeaderHeight, 160, 16),
Bounds = new Rectangle(FlaxEditor.Surface.Constants.NodeMarginX + 20, FlaxEditor.Surface.Constants.NodeMarginY + FlaxEditor.Surface.Constants.NodeHeaderSize, 160, 16),
Parent = this,
};
_picker.ValueChanged += () => SetValue(0, _picker.ValueTypeName);
@@ -1070,11 +1071,7 @@ namespace FlaxEditor.Surface.Archetypes
internal class RerouteNode : SurfaceNode, IConnectionInstigator
{
internal static readonly Float2 DefaultSize = new Float2(FlaxEditor.Surface.Constants.BoxRowHeight);
internal bool DrawDisabled => _input.AllConnectionsDisabled || _output.AllConnectionsDisabled;
internal override bool DrawBasicShadow => false;
internal static readonly Float2 DefaultSize = new Float2(FlaxEditor.Surface.Constants.BoxSize);
private Rectangle _localBounds;
private InputBox _input;
private OutputBox _output;
@@ -1177,18 +1174,9 @@ namespace FlaxEditor.Surface.Archetypes
_footerRect = Rectangle.Empty;
}
/// <inheritdoc />
public override void Resize(float width, float height)
{
// Do nothing so the input and output boxes do not change position
}
/// <inheritdoc />
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;
@@ -1202,10 +1190,6 @@ 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)
@@ -1216,11 +1200,6 @@ 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();
@@ -1465,8 +1444,8 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 6,
Title = "Panner",
Description = "Animates UVs over time",
Flags = NodeFlags.MaterialGraph | NodeFlags.FixedSize,
Size = new Float2(170, 96),
Flags = NodeFlags.MaterialGraph,
Size = new Float2(170, 80),
DefaultValues = new object[]
{
false
@@ -1476,7 +1455,7 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(0, "UV", true, typeof(Float2), 0),
NodeElementArchetype.Factory.Input(1, "Time", true, typeof(float), 1),
NodeElementArchetype.Factory.Input(2, "Speed", true, typeof(Float2), 2),
NodeElementArchetype.Factory.Text(20, Surface.Constants.LayoutOffsetY * 3 + 5, "Fractional Part"),
NodeElementArchetype.Factory.Text(18, Surface.Constants.LayoutOffsetY * 3 + 5, "Fractional Part"),
NodeElementArchetype.Factory.Bool(0, Surface.Constants.LayoutOffsetY * 3 + 5, 0),
NodeElementArchetype.Factory.Output(0, "", typeof(Float2), 3)
}
@@ -1526,7 +1505,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Color Gradient",
Create = (id, context, arch, groupArch) => new ColorGradientNode(id, context, arch, groupArch),
Description = "Linear color gradient sampler",
Flags = NodeFlags.AllGraphs | NodeFlags.FixedSize,
Flags = NodeFlags.AllGraphs,
Size = new Float2(400, 150.0f),
DefaultValues = new object[]
{
@@ -1846,7 +1825,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Reroute",
Create = (id, context, arch, groupArch) => new RerouteNode(id, context, arch, groupArch),
Description = "Reroute a connection.",
Flags = NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaGUI | NodeFlags.AllGraphs | NodeFlags.FixedSize,
Flags = NodeFlags.NoCloseButton | NodeFlags.NoSpawnViaGUI | NodeFlags.AllGraphs,
Size = RerouteNode.DefaultSize,
ConnectionsHints = ConnectionsHint.All,
IndependentBoxes = new int[] { 0 },

View File

@@ -13,61 +13,46 @@ namespace FlaxEditor.Surface
/// <summary>
/// The node close button size.
/// </summary>
public const float NodeCloseButtonSize = 10.0f;
public const float NodeCloseButtonSize = 12.0f;
/// <summary>
/// The node close button margin from the edges.
/// </summary>
public const float NodeCloseButtonMargin = 5.0f;
public const float NodeCloseButtonMargin = 2.0f;
/// <summary>
/// The node header height.
/// </summary>
public const float NodeHeaderHeight = 25.0f;
/// <summary>
/// The scale of the header text.
/// </summary>
public const float NodeHeaderTextScale = 0.8f;
public const float NodeHeaderSize = 28.0f;
/// <summary>
/// The node footer height.
/// </summary>
public const float NodeFooterSize = 2.0f;
public const float NodeFooterSize = 4.0f;
/// <summary>
/// The horizontal node margin.
/// The node left margin.
/// </summary>
public const float NodeMarginX = 6.0f;
public const float NodeMarginX = 5.0f;
/// <summary>
/// The vertical node right margin.
/// The node right margin.
/// </summary>
public const float NodeMarginY = 8.0f;
public const float NodeMarginY = 5.0f;
/// <summary>
/// The size of the row that is started by a box.
/// The box position offset on the x axis.
/// </summary>
public const float BoxRowHeight = 19.0f;
public const float BoxOffsetX = 2.0f;
/// <summary>
/// The box size (with and height).
/// </summary>
public const float BoxSize = 15.0f;
public const float BoxSize = 20.0f;
/// <summary>
/// The node layout offset on the y axis (height of the boxes rows, etc.). It's used to make the design more consistent.
/// </summary>
public const float LayoutOffsetY = 24.0f;
/// <summary>
/// The offset between the box text and the box
/// </summary>
public const float BoxTextOffset = 1.65f;
/// <summary>
/// The width of the rectangle used to draw the box text.
/// </summary>
public const float BoxTextRectWidth = 500.0f;
public const float LayoutOffsetY = 20.0f;
}
}

View File

@@ -585,7 +585,7 @@ namespace FlaxEditor.Surface.ContextMenu
private void UpdateFilters()
{
if (string.IsNullOrEmpty(_searchBox.Text) && _selectedBoxes.Count == 0)
if (string.IsNullOrEmpty(_searchBox.Text) && _selectedBoxes[0] == null)
{
ResetView();
Profiler.EndEvent();

View File

@@ -33,7 +33,7 @@ namespace FlaxEditor.Surface.Elements
/// <inheritdoc />
public BoolValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(parentNode, archetype, archetype.ActualPosition, new Float2(Constants.BoxRowHeight), true)
: base(parentNode, archetype, archetype.ActualPosition, new Float2(16), true)
{
}

View File

@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Undo;
using FlaxEngine;
@@ -195,19 +194,9 @@ namespace FlaxEditor.Surface.Elements
set => _isActive = value;
}
/// <summary>
/// Gets if the box is disabled (user can still connect, but connections will be ignored).
/// </summary>
public bool IsDisabled => !(Enabled && IsActive);
/// <summary>
/// Gets a value indicating whether all connections are disabled.
/// </summary>
public bool AllConnectionsDisabled => Connections.All(c => c.IsDisabled);
/// <inheritdoc />
protected Box(SurfaceNode parentNode, NodeElementArchetype archetype, Float2 location)
: base(parentNode, archetype, location, new Float2(Constants.BoxRowHeight), false)
: base(parentNode, archetype, location, new Float2(Constants.BoxSize), false)
{
_currentType = DefaultType;
_isSingle = Archetype.Single;
@@ -363,10 +352,10 @@ namespace FlaxEditor.Surface.Elements
Assert.AreEqual(r1, r2);
// Update
OnConnectionsChanged();
box.OnConnectionsChanged();
ConnectionTick();
box.ConnectionTick();
OnConnectionsChanged();
box.OnConnectionsChanged();
Surface?.OnNodesDisconnected(this, box);
}
@@ -390,10 +379,10 @@ namespace FlaxEditor.Surface.Elements
Assert.IsTrue(AreConnected(box));
// Update
OnConnectionsChanged();
box.OnConnectionsChanged();
ConnectionTick();
box.ConnectionTick();
OnConnectionsChanged();
box.OnConnectionsChanged();
Surface?.OnNodesConnected(this, box);
}

View File

@@ -28,7 +28,6 @@ namespace FlaxEditor.Surface.Elements
public ColorValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(Get(parentNode, archetype), archetype.Position.X, archetype.Position.Y)
{
Height = Constants.BoxRowHeight;
ParentNode = parentNode;
Archetype = archetype;
UseDynamicEditing = false;

View File

@@ -33,7 +33,6 @@ namespace FlaxEditor.Surface.Elements
public ComboBoxElement(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(archetype.ActualPositionX, archetype.ActualPositionY, archetype.Size.X)
{
Height = Constants.BoxRowHeight;
ParentNode = parentNode;
Archetype = archetype;

View File

@@ -2,7 +2,6 @@
using System;
using FlaxEditor.GUI;
using FlaxEngine;
using FlaxEngine.Utilities;
namespace FlaxEditor.Surface.Elements
@@ -30,7 +29,9 @@ namespace FlaxEditor.Surface.Elements
public EnumValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(TypeUtils.GetType(archetype.Text).Type)
{
Bounds = new Rectangle(archetype.ActualPositionX, archetype.ActualPositionY, archetype.Size.X, Constants.BoxRowHeight);
X = archetype.ActualPositionX;
Y = archetype.ActualPositionY;
Width = archetype.Size.X;
ParentNode = parentNode;
Archetype = archetype;
Value = Convert.ToInt32(ParentNode.Values[Archetype.ValueIndex]);

View File

@@ -29,7 +29,6 @@ namespace FlaxEditor.Surface.Elements
public FloatValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(Get(parentNode, archetype), archetype.Position.X, archetype.Position.Y, 50, archetype.ValueMin, archetype.ValueMax, 0.01f)
{
Height = Constants.BoxRowHeight;
ParentNode = parentNode;
Archetype = archetype;

View File

@@ -120,7 +120,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = IntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
var width = 50;
var width = 40;
var control = new IntValueBox(value, bounds.X, bounds.Y, width + 12, int.MinValue, int.MaxValue, 0.01f)
{
Height = bounds.Height,
@@ -166,7 +166,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = UnsignedIntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
var width = 50;
var width = 40;
var control = new UIntValueBox(value, bounds.X, bounds.Y, width + 12, uint.MinValue, uint.MaxValue, 0.01f)
{
Height = bounds.Height,
@@ -212,7 +212,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = FloatValue.Get(box.ParentNode, box.Archetype, box.Value);
var width = 50;
var width = 40;
var control = new FloatValueBox(value, bounds.X, bounds.Y, width + 12, float.MinValue, float.MaxValue, 0.01f)
{
Height = bounds.Height,
@@ -303,7 +303,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
{
ClipChildren = false,
@@ -377,7 +377,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
{
ClipChildren = false,
@@ -460,7 +460,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 20;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
{
ClipChildren = false,
@@ -553,7 +553,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
{
ClipChildren = false,
@@ -627,7 +627,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
{
ClipChildren = false,
@@ -710,7 +710,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 20;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
{
ClipChildren = false,
@@ -803,7 +803,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
{
ClipChildren = false,
@@ -877,7 +877,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 30;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
{
ClipChildren = false,
@@ -960,7 +960,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box);
var width = 50;
var width = 20;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
{
ClipChildren = false,
@@ -1053,7 +1053,7 @@ namespace FlaxEditor.Surface.Elements
public Control Create(InputBox box, ref Rectangle bounds)
{
var value = GetValue(box).EulerAngles;
var width = 50;
var width = 20;
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
{
ClipChildren = false,
@@ -1442,8 +1442,8 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
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);
var rect = new Rectangle(Width + 4, 0, 1410, Height);
Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
/// <inheritdoc />

View File

@@ -32,7 +32,6 @@ namespace FlaxEditor.Surface.Elements
public IntegerValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(Get(parentNode, archetype), archetype.Position.X, archetype.Position.Y, 50, (int)archetype.ValueMin, (int)archetype.ValueMax, 0.05f)
{
Height = Constants.BoxRowHeight;
ParentNode = parentNode;
Archetype = archetype;

View File

@@ -34,6 +34,11 @@ namespace FlaxEditor.Surface.Elements
/// </summary>
public const float DefaultConnectionOffset = 24f;
/// <summary>
/// Distance for the mouse to be considered above the connection
/// </summary>
public float MouseOverConnectionDistance => 100f / Surface.ViewScale;
/// <inheritdoc />
public OutputBox(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(parentNode, archetype, archetype.Position + new Float2(parentNode.Archetype.Size.X, 0))
@@ -104,13 +109,12 @@ namespace FlaxEditor.Surface.Elements
/// </summary>
/// <param name="targetBox">The other box.</param>
/// <param name="mousePosition">The mouse position</param>
/// <param name="distance">Distance at which its an intersection</param>
public bool IntersectsConnection(Box targetBox, ref Float2 mousePosition, float distance)
public bool IntersectsConnection(Box targetBox, ref Float2 mousePosition)
{
float connectionOffset = Mathf.Max(0f, DefaultConnectionOffset * (1 - Editor.Instance.Options.Options.Interface.ConnectionCurvature));
Float2 start = new Float2(ConnectionOrigin.X + connectionOffset, ConnectionOrigin.Y);
Float2 end = new Float2(targetBox.ConnectionOrigin.X - connectionOffset, targetBox.ConnectionOrigin.Y);
return IntersectsConnection(ref start, ref end, ref mousePosition, distance);
return IntersectsConnection(ref start, ref end, ref mousePosition, MouseOverConnectionDistance);
}
/// <summary>
@@ -178,7 +182,7 @@ namespace FlaxEditor.Surface.Elements
{
// Draw all the connections
var style = Surface.Style;
var mouseOverDistance = Surface.MouseOverConnectionDistance;
var mouseOverDistance = MouseOverConnectionDistance;
var startPos = ConnectionOrigin;
var startHighlight = ConnectionsHighlightIntensity;
for (int i = 0; i < Connections.Count; i++)
@@ -186,7 +190,7 @@ namespace FlaxEditor.Surface.Elements
Box targetBox = Connections[i];
var endPos = targetBox.ConnectionOrigin;
var highlight = DefaultConnectionThickness + Mathf.Max(startHighlight, targetBox.ConnectionsHighlightIntensity);
var alpha = targetBox.IsDisabled ? 0.6f : 1.0f;
var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f;
// 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 +216,7 @@ namespace FlaxEditor.Surface.Elements
// Draw all the connections
var startPos = ConnectionOrigin;
var endPos = targetBox.ConnectionOrigin;
var alpha = targetBox.IsDisabled ? 0.6f : 1.0f;
var alpha = targetBox.Enabled && targetBox.IsActive ? 1.0f : 0.6f;
var color = _currentTypeColor * alpha;
DrawConnection(Surface.Style, ref startPos, ref endPos, ref color, SelectedConnectionThickness);
}
@@ -230,8 +234,8 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
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);
var rect = new Rectangle(-100, 0, 100 - 2, Height);
Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center);
}
}
}

View File

@@ -24,7 +24,6 @@ namespace FlaxEditor.Surface.Elements
public UnsignedIntegerValue(SurfaceNode parentNode, NodeElementArchetype archetype)
: base(Get(parentNode, archetype), archetype.Position.X, archetype.Position.Y, 50, (uint)archetype.ValueMin, (uint)archetype.ValueMax, 0.05f)
{
Height = Constants.BoxRowHeight;
ParentNode = parentNode;
Archetype = archetype;

View File

@@ -3,9 +3,8 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using FlaxEditor.GUI.Input;
using FlaxEditor.CustomEditors;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Elements;
using FlaxEngine;
namespace FlaxEditor.Surface
@@ -79,12 +78,12 @@ namespace FlaxEditor.Surface
/// <summary>
/// Gets the actual element position on the y axis.
/// </summary>
public float ActualPositionY => Position.Y + Constants.NodeMarginY + Constants.NodeHeaderHeight;
public float ActualPositionY => Position.Y + Constants.NodeMarginY + Constants.NodeHeaderSize;
/// <summary>
/// Gets the actual element position.
/// </summary>
public Float2 ActualPosition => new Float2(Position.X + Constants.NodeMarginX, Position.Y + Constants.NodeMarginY + Constants.NodeHeaderHeight);
public Float2 ActualPosition => new Float2(Position.X + Constants.NodeMarginX, Position.Y + Constants.NodeMarginY + Constants.NodeHeaderSize);
/// <summary>
/// Node element archetypes factory object. Helps to build surface nodes archetypes.
@@ -107,8 +106,8 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.Input,
Position = new Float2(
Constants.NodeMarginX,
Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY),
Constants.NodeMarginX - Constants.BoxOffsetX,
Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY),
Text = text,
Single = single,
ValueIndex = valueIndex,
@@ -133,8 +132,8 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.Input,
Position = new Float2(
Constants.NodeMarginX,
Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY),
Constants.NodeMarginX - Constants.BoxOffsetX,
Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY),
Text = text,
Single = single,
ValueIndex = valueIndex,
@@ -158,8 +157,8 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.Output,
Position = new Float2(
-Constants.NodeMarginX,
Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY),
Constants.NodeMarginX - Constants.BoxSize + Constants.BoxOffsetX,
Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY),
Text = text,
Single = single,
ValueIndex = -1,
@@ -183,8 +182,8 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.Output,
Position = new Float2(
-Constants.NodeMarginX,
Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY),
Constants.NodeMarginX - Constants.BoxSize + Constants.BoxOffsetX,
Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY),
Text = text,
Single = single,
ValueIndex = -1,
@@ -206,7 +205,6 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.BoolValue,
Position = new Float2(x, y),
Size = new Float2(16f),
Text = null,
Single = false,
ValueIndex = valueIndex,
@@ -230,8 +228,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.IntegerValue,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Size = new Float2(50f, IntegerValue.DefaultHeight),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Text = null,
Single = false,
ValueIndex = valueIndex,
@@ -257,8 +254,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.UnsignedIntegerValue,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Size = new Float2(50f, UnsignedIntegerValue.DefaultHeight),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Text = null,
Single = false,
ValueIndex = valueIndex,
@@ -284,8 +280,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.FloatValue,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Size = new Float2(50f, FloatValueBox.DefaultHeight),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Text = null,
Single = false,
ValueIndex = valueIndex,
@@ -364,8 +359,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.ColorValue,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Size = new Float2(32, 18),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Text = null,
Single = false,
ValueIndex = valueIndex,
@@ -388,7 +382,6 @@ namespace FlaxEditor.Surface
{
Type = NodeElementType.Asset,
Position = new Float2(x, y),
Size = new Float2(78f, 90f),
Text = type.FullName,
Single = false,
ValueIndex = valueIndex,
@@ -506,7 +499,7 @@ namespace FlaxEditor.Surface
/// <param name="height">The control height.</param>
/// <param name="tooltip">The control tooltip text.</param>
/// <returns>The archetype.</returns>
public static NodeElementArchetype Text(float x, float y, string text, float width = 100.0f, float height = 19.0f, string tooltip = null)
public static NodeElementArchetype Text(float x, float y, string text, float width = 100.0f, float height = 16.0f, string tooltip = null)
{
return new NodeElementArchetype
{
@@ -537,7 +530,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.TextBox,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Size = new Float2(width, height),
Single = false,
ValueIndex = valueIndex,
@@ -602,7 +595,7 @@ namespace FlaxEditor.Surface
return new NodeElementArchetype
{
Type = NodeElementType.BoxValue,
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderHeight + y),
Position = new Float2(Constants.NodeMarginX + x, Constants.NodeMarginY + Constants.NodeHeaderSize + y),
Text = null,
Single = false,
ValueIndex = valueIndex,

View File

@@ -60,84 +60,84 @@ namespace FlaxEditor.Surface
{
GroupID = 1,
Name = "Material",
Color = new Color(181, 89, 49),
Color = new Color(231, 76, 60),
Archetypes = Archetypes.Material.Nodes
},
new GroupArchetype
{
GroupID = 2,
Name = "Constants",
Color = new Color(163, 106, 21),
Color = new Color(243, 156, 18),
Archetypes = Archetypes.Constants.Nodes
},
new GroupArchetype
{
GroupID = 3,
Name = "Math",
Color = new Color(45, 126, 181),
Color = new Color(52, 152, 219),
Archetypes = Archetypes.Math.Nodes
},
new GroupArchetype
{
GroupID = 4,
Name = "Packing",
Color = new Color(124, 66, 143),
Color = new Color(155, 89, 182),
Archetypes = Archetypes.Packing.Nodes
},
new GroupArchetype
{
GroupID = 5,
Name = "Textures",
Color = new Color(43, 130, 83),
Color = new Color(46, 204, 113),
Archetypes = Archetypes.Textures.Nodes
},
new GroupArchetype
{
GroupID = 6,
Name = "Parameters",
Color = new Color(55, 78, 99),
Color = new Color(52, 73, 94),
Archetypes = Archetypes.Parameters.Nodes
},
new GroupArchetype
{
GroupID = 7,
Name = "Tools",
Color = new Color(88, 96, 97),
Color = new Color(149, 165, 166),
Archetypes = Archetypes.Tools.Nodes
},
new GroupArchetype
{
GroupID = 8,
Name = "Layers",
Color = new Color(189, 75, 81),
Color = new Color(249, 105, 116),
Archetypes = Archetypes.Layers.Nodes
},
new GroupArchetype
{
GroupID = 9,
Name = "Animations",
Color = new Color(72, 125, 107),
Color = new Color(105, 179, 160),
Archetypes = Archetypes.Animation.Nodes
},
new GroupArchetype
{
GroupID = 10,
Name = "Boolean",
Color = new Color(166, 27, 32),
Color = new Color(237, 28, 36),
Archetypes = Archetypes.Boolean.Nodes
},
new GroupArchetype
{
GroupID = 11,
Name = "Bitwise",
Color = new Color(96, 125, 34),
Color = new Color(181, 230, 29),
Archetypes = Archetypes.Bitwise.Nodes
},
new GroupArchetype
{
GroupID = 12,
Name = "Comparisons",
Color = new Color(166, 33, 57),
Color = new Color(148, 30, 34),
Archetypes = Archetypes.Comparisons.Nodes
},
// GroupID = 13 -> Custom Nodes provided externally
@@ -145,7 +145,7 @@ namespace FlaxEditor.Surface
{
GroupID = 14,
Name = "Particles",
Color = new Color(72, 125, 107),
Color = new Color(121, 210, 176),
Archetypes = Archetypes.Particles.Nodes
},
new GroupArchetype
@@ -166,7 +166,7 @@ namespace FlaxEditor.Surface
{
GroupID = 17,
Name = "Flow",
Color = new Color(181, 91, 33),
Color = new Color(237, 136, 64),
Archetypes = Archetypes.Flow.Nodes
},
new GroupArchetype

View File

@@ -78,11 +78,6 @@ namespace FlaxEditor.Surface
/// </summary>
VariableValuesSize = 2048,
/// <summary>
/// Node has fixed size defined and should not use automatic layout.
/// </summary>
FixedSize = 4096,
/// <summary>
/// Node can be used in the all visual graphs.
/// </summary>

View File

@@ -59,7 +59,7 @@ namespace FlaxEditor.Surface
var width = _rootNode.Width;
var rootPos = _rootNode.Location;
var pos = rootPos;
pos.Y += Constants.NodeHeaderHeight + 1.0f + 7 * Constants.LayoutOffsetY + 6.0f + 4.0f;
pos.Y += Constants.NodeHeaderSize + 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.NodeHeaderHeight + 2.0f;
pos.Y += Constants.NodeHeaderSize + 2.0f;
if (modules != null)
{
foreach (var module in modules)

View File

@@ -74,12 +74,6 @@ namespace FlaxEditor.Surface
Resize(size.X, size.Y);
}
/// <inheritdoc />
public override void ResizeAuto()
{
// Do nothing, we want to put full control of node size into the users hands
}
/// <inheritdoc />
public override void Draw()
{

View File

@@ -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.NodeHeaderHeight);
_sizeMin = new Float2(140.0f, Constants.NodeHeaderSize);
_renameTextBox = new TextBox(false, 0, 0, Width)
{
Height = Constants.NodeHeaderHeight,
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
@@ -124,11 +124,11 @@ namespace FlaxEditor.Surface
{
base.UpdateRectangles();
const float headerSize = Constants.NodeHeaderHeight;
const float headerSize = Constants.NodeHeaderSize;
const float buttonMargin = Constants.NodeCloseButtonMargin;
const float buttonSize = Constants.NodeCloseButtonSize;
_headerRect = new Rectangle(0, 0, Width, headerSize);
_closeButtonRect = new Rectangle(Width - buttonSize * 0.75f - buttonMargin, buttonMargin, buttonSize * 0.75f, buttonSize * 0.75f);
_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;
@@ -183,7 +183,7 @@ namespace FlaxEditor.Surface
if (Surface.CanEdit)
{
// Close button
DrawCloseButton(_closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
Render2D.DrawSprite(style.Cross, _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);

View File

@@ -40,13 +40,6 @@ namespace FlaxEditor.Surface
[HideInEditor]
public class SurfaceNode : SurfaceControl
{
internal const float ShadowOffset = 2.25f;
/// <summary>
/// If true, draws a basic rectangle shadow behind the node. Disable to hide shadow or if the node is drawing a custom shadow.
/// </summary>
internal virtual bool DrawBasicShadow => true;
/// <summary>
/// The box to draw a highlight around. Drawing will be skipped if null.
/// </summary>
@@ -62,11 +55,6 @@ namespace FlaxEditor.Surface
/// </summary>
protected Rectangle _headerRect;
/// <summary>
/// The header text rectangle (local space).
/// </summary>
protected Rectangle _headerTextRect;
/// <summary>
/// The close button rectangle (local space).
/// </summary>
@@ -135,7 +123,7 @@ namespace FlaxEditor.Surface
/// <param name="nodeArch">The node archetype.</param>
/// <param name="groupArch">The group archetype.</param>
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.NodeHeaderHeight + Constants.NodeFooterSize)
: base(context, nodeArch.Size.X + Constants.NodeMarginX * 2, nodeArch.Size.Y + Constants.NodeMarginY * 2 + Constants.NodeHeaderSize + Constants.NodeFooterSize)
{
Title = nodeArch.Title;
ID = id;
@@ -144,7 +132,7 @@ namespace FlaxEditor.Surface
AutoFocus = false;
TooltipText = GetTooltip();
CullChildren = false;
BackgroundColor = Color.Lerp(Style.Current.Background, Style.Current.BackgroundHighlighted, 0.55f);
BackgroundColor = Style.Current.BackgroundNormal;
if (Archetype.DefaultValues != null)
{
@@ -159,9 +147,9 @@ namespace FlaxEditor.Surface
public virtual string ContentSearchText => null;
/// <summary>
/// Gets the color of the header of the node.
/// Gets the color of the footer of the node.
/// </summary>
protected virtual Color ArchetypeColor => GroupArchetype.Color;
protected virtual Color FooterColor => GroupArchetype.Color;
private Float2 mouseDownMousePosition;
@@ -173,7 +161,7 @@ namespace FlaxEditor.Surface
/// <returns>The node control total size.</returns>
protected virtual Float2 CalculateNodeSize(float width, float height)
{
return new Float2(width + Constants.NodeMarginX * 2, height + Constants.NodeMarginY * 2 + Constants.NodeHeaderHeight + Constants.NodeFooterSize);
return new Float2(width + Constants.NodeMarginX * 2, height + Constants.NodeMarginY * 2 + Constants.NodeHeaderSize + Constants.NodeFooterSize);
}
/// <summary>
@@ -181,7 +169,7 @@ namespace FlaxEditor.Surface
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public virtual void Resize(float width, float height)
public void Resize(float width, float height)
{
if (Surface == null)
return;
@@ -199,7 +187,7 @@ namespace FlaxEditor.Surface
{
if (Elements[i] is OutputBox box)
{
box.Location = box.Archetype.Position + new Float2(width - Constants.NodeMarginX, 0);
box.Location = box.Archetype.Position + new Float2(width, 0);
}
}
@@ -227,41 +215,30 @@ 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 + 25;
if (inputBox.DefaultValueEditor != null && inputBox.DefaultValueEditor.Visible)
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.NodeHeaderHeight + Constants.BoxRowHeight);
leftHeight = Mathf.Max(leftHeight, inputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
// Output boxes
else if (child is OutputBox outputBox)
{
rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 25);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderHeight + Constants.BoxRowHeight);
rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 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);
}
// Other controls in the node
else if (child is Control control)
{
if (control.AnchorPreset == AnchorPresets.TopLeft)
{
width = Mathf.Max(width, control.Right + 15 + Constants.NodeMarginX);
height = Mathf.Max(height, control.Bottom - Constants.NodeMarginY - Constants.NodeHeaderHeight);
width = Mathf.Max(width, control.Right + 4 - Constants.NodeMarginX);
height = Mathf.Max(height, control.Bottom + 4 - Constants.NodeMarginY - Constants.NodeHeaderSize);
}
else if (!_headerRect.Intersects(control.Bounds))
{
width = Mathf.Max(width, control.Width + 15 + Constants.NodeMarginX);
height = Mathf.Max(height, control.Height);
width = Mathf.Max(width, control.Width + 4);
height = Mathf.Max(height, control.Height + 4);
}
}
}
@@ -348,9 +325,6 @@ namespace FlaxEditor.Surface
Elements.Add(element);
if (element is Control control)
AddChild(control);
if (!IsLayoutLocked)
UpdateSize();
}
/// <summary>
@@ -391,7 +365,7 @@ namespace FlaxEditor.Surface
// Sync properties for exiting box
box.Text = text;
box.CurrentType = type;
box.Y = Constants.NodeMarginY + Constants.NodeHeaderHeight + yLevel * Constants.LayoutOffsetY;
box.Y = Constants.NodeMarginY + Constants.NodeHeaderSize + yLevel * Constants.LayoutOffsetY;
}
// Update box
@@ -460,7 +434,7 @@ namespace FlaxEditor.Surface
private static readonly List<SurfaceNode> UpdateStack = new List<SurfaceNode>();
/// <summary>
/// Updates dependent/independent boxes types.
/// Updates dependant/independent boxes types.
/// </summary>
public void UpdateBoxesTypes()
{
@@ -802,24 +776,6 @@ namespace FlaxEditor.Surface
return output;
}
/// <summary>
/// Draws the close button inside of the <paramref name="rect"/>.
/// </summary>
/// <param name="rect">The rectangle to draw the close button in.</param>
/// <param name="color">The color of the close button.</param>
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;
}
/// <summary>
/// Draws all the connections between surface objects related to this node.
/// </summary>
@@ -911,14 +867,6 @@ namespace FlaxEditor.Surface
return sb.ToString();
}
private void UpdateSize()
{
if (Archetype.Flags.HasFlag(NodeFlags.FixedSize))
Resize(Archetype.Size.X, Archetype.Size.Y);
else
ResizeAuto();
}
/// <inheritdoc />
protected override bool ShowTooltip => base.ShowTooltip && _headerRect.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
@@ -971,8 +919,6 @@ namespace FlaxEditor.Surface
if (Elements[i] is Box box)
box.OnConnectionsChanged();
}
UpdateSize();
}
/// <inheritdoc />
@@ -1010,8 +956,6 @@ namespace FlaxEditor.Surface
Surface.AddBatchedUndoAction(new EditNodeValuesAction(this, before, graphEdited));
_isDuringValuesEditing = false;
UpdateSize();
}
/// <summary>
@@ -1046,8 +990,6 @@ namespace FlaxEditor.Surface
}
_isDuringValuesEditing = false;
UpdateSize();
}
internal void SetIsDuringValuesEditing(bool value)
@@ -1056,7 +998,7 @@ namespace FlaxEditor.Surface
}
/// <summary>
/// Sets teh node values from the given pasted source. Can be overridden to perform validation or custom values processing.
/// Sets teh node values from the given pasted source. Can be overriden to perform validation or custom values processing.
/// </summary>
/// <param name="values">The input values array.</param>
public virtual void SetValuesPaste(object[] values)
@@ -1080,18 +1022,16 @@ namespace FlaxEditor.Surface
public virtual void ConnectionTick(Box box)
{
UpdateBoxesTypes();
UpdateSize();
}
/// <inheritdoc />
protected override void UpdateRectangles()
{
const float footerSize = Constants.NodeFooterSize;
const float headerSize = Constants.NodeHeaderHeight;
const float headerSize = Constants.NodeHeaderSize;
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);
}
@@ -1100,16 +1040,9 @@ namespace FlaxEditor.Surface
public override void 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
var backgroundRect = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(backgroundRect, BackgroundColor);
// Breakpoint hit
@@ -1125,18 +1058,18 @@ namespace FlaxEditor.Surface
var headerColor = style.BackgroundHighlighted;
if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting)
headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, ArchetypeColor);
Render2D.DrawText(style.FontLarge, Title, _headerTextRect, style.Foreground, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1f, Constants.NodeHeaderTextScale);
Render2D.FillRectangle(_headerRect, headerColor);
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// 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);
Render2D.DrawSprite(style.Cross, _closeButtonRect, highlightClose ? style.Foreground : style.ForegroundGrey);
}
// Footer
Render2D.FillRectangle(_footerRect, ArchetypeColor);
Render2D.FillRectangle(_footerRect, FooterColor);
DrawChildren();
@@ -1145,7 +1078,7 @@ namespace FlaxEditor.Surface
{
var colorTop = Color.Orange;
var colorBottom = Color.OrangeRed;
Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom, 2.5f);
Render2D.DrawRectangle(backgroundRect, colorTop, colorTop, colorBottom, colorBottom);
}
// Breakpoint dot

View File

@@ -2,7 +2,6 @@
using System;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Elements;
using FlaxEngine;
using FlaxEngine.Utilities;
@@ -141,11 +140,6 @@ namespace FlaxEditor.Surface
/// </summary>
public Texture Background;
/// <summary>
/// The color used as a surface background.
/// </summary>
public Color BackgroundColor;
/// <summary>
/// Boxes drawing callback.
/// </summary>
@@ -222,20 +216,19 @@ namespace FlaxEditor.Surface
private static void DefaultDrawBox(Elements.Box box)
{
var rect = new Rectangle(box.Width * 0.5f - Constants.BoxSize * 0.5f, box.Height * 0.5f - Constants.BoxSize * 0.5f, new Float2(Constants.BoxSize));
var rect = new Rectangle(Float2.Zero, box.Size);
// Size culling
const float minBoxSize = 5.0f;
if (rect.Size.LengthSquared < minBoxSize * minBoxSize)
return;
// Debugging boxes size and bounds
// Debugging boxes size
//Render2D.DrawRectangle(rect, Color.Orange); return;
//Render2D.DrawRectangle(box.Bounds, Color.Green);
// Draw icon
bool hasConnections = box.HasAnyConnection;
float alpha = box.IsDisabled ? 0.6f : 1.0f;
float alpha = box.Enabled && box.IsActive ? 1.0f : 0.6f;
Color color = box.CurrentTypeColor * alpha;
var style = box.Surface.Style;
SpriteHandle icon;
@@ -244,42 +237,20 @@ namespace FlaxEditor.Surface
else
icon = hasConnections ? style.Icons.BoxClose : style.Icons.BoxOpen;
color *= box.ConnectionsHighlightIntensity + 1;
if (box.IsMouseOver)
{
color *= 1.3f;
rect = rect.MakeExpanded(1.0f);
}
// 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);
Color selectionColor = FlaxEngine.GUI.Style.Current.BorderSelected.RGBMultiplied(1.0f + outlineAlpha * 0.4f);
Render2D.DrawSprite(icon, outlineRect, selectionColor.AlphaMultiplied(0.4f));
Render2D.DrawSprite(icon, outlineRect, FlaxEngine.GUI.Style.Current.BorderSelected.RGBMultiplied(1.0f + outlineAlpha * 0.4f));
}
Render2D.Features = features;
}
/// <summary>
/// Function used to create style for the given surface type. Can be overridden to provide some customization via user plugin.
/// Function used to create style for the given surface type. Can be overriden to provide some customization via user plugin.
/// </summary>
public static Func<Editor, SurfaceStyle> CreateStyleHandler = CreateDefault;
@@ -322,7 +293,6 @@ namespace FlaxEditor.Surface
ArrowClose = editor.Icons.VisjectArrowClosed32,
},
Background = editor.UI.VisjectSurfaceBackground,
BackgroundColor = new Color(31, 31, 31),
};
}
@@ -341,11 +311,13 @@ namespace FlaxEditor.Surface
{
var dir = sub / length;
var arrowRect = new Rectangle(0, 0, 16.0f, 16.0f);
float rotation = Mathf.Atan2(dir.Y, dir.X);
float rotation = Float2.Dot(dir, Float2.UnitY);
if (endPos.X < startPos.X)
rotation = 2 - rotation;
var sprite = Editor.Instance.Icons.VisjectArrowClosed32;
var arrowTransform =
Matrix3x3.Translation2D(-6.5f, -8) *
Matrix3x3.RotationZ(rotation) *
Matrix3x3.RotationZ(rotation * Mathf.PiOverTwo) *
Matrix3x3.Translation2D(endPos - dir * 8);
Render2D.PushTransform(ref arrowTransform);

View File

@@ -574,13 +574,13 @@ namespace FlaxEditor.Surface
var showSearch = () => editor.ContentFinding.ShowSearch(window);
// Toolstrip
saveButton = toolStrip.AddButton(editor.Icons.Save64, window.Save).LinkTooltip("Save.", ref inputOptions.Save);
saveButton = toolStrip.AddButton(editor.Icons.Save64, window.Save).LinkTooltip("Save", ref inputOptions.Save);
toolStrip.AddSeparator();
undoButton = toolStrip.AddButton(editor.Icons.Undo64, undo.PerformUndo).LinkTooltip("Undo.", ref inputOptions.Undo);
redoButton = toolStrip.AddButton(editor.Icons.Redo64, undo.PerformRedo).LinkTooltip("Redo.", ref inputOptions.Redo);
undoButton = toolStrip.AddButton(editor.Icons.Undo64, undo.PerformUndo).LinkTooltip("Undo", ref inputOptions.Undo);
redoButton = toolStrip.AddButton(editor.Icons.Redo64, undo.PerformRedo).LinkTooltip("Redo", ref inputOptions.Redo);
toolStrip.AddSeparator();
toolStrip.AddButton(editor.Icons.Search64, showSearch).LinkTooltip("Open content search tool.", ref inputOptions.Search);
toolStrip.AddButton(editor.Icons.CenterView64, surface.ShowWholeGraph).LinkTooltip("Show whole graph.");
toolStrip.AddButton(editor.Icons.Search64, showSearch).LinkTooltip("Open content search tool", ref inputOptions.Search);
toolStrip.AddButton(editor.Icons.CenterView64, surface.ShowWholeGraph).LinkTooltip("Show whole graph");
var gridSnapButton = toolStrip.AddButton(editor.Icons.Grid32, surface.ToggleGridSnapping);
gridSnapButton.LinkTooltip("Toggle grid snapping for nodes.");
gridSnapButton.AutoCheck = true;

View File

@@ -410,11 +410,8 @@ namespace FlaxEditor.Surface
}
menu.AddSeparator();
bool allNodesNoMove = SelectedNodes.All(n => n.Archetype.Flags.HasFlag(NodeFlags.NoMove));
bool clickedNodeNoMove = ((SelectedNodes.Count == 1 && controlUnderMouse is SurfaceNode n && n.Archetype.Flags.HasFlag(NodeFlags.NoMove)));
_cmFormatNodesMenu = menu.AddChildMenu("Format nodes");
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection && !(allNodesNoMove || clickedNodeNoMove);
_cmFormatNodesMenu = menu.AddChildMenu("Format node(s)");
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection;
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Auto format", Editor.Instance.Options.Options.Input.NodesAutoFormat, () => { FormatGraph(SelectedNodes); });
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Straighten connections", Editor.Instance.Options.Options.Input.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); });

View File

@@ -65,68 +65,31 @@ namespace FlaxEditor.Surface
/// </summary>
protected virtual void DrawBackground()
{
DrawBackgroundDefault(Style.Background, Size, _rootControl.Location);
//DrawBackgroundSolidColor(Style.BackgroundColor, Width, Height);
DrawGridBackground();
DrawBackgroundDefault(Style.Background, 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()
{
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 = null;
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, Float2 size, Float2 offset)
internal static void DrawBackgroundDefault(Texture background, float width, float height)
{
if (background && background.ResidentMipLevels > 0)
{
var bSize = background.Size;
var pos = Float2.Mod(offset / bSize) * bSize;
var max = Float2.Ceil(size / bSize + 1.0f);
float bw = bSize.X;
float bh = bSize.Y;
var pos = Float2.Mod(bSize);
if (pos.X > 0)
pos.X -= bSize.X;
pos.X -= bw;
if (pos.Y > 0)
pos.Y -= bSize.Y;
pos.Y -= bh;
for (int i = 0; i < max.X; i++)
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 < max.Y; j++)
for (int j = 0; j < maxJ; j++)
{
Render2D.DrawTexture(background, new Rectangle(pos.X + i * bSize.X, pos.Y + j * bSize.Y, bSize), Color.White);
Render2D.DrawTexture(background, new Rectangle(pos.X + i * bw, pos.Y + j * bh, bw, bh), Color.White);
}
}
}
@@ -250,44 +213,6 @@ namespace FlaxEditor.Surface
}
}
/// <summary>
/// Draw connection hints for lazy connect feature.
/// </summary>
protected virtual void DrawLazyConnect()
{
var style = FlaxEngine.GUI.Style.Current;
if (_lazyConnectStartNode != null)
{
Float2 upperLeft = _rootControl.PointToParent(_lazyConnectStartNode.UpperLeft);
Rectangle startNodeOutline = new Rectangle(upperLeft + 1f, _lazyConnectStartNode.Size - 1f);
startNodeOutline.Size *= ViewScale;
Render2D.DrawRectangle(startNodeOutline.MakeExpanded(4f), style.BackgroundSelected, 4f);
}
if (_lazyConnectEndNode != null)
{
Float2 upperLeft = _rootControl.PointToParent(_lazyConnectEndNode.UpperLeft);
Rectangle startNodeOutline = new Rectangle(upperLeft + 1f, _lazyConnectEndNode.Size - 1f);
startNodeOutline.Size *= ViewScale;
Render2D.DrawRectangle(startNodeOutline.MakeExpanded(4f), style.BackgroundSelected, 4f);
}
Rectangle startRect = new Rectangle(_rightMouseDownPos - 6f, new Float2(12f));
Rectangle endRect = new Rectangle(_mousePos - 6f, new Float2(12f));
// Start and end shadows/ outlines
Render2D.FillRectangle(startRect.MakeExpanded(2.5f), Color.Black);
Render2D.FillRectangle(endRect.MakeExpanded(2.5f), Color.Black);
Render2D.DrawLine(_rightMouseDownPos, _mousePos, Color.Black, 7.5f);
Render2D.DrawLine(_rightMouseDownPos, _mousePos, style.ForegroundGrey, 5f);
// Draw start and end boxes over the lines to hide ugly artifacts at the ends
Render2D.FillRectangle(startRect, style.ForegroundGrey);
Render2D.FillRectangle(endRect, style.ForegroundGrey);
}
/// <summary>
/// Draws the contents of the surface (nodes, connections, comments, etc.).
/// </summary>
@@ -335,9 +260,6 @@ namespace FlaxEditor.Surface
DrawContents();
if (_isLazyConnecting)
DrawLazyConnect();
//Render2D.DrawText(style.FontTitle, string.Format("Scale: {0}", _rootControl.Scale), rect, Enabled ? Color.Red : Color.Black);
// Draw border

View File

@@ -39,8 +39,6 @@ namespace FlaxEditor.Surface
if (nodes.Count <= 1)
return;
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
var nodesToVisit = new HashSet<SurfaceNode>(nodes);
// While we haven't formatted every node
@@ -75,23 +73,18 @@ namespace FlaxEditor.Surface
}
}
undoActions.AddRange(FormatConnectedGraph(connectedNodes));
FormatConnectedGraph(connectedNodes);
}
Undo?.AddAction(new MultiUndoAction(undoActions, "Format nodes"));
MarkAsEdited(false);
}
/// <summary>
/// Formats a graph where all nodes are connected.
/// </summary>
/// <param name="nodes">List of connected nodes.</param>
private List<MoveNodesAction> FormatConnectedGraph(List<SurfaceNode> nodes)
protected void FormatConnectedGraph(List<SurfaceNode> nodes)
{
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
if (nodes.Count <= 1)
return undoActions;
return;
var boundingBox = GetNodesBounds(nodes);
@@ -147,6 +140,7 @@ namespace FlaxEditor.Surface
}
// Set the node positions
var undoActions = new List<MoveNodesAction>();
var topRightPosition = endNodes[0].Location;
for (int i = 0; i < nodes.Count; i++)
{
@@ -161,18 +155,16 @@ namespace FlaxEditor.Surface
}
}
return undoActions;
MarkAsEdited(false);
Undo?.AddAction(new MultiUndoAction(undoActions, "Format nodes"));
}
/// <summary>
/// Straightens every connection between nodes in <paramref name="nodes"/>.
/// </summary>
/// <param name="nodes">List of nodes.</param>
/// <returns>List of undo actions.</returns>
public void StraightenGraphConnections(List<SurfaceNode> nodes)
{
nodes = nodes.Where(n => !n.Archetype.Flags.HasFlag(NodeFlags.NoMove)).ToList();
{
if (nodes.Count <= 1)
return;
@@ -358,10 +350,8 @@ namespace FlaxEditor.Surface
/// <param name="nodes">List of nodes.</param>
/// <param name="alignmentType">Alignemnt type.</param>
public void AlignNodes(List<SurfaceNode> nodes, NodeAlignmentType alignmentType)
{
nodes = nodes.Where(n => !n.Archetype.Flags.HasFlag(NodeFlags.NoMove)).ToList();
if (nodes.Count <= 1)
{
if(nodes.Count <= 1)
return;
var undoActions = new List<MoveNodesAction>();
@@ -402,8 +392,6 @@ namespace FlaxEditor.Surface
/// <param name="vertically">If false will be done horizontally, if true will be done vertically.</param>
public void DistributeNodes(List<SurfaceNode> nodes, bool vertically)
{
nodes = nodes.Where(n => !n.Archetype.Flags.HasFlag(NodeFlags.NoMove)).ToList();
if(nodes.Count <= 1)
return;

View File

@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using static FlaxEditor.Surface.Archetypes.Particles;
using FlaxEditor.Options;
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
@@ -24,26 +23,12 @@ namespace FlaxEditor.Surface
/// </summary>
public bool PanWithMiddleMouse = false;
/// <summary>
/// Distance for the mouse to be considered above the connection.
/// </summary>
public float MouseOverConnectionDistance => 100f / ViewScale;
/// <summary>
/// Distance of a node from which it is able to be slotted into an existing connection.
/// </summary>
public float SlotNodeIntoConnectionDistance => 250f / ViewScale;
private string _currentInputText = string.Empty;
private Float2 _movingNodesDelta;
private Float2 _gridRoundingDelta;
private HashSet<SurfaceNode> _movingNodes;
private HashSet<SurfaceNode> _temporarySelectedNodes;
private readonly Stack<InputBracket> _inputBrackets = new Stack<InputBracket>();
private bool _isLazyConnecting;
private SurfaceNode _lazyConnectStartNode;
private SurfaceNode _lazyConnectEndNode;
private InputBinding _focusSelectedNodeBinding;
private class InputBracket
{
@@ -265,13 +250,8 @@ namespace FlaxEditor.Surface
// Cache mouse location
_mousePos = location;
if (_isLazyConnecting && GetControlUnderMouse() is SurfaceNode nodeUnderMouse && !(nodeUnderMouse is SurfaceComment || nodeUnderMouse is ParticleEmitterNode))
_lazyConnectEndNode = nodeUnderMouse;
else if (_isLazyConnecting && Nodes.Count > 0)
_lazyConnectEndNode = GetClosestNodeAtLocation(location);
// Moving around surface with mouse
if (_rightMouseDown && !_isLazyConnecting)
if (_rightMouseDown)
{
// Calculate delta
var delta = location - _rightMouseDownPos;
@@ -341,33 +321,6 @@ namespace FlaxEditor.Surface
foreach (var node in _movingNodes)
{
// Allow ripping the node from its current connection
if (RootWindow.GetKey(KeyboardKeys.Alt))
{
InputBox nodeConnectedInput = null;
OutputBox nodeConnectedOuput = null;
var boxes = node.GetBoxes();
foreach (var box in boxes)
{
if (!box.IsOutput && box.Connections.Count > 0)
{
nodeConnectedInput = (InputBox)box;
continue;
}
if (box.IsOutput && box.Connections.Count > 0)
{
nodeConnectedOuput = (OutputBox)box;
continue;
}
}
if (nodeConnectedInput != null && nodeConnectedOuput != null)
TryConnect(nodeConnectedOuput.Connections[0], nodeConnectedInput.Connections[0]);
node.RemoveConnections();
}
if (gridSnap)
{
Float2 unroundedLocation = node.Location;
@@ -467,7 +420,7 @@ namespace FlaxEditor.Surface
if (!handled && CanEdit && CanUseNodeType(7, 29))
{
var mousePos = _rootControl.PointFromParent(ref _mousePos);
if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox, MouseOverConnectionDistance) && GetControlUnderMouse() == null)
if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox) && GetControlUnderMouse() == null)
{
if (Undo != null)
{
@@ -562,17 +515,11 @@ namespace FlaxEditor.Surface
_middleMouseDownPos = location;
}
if (root.GetKey(KeyboardKeys.Alt) && button == MouseButton.Right)
_isLazyConnecting = true;
// Check if any node is under the mouse
SurfaceControl controlUnderMouse = GetControlUnderMouse();
var cLocation = _rootControl.PointFromParent(ref location);
if (controlUnderMouse != null)
{
if (controlUnderMouse is SurfaceNode node && _isLazyConnecting && !(controlUnderMouse is SurfaceComment || controlUnderMouse is ParticleEmitterNode))
_lazyConnectStartNode = node;
// Check if mouse is over header and user is pressing mouse left button
if (_leftMouseDown && controlUnderMouse.CanSelect(ref cLocation))
{
@@ -607,9 +554,6 @@ namespace FlaxEditor.Surface
}
else
{
if (_isLazyConnecting && Nodes.Count > 0)
_lazyConnectStartNode = GetClosestNodeAtLocation(location);
// Cache flags and state
if (_leftMouseDown)
{
@@ -658,71 +602,8 @@ namespace FlaxEditor.Surface
{
if (_movingNodes != null && _movingNodes.Count > 0)
{
// Allow dropping a single node onto an existing connection and connect it
if (_movingNodes.Count == 1)
{
var mousePos = _rootControl.PointFromParent(ref _mousePos);
InputBox intersectedConnectionInputBox;
OutputBox intersectedConnectionOutputBox;
if (IntersectsConnection(mousePos, out intersectedConnectionInputBox, out intersectedConnectionOutputBox, SlotNodeIntoConnectionDistance))
{
SurfaceNode node = _movingNodes.First();
InputBox nodeInputBox = (InputBox)node.GetBoxes().First(b => !b.IsOutput);
OutputBox nodeOutputBox = (OutputBox)node.GetBoxes().First(b => b.IsOutput);
TryConnect(intersectedConnectionOutputBox, nodeInputBox);
TryConnect(nodeOutputBox, intersectedConnectionInputBox);
float intersectedConnectionNodesXDistance = intersectedConnectionInputBox.ParentNode.Left - intersectedConnectionOutputBox.ParentNode.Right;
float paddedNodeWidth = node.Width + 2f;
if (intersectedConnectionNodesXDistance < paddedNodeWidth)
{
List<SurfaceNode> visitedNodes = new List<SurfaceNode>{ node };
List<SurfaceNode> movedNodes = new List<SurfaceNode>();
Float2 locationDelta = new Float2(paddedNodeWidth, 0f);
MoveConnectedNodes(intersectedConnectionInputBox.ParentNode);
void MoveConnectedNodes(SurfaceNode node)
{
// Only move node if it is to the right of the node we have connected the moved node to
if (node.Right > intersectedConnectionInputBox.ParentNode.Left + 15f && !node.Archetype.Flags.HasFlag(NodeFlags.NoMove))
{
node.Location += locationDelta;
movedNodes.Add(node);
}
visitedNodes.Add(node);
foreach (var box in node.GetBoxes())
{
if (!box.HasAnyConnection || box == intersectedConnectionInputBox)
continue;
foreach (var connectedBox in box.Connections)
{
SurfaceNode nextNode = connectedBox.ParentNode;
if (visitedNodes.Contains(nextNode))
continue;
MoveConnectedNodes(nextNode);
}
}
}
Float2 nodeMoveOffset = new Float2(node.Width * 0.5f, 0f);
node.Location += nodeMoveOffset;
var moveNodesAction = new MoveNodesAction(Context, movedNodes.Select(n => n.ID).ToArray(), locationDelta);
var moveNodeAction = new MoveNodesAction(Context, [node.ID], nodeMoveOffset);
var multiAction = new MultiUndoAction(moveNodeAction, moveNodesAction);
AddBatchedUndoAction(multiAction);
}
}
}
if (Undo != null && !_movingNodesDelta.IsZero && CanEdit)
AddBatchedUndoAction(new MoveNodesAction(Context, _movingNodes.Select(x => x.ID).ToArray(), _movingNodesDelta));
Undo.AddAction(new MoveNodesAction(Context, _movingNodes.Select(x => x.ID).ToArray(), _movingNodesDelta));
_movingNodes.Clear();
}
_movingNodesDelta = Float2.Zero;
@@ -749,36 +630,12 @@ namespace FlaxEditor.Surface
{
// Check if any control is under the mouse
_cmStartPos = location;
if (controlUnderMouse == null && !_isLazyConnecting)
if (controlUnderMouse == null)
{
showPrimaryMenu = true;
}
}
_mouseMoveAmount = 0;
if (_isLazyConnecting)
{
if (_lazyConnectStartNode != null && _lazyConnectEndNode != null && _lazyConnectStartNode != _lazyConnectEndNode)
{
// First check if there is a type matching input and output where input
OutputBox startNodeOutput = (OutputBox)_lazyConnectStartNode.GetBoxes().FirstOrDefault(b => b.IsOutput, null);
InputBox endNodeInput = null;
if (startNodeOutput != null)
endNodeInput = (InputBox)_lazyConnectEndNode.GetBoxes().FirstOrDefault(b => !b.IsOutput && b.CurrentType == startNodeOutput.CurrentType && !b.HasAnyConnection && b.IsActive && b.CanConnectWith(startNodeOutput), null);
// Perform less strict checks (less ideal conditions for connection but still good) if the first checks failed
if (endNodeInput == null)
endNodeInput = (InputBox)_lazyConnectEndNode.GetBoxes().FirstOrDefault(b => !b.IsOutput && !b.HasAnyConnection && b.CanConnectWith(startNodeOutput), null);
if (startNodeOutput != null && endNodeInput != null)
TryConnect(startNodeOutput, endNodeInput);
}
_isLazyConnecting = false;
_lazyConnectStartNode = null;
_lazyConnectEndNode = null;
}
}
if (_middleMouseDown && button == MouseButton.Middle)
{
@@ -794,7 +651,7 @@ namespace FlaxEditor.Surface
{
// Surface was not moved with MMB so try to remove connection underneath
var mousePos = _rootControl.PointFromParent(ref location);
if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox, MouseOverConnectionDistance))
if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox))
{
var action = new EditNodeConnections(inputBox.ParentNode.Context, inputBox.ParentNode);
inputBox.BreakConnection(outputBox);
@@ -847,21 +704,13 @@ namespace FlaxEditor.Surface
private void MoveSelectedNodes(Float2 delta)
{
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
// TODO: undo
delta /= _targetScale;
OnGetNodesToMove();
foreach (var node in _movingNodes)
{
node.Location += delta;
if (Undo != null)
undoActions.Add(new MoveNodesAction(Context, new[] { node.ID }, delta));
}
_isMovingSelection = false;
MarkAsEdited(false);
if (undoActions.Count > 0)
Undo?.AddAction(new MultiUndoAction(undoActions, "Moved "));
}
/// <inheritdoc />
@@ -988,29 +837,6 @@ namespace FlaxEditor.Surface
return false;
}
private SurfaceNode GetClosestNodeAtLocation(Float2 location)
{
SurfaceNode currentClosestNode = null;
float currentClosestDistanceSquared = float.MaxValue;
foreach (var node in Nodes)
{
if (node is SurfaceComment || node is ParticleEmitterNode)
continue;
Float2 nodeSurfaceLocation = _rootControl.PointToParent(node.Center);
float distanceSquared = Float2.DistanceSquared(location, nodeSurfaceLocation);
if (distanceSquared < currentClosestDistanceSquared)
{
currentClosestNode = node;
currentClosestDistanceSquared = distanceSquared;
}
}
return currentClosestNode;
}
private void ResetInput()
{
InputText = "";
@@ -1019,8 +845,7 @@ namespace FlaxEditor.Surface
private void CurrentInputTextChanged(string currentInputText)
{
// Check if focus selected nodes binding is being pressed to prevent it triggering primary menu
if (string.IsNullOrEmpty(currentInputText) || _focusSelectedNodeBinding.Process(RootWindow))
if (string.IsNullOrEmpty(currentInputText))
return;
if (IsPrimaryMenuOpened || !CanEdit)
{
@@ -1200,7 +1025,7 @@ namespace FlaxEditor.Surface
return new Float2(xLocation, yLocation);
}
private bool IntersectsConnection(Float2 mousePosition, out InputBox inputBox, out OutputBox outputBox, float distance)
private bool IntersectsConnection(Float2 mousePosition, out InputBox inputBox, out OutputBox outputBox)
{
for (int i = 0; i < Nodes.Count; i++)
{
@@ -1210,7 +1035,7 @@ namespace FlaxEditor.Surface
{
for (int k = 0; k < ob.Connections.Count; k++)
{
if (ob.IntersectsConnection(ob.Connections[k], ref mousePosition, distance))
if (ob.IntersectsConnection(ob.Connections[k], ref mousePosition))
{
outputBox = ob;
inputBox = ob.Connections[k] as InputBox;

View File

@@ -217,7 +217,7 @@ namespace FlaxEditor.Surface
set
{
// Clamp
value = Mathf.Clamp(value, 0.05f, 1.85f);
value = Mathf.Clamp(value, 0.05f, 1.6f);
// Check if value will change
if (Mathf.Abs(value - _targetScale) > 0.0001f)
@@ -423,9 +423,8 @@ namespace FlaxEditor.Surface
new InputActionsContainer.Binding(options => options.NodesAlignLeft, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Left); }),
new InputActionsContainer.Binding(options => options.NodesAlignCenter, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Center); }),
new InputActionsContainer.Binding(options => options.NodesAlignRight, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Right); }),
new InputActionsContainer.Binding(options => options.NodesDistributeHorizontal, () => { DistributeNodes(SelectedNodes, false); }),
new InputActionsContainer.Binding(options => options.NodesDistributeVertical, () => { DistributeNodes(SelectedNodes, true); }),
new InputActionsContainer.Binding(options => options.FocusSelectedNodes, () => { FocusSelectionOrWholeGraph(); }),
new InputActionsContainer.Binding(options => options.NodesDistributeHorizontal, () => { DistributeNodes(SelectedNodes, false); }),
new InputActionsContainer.Binding(options => options.NodesDistributeVertical, () => { DistributeNodes(SelectedNodes, true); }),
});
Context.ControlSpawned += OnSurfaceControlSpawned;
@@ -437,10 +436,7 @@ namespace FlaxEditor.Surface
DragHandlers.Add(_dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem));
DragHandlers.Add(_dragParameters = new DragNames<DragDropEventArgs>(SurfaceParameter.DragPrefix, ValidateDragParameter));
OnEditorOptionsChanged(Editor.Instance.Options.Options);
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
}
private void OnScriptsReloadBegin()
@@ -450,11 +446,6 @@ namespace FlaxEditor.Surface
_cmPrimaryMenu = null;
}
private void OnEditorOptionsChanged(EditorOptions options)
{
_focusSelectedNodeBinding = options.Input.FocusSelectedNodes;
}
/// <summary>
/// Gets the display name of the connection type used in the surface.
/// </summary>
@@ -511,7 +502,7 @@ namespace FlaxEditor.Surface
{
GroupID = Custom.GroupID,
Name = "Custom",
Color = Color.Wheat.RGBMultiplied(0.4f),
Color = Color.Wheat
};
}
else
@@ -592,11 +583,6 @@ namespace FlaxEditor.Surface
/// </summary>
public virtual bool CanSetParameters => false;
/// <summary>
/// Gets a value indicating whether surface private parameters can be used, otherwise they will remain hidden.
/// </summary>
public virtual bool CanShowPrivateParameters => false;
/// <summary>
/// True of the context menu should make use of a description panel drawn at the bottom of the menu
/// </summary>
@@ -657,37 +643,6 @@ namespace FlaxEditor.Surface
ViewCenterPosition = areaRect.Center;
}
/// <summary>
/// Adjusts the view to focus on the currently selected nodes, or the entire graph if no nodes are selected.
/// </summary>
public void FocusSelectionOrWholeGraph()
{
if (SelectedNodes.Count > 0)
ShowSelection();
else
ShowWholeGraph();
}
/// <summary>
/// Shows the selected controls by changing the view scale and the position.
/// </summary>
public void ShowSelection()
{
var selection = SelectedControls;
if (selection.Count == 0)
return;
// Calculate the bounds of all selected controls
Rectangle bounds = selection[0].Bounds;
for (int i = 1; i < selection.Count; i++)
bounds = Rectangle.Union(bounds, selection[i].Bounds);
// Add margin
bounds = bounds.MakeExpanded(250.0f);
ShowArea(bounds);
}
/// <summary>
/// Shows the given surface node by changing the view scale and the position and focuses the node.
/// </summary>
@@ -1111,7 +1066,6 @@ namespace FlaxEditor.Surface
_cmPrimaryMenu?.Dispose();
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
base.OnDestroy();
}

View File

@@ -254,10 +254,9 @@ namespace FlaxEditor.Surface
public SurfaceParameter GetParameter(Guid id)
{
SurfaceParameter result = null;
var parameters = Parameters;
for (int i = 0; i < parameters.Count; i++)
for (int i = 0; i < Parameters.Count; i++)
{
var parameter = parameters[i];
var parameter = Parameters[i];
if (parameter.ID == id)
{
result = parameter;
@@ -275,10 +274,9 @@ namespace FlaxEditor.Surface
public SurfaceParameter GetParameter(string name)
{
SurfaceParameter result = null;
var parameters = Parameters;
for (int i = 0; i < parameters.Count; i++)
for (int i = 0; i < Parameters.Count; i++)
{
var parameter = parameters[i];
var parameter = Parameters[i];
if (parameter.Name == name)
{
result = parameter;

View File

@@ -187,9 +187,6 @@ namespace FlaxEditor.Surface
/// <inheritdoc />
public override bool CanSetParameters => true;
/// <inheritdoc />
public override bool CanShowPrivateParameters => true;
/// <inheritdoc />
public override bool UseContextMenuDescriptionPanel => true;

View File

@@ -89,7 +89,7 @@ namespace FlaxEditor.Tools.Terrain
if (!terrain.HasPatch(ref patchCoord) && _planeModel)
{
var planeSize = 100.0f;
var patchSize = terrain.PatchSize;
var patchSize = terrain.ChunkSize * FlaxEngine.Terrain.UnitsPerVertex * FlaxEngine.Terrain.PatchEdgeChunksCount;
Matrix world = Matrix.RotationX(-Mathf.PiOverTwo) *
Matrix.Scaling(patchSize / planeSize) *
Matrix.Translation(patchSize * (0.5f + patchCoord.X), 0, patchSize * (0.5f + patchCoord.Y)) *

View File

@@ -69,9 +69,9 @@ namespace FlaxEditor.Tools.Terrain.Paint
var splatmapIndex = ActiveSplatmapIndex;
var splatmapIndexOther = (splatmapIndex + 1) % 2;
var chunkSize = terrain.ChunkSize;
var heightmapSize = terrain.HeightmapSize;
var heightmapSize = chunkSize * FlaxEngine.Terrain.PatchEdgeChunksCount + 1;
var heightmapLength = heightmapSize * heightmapSize;
var patchSize = terrain.PatchSize;
var patchSize = chunkSize * FlaxEngine.Terrain.UnitsPerVertex * FlaxEngine.Terrain.PatchEdgeChunksCount;
var tempBuffer = (Color32*)gizmo.GetSplatmapTempBuffer(heightmapLength * Color32.SizeInBytes, splatmapIndex).ToPointer();
var tempBufferOther = (Color32*)gizmo.GetSplatmapTempBuffer(heightmapLength * Color32.SizeInBytes, (splatmapIndex + 1) % 2).ToPointer();
var unitsPerVertexInv = 1.0f / FlaxEngine.Terrain.UnitsPerVertex;

View File

@@ -70,9 +70,9 @@ namespace FlaxEditor.Tools.Terrain.Sculpt
// Prepare
var chunkSize = terrain.ChunkSize;
var heightmapSize = terrain.HeightmapSize;
var heightmapSize = chunkSize * FlaxEngine.Terrain.PatchEdgeChunksCount + 1;
var heightmapLength = heightmapSize * heightmapSize;
var patchSize = terrain.PatchSize;
var patchSize = chunkSize * FlaxEngine.Terrain.UnitsPerVertex * FlaxEngine.Terrain.PatchEdgeChunksCount;
var tempBuffer = (float*)gizmo.GetHeightmapTempBuffer(heightmapLength * sizeof(float)).ToPointer();
var unitsPerVertexInv = 1.0f / FlaxEngine.Terrain.UnitsPerVertex;

View File

@@ -382,8 +382,7 @@ bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder)
const Int2 heightmapSize = size * Terrain::ChunksCountEdge * terrain->GetChunkSize() + 1;
Array<float> heightmap;
heightmap.Resize(heightmapSize.X * heightmapSize.Y);
if (const float* heightmapData = firstPatch->GetHeightmapData())
heightmap.SetAll(heightmapData[0]);
heightmap.SetAll(firstPatch->GetHeightmapData()[0]);
// Fill heightmap with data from all patches
const int32 rowSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1;
@@ -393,16 +392,8 @@ bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder)
const Int2 pos(patch->GetX() - start.X, patch->GetZ() - start.Y);
const float* src = patch->GetHeightmapData();
float* dst = heightmap.Get() + pos.X * (rowSize - 1) + pos.Y * heightmapSize.X * (rowSize - 1);
if (src)
{
for (int32 row = 0; row < rowSize; row++)
Platform::MemoryCopy(dst + row * heightmapSize.X, src + row * rowSize, rowSize * sizeof(float));
}
else
{
for (int32 row = 0; row < rowSize; row++)
Platform::MemoryClear(dst + row * heightmapSize.X, rowSize * sizeof(float));
}
for (int32 row = 0; row < rowSize; row++)
Platform::MemoryCopy(dst + row * heightmapSize.X, src + row * rowSize, rowSize * sizeof(float));
}
// Interpolate to 16-bit int

View File

@@ -85,7 +85,8 @@ namespace FlaxEditor.Tools.Terrain.Undo
{
_terrain = terrain.ID;
_patches = new List<PatchData>(4);
var heightmapSize = terrain.HeightmapSize;
var chunkSize = terrain.ChunkSize;
var heightmapSize = chunkSize * FlaxEngine.Terrain.PatchEdgeChunksCount + 1;
_heightmapLength = heightmapSize * heightmapSize;
_heightmapDataSize = _heightmapLength * stride;

View File

@@ -41,7 +41,7 @@ namespace FlaxEditor.Actions
ActionString = name;
_pasteParent = pasteParent;
_idsMapping = new Dictionary<Guid, Guid>(objectIds.Length);
_idsMapping = new Dictionary<Guid, Guid>(objectIds.Length * 4);
for (int i = 0; i < objectIds.Length; i++)
{
_idsMapping[objectIds[i]] = Guid.NewGuid();
@@ -72,24 +72,13 @@ namespace FlaxEditor.Actions
/// <summary>
/// Links the broken parent reference (missing parent). By default links the actor to the first scene.
/// </summary>
/// <param name="actorNode">The actor node.</param>
protected virtual void LinkBrokenParentReference(ActorNode actorNode)
/// <param name="actor">The actor.</param>
protected virtual void LinkBrokenParentReference(Actor actor)
{
// Link to the first scene root
if (Level.ScenesCount == 0)
throw new Exception("Failed to paste actor with a broken reference. No loaded scenes.");
actorNode.Actor.SetParent(Level.GetScene(0), false);
}
/// <summary>
/// Checks if actor has a broken parent reference. For example, it's linked to the parent that is indie prefab editor while it should be pasted into scene.
/// </summary>
/// <param name="actorNode">The actor node.</param>
protected virtual void CheckBrokenParentReference(ActorNode actorNode)
{
// Ensure pasted object ends up on a scene
if (actorNode.Actor.Scene == null)
LinkBrokenParentReference(actorNode);
actor.SetParent(Level.GetScene(0), false);
}
/// <inheritdoc />
@@ -114,13 +103,16 @@ namespace FlaxEditor.Actions
for (int i = 0; i < actors.Length; i++)
{
var actor = actors[i];
// Check if has no parent linked (broken reference eg. old parent not existing)
if (actor.Parent == null)
{
LinkBrokenParentReference(actor);
}
var node = GetNode(actor.ID);
if (node is ActorNode actorNode)
{
// Check if has no parent linked (broken reference eg. old parent not existing)
if (actor.Parent == null)
LinkBrokenParentReference(actorNode);
nodes.Add(actorNode);
}
}
@@ -144,12 +136,6 @@ namespace FlaxEditor.Actions
nodeParents[i].Actor.SetParent(pasteParentNode.Actor, false);
}
}
else
{
// Sanity check on pasted actor to ensure they end up i na proper context (scene editor or specific prefab editor)
foreach (var node in nodeParents)
CheckBrokenParentReference(node);
}
// Store previously looked up names and the results
Dictionary<string, bool> foundNamesResults = new();

View File

@@ -166,6 +166,7 @@ namespace FlaxEditor.Viewport
#endif
// Input
internal bool _disableInputUpdate;
private bool _isControllingMouse, _isViewportControllingMouse, _wasVirtualMouseRightDown, _isVirtualMouseRightDown;
private Float2 _startPos;
@@ -1228,7 +1229,7 @@ namespace FlaxEditor.Viewport
/// Orients the viewport.
/// </summary>
/// <param name="orientation">The orientation.</param>
public void OrientViewport(Quaternion orientation)
protected void OrientViewport(Quaternion orientation)
{
OrientViewport(ref orientation);
}
@@ -1237,7 +1238,7 @@ namespace FlaxEditor.Viewport
/// Orients the viewport.
/// </summary>
/// <param name="orientation">The orientation.</param>
public virtual void OrientViewport(ref Quaternion orientation)
protected virtual void OrientViewport(ref Quaternion orientation)
{
if (ViewportCamera is FPSCamera fpsCamera)
{

View File

@@ -1,19 +1,18 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using Object = FlaxEngine.Object;
using FlaxEditor.Content;
using FlaxEditor.Gizmo;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Options;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEditor.Viewport.Modes;
using FlaxEditor.Viewport.Widgets;
using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.Gizmo;
using FlaxEngine.GUI;
using Object = FlaxEngine.Object;
namespace FlaxEditor.Viewport
{
@@ -27,7 +26,6 @@ namespace FlaxEditor.Viewport
private readonly ContextMenuButton _showGridButton;
private readonly ContextMenuButton _showNavigationButton;
private readonly ContextMenuButton _toggleGameViewButton;
private readonly ContextMenuButton _showDirectionGizmoButton;
private SelectionOutline _customSelectionOutline;
/// <summary>
@@ -110,14 +108,13 @@ namespace FlaxEditor.Viewport
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
private EditorSpritesRenderer _editorSpritesRenderer;
private ViewportRubberBandSelector _rubberBandSelector;
private DirectionGizmo _directionGizmo;
private bool _gameViewActive;
private ViewFlags _preGameViewFlags;
private ViewMode _preGameViewViewMode;
private bool _gameViewWasGridShown;
private bool _gameViewWasFpsCounterShown;
private bool _gameViewWasNavigationShown;
private bool _gameViewWasNagivationShown;
/// <summary>
/// Drag and drop handlers
@@ -229,13 +226,6 @@ namespace FlaxEditor.Viewport
// Add rubber band selector
_rubberBandSelector = new ViewportRubberBandSelector(this);
// Add direction gizmo
_directionGizmo = new DirectionGizmo(this)
{
AnchorPreset = AnchorPresets.TopRight,
Parent = this,
};
// Add grid
Grid = new GridGizmo(this);
Grid.EnabledChanged += gizmo => _showGridButton.Icon = gizmo.Enabled ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
@@ -254,11 +244,6 @@ namespace FlaxEditor.Viewport
_showNavigationButton = ViewWidgetShowMenu.AddButton("Navigation", inputOptions.ToggleNavMeshVisibility, () => ShowNavigation = !ShowNavigation);
_showNavigationButton.CloseMenuOnClick = false;
// Show direction gizmo widget
_showDirectionGizmoButton = ViewWidgetShowMenu.AddButton("Direction Gizmo", () => _directionGizmo.Visible = !_directionGizmo.Visible);
_showDirectionGizmoButton.AutoCheck = true;
_showDirectionGizmoButton.CloseMenuOnClick = false;
// Game View
ViewWidgetButtonMenu.AddSeparator();
_toggleGameViewButton = ViewWidgetButtonMenu.AddButton("Game View", inputOptions.ToggleGameView, ToggleGameView);
@@ -292,18 +277,6 @@ namespace FlaxEditor.Viewport
// Game View
InputActions.Add(options => options.ToggleGameView, ToggleGameView);
editor.Options.OptionsChanged += OnEditorOptionsChanged;
OnEditorOptionsChanged(editor.Options.Options);
}
private void OnEditorOptionsChanged(EditorOptions options)
{
_directionGizmo.Visible = options.Viewport.ShowDirectionGizmo;
_showDirectionGizmoButton.Checked = _directionGizmo.Visible;
_directionGizmo.Size = new Float2(DirectionGizmo.DefaultGizmoSize * options.Viewport.DirectionGizmoScale);
_directionGizmo.LocalX = -_directionGizmo.Size.X * 0.5f;
_directionGizmo.LocalY = _directionGizmo.Size.Y * 0.5f + ViewportWidgetsContainer.WidgetsHeight;
}
/// <inheritdoc />
@@ -541,14 +514,14 @@ namespace FlaxEditor.Viewport
_preGameViewViewMode = Task.ViewMode;
_gameViewWasGridShown = Grid.Enabled;
_gameViewWasFpsCounterShown = ShowFpsCounter;
_gameViewWasNavigationShown = ShowNavigation;
_gameViewWasNagivationShown = ShowNavigation;
}
// Set flags & values
Task.ViewFlags = _gameViewActive ? _preGameViewFlags : ViewFlags.DefaultGame;
Task.ViewMode = _gameViewActive ? _preGameViewViewMode : ViewMode.Default;
ShowFpsCounter = _gameViewActive ? _gameViewWasFpsCounterShown : false;
ShowNavigation = _gameViewActive ? _gameViewWasNavigationShown : false;
ShowNavigation = _gameViewActive ? _gameViewWasNagivationShown : false;
Grid.Enabled = _gameViewActive ? _gameViewWasGridShown : false;
_gameViewActive = !_gameViewActive;
@@ -674,7 +647,7 @@ namespace FlaxEditor.Viewport
}
/// <inheritdoc />
public override void OrientViewport(ref Quaternion orientation)
protected override void OrientViewport(ref Quaternion orientation)
{
if (TransformGizmo.SelectedParents.Count != 0)
FocusSelection(ref orientation);

View File

@@ -681,7 +681,7 @@ namespace FlaxEditor.Viewport
}
/// <inheritdoc />
public override void OrientViewport(ref Quaternion orientation)
protected override void OrientViewport(ref Quaternion orientation)
{
if (TransformGizmo.SelectedParents.Count != 0)
FocusSelection(ref orientation);

Some files were not shown because too many files have changed in this diff Show More