diff --git a/Content/Shaders/DepthOfField.flax b/Content/Shaders/DepthOfField.flax
index 7febbf090..167b0bdf8 100644
--- a/Content/Shaders/DepthOfField.flax
+++ b/Content/Shaders/DepthOfField.flax
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:abd45cf24b2b6c728ec603052a2aace6f335d6ccfc8b0d5e3184c48c7c2a35f1
+oid sha256:ba2624e8a3949e339c4b10d356be69c67d6e39bad89a34755fbbad191135f953
size 13356
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 4928722b6..5382bd731 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -384,7 +384,7 @@ namespace FlaxEditor.Content.GUI
/// Selects the specified item.
///
/// The item.
- /// If set to true item will be added to the current selection. Otherwise selection will be cleared before.
+ /// If set to true item will be added to the current selection. Otherwise, selection will be cleared before.
public void Select(ContentItem item, bool additive = false)
{
if (item == null)
diff --git a/Source/Editor/Content/Import/ImportFilesDialog.cs b/Source/Editor/Content/Import/ImportFilesDialog.cs
index c9b1b8c4f..f245f49ee 100644
--- a/Source/Editor/Content/Import/ImportFilesDialog.cs
+++ b/Source/Editor/Content/Import/ImportFilesDialog.cs
@@ -21,6 +21,7 @@ namespace FlaxEditor.Content.Import
{
private TreeNode _rootNode;
private CustomEditorPresenter _settingsEditor;
+ private Tree _tree;
///
/// Gets the entries count.
@@ -106,11 +107,11 @@ namespace FlaxEditor.Content.Import
_settingsEditor.Panel.Parent = splitPanel.Panel2;
// Setup tree
- var tree = new Tree(true)
+ _tree = new Tree(true)
{
Parent = splitPanel.Panel1
};
- tree.RightClick += OnTreeRightClick;
+ _tree.RightClick += OnTreeRightClick;
_rootNode = new TreeNode(false);
for (int i = 0; i < entries.Count; i++)
{
@@ -124,12 +125,12 @@ namespace FlaxEditor.Content.Import
}
_rootNode.Expand();
_rootNode.ChildrenIndent = 0;
- _rootNode.Parent = tree;
- tree.Margin = new Margin(0.0f, 0.0f, -14.0f, 2.0f); // Hide root node
- tree.SelectedChanged += OnSelectedChanged;
+ _rootNode.Parent = _tree;
+ _tree.Margin = new Margin(0.0f, 0.0f, -16.0f, 2.0f); // Hide root node
+ _tree.SelectedChanged += OnSelectedChanged;
// Select the first item
- tree.Select(_rootNode.Children[0] as TreeNode);
+ _tree.Select(_rootNode.Children[0] as TreeNode);
_dialogSize = new Float2(TotalWidth, EditorHeight + splitPanel.Offsets.Height);
}
@@ -257,5 +258,12 @@ namespace FlaxEditor.Content.Import
settings.MinimumSize = new Float2(300, 400);
settings.HasSizingFrame = true;
}
+
+ ///
+ public override void Focus()
+ {
+ base.Focus();
+ _tree.SelectedNode?.Focus();
+ }
}
}
diff --git a/Source/Editor/GUI/Tree/Tree.cs b/Source/Editor/GUI/Tree/Tree.cs
index 3f60572f6..d48b1756e 100644
--- a/Source/Editor/GUI/Tree/Tree.cs
+++ b/Source/Editor/GUI/Tree/Tree.cs
@@ -138,7 +138,8 @@ namespace FlaxEditor.GUI.Tree
/// Selects single tree node.
///
/// Node to select.
- public void Select(TreeNode node)
+ /// If set to true item will be added to the current selection. Otherwise, selection will be cleared before.
+ public void Select(TreeNode node, bool additive = false)
{
if (node == null)
throw new ArgumentNullException();
@@ -151,8 +152,16 @@ namespace FlaxEditor.GUI.Tree
var prev = new List(Selection);
// Update selection
- Selection.Clear();
- Selection.Add(node);
+ if (additive)
+ {
+ if (!Selection.Contains(node))
+ Selection.Add(node);
+ }
+ else
+ {
+ Selection.Clear();
+ Selection.Add(node);
+ }
// Ensure that node can be visible (all it's parents are expanded)
node.ExpandAllParents();
diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs
index 53075fe38..0559e18db 100644
--- a/Source/Editor/Modules/ContentDatabaseModule.cs
+++ b/Source/Editor/Modules/ContentDatabaseModule.cs
@@ -1261,7 +1261,6 @@ namespace FlaxEditor.Modules
private void OnImportFileDone(string path)
{
- // Check if already has that element
var item = Find(path);
if (item is BinaryAssetItem binaryAssetItem)
{
@@ -1284,9 +1283,6 @@ namespace FlaxEditor.Modules
binaryAssetItem.OnReimport(ref assetInfo.ID);
}
}
-
- // Refresh content view (not the best design because window could also track this event but it gives better performance)
- Editor.Windows.ContentWin?.RefreshView();
}
}
diff --git a/Source/Editor/Modules/ContentImportingModule.cs b/Source/Editor/Modules/ContentImportingModule.cs
index 8029c7418..99994ec1f 100644
--- a/Source/Editor/Modules/ContentImportingModule.cs
+++ b/Source/Editor/Modules/ContentImportingModule.cs
@@ -252,6 +252,8 @@ namespace FlaxEditor.Modules
/// Import settings to override. Use null to skip this value.
private void Import(string inputPath, string outputPath, bool isInBuilt, bool skipSettingsDialog = false, object settings = null)
{
+ inputPath = StringUtils.NormalizePath(inputPath);
+ outputPath = StringUtils.NormalizePath(outputPath);
lock (_requests)
{
_requests.Add(new Request
@@ -311,7 +313,9 @@ namespace FlaxEditor.Modules
}
_importBatchDone++;
+ Profiler.BeginEvent("ImportFileEnd");
ImportFileEnd?.Invoke(entry, failed);
+ Profiler.EndEvent();
}
}
else
diff --git a/Source/Editor/Options/ViewportOptions.cs b/Source/Editor/Options/ViewportOptions.cs
index 2dd08b6d1..485ac7294 100644
--- a/Source/Editor/Options/ViewportOptions.cs
+++ b/Source/Editor/Options/ViewportOptions.cs
@@ -136,6 +136,13 @@ namespace FlaxEditor.Options
[DefaultValue(50.0f), Limit(25.0f, 500.0f, 5.0f)]
[EditorDisplay("Defaults"), EditorOrder(220), Tooltip("The default editor viewport grid scale.")]
public float ViewportGridScale { get; set; } = 50.0f;
+
+ ///
+ /// Gets or sets the use persistence over defaults setting
+ ///
+ [DefaultValue(true)]
+ [EditorDisplay("Defaults"), EditorOrder(230), Tooltip("Allow persistence setting from last session to override default settings")]
+ public bool UsePersistenceOverDefaults { get; set; } = true;
///
/// Gets or sets the view distance you can see the grid.
diff --git a/Source/Editor/Surface/VisualScriptSurface.cs b/Source/Editor/Surface/VisualScriptSurface.cs
index 57aa29d67..0d9a29e7f 100644
--- a/Source/Editor/Surface/VisualScriptSurface.cs
+++ b/Source/Editor/Surface/VisualScriptSurface.cs
@@ -39,8 +39,16 @@ namespace FlaxEditor.Surface
{
"Newtonsoft.Json.",
"System.Array",
+ "System.ComponentModel.",
"System.Linq.Expressions.",
"System.Reflection.",
+ "System.Runtime.CompilerServices.",
+ "System.Runtime.InteropServices.",
+ "System.Runtime.Intrinsics.",
+ "System.Security.",
+ "System.Text.",
+ "System.Xml.",
+ "MS.",
};
private static NodesCache _nodesCache = new NodesCache(IterateNodesCache);
diff --git a/Source/Editor/Windows/ContentWindow.Navigation.cs b/Source/Editor/Windows/ContentWindow.Navigation.cs
index 4c7373aa6..27826e195 100644
--- a/Source/Editor/Windows/ContentWindow.Navigation.cs
+++ b/Source/Editor/Windows/ContentWindow.Navigation.cs
@@ -81,28 +81,10 @@ namespace FlaxEditor.Windows
_navigationUndo.Push(source);
}
- // Show folder contents and select tree node
- if (!_showAllContentInTree)
- RefreshView(target);
- _tree.Select(target);
- target.ExpandAllParents();
-
// Clear redo list
_navigationRedo.Clear();
- // Set valid sizes for stacks
- //RedoList.SetSize(32);
- //UndoList.SetSize(32);
-
- // Update search
- if (!_showAllContentInTree)
- UpdateItemsSearch();
-
- // Unlock navigation
- _navigationUnlocked = true;
-
- // Update UI
- UpdateUI();
+ DoNavigate(target);
}
}
@@ -123,25 +105,7 @@ namespace FlaxEditor.Windows
// Add to Redo list
_navigationRedo.Push(SelectedNode);
- // Select node
- if (!_showAllContentInTree)
- RefreshView(node);
- _tree.Select(node);
- node.ExpandAllParents();
-
- // Set valid sizes for stacks
- //RedoList.SetSize(32);
- //UndoList.SetSize(32);
-
- // Update search
- if (!_showAllContentInTree)
- UpdateItemsSearch();
-
- // Unlock navigation
- _navigationUnlocked = true;
-
- // Update UI
- UpdateUI();
+ DoNavigate(node);
if (!_showAllContentInTree)
_view.SelectFirstItem();
}
@@ -164,25 +128,7 @@ namespace FlaxEditor.Windows
// Add to Undo list
_navigationUndo.Push(SelectedNode);
- // Select node
- if (!_showAllContentInTree)
- RefreshView(node);
- _tree.Select(node);
- node.ExpandAllParents();
-
- // Set valid sizes for stacks
- //RedoList.SetSize(32);
- //UndoList.SetSize(32);
-
- // Update search
- if (!_showAllContentInTree)
- UpdateItemsSearch();
-
- // Unlock navigation
- _navigationUnlocked = true;
-
- // Update UI
- UpdateUI();
+ DoNavigate(node);
if (!_showAllContentInTree)
_view.SelectFirstItem();
}
@@ -214,6 +160,32 @@ namespace FlaxEditor.Windows
UpdateUI();
}
+ private void DoNavigate(ContentFolderTreeNode node)
+ {
+ // Select node
+ if (!_showAllContentInTree)
+ RefreshView(node);
+ _tree.Select(node);
+ node.ExpandAllParents();
+
+ // Set valid sizes for stacks
+ //RedoList.SetSize(32);
+ //UndoList.SetSize(32);
+
+ // Update search
+ if (!_showAllContentInTree)
+ UpdateItemsSearch();
+
+ // Unlock navigation
+ _navigationUnlocked = true;
+
+ UpdateUI();
+
+ // Clear auto-select cache for new/imported files
+ _newFilesCache?.Clear();
+ _newFilesCacheSize = 0;
+ }
+
private void UpdateNavigationBar()
{
if (_navigationBar == null)
diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs
index 5a73530bc..2d9daabeb 100644
--- a/Source/Editor/Windows/ContentWindow.cs
+++ b/Source/Editor/Windows/ContentWindow.cs
@@ -67,6 +67,8 @@ namespace FlaxEditor.Windows
private readonly Stack _navigationRedo = new Stack(32);
private NewItem _newElement;
+ private List _newFilesCache;
+ private int _newFilesCacheSize;
///
/// Gets the toolstrip.
@@ -598,21 +600,9 @@ namespace FlaxEditor.Windows
// Disable scrolling in proper view
_renameInTree = _showAllContentInTree;
if (_renameInTree)
- {
- if (_contentTreePanel.VScrollBar != null)
- _contentTreePanel.VScrollBar.ThumbEnabled = false;
- if (_contentTreePanel.HScrollBar != null)
- _contentTreePanel.HScrollBar.ThumbEnabled = false;
ScrollingOnTreeView(false);
- }
else
- {
- if (_contentViewPanel.VScrollBar != null)
- _contentViewPanel.VScrollBar.ThumbEnabled = false;
- if (_contentViewPanel.HScrollBar != null)
- _contentViewPanel.HScrollBar.ThumbEnabled = false;
ScrollingOnContentView(false);
- }
// Show rename popup
RenamePopup popup;
@@ -664,21 +654,9 @@ namespace FlaxEditor.Windows
{
// Restore scrolling in proper view
if (_renameInTree)
- {
- if (_contentTreePanel.VScrollBar != null)
- _contentTreePanel.VScrollBar.ThumbEnabled = true;
- if (_contentTreePanel.HScrollBar != null)
- _contentTreePanel.HScrollBar.ThumbEnabled = true;
ScrollingOnTreeView(true);
- }
else
- {
- if (_contentViewPanel.VScrollBar != null)
- _contentViewPanel.VScrollBar.ThumbEnabled = true;
- if (_contentViewPanel.HScrollBar != null)
- _contentViewPanel.HScrollBar.ThumbEnabled = true;
ScrollingOnContentView(true);
- }
_renameInTree = false;
// Check if was creating new element
@@ -704,7 +682,6 @@ namespace FlaxEditor.Windows
// Check if can rename this item
if (!item.CanRename)
{
- // Cannot
MessageBox.Show("Cannot rename this item.", "Cannot rename", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
@@ -718,7 +695,6 @@ namespace FlaxEditor.Windows
// Check if name is valid
if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out string hint))
{
- // Invalid name
MessageBox.Show("Given asset name is invalid. " + hint, "Invalid name", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
@@ -740,6 +716,7 @@ namespace FlaxEditor.Windows
// Note: we create `_newElement` and then rename it to create new asset
var itemFolder = item.ParentFolder;
Action endEvent = null;
+ bool lazyCreation = false;
if (_newElement == item)
{
try
@@ -750,6 +727,9 @@ namespace FlaxEditor.Windows
var proxy = _newElement.Proxy;
Editor.Log(string.Format("Creating asset {0} in {1}", proxy.Name, newPath));
proxy.Create(newPath, _newElement.Argument);
+
+ // When creating item with options dialog deffer processing
+ lazyCreation = !File.Exists(newPath);
}
catch (Exception ex)
{
@@ -773,6 +753,16 @@ namespace FlaxEditor.Windows
if (_newElement.Proxy is ScriptProxy && Editor.Instance.Options.Options.General.AutoReloadScriptsOnMainWindowFocus)
ScriptsBuilder.MarkWorkspaceDirty();
+ // Cache new file to be auto-selected after actual creation
+ _newFilesCache?.Clear();
+ _newFilesCacheSize = 0;
+ if (lazyCreation)
+ {
+ _newFilesCache ??= new List();
+ _newFilesCache.Add(newPath);
+ _newFilesCacheSize = 1;
+ }
+
// Destroy mock control
_newElement.ParentFolder = null;
_newElement.Dispose();
@@ -789,7 +779,8 @@ namespace FlaxEditor.Windows
var newItem = itemFolder.FindChild(newPath);
if (newItem == null)
{
- Editor.LogWarning("Failed to find the created new item.");
+ if (!lazyCreation)
+ Editor.LogWarning("Failed to find the created new item.");
return;
}
@@ -1143,11 +1134,12 @@ namespace FlaxEditor.Windows
}
///
- /// Selects the specified item in the content view.
+ /// Selects the specified item in the content view. Does nothing if the current view doesn't show the folder containing that item.
///
/// The item to select.
/// True of scroll to the item quickly without smoothing.
- public void Select(ContentItem item, bool fastScroll = false)
+ /// True of select item in additive mode with existing selection preservation, otherwise current selection will be cleared.
+ public void Select(ContentItem item, bool fastScroll = false, bool additive = false)
{
if (item == null)
throw new ArgumentNullException();
@@ -1169,7 +1161,7 @@ namespace FlaxEditor.Windows
targetNode.ExpandAllParents();
if (item is ContentFolder)
{
- _tree.Select(targetNode);
+ _tree.Select(targetNode, additive);
_contentTreePanel.ScrollViewTo(targetNode, fastScroll);
targetNode.Focus();
}
@@ -1178,13 +1170,13 @@ namespace FlaxEditor.Windows
var itemNode = FindTreeItemNode(targetNode, item);
if (itemNode != null)
{
- _tree.Select(itemNode);
+ _tree.Select(itemNode, additive);
_contentTreePanel.ScrollViewTo(itemNode, fastScroll);
itemNode.Focus();
}
else
{
- _tree.Select(targetNode);
+ _tree.Select(targetNode, additive);
}
}
}
@@ -1195,7 +1187,7 @@ namespace FlaxEditor.Windows
Navigate(parent.Node);
// Select and scroll to cover in view
- _view.Select(item);
+ _view.Select(item, additive);
_contentViewPanel.ScrollViewTo(item, fastScroll);
// Focus
@@ -1574,7 +1566,7 @@ namespace FlaxEditor.Windows
///
public override void OnInit()
{
- // Content database events
+ // Content events
Editor.ContentDatabase.WorkspaceModified += () => _isWorkspaceDirty = true;
Editor.ContentDatabase.ItemAdded += OnContentDatabaseItemAdded;
Editor.ContentDatabase.ItemRemoved += OnContentDatabaseItemRemoved;
@@ -1594,6 +1586,9 @@ namespace FlaxEditor.Windows
else if (_root != null)
ShowRoot();
};
+ Editor.ContentImporting.ImportFileBegin += OnImportFileBegin;
+ Editor.ContentImporting.ImportFileEnd += OnImportFileEnd;
+ Editor.ContentImporting.ImportingQueueBegin += OnImportingQueueBegin;
LoadExpandedFolders();
Refresh();
@@ -1631,6 +1626,64 @@ namespace FlaxEditor.Windows
OnFoldersSearchBoxTextChanged();
}
+ private void OnImportFileBegin(IFileEntryAction entry)
+ {
+ // Add to auto-select cache
+ _newFilesCache ??= new List();
+ _newFilesCache.Add(entry.ResultUrl);
+ _newFilesCacheSize++;
+ }
+
+ private void OnImportFileEnd(IFileEntryAction entry, bool failed)
+ {
+ if (failed)
+ return;
+ if (!Platform.IsInMainThread)
+ {
+ FlaxEngine.Scripting.InvokeOnUpdate(() => OnImportFileEnd(entry, false));
+ return;
+ }
+
+ // Refresh view (gives faster response than waiting for filesystem event)
+ //RefreshView(); // TODO: is this still needed?
+
+ // Auto-select pending items
+ if (_newFilesCache != null && _newFilesCache.Contains(entry.ResultUrl))
+ {
+ var item = EnsureItem(entry.ResultUrl);
+ if (item != null)
+ {
+ bool additive = _newFilesCache.Count != _newFilesCacheSize;
+ Select(item, true, additive);
+ }
+ _newFilesCache.Remove(entry.ResultUrl);
+ }
+ }
+
+ private void OnImportingQueueBegin()
+ {
+ // Clear cache to auto-select all imported files
+ _newFilesCache?.Clear();
+ _newFilesCacheSize = 0;
+ }
+
+ private ContentItem EnsureItem(string path)
+ {
+ var item = Editor.ContentDatabase.Find(path);
+ if (item == null)
+ {
+ // Cannot find the item (eg. just created file, content database event not yet handled) so refresh to take effect quickly
+ var parentPath = Path.GetDirectoryName(path);
+ var parentItem = Editor.ContentDatabase.Find(parentPath);
+ if (parentItem != null)
+ {
+ Editor.ContentDatabase.RefreshFolder(parentItem, false);
+ item = Editor.ContentDatabase.Find(path);
+ }
+ }
+ return item;
+ }
+
private void Refresh()
{
// Setup content root node
@@ -1774,16 +1827,11 @@ namespace FlaxEditor.Windows
return base.OnMouseUp(location, button);
}
- ///
- protected override void PerformLayoutBeforeChildren()
- {
- base.PerformLayoutBeforeChildren();
- }
-
///
protected override void PerformLayoutAfterChildren()
{
base.PerformLayoutAfterChildren();
+
UpdateNavigationBarBounds();
}
@@ -1846,12 +1894,18 @@ namespace FlaxEditor.Windows
_treeHeaderPanel = null;
_treeOnlyPanel = null;
_contentItemsSearchPanel = null;
+ _newFilesCache = null;
Editor.Options.OptionsChanged -= OnOptionsChanged;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
if (Editor?.ContentDatabase != null)
+ {
Editor.ContentDatabase.ItemAdded -= OnContentDatabaseItemAdded;
+ Editor.ContentImporting.ImportFileBegin -= OnImportFileBegin;
+ Editor.ContentImporting.ImportFileEnd -= OnImportFileEnd;
+ Editor.ContentImporting.ImportingQueueBegin -= OnImportingQueueBegin;
+ }
base.OnDestroy();
}
diff --git a/Source/Editor/Windows/EditGameWindow.cs b/Source/Editor/Windows/EditGameWindow.cs
index 5f91aebe6..8d0c146d9 100644
--- a/Source/Editor/Windows/EditGameWindow.cs
+++ b/Source/Editor/Windows/EditGameWindow.cs
@@ -433,25 +433,34 @@ namespace FlaxEditor.Windows
writer.WriteAttributeString("GridEnabled", Viewport.Grid.Enabled.ToString());
writer.WriteAttributeString("ShowFpsCounter", Viewport.ShowFpsCounter.ToString());
writer.WriteAttributeString("ShowNavigation", Viewport.ShowNavigation.ToString());
+ writer.WriteAttributeString("UseOrthographicProjection", Viewport.UseOrthographicProjection.ToString());
writer.WriteAttributeString("NearPlane", Viewport.NearPlane.ToString());
writer.WriteAttributeString("FarPlane", Viewport.FarPlane.ToString());
writer.WriteAttributeString("FieldOfView", Viewport.FieldOfView.ToString());
writer.WriteAttributeString("MovementSpeed", Viewport.MovementSpeed.ToString());
+ writer.WriteAttributeString("Brightness", Viewport.Brightness.ToString());
writer.WriteAttributeString("ViewportIconsScale", ViewportIconsRenderer.Scale.ToString());
+ writer.WriteAttributeString("ResolutionScale", Viewport.ResolutionScale.ToString());
writer.WriteAttributeString("OrthographicScale", Viewport.OrthographicScale.ToString());
- writer.WriteAttributeString("UseOrthographicProjection", Viewport.UseOrthographicProjection.ToString());
writer.WriteAttributeString("ViewFlags", ((ulong)Viewport.Task.View.Flags).ToString());
+ writer.WriteAttributeString("DebugView", ((int)Viewport.Task.ViewMode).ToString());
+ writer.WriteAttributeString("LayerMask", Viewport.Task.ViewLayersMask.Mask.ToString());
}
///
public override void OnLayoutDeserialize(XmlElement node)
{
+ if (!Editor.Options.Options.Viewport.UsePersistenceOverDefaults)
+ return;
+
if (bool.TryParse(node.GetAttribute("GridEnabled"), out bool value1))
Viewport.Grid.Enabled = value1;
if (bool.TryParse(node.GetAttribute("ShowFpsCounter"), out value1))
Viewport.ShowFpsCounter = value1;
if (bool.TryParse(node.GetAttribute("ShowNavigation"), out value1))
Viewport.ShowNavigation = value1;
+ if (bool.TryParse(node.GetAttribute("UseOrthographicProjection"), out value1))
+ Viewport.UseOrthographicProjection = value1;
if (float.TryParse(node.GetAttribute("NearPlane"), out float value2))
Viewport.NearPlane = value2;
if (float.TryParse(node.GetAttribute("FarPlane"), out value2))
@@ -460,18 +469,28 @@ namespace FlaxEditor.Windows
Viewport.FieldOfView = value2;
if (float.TryParse(node.GetAttribute("MovementSpeed"), out value2))
Viewport.MovementSpeed = value2;
+ if (float.TryParse(node.GetAttribute("Brightness"), out value2))
+ Viewport.Brightness = value2;
+ if (float.TryParse(node.GetAttribute("ResolutionScale"), out value2))
+ Viewport.ResolutionScale = value2;
if (float.TryParse(node.GetAttribute("ViewportIconsScale"), out value2))
ViewportIconsRenderer.Scale = value2;
if (float.TryParse(node.GetAttribute("OrthographicScale"), out value2))
Viewport.OrthographicScale = value2;
- if (bool.TryParse(node.GetAttribute("UseOrthographicProjection"), out value1))
- Viewport.UseOrthographicProjection = value1;
if (ulong.TryParse(node.GetAttribute("ViewFlags"), out ulong value3))
Viewport.Task.ViewFlags = (ViewFlags)value3;
-
- // Reset view flags if opening with different engine version (ViewFlags enum could be modified)
+ if (int.TryParse(node.GetAttribute("DebugView"), out int value4))
+ Viewport.Task.ViewMode = (ViewMode)value4;
+ if (uint.TryParse(node.GetAttribute("LayerMask"), out uint value5))
+ Viewport.Task.ViewLayersMask = new LayersMask(value5);
+
+ // Reset view flags and view mode if opening with different engine version
+ // (ViewFlags and ViewMode enums could be modified)
if (Editor.LastProjectOpenedEngineBuild != Globals.EngineBuildNumber)
+ {
Viewport.Task.ViewFlags = ViewFlags.DefaultEditor;
+ Viewport.Task.ViewMode = ViewMode.Default;
+ }
}
///
diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp
index 5560c20b9..5960badf6 100644
--- a/Source/Engine/Content/Asset.cpp
+++ b/Source/Engine/Content/Asset.cpp
@@ -430,7 +430,7 @@ void Asset::Reload()
ScopeLock lock(Locker);
- if (IsLoaded())
+ if (IsLoaded() || LastLoadFailed())
{
// Unload current data
unload(true);
diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp
index 0e1768f63..1699626aa 100644
--- a/Source/Engine/Debug/DebugDraw.cpp
+++ b/Source/Engine/Debug/DebugDraw.cpp
@@ -1526,6 +1526,44 @@ void DebugDraw::DrawCircle(const Vector3& position, const Float3& normal, float
}
}
+void DebugDraw::DrawPoint(const Vector3& position, float radius, const Color& color, float duration, bool depthTest)
+{
+ Float3 normal = (Float3)(Context->LastViewPosition - position);
+ if (normal.Length() < ZeroTolerance)
+ normal = Float3::Up;
+ normal.Normalize();
+
+ // Create matrix transform for unit circle points
+ Matrix world, scale, matrix;
+ Float3 right, up;
+ if (Float3::Dot(normal, Float3::Up) > 0.99f)
+ right = Float3::Right;
+ else if (Float3::Dot(normal, Float3::Down) > 0.99f)
+ right = Float3::Left;
+ else
+ Float3::Cross(normal, Float3::Up, right);
+ Float3::Cross(right, normal, up);
+ Matrix::Scaling(radius, scale);
+ const Float3 positionF = position - Context->Origin;
+ Matrix::CreateWorld(positionF, normal, up, world);
+ Matrix::Multiply(scale, world, matrix);
+
+ // Build a filled disc as a triangle fan from the center over the transformed unit circle points
+ PROFILE_MEM(EngineDebug);
+ auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
+ auto& debugDrawList = duration > 0 ? debugDrawData.DefaultTriangles : debugDrawData.OneFrameTriangles;
+ for (int32 i = 0; i < DEBUG_DRAW_CIRCLE_VERTICES; i += 2)
+ {
+ DebugTriangle t;
+ t.Color = Color32(color);
+ t.TimeLeft = duration;
+ t.V0 = positionF;
+ t.V1 = Float3::Transform(CircleCache[i], matrix);
+ t.V2 = Float3::Transform(CircleCache[i + 1], matrix);
+ debugDrawList.Add(t);
+ }
+}
+
void DebugDraw::DrawWireTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color, float duration, bool depthTest)
{
DrawLine(v0, v1, color, duration, depthTest);
diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h
index c4ae12283..9084ab962 100644
--- a/Source/Engine/Debug/DebugDraw.h
+++ b/Source/Engine/Debug/DebugDraw.h
@@ -267,6 +267,16 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// The duration (in seconds). Use 0 to draw it only once.
/// If set to true depth test will be performed, otherwise depth will be ignored.
API_FUNCTION() static void DrawCircle(const Vector3& position, const Float3& normal, float radius, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
+
+ ///
+ /// Draws the point facing camera.
+ ///
+ /// The center position.
+ /// The radius.
+ /// The color.
+ /// The duration (in seconds). Use 0 to draw it only once.
+ /// If set to true depth test will be performed, otherwise depth will be ignored.
+ API_FUNCTION() static void DrawPoint(const Vector3& position, float radius, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
///
/// Draws the wireframe triangle.
@@ -780,6 +790,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
#define DEBUG_DRAW_LINES(lines, transform, color, duration, depthTest) DebugDraw::DrawLines(lines, transform, color, duration, depthTest)
#define DEBUG_DRAW_BEZIER(p1, p2, p3, p4, color, duration, depthTest) DebugDraw::DrawBezier(p1, p2, p3, p4, color, duration, depthTest)
#define DEBUG_DRAW_CIRCLE(position, normal, radius, color, duration, depthTest) DebugDraw::DrawCircle(position, normal, radius, color, duration, depthTest)
+#define DEBUG_DRAW_POINT(position, radius, color, duration, depthTest) DebugDraw::DrawPoint(position, radius, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLE(v0, v1, v2, color, duration, depthTest) DebugDraw::DrawTriangle(v0, v1, v2, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES(vertices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES_EX(vertices, indices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, indices, color, duration, depthTest)
diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp
index c2f340645..b793cfe38 100644
--- a/Source/Engine/Graphics/Models/Mesh.cpp
+++ b/Source/Engine/Graphics/Models/Mesh.cpp
@@ -70,8 +70,7 @@ namespace
if (accessor.AllocateBuffer(MeshBufferType::Vertex0, vertexCount, vb0layout))
return true;
auto positionStream = accessor.Position();
- ASSERT(positionStream.IsLinear(PixelFormat::R32G32B32_Float));
- positionStream.SetLinear(vertices);
+ positionStream.Set(Span(vertices, vertexCount));
}
// Vertex Buffer 1 (general purpose components)
diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
index 0377003be..97aa6f6fb 100644
--- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp
+++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
@@ -44,7 +44,7 @@ namespace
// Index Buffer
{
- if (accessor.AllocateBuffer(MeshBufferType::Index, triangleCount, indexFormat))
+ if (accessor.AllocateBuffer(MeshBufferType::Index, triangleCount * 3, indexFormat))
return true;
auto indexStream = accessor.Index();
ASSERT(indexStream.IsLinear(indexFormat));
@@ -73,8 +73,7 @@ namespace
return true;
auto positionStream = accessor.Position();
- ASSERT(positionStream.IsLinear(PixelFormat::R32G32B32_Float));
- positionStream.SetLinear(vertices);
+ positionStream.Set(Span(vertices, vertexCount));
if (normals)
{
auto normalStream = accessor.Normal();
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
index 09ad93cec..e09b1e9ad 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
@@ -475,7 +475,11 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
uv = MaterialValue::Cast(tryGetValue(uvBox, getUVs), VariantType::Float2).Value;
else
uv = TEXT("input.TexCoord.xy");
- value = writeLocal(VariantType::Float3, String::Format(TEXT("GetWorldPos({1}, {0}.rgb)"), depthSample->Value, uv), node);
+ const auto layer = GetRootLayer();
+ if (layer && layer->Domain == MaterialDomain::PostProcess)
+ value = writeLocal(VariantType::Float3, String::Format(TEXT("GetWorldPos({1}, {0})"), depthSample->Value, uv), node);
+ else // TODO: reimpl GetWorldPos() for other domains (see 'Content/Editor/MaterialTemplates/PostProcess.shader'), can be via matrix inverse in a shader
+ value = ShaderGraphValue::InitForZero(VariantType::Float3);
break;
}
case MaterialSceneTextures::SceneStencil: