Compare commits
4 Commits
sdl_mac_fi
...
emscripten
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cf6979f90 | |||
| 1ff4ac0402 | |||
| 801f0f7432 | |||
| 8b605dff89 |
8
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
8
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
@@ -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:
|
||||
|
||||
@@ -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
1
.github/data/bt.sh
vendored
@@ -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' \
|
||||
|
||||
6
.github/workflows/build_android.yml
vendored
6
.github/workflows/build_android.yml
vendored
@@ -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
|
||||
|
||||
11
.github/workflows/build_windows.yml
vendored
11
.github/workflows/build_windows.yml
vendored
@@ -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
|
||||
|
||||
11
.github/workflows/cd.yml
vendored
11
.github/workflows/cd.yml
vendored
@@ -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
|
||||
|
||||
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
Content/Editor/HSWheel.flax
LFS
BIN
Content/Editor/HSWheel.flax
LFS
Binary file not shown.
@@ -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
|
||||
|
||||
|
||||
BIN
Content/Shaders/SSR.flax
LFS
BIN
Content/Shaders/SSR.flax
LFS
Binary file not shown.
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
333
Source/Editor/Content/Tree/ContentTreeNode.cs
Normal file
333
Source/Editor/Content/Tree/ContentTreeNode.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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[]
|
||||
{
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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[]
|
||||
{
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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[]
|
||||
{
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); });
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)) *
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user