diff --git a/Source/Editor/Content/Proxy/SceneAnimationProxy.cs b/Source/Editor/Content/Proxy/SceneAnimationProxy.cs
index 73c51c072..fe31f0e34 100644
--- a/Source/Editor/Content/Proxy/SceneAnimationProxy.cs
+++ b/Source/Editor/Content/Proxy/SceneAnimationProxy.cs
@@ -36,6 +36,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Animation/Scene Animation")]
public class SceneAnimationProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp
index 6e9fefa0e..15ea13153 100644
--- a/Source/Editor/Cooker/GameCooker.cpp
+++ b/Source/Editor/Cooker/GameCooker.cpp
@@ -562,7 +562,7 @@ bool GameCookerImpl::Build()
{
if (GameCooker::IsCancelRequested())
break;
- if (data.Options & BuildOptions::NoCook)
+ if (EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
continue;
auto step = Steps[stepIndex];
data.NextStep();
@@ -587,12 +587,12 @@ bool GameCookerImpl::Build()
{
LOG(Info, "Game building done!");
- if (data.Options & BuildOptions::ShowOutput)
+ if (EnumHasAnyFlags(data.Options, BuildOptions::ShowOutput))
{
FileSystem::ShowFileExplorer(data.OriginalOutputPath);
}
- if (data.Options & BuildOptions::AutoRun)
+ if (EnumHasAnyFlags(data.Options, BuildOptions::AutoRun))
{
String executableFile, commandLineFormat, workingDir;
data.Tools->OnRun(data, executableFile, commandLineFormat, workingDir);
diff --git a/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs
index bd5248e67..e784048af 100644
--- a/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs
@@ -77,11 +77,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
prop.Label(string.Format("Progress: {0}% ({1}/{2})", allKeys.Count > 0 ? (int)(((float)validCount / allKeys.Count * 100.0f)) : 0, validCount, allKeys.Count));
prop.Label("Tables:");
+ var projectFolder = Globals.ProjectFolder;
foreach (var table in e)
{
var namePath = table.Path;
- if (namePath.StartsWith(Globals.ProjectFolder))
- namePath = namePath.Substring(Globals.ProjectFolder.Length + 1);
+ if (namePath.StartsWith(projectFolder))
+ namePath = namePath.Substring(projectFolder.Length + 1);
var tableLabel = prop.ClickableLabel(namePath).CustomControl;
tableLabel.TextColorHighlighted = Color.Wheat;
tableLabel.DoubleClick += delegate { Editor.Instance.Windows.ContentWin.Select(table); };
diff --git a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
index f6d8b1671..434d0c558 100644
--- a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs
@@ -3,7 +3,6 @@
using System;
using System.Linq;
using FlaxEditor.Content;
-using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.Scripting;
using FlaxEngine;
@@ -33,7 +32,7 @@ namespace FlaxEditor.CustomEditors.Editors
[CustomEditor(typeof(Asset)), DefaultEditor]
public class AssetRefEditor : CustomEditor
{
- private CustomElement _element;
+ private AssetPicker _picker;
private ScriptType _valueType;
///
@@ -42,46 +41,59 @@ namespace FlaxEditor.CustomEditors.Editors
///
public override void Initialize(LayoutElementsContainer layout)
{
- if (!HasDifferentTypes)
+ if (HasDifferentTypes)
+ return;
+ _picker = layout.Custom().CustomControl;
+
+ _valueType = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
+ var assetType = _valueType;
+ if (assetType == typeof(string))
+ assetType = new ScriptType(typeof(Asset));
+
+ float height = 48;
+ var attributes = Values.GetAttributes();
+ var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
+ if (assetReference != null)
{
- _valueType = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
- var assetType = _valueType;
+ if (assetReference.UseSmallPicker)
+ height = 32;
- float height = 48;
- var attributes = Values.GetAttributes();
- var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
- if (assetReference != null)
+ if (string.IsNullOrEmpty(assetReference.TypeName))
{
- if (assetReference.UseSmallPicker)
- height = 32;
-
- if (!string.IsNullOrEmpty(assetReference.TypeName))
- {
- var customType = TypeUtils.GetType(assetReference.TypeName);
- if (customType != ScriptType.Null)
- assetType = customType;
- else
- Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
- }
}
-
- _element = layout.Custom();
- _element.CustomControl.AssetType = assetType;
- _element.CustomControl.Height = height;
- _element.CustomControl.SelectedItemChanged += OnSelectedItemChanged;
+ else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
+ {
+ // Generic file picker
+ assetType = ScriptType.Null;
+ _picker.FileExtension = assetReference.TypeName;
+ }
+ else
+ {
+ var customType = TypeUtils.GetType(assetReference.TypeName);
+ if (customType != ScriptType.Null)
+ assetType = customType;
+ else
+ Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
+ }
}
+
+ _picker.AssetType = assetType;
+ _picker.Height = height;
+ _picker.SelectedItemChanged += OnSelectedItemChanged;
}
private void OnSelectedItemChanged()
{
if (typeof(AssetItem).IsAssignableFrom(_valueType.Type))
- SetValue(_element.CustomControl.SelectedItem);
+ SetValue(_picker.SelectedItem);
else if (_valueType.Type == typeof(Guid))
- SetValue(_element.CustomControl.SelectedID);
+ SetValue(_picker.SelectedID);
else if (_valueType.Type == typeof(SceneReference))
- SetValue(new SceneReference(_element.CustomControl.SelectedID));
+ SetValue(new SceneReference(_picker.SelectedID));
+ else if (_valueType.Type == typeof(string))
+ SetValue(_picker.SelectedPath);
else
- SetValue(_element.CustomControl.SelectedAsset);
+ SetValue(_picker.SelectedAsset);
}
///
@@ -92,13 +104,15 @@ namespace FlaxEditor.CustomEditors.Editors
if (!HasDifferentValues)
{
if (Values[0] is AssetItem assetItem)
- _element.CustomControl.SelectedItem = assetItem;
+ _picker.SelectedItem = assetItem;
else if (Values[0] is Guid guid)
- _element.CustomControl.SelectedID = guid;
+ _picker.SelectedID = guid;
else if (Values[0] is SceneReference sceneAsset)
- _element.CustomControl.SelectedItem = Editor.Instance.ContentDatabase.FindAsset(sceneAsset.ID);
+ _picker.SelectedItem = Editor.Instance.ContentDatabase.FindAsset(sceneAsset.ID);
+ else if (Values[0] is string path)
+ _picker.SelectedPath = path;
else
- _element.CustomControl.SelectedAsset = Values[0] as Asset;
+ _picker.SelectedAsset = Values[0] as Asset;
}
}
}
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index cd1f9a332..b95f9e722 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -237,13 +237,13 @@ namespace FlaxEditor.CustomEditors.Editors
{
// Get tag name
var tagName = popup.Text;
- var name = tagName.Substring(popup.InitialValue.Length);
- if (name.Length == 0)
+ var tagShortName = tagName.Substring(popup.InitialValue.Length);
+ if (tagShortName.Length == 0)
return;
// Add tag
var tag = Tags.Get(tagName);
- node.Text = name;
+ node.Text = tagShortName;
node.Tag = tag;
var settingsAsset = GameSettings.LoadAsset();
if (settingsAsset && !settingsAsset.WaitForLoaded())
@@ -257,6 +257,9 @@ namespace FlaxEditor.CustomEditors.Editors
var settingsObj = (LayersAndTagsSettings)settingsAsset.Instance;
settingsObj.Tags.Add(tagName);
settingsAsset.SetInstance(settingsObj);
+
+ // Reload editor window to reflect new tag
+ assetWindow?.RefreshAsset();
}
};
dialog.Closed += popup =>
@@ -282,23 +285,33 @@ namespace FlaxEditor.CustomEditors.Editors
var root = tree.AddChild();
for (var i = 0; i < tags.Length; i++)
{
- var tag = tags[i];
+ var tagName = tags[i];
var tagValue = new Tag((uint)(i + 1));
bool isSelected = pickerData.IsSingle ? value == tagValue : values.Contains(tagValue);
// Count parent tags count
- int indentation = 0;
- for (int j = 0; j < tag.Length; j++)
+ int indentation = 0, lastDotIndex = -1;
+ for (int j = 0; j < tagName.Length; j++)
{
- if (tag[j] == '.')
+ if (tagName[j] == '.')
+ {
indentation++;
+ lastDotIndex = j;
+ }
}
-
+ var tagShortName = tagName;
+ var tagParentName = string.Empty;
+ if (lastDotIndex != -1)
+ {
+ tagShortName = tagName.Substring(lastDotIndex + 1);
+ tagParentName = tagName.Substring(0, lastDotIndex);
+ }
+
// Create node
var node = new TreeNodeWithAddons
{
Tag = tagValue,
- Text = tag,
+ Text = tagShortName,
ChildrenIndent = nodeIndent,
CullChildren = false,
ClipChildren = false,
@@ -330,13 +343,11 @@ namespace FlaxEditor.CustomEditors.Editors
// Link to parent
{
- var lastDotIndex = tag.LastIndexOf('.');
- var parentTagName = lastDotIndex != -1 ? tag.Substring(0, lastDotIndex) : string.Empty;
- if (!nameToNode.TryGetValue(parentTagName, out ContainerControl parent))
+ if (!nameToNode.TryGetValue(tagParentName, out ContainerControl parent))
parent = root;
node.Parent = parent;
}
- nameToNode[tag] = node;
+ nameToNode[tagName] = node;
// Expand selected nodes to be visible in hierarchy
if (isSelected)
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index dcf41a072..f6eaef250 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -10,6 +10,7 @@ using FlaxEditor.Content;
using FlaxEditor.Content.Import;
using FlaxEditor.Content.Settings;
using FlaxEditor.Content.Thumbnails;
+using FlaxEditor.GUI;
using FlaxEditor.Modules;
using FlaxEditor.Modules.SourceCodeEditing;
using FlaxEditor.Options;
@@ -49,6 +50,8 @@ namespace FlaxEditor
private bool _isAfterInit, _areModulesInited, _areModulesAfterInitEnd, _isHeadlessMode;
private string _projectToOpen;
private float _lastAutoSaveTimer;
+ private AutoSavePopup _autoSavePopup;
+ private bool _autoSaveNow;
private Guid _startupSceneCmdLine;
private const string ProjectDataLastScene = "LastScene";
@@ -497,7 +500,28 @@ namespace FlaxEditor
var timeToNextSave = options.AutoSaveFrequency * 60.0f - timeSinceLastSave;
var countDownDuration = 4.0f;
- if (timeToNextSave <= 0.0f)
+ // Show auto save popup
+ if (timeToNextSave <= options.AutoSaveReminderTime && timeToNextSave >= 0)
+ {
+ if (_autoSavePopup == null)
+ {
+ _autoSavePopup = AutoSavePopup.Show(Instance.Windows.MainWindow.GUI, timeToNextSave);
+ _autoSavePopup.SaveNowButton.Clicked += () => _autoSaveNow = true;
+ _autoSavePopup.CancelSaveButton.Clicked += () =>
+ {
+ Log("Auto save canceled");
+ _autoSavePopup.HidePopup();
+ _lastAutoSaveTimer = Time.UnscaledGameTime; // Reset timer
+ };
+ }
+ else if (!_autoSavePopup.Visible && !_autoSavePopup.UserClosed)
+ _autoSavePopup.ShowPopup();
+
+ if (_autoSavePopup.Visible)
+ _autoSavePopup.UpdateTime(timeToNextSave);
+ }
+
+ if (timeToNextSave <= 0.0f || _autoSaveNow)
{
Log("Auto save");
_lastAutoSaveTimer = Time.UnscaledGameTime;
@@ -505,6 +529,11 @@ namespace FlaxEditor
Scene.SaveScenes();
if (options.AutoSaveContent)
SaveContent();
+
+ // Hide auto save popup and reset user closed
+ _autoSavePopup.HidePopup();
+ _autoSavePopup.UserClosed = false;
+ _autoSaveNow = false;
}
else if (timeToNextSave < countDownDuration)
{
diff --git a/Source/Editor/GUI/AssetPicker.cs b/Source/Editor/GUI/AssetPicker.cs
index a978409fe..a359c288c 100644
--- a/Source/Editor/GUI/AssetPicker.cs
+++ b/Source/Editor/GUI/AssetPicker.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.IO;
using FlaxEditor.Content;
using FlaxEditor.GUI.Drag;
using FlaxEditor.Scripting;
@@ -22,22 +23,25 @@ namespace FlaxEditor.GUI
private const float ButtonsSize = 12;
private Asset _selected;
- private AssetItem _selectedItem;
+ private ContentItem _selectedItem;
private ScriptType _type;
+ private string _fileExtension;
private bool _isMouseDown;
private Float2 _mouseDownPos;
private Float2 _mousePos;
- private DragAssets _dragOverElement;
+ private DragItems _dragOverElement;
///
/// Gets or sets the selected item.
///
- public AssetItem SelectedItem
+ public ContentItem SelectedItem
{
get => _selectedItem;
set
{
+ if (_selectedItem == value)
+ return;
if (value == null)
{
if (_selected == null && _selectedItem is SceneItem)
@@ -46,13 +50,15 @@ namespace FlaxEditor.GUI
_selectedItem.RemoveReference(this);
_selectedItem = null;
_selected = null;
- TooltipText = string.Empty;
OnSelectedItemChanged();
return;
}
// Deselect
- SelectedAsset = null;
+ _selectedItem?.RemoveReference(this);
+ _selectedItem = null;
+ _selected = null;
+ OnSelectedItemChanged();
}
else if (value is SceneItem item)
{
@@ -66,15 +72,19 @@ namespace FlaxEditor.GUI
_selectedItem = item;
_selected = null;
_selectedItem?.AddReference(this);
-
- // Update tooltip
- TooltipText = _selectedItem?.NamePath;
-
OnSelectedItemChanged();
}
+ else if (value is AssetItem assetItem)
+ {
+ SelectedAsset = FlaxEngine.Content.LoadAsync(assetItem.ID);
+ }
else
{
- SelectedAsset = FlaxEngine.Content.LoadAsync(value.ID);
+ // Change value
+ _selectedItem?.RemoveReference(this);
+ _selectedItem = value;
+ _selected = null;
+ OnSelectedItemChanged();
}
}
}
@@ -88,13 +98,44 @@ namespace FlaxEditor.GUI
{
if (_selected != null)
return _selected.ID;
- if (_selectedItem != null)
- return _selectedItem.ID;
+ if (_selectedItem is AssetItem assetItem)
+ return assetItem.ID;
return Guid.Empty;
}
set => SelectedItem = Editor.Instance.ContentDatabase.FindAsset(value);
}
+ ///
+ /// Gets or sets the selected content item path.
+ ///
+ public string SelectedPath
+ {
+ get
+ {
+ string path = _selectedItem?.Path ?? _selected?.Path;
+ if (path != null)
+ {
+ // Convert into path relative to the project (cross-platform)
+ var projectFolder = Globals.ProjectFolder;
+ if (path.StartsWith(projectFolder))
+ path = path.Substring(projectFolder.Length + 1);
+ }
+ return path;
+ }
+ set
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ SelectedItem = null;
+ }
+ else
+ {
+ var path = StringUtils.IsRelative(value) ? Path.Combine(Globals.ProjectFolder, value) : value;
+ SelectedItem = Editor.Instance.ContentDatabase.Find(path);
+ }
+ }
+ }
+
///
/// Gets or sets the selected asset object.
///
@@ -117,16 +158,12 @@ namespace FlaxEditor.GUI
_selectedItem = item;
_selected = value;
_selectedItem?.AddReference(this);
-
- // Update tooltip
- TooltipText = _selectedItem?.NamePath;
-
OnSelectedItemChanged();
}
}
///
- /// Gets or sets the assets types that this picker accepts (it supports types derived from the given type).
+ /// Gets or sets the assets types that this picker accepts (it supports types derived from the given type). Use for generic file picker.
///
public ScriptType AssetType
{
@@ -144,6 +181,25 @@ namespace FlaxEditor.GUI
}
}
+ ///
+ /// Gets or sets the content items extensions filter. Null if unused.
+ ///
+ public string FileExtension
+ {
+ get => _fileExtension;
+ set
+ {
+ if (_fileExtension != value)
+ {
+ _fileExtension = value;
+
+ // Auto deselect if the current value is invalid
+ if (_selectedItem != null && !IsValid(_selectedItem))
+ SelectedItem = null;
+ }
+ }
+ }
+
///
/// Occurs when selected item gets changed.
///
@@ -154,24 +210,32 @@ namespace FlaxEditor.GUI
///
public bool CanEdit = true;
- private bool IsValid(AssetItem item)
+ private bool IsValid(ContentItem item)
{
- // Faster path for binary items (in-build)
- if (item is BinaryAssetItem binaryItem)
- return _type.IsAssignableFrom(new ScriptType(binaryItem.Type));
-
- // Type filter
- var type = TypeUtils.GetType(item.TypeName);
- if (_type.IsAssignableFrom(type))
+ if (_fileExtension != null && !item.Path.EndsWith(_fileExtension))
+ return false;
+ if (_type == ScriptType.Null)
return true;
- // Json assets can contain any type of the object defined by the C# type (data oriented design)
- if (item is JsonAssetItem && (_type.Type == typeof(JsonAsset) || _type.Type == typeof(Asset)))
- return true;
+ if (item is AssetItem assetItem)
+ {
+ // Faster path for binary items (in-built)
+ if (assetItem is BinaryAssetItem binaryItem)
+ return _type.IsAssignableFrom(new ScriptType(binaryItem.Type));
- // Special case for scene asset references
- if (_type.Type == typeof(SceneReference) && item is SceneItem)
- return true;
+ // Type filter
+ var type = TypeUtils.GetType(assetItem.TypeName);
+ if (_type.IsAssignableFrom(type))
+ return true;
+
+ // Json assets can contain any type of the object defined by the C# type (data oriented design)
+ if (assetItem is JsonAssetItem && (_type.Type == typeof(JsonAsset) || _type.Type == typeof(Asset)))
+ return true;
+
+ // Special case for scene asset references
+ if (_type.Type == typeof(SceneReference) && assetItem is SceneItem)
+ return true;
+ }
return false;
}
@@ -201,15 +265,26 @@ namespace FlaxEditor.GUI
///
protected virtual void OnSelectedItemChanged()
{
+ // Update tooltip
+ string tooltip;
+ if (_selectedItem is AssetItem assetItem)
+ tooltip = assetItem.NamePath;
+ else
+ tooltip = SelectedPath;
+ TooltipText = tooltip;
+
SelectedItemChanged?.Invoke();
}
private void DoDrag()
{
// Do the drag drop operation if has selected element
- if (_selected != null && new Rectangle(Float2.Zero, Size).Contains(ref _mouseDownPos))
+ if (new Rectangle(Float2.Zero, Size).Contains(ref _mouseDownPos))
{
- DoDragDrop(DragAssets.GetDragData(_selected));
+ if (_selected != null)
+ DoDragDrop(DragAssets.GetDragData(_selected));
+ else if (_selectedItem != null)
+ DoDragDrop(DragItems.GetDragData(_selectedItem));
}
}
@@ -339,10 +414,7 @@ namespace FlaxEditor.GUI
// Check if start drag drop
if (_isMouseDown)
{
- // Clear flag
_isMouseDown = false;
-
- // Do the drag
DoDrag();
}
@@ -366,7 +438,6 @@ namespace FlaxEditor.GUI
// Check if start drag drop
if (_isMouseDown && Float2.Distance(location, _mouseDownPos) > 10.0f && IconRect.Contains(_mouseDownPos))
{
- // Do the drag
_isMouseDown = false;
DoDrag();
}
@@ -392,14 +463,27 @@ namespace FlaxEditor.GUI
}
else if (Button1Rect.Contains(location))
{
- // Show asset picker popup
Focus();
- AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, assetItem =>
+ if (_type != ScriptType.Null)
{
- SelectedItem = assetItem;
- RootWindow.Focus();
- Focus();
- });
+ // Show asset picker popup
+ AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
+ {
+ SelectedItem = item;
+ RootWindow.Focus();
+ Focus();
+ });
+ }
+ else
+ {
+ // Show content item picker popup
+ ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
+ {
+ SelectedItem = item;
+ RootWindow.Focus();
+ Focus();
+ });
+ }
}
else if (_selected != null || _selectedItem != null)
{
@@ -437,10 +521,8 @@ namespace FlaxEditor.GUI
///
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
- // Focus
Focus();
- // Check if has element selected
if (_selectedItem != null && IconRect.Contains(location))
{
// Open it
@@ -458,7 +540,7 @@ namespace FlaxEditor.GUI
// Check if drop asset
if (_dragOverElement == null)
- _dragOverElement = new DragAssets(IsValid);
+ _dragOverElement = new DragItems(IsValid);
if (CanEdit && _dragOverElement.OnDragEnter(data))
{
}
diff --git a/Source/Editor/GUI/Popups/AssetSearchPopup.cs b/Source/Editor/GUI/Popups/AssetSearchPopup.cs
index f11612e3b..c8b88b7a6 100644
--- a/Source/Editor/GUI/Popups/AssetSearchPopup.cs
+++ b/Source/Editor/GUI/Popups/AssetSearchPopup.cs
@@ -8,40 +8,38 @@ using FlaxEngine.GUI;
namespace FlaxEditor.GUI
{
///
- /// Popup that shows the list of assets to pick. Supports searching and basic items filtering.
+ /// Popup that shows the list of content items to pick. Supports searching and basic items filtering.
///
///
- public class AssetSearchPopup : ItemsListContextMenu
+ public class ContentSearchPopup : ItemsListContextMenu
{
///
- /// The asset item.
+ /// The content item.
///
///
- public class AssetItemView : Item, IContentItemOwner
+ public class ContentItemView : Item, IContentItemOwner
{
- private AssetItem _asset;
-
///
/// The icon size (in pixels).
///
public const float IconSize = 28;
///
- /// Gets the asset.
+ /// Gets the item.
///
- public AssetItem Asset => _asset;
+ public ContentItem ContentItem;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- /// The asset.
- public AssetItemView(AssetItem asset)
+ /// The item.
+ public ContentItemView(ContentItem item)
{
- _asset = asset;
- _asset.AddReference(this);
+ ContentItem = item;
+ ContentItem.AddReference(this);
- Name = asset.ShortName;
- TooltipText = asset.Path;
+ Name = item.ShortName;
+ TooltipText = item.Path;
Height = IconSize + 4;
}
@@ -60,16 +58,16 @@ namespace FlaxEditor.GUI
// Draw icon
var iconRect = new Rectangle(2, 2, IconSize, IconSize);
- _asset.DrawThumbnail(ref iconRect);
+ ContentItem.DrawThumbnail(ref iconRect);
}
///
public override void OnDestroy()
{
- if (_asset != null)
+ if (ContentItem != null)
{
- _asset.RemoveReference(this);
- _asset = null;
+ ContentItem.RemoveReference(this);
+ ContentItem = null;
}
base.OnDestroy();
@@ -84,7 +82,7 @@ namespace FlaxEditor.GUI
///
public void OnItemRenamed(ContentItem item)
{
- Name = _asset.ShortName;
+ Name = ContentItem.ShortName;
}
///
@@ -99,12 +97,118 @@ namespace FlaxEditor.GUI
}
}
+ ///
+ /// Validates if the given content item can be used to pick it.
+ ///
+ /// The item.
+ /// True if is valid.
+ public delegate bool IsValidDelegate(ContentItem item);
+
+ private IsValidDelegate _isValid;
+ private Action _selected;
+
+ ///
+ protected ContentSearchPopup()
+ {
+ }
+
+ ///
+ protected ContentSearchPopup(IsValidDelegate isValid, Action selected)
+ {
+ _isValid = isValid;
+ _selected = selected;
+
+ ItemClicked += OnItemClicked;
+
+ // TODO: use async thread to search workspace items
+ foreach (var project in Editor.Instance.ContentDatabase.Projects)
+ {
+ if (project.Content != null)
+ FindItems(project.Content.Folder);
+ }
+ SortItems();
+ }
+
+ private void OnItemClicked(Item item)
+ {
+ _selected.Invoke(((ContentItemView)item).ContentItem);
+ }
+
+ private void FindItems(ContentFolder folder)
+ {
+ for (int i = 0; i < folder.Children.Count; i++)
+ {
+ if (folder.Children[i] is ContentItem item && _isValid(item))
+ {
+ AddItem(new ContentItemView(item));
+ }
+ }
+
+ for (int i = 0; i < folder.Children.Count; i++)
+ {
+ if (folder.Children[i] is ContentFolder child)
+ {
+ FindItems(child);
+ }
+ }
+ }
+
+ ///
+ /// Shows the popup.
+ ///
+ /// The show target.
+ /// The show target location.
+ /// Event called to check if a given content item is valid to be used.
+ /// Event called on content item pick.
+ /// The dialog.
+ public static ContentSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action selected)
+ {
+ var popup = new ContentSearchPopup(isValid, selected);
+ popup.Show(showTarget, showTargetLocation);
+ return popup;
+ }
+
+ ///
+ public override void OnDestroy()
+ {
+ _isValid = null;
+ _selected = null;
+
+ base.OnDestroy();
+ }
+ }
+
+ ///
+ /// Popup that shows the list of assets to pick. Supports searching and basic items filtering.
+ ///
+ public class AssetSearchPopup : ContentSearchPopup
+ {
+ ///
+ /// The asset item.
+ ///
+ public class AssetItemView : ContentItemView
+ {
+ ///
+ /// Gets the asset.
+ ///
+ public AssetItem AssetItem => (AssetItem)ContentItem;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The asset.
+ public AssetItemView(AssetItem asset)
+ : base(asset)
+ {
+ }
+ }
+
///
/// Validates if the given asset item can be used to pick it.
///
/// The asset.
/// True if is valid.
- public delegate bool IsValidDelegate(AssetItem asset);
+ public new delegate bool IsValidDelegate(AssetItem asset);
private IsValidDelegate _isValid;
private Action _selected;
@@ -127,7 +231,7 @@ namespace FlaxEditor.GUI
private void OnItemClicked(Item item)
{
- _selected(((AssetItemView)item).Asset);
+ _selected(((AssetItemView)item).AssetItem);
}
private void FindAssets(ContentFolder folder)
diff --git a/Source/Editor/GUI/Popups/AutoSavePopup.cs b/Source/Editor/GUI/Popups/AutoSavePopup.cs
new file mode 100644
index 000000000..0992def3e
--- /dev/null
+++ b/Source/Editor/GUI/Popups/AutoSavePopup.cs
@@ -0,0 +1,169 @@
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.GUI
+{
+ ///
+ /// Popup menu for reminding of an upcoming auto save.
+ ///
+ public class AutoSavePopup : ContainerControl
+ {
+ ///
+ /// Gets or sets the value for if the user has manually closed this popup.
+ ///
+ public bool UserClosed { get; set; }
+
+ ///
+ /// The save now button. Used to skip the last remaining auto save time.
+ ///
+ public Button SaveNowButton => _saveNowButton;
+
+ ///
+ /// Button that should be used to cancel the auto save.
+ ///
+ public Button CancelSaveButton => _cancelSaveButton;
+
+ private int _timeRemaining;
+ private Panel _backgroundPanel;
+ private Label _timeLabel;
+ private Button _saveNowButton;
+ private Button _cancelSaveButton;
+ private Color _defaultTextColor;
+ private bool _isMoved = false;
+
+ ///
+ /// Initialize the AutoSavePopup.
+ ///
+ /// The initial time to set the time label to.
+ public AutoSavePopup(float initialTime)
+ {
+ UpdateTime(initialTime);
+
+ _backgroundPanel = new Panel(ScrollBars.None)
+ {
+ Parent = this,
+ AnchorPreset = AnchorPresets.StretchAll,
+ BackgroundColor = Color.Transparent,
+ };
+
+ _timeLabel = new Label(0, 0, 25, 10)
+ {
+ Parent = _backgroundPanel,
+ Text = _timeRemaining.ToString(),
+ HorizontalAlignment = TextAlignment.Near,
+ VerticalAlignment = TextAlignment.Near,
+ AutoWidth = true,
+ Height = 14,
+ AnchorPreset = AnchorPresets.MiddleLeft,
+ };
+
+ _saveNowButton = new Button
+ {
+ Parent = _backgroundPanel,
+ Height = 14,
+ Width = 60,
+ AnchorPreset = AnchorPresets.MiddleRight,
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Transparent,
+ BackgroundColorHighlighted = Color.Transparent,
+ BackgroundColorSelected = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ Text = "Save Now",
+ TooltipText = "Saves now and restarts the auto save timer."
+ };
+ _saveNowButton.LocalX -= 85;
+
+ _cancelSaveButton = new Button
+ {
+ Parent = _backgroundPanel,
+ Height = 14,
+ Width = 70,
+ AnchorPreset = AnchorPresets.MiddleRight,
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Transparent,
+ BackgroundColorHighlighted = Color.Transparent,
+ BackgroundColorSelected = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ Text = "Cancel Save",
+ TooltipText = "Cancels this auto save."
+ };
+ _cancelSaveButton.LocalX -= 5;
+
+ _defaultTextColor = _saveNowButton.TextColor;
+ }
+
+ ///
+ /// Updates the time label
+ ///
+ /// The time to change the label to.
+ public void UpdateTime(float time)
+ {
+ _timeRemaining = Mathf.CeilToInt(time);
+ if (_timeLabel != null)
+ _timeLabel.Text = "Auto Save in: " + _timeRemaining;
+ }
+
+ ///
+ public override void Update(float deltaTime)
+ {
+ if (IsMouseOver)
+ {
+ _saveNowButton.TextColor = _saveNowButton.IsMouseOver ? Style.Current.BackgroundHighlighted : _defaultTextColor;
+ _cancelSaveButton.TextColor = _cancelSaveButton.IsMouseOver ? Style.Current.BackgroundHighlighted : _defaultTextColor;
+ }
+
+ // Move if the progress bar is visible
+ if (Editor.Instance.UI.ProgressVisible && !_isMoved)
+ {
+ _isMoved = true;
+ LocalX -= 280;
+ }
+ else if (!Editor.Instance.UI.ProgressVisible && _isMoved)
+ {
+ LocalX += 280;
+ _isMoved = false;
+ }
+ base.Update(deltaTime);
+ }
+
+ ///
+ /// Creates and shows the AutoSavePopup
+ ///
+ /// The parent control.
+ /// The time to start at.
+ ///
+ public static AutoSavePopup Show(ContainerControl parentControl, float initialTime)
+ {
+ var popup = new AutoSavePopup(initialTime)
+ {
+ Parent = parentControl,
+ Height = Editor.Instance.UI.StatusBar.Height,
+ Width = 250,
+ AnchorPreset = AnchorPresets.BottomRight,
+ };
+ popup.ShowPopup();
+ return popup;
+ }
+
+ ///
+ /// Shows the popup by changing its visibility
+ ///
+ public void ShowPopup()
+ {
+ Visible = true;
+ UserClosed = false;
+ _saveNowButton.TextColor = _defaultTextColor;
+ _cancelSaveButton.TextColor = _defaultTextColor;
+ }
+
+ ///
+ /// Hides the popup by changing its visibility
+ ///
+ public void HidePopup()
+ {
+ Visible = false;
+ if (_containsFocus)
+ Defocus();
+ }
+ }
+}
diff --git a/Source/Editor/GUI/StatusBar.cs b/Source/Editor/GUI/StatusBar.cs
index 80a500236..f8f7ae839 100644
--- a/Source/Editor/GUI/StatusBar.cs
+++ b/Source/Editor/GUI/StatusBar.cs
@@ -30,6 +30,11 @@ namespace FlaxEditor.GUI
///
public string Text { get; set; }
+ ///
+ /// Gets or sets the status text color
+ ///
+ public Color TextColor { get; set; } = Style.Current.Foreground;
+
///
/// Initializes a new instance of the class.
///
@@ -51,7 +56,7 @@ namespace FlaxEditor.GUI
Render2D.DrawSprite(style.StatusBarSizeGrip, new Rectangle(Width - 12, 10, 12, 12), style.Foreground);
// Draw status text
- Render2D.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), style.Foreground, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), TextColor, TextAlignment.Near, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Modules/ProgressReportingModule.cs b/Source/Editor/Modules/ProgressReportingModule.cs
index 713292657..16acd7f8b 100644
--- a/Source/Editor/Modules/ProgressReportingModule.cs
+++ b/Source/Editor/Modules/ProgressReportingModule.cs
@@ -96,6 +96,7 @@ namespace FlaxEditor.Modules
handler.ProgressStart += HandlerOnProgressStart;
handler.ProgressChanged += HandlerOnProgressChanged;
handler.ProgressEnd += HandlerOnProgressEnd;
+ handler.ProgressFailed += HandlerOnProgressFail;
}
///
@@ -113,6 +114,7 @@ namespace FlaxEditor.Modules
handler.ProgressStart -= HandlerOnProgressStart;
handler.ProgressChanged -= HandlerOnProgressChanged;
handler.ProgressEnd -= HandlerOnProgressEnd;
+ handler.ProgressFailed -= HandlerOnProgressFail;
}
private void UpdateProgress()
@@ -150,5 +152,11 @@ namespace FlaxEditor.Modules
Editor.Windows.FlashMainWindow();
}
}
+
+ private void HandlerOnProgressFail(ProgressHandler handler, string message)
+ {
+ UpdateProgress();
+ Editor.UI.ProgressFailed(message);
+ }
}
}
diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs
index 2910e122f..4edd4540b 100644
--- a/Source/Editor/Modules/UIModule.cs
+++ b/Source/Editor/Modules/UIModule.cs
@@ -31,8 +31,10 @@ namespace FlaxEditor.Modules
{
private Label _progressLabel;
private ProgressBar _progressBar;
+ private Button _outputLogButton;
private List> _statusMessages;
private ContentStats _contentStats;
+ private bool _progressFailed;
private ContextMenuButton _menuFileSaveScenes;
private ContextMenuButton _menuFileCloseScenes;
@@ -252,6 +254,12 @@ namespace FlaxEditor.Modules
{
if (StatusBar == null)
return;
+
+ if (ScriptsBuilder.LastCompilationFailed)
+ {
+ ProgressFailed("Scripts Compilation Failed");
+ return;
+ }
var contentStats = FlaxEngine.Content.Stats;
Color color;
@@ -303,7 +311,28 @@ namespace FlaxEditor.Modules
if (_progressLabel != null)
_progressLabel.Text = text;
if (_progressBar != null)
+ {
+ if (_progressFailed)
+ {
+ ResetProgressFailure();
+ }
_progressBar.Value = progress * 100.0f;
+ }
+ }
+
+ internal void ProgressFailed(string message)
+ {
+ _progressFailed = true;
+ StatusBar.StatusColor = Color.Red;
+ StatusBar.Text = message;
+ _outputLogButton.Visible = true;
+ }
+
+ internal void ResetProgressFailure()
+ {
+ _outputLogButton.Visible = false;
+ _progressFailed = false;
+ UpdateStatusBar();
}
///
@@ -584,6 +613,30 @@ namespace FlaxEditor.Modules
Parent = mainWindow,
Offsets = new Margin(0, 0, -StatusBar.DefaultHeight, StatusBar.DefaultHeight),
};
+ // Output log button
+ _outputLogButton = new Button()
+ {
+ AnchorPreset = AnchorPresets.TopLeft,
+ Parent = StatusBar,
+ Visible = false,
+ Text = "",
+ Width = 200,
+ TooltipText = "Opens or shows the output log window.",
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Transparent,
+ BackgroundColorHighlighted = Color.Transparent,
+ BackgroundColorSelected = Color.Transparent,
+ BorderColorHighlighted = Color.Transparent,
+ BorderColorSelected = Color.Transparent,
+ };
+ _outputLogButton.LocalY -= 2;
+ var defaultTextColor = StatusBar.TextColor;
+ _outputLogButton.HoverBegin += () => StatusBar.TextColor = Style.Current.BackgroundSelected;
+ _outputLogButton.HoverEnd += () => StatusBar.TextColor = defaultTextColor;
+ _outputLogButton.Clicked += () =>
+ {
+ Editor.Windows.OutputLogWin.FocusOrShow();
+ };
// Progress bar with label
const float progressBarWidth = 120.0f;
diff --git a/Source/Editor/Options/GeneralOptions.cs b/Source/Editor/Options/GeneralOptions.cs
index 6d4fa7e67..e97278aa0 100644
--- a/Source/Editor/Options/GeneralOptions.cs
+++ b/Source/Editor/Options/GeneralOptions.cs
@@ -196,19 +196,26 @@ namespace FlaxEditor.Options
[DefaultValue(5), Limit(1)]
[EditorDisplay("Auto Save", "Auto Save Frequency"), EditorOrder(801), Tooltip("The interval between auto saves (in minutes)")]
public int AutoSaveFrequency { get; set; } = 5;
+
+ ///
+ /// Gets or sets a value indicating the time before the auto save that the popup shows (in seconds).
+ ///
+ [DefaultValue(10), Limit(-1)]
+ [EditorDisplay("Auto Save", "Auto Save Reminder Time"), EditorOrder(802), Tooltip("The time before the auto save that the reminder popup shows (in seconds). Set to -1 to not show the reminder popup.")]
+ public int AutoSaveReminderTime { get; set; } = 10;
///
/// Gets or sets a value indicating whether enable auto saves for scenes.
///
[DefaultValue(true)]
- [EditorDisplay("Auto Save", "Auto Save Scenes"), EditorOrder(802), Tooltip("Enables or disables auto saving opened scenes")]
+ [EditorDisplay("Auto Save", "Auto Save Scenes"), EditorOrder(803), Tooltip("Enables or disables auto saving opened scenes")]
public bool AutoSaveScenes { get; set; } = true;
///
/// Gets or sets a value indicating whether enable auto saves for content.
///
[DefaultValue(true)]
- [EditorDisplay("Auto Save", "Auto Save Content"), EditorOrder(803), Tooltip("Enables or disables auto saving content")]
+ [EditorDisplay("Auto Save", "Auto Save Content"), EditorOrder(804), Tooltip("Enables or disables auto saving content")]
public bool AutoSaveContent { get; set; } = true;
///
diff --git a/Source/Editor/Progress/Handlers/CompileScriptsProgress.cs b/Source/Editor/Progress/Handlers/CompileScriptsProgress.cs
index c8c931936..310612a73 100644
--- a/Source/Editor/Progress/Handlers/CompileScriptsProgress.cs
+++ b/Source/Editor/Progress/Handlers/CompileScriptsProgress.cs
@@ -1,6 +1,5 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-using FlaxEngine;
using FlaxEditor.Utilities;
namespace FlaxEditor.Progress.Handlers
@@ -21,7 +20,7 @@ namespace FlaxEditor.Progress.Handlers
// Link for events
ScriptsBuilder.CompilationBegin += OnStart;
ScriptsBuilder.CompilationSuccess += OnEnd;
- ScriptsBuilder.CompilationFailed += OnEnd;
+ ScriptsBuilder.CompilationFailed += OnCompilationFailed;
ScriptsBuilder.CompilationStarted += () => OnUpdate(0.2f, "Compiling scripts...");
ScriptsBuilder.ScriptsReloadCalled += () => OnUpdate(0.8f, "Reloading scripts...");
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
@@ -47,6 +46,11 @@ namespace FlaxEditor.Progress.Handlers
#endif
}
+ private void OnCompilationFailed()
+ {
+ OnFail("Scripts compilation failed");
+ }
+
private void OnScriptsReloadEnd()
{
_selectionCache.Restore();
diff --git a/Source/Editor/Progress/ProgressHandler.cs b/Source/Editor/Progress/ProgressHandler.cs
index 74b31ff1f..2738b7c57 100644
--- a/Source/Editor/Progress/ProgressHandler.cs
+++ b/Source/Editor/Progress/ProgressHandler.cs
@@ -16,6 +16,11 @@ namespace FlaxEditor.Progress
///
/// The calling handler.
public delegate void ProgressDelegate(ProgressHandler handler);
+
+ ///
+ /// Progress failed handler event delegate
+ ///
+ public delegate void ProgressFailedDelegate(ProgressHandler handler, string message);
private float _progress;
private bool _isActive;
@@ -51,6 +56,11 @@ namespace FlaxEditor.Progress
///
public event ProgressDelegate ProgressEnd;
+ ///
+ /// Occurs when the progress fails
+ ///
+ public event ProgressFailedDelegate ProgressFailed;
+
///
/// Gets a value indicating whether this handler action can be cancelled.
///
@@ -109,5 +119,19 @@ namespace FlaxEditor.Progress
ProgressChanged?.Invoke(this);
ProgressEnd?.Invoke(this);
}
+
+ ///
+ /// Called when progress action fails
+ ///
+ protected virtual void OnFail(string message)
+ {
+ if (!_isActive)
+ throw new InvalidOperationException("Already ended.");
+
+ _isActive = false;
+ _progress = 0;
+ _infoText = string.Empty;
+ ProgressFailed?.Invoke(this, message);
+ }
}
}
diff --git a/Source/Editor/Surface/Archetypes/Textures.cs b/Source/Editor/Surface/Archetypes/Textures.cs
index c484c12a1..258bfd41a 100644
--- a/Source/Editor/Surface/Archetypes/Textures.cs
+++ b/Source/Editor/Surface/Archetypes/Textures.cs
@@ -405,6 +405,31 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float3), 3)
}
},
+ new NodeArchetype
+ {
+ TypeID = 17,
+ Create = (id, context, arch, groupArch) => new SampleTextureNode(id, context, arch, groupArch),
+ Title = "Procedural Sample Texture",
+ Description = "Samples a texture to create a more natural look with less obvious tiling.",
+ Flags = NodeFlags.MaterialGraph,
+ Size = new Float2(240, 110),
+ ConnectionsHints = ConnectionsHint.Vector,
+ DefaultValues = new object[]
+ {
+ 2,
+ -1.0f,
+ 0,
+ },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
+ NodeElementArchetype.Factory.Input(1, "UVs", true, null, 1),
+ NodeElementArchetype.Factory.Input(2, "Offset", true, typeof(Float2), 3),
+ NodeElementArchetype.Factory.Output(0, "Color", typeof(Float4), 4),
+ NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY * 4, "Sampler"),
+ NodeElementArchetype.Factory.ComboBox(50, Surface.Constants.LayoutOffsetY * 4, 100, 0, typeof(CommonSamplerType))
+ }
+ },
};
}
}
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
index 0590326e0..9551f0f34 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
@@ -397,6 +397,13 @@ namespace FlaxEditor.Surface.ContextMenu
return;
Profiler.BeginEvent("VisjectCM.OnSearchFilterChanged");
+
+ if (string.IsNullOrEmpty(_searchBox.Text))
+ {
+ ResetView();
+ Profiler.EndEvent();
+ return;
+ }
// Update groups
LockChildrenRecursive();
diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs
index f859854b7..2012436ae 100644
--- a/Source/Editor/Utilities/Utils.cs
+++ b/Source/Editor/Utilities/Utils.cs
@@ -906,12 +906,21 @@ namespace FlaxEditor.Utilities
if (name.StartsWith("g_") || name.StartsWith("m_"))
startIndex = 2;
+ if (name.StartsWith("_"))
+ startIndex = 1;
+
// Filter text
var lastChar = '\0';
for (int i = startIndex; i < length; i++)
{
var c = name[i];
+ if (i == startIndex)
+ {
+ sb.Append(char.ToUpper(c));
+ continue;
+ }
+
// Space before word starting with uppercase letter
if (char.IsUpper(c) && i > 0)
{
@@ -1015,10 +1024,9 @@ namespace FlaxEditor.Utilities
/// The processed name path.
public static string GetAssetNamePath(string path)
{
- if (path.StartsWith(Globals.ProjectFolder))
- {
- path = path.Substring(Globals.ProjectFolder.Length + 1);
- }
+ var projectFolder = Globals.ProjectFolder;
+ if (path.StartsWith(projectFolder))
+ path = path.Substring(projectFolder.Length + 1);
return StringUtils.GetPathWithoutExtension(path);
}
diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp
index dfc6aa05d..69cc1158e 100644
--- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp
+++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp
@@ -63,7 +63,7 @@ ViewportIconsRendererService ViewportIconsRendererServiceInstance;
void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor)
{
auto& view = renderContext.View;
- if (!actor || (view.Flags & ViewFlags::EditorSprites) == 0 || QuadModel == nullptr || !QuadModel->IsLoaded())
+ if (!actor || (view.Flags & ViewFlags::EditorSprites) == ViewFlags::None || QuadModel == nullptr || !QuadModel->IsLoaded())
return;
Mesh::DrawInfo draw;
diff --git a/Source/Editor/Windows/AssetReferencesGraphWindow.cs b/Source/Editor/Windows/AssetReferencesGraphWindow.cs
index 78513f037..6e7d3d0ef 100644
--- a/Source/Editor/Windows/AssetReferencesGraphWindow.cs
+++ b/Source/Editor/Windows/AssetReferencesGraphWindow.cs
@@ -53,7 +53,7 @@ namespace FlaxEditor.Windows
else
{
picker.SelectedID = AssetId;
- var assetItem = picker.SelectedItem;
+ var assetItem = picker.SelectedItem as AssetItem;
if (assetItem != null)
{
Title = assetItem.ShortName;
diff --git a/Source/Editor/Windows/Assets/AssetEditorWindow.cs b/Source/Editor/Windows/Assets/AssetEditorWindow.cs
index cf7b41dca..05a9151c2 100644
--- a/Source/Editor/Windows/Assets/AssetEditorWindow.cs
+++ b/Source/Editor/Windows/Assets/AssetEditorWindow.cs
@@ -308,6 +308,14 @@ namespace FlaxEditor.Windows.Assets
{
}
+ ///
+ /// Drops any loaded asset data and refreshes the UI state.
+ ///
+ public void RefreshAsset()
+ {
+ _isWaitingForLoaded = true;
+ }
+
///
/// Reloads the asset (window will receive or events).
///
diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs
index 8084d638e..f17deb4bd 100644
--- a/Source/Editor/Windows/GameWindow.cs
+++ b/Source/Editor/Windows/GameWindow.cs
@@ -8,6 +8,7 @@ using FlaxEditor.GUI.Input;
using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.GUI;
+using FlaxEngine.Json;
namespace FlaxEditor.Windows
{
@@ -28,6 +29,14 @@ namespace FlaxEditor.Windows
private GUI.Docking.DockPanel _maximizeRestoreDockTo;
private CursorLockMode _cursorLockMode = CursorLockMode.None;
+ // Viewport scaling variables
+ private List _defaultViewportScaling = new List();
+ private List _customViewportScaling = new List();
+ private float _viewportAspectRatio = 1;
+ private float _windowAspectRatio = 1;
+ private bool _useAspect = false;
+ private bool _freeAspect = true;
+
///
/// Gets the viewport.
///
@@ -106,6 +115,35 @@ namespace FlaxEditor.Windows
///
public bool FocusOnPlay { get; set; }
+ private enum ViewportScaleType
+ {
+ Resolution = 0,
+ Aspect = 1,
+ }
+
+ private class ViewportScaleOptions
+ {
+ ///
+ /// The name.
+ ///
+ public string Label;
+
+ ///
+ /// The Type of scaling to do.
+ ///
+ public ViewportScaleType ScaleType;
+
+ ///
+ /// The width and height to scale by.
+ ///
+ public Int2 Size;
+
+ ///
+ /// If the scaling is active.
+ ///
+ public bool Active;
+ }
+
private class GameRoot : ContainerControl
{
public bool EnableEvents => !Time.GamePaused;
@@ -255,6 +293,9 @@ namespace FlaxEditor.Windows
Parent = _viewport
};
RootControl.GameRoot = _guiRoot;
+
+ SizeChanged += control => { ResizeViewport(); };
+
Editor.StateMachine.PlayingState.SceneDuplicating += PlayingStateOnSceneDuplicating;
Editor.StateMachine.PlayingState.SceneRestored += PlayingStateOnSceneRestored;
@@ -267,6 +308,85 @@ namespace FlaxEditor.Windows
InputActions.Add(options => options.StepFrame, Editor.Simulation.RequestPlayOneFrame);
}
+ private void ChangeViewportRatio(ViewportScaleOptions v)
+ {
+ if (v == null)
+ return;
+
+ if (v.Size.Y <= 0 || v.Size.X <= 0)
+ {
+ return;
+ }
+
+ if (string.Equals(v.Label, "Free Aspect") && v.Size == new Int2(1, 1))
+ {
+ _freeAspect = true;
+ _useAspect = true;
+ }
+ else
+ {
+ switch (v.ScaleType)
+ {
+ case ViewportScaleType.Aspect:
+ _useAspect = true;
+ _freeAspect = false;
+ break;
+ case ViewportScaleType.Resolution:
+ _useAspect = false;
+ _freeAspect = false;
+ break;
+ }
+ }
+
+ _viewportAspectRatio = (float)v.Size.X / v.Size.Y;
+
+ if (!_freeAspect)
+ {
+ if (!_useAspect)
+ {
+ _viewport.KeepAspectRatio = true;
+ _viewport.CustomResolution = new Int2(v.Size.X, v.Size.Y);
+ }
+ else
+ {
+ _viewport.CustomResolution = new Int2?();
+ _viewport.KeepAspectRatio = true;
+ }
+ }
+ else
+ {
+ _viewport.CustomResolution = new Int2?();
+ _viewport.KeepAspectRatio = false;
+ }
+
+ ResizeViewport();
+ }
+
+ private void ResizeViewport()
+ {
+ if (!_freeAspect)
+ {
+ _windowAspectRatio = Width / Height;
+ }
+ else
+ {
+ _windowAspectRatio = 1;
+ }
+
+ var scaleWidth = _viewportAspectRatio / _windowAspectRatio;
+ var scaleHeight = _windowAspectRatio / _viewportAspectRatio;
+
+ if (scaleHeight < 1)
+ {
+ _viewport.Bounds = new Rectangle(0, Height * (1 - scaleHeight) / 2, Width, Height * scaleHeight);
+ }
+ else
+ {
+ _viewport.Bounds = new Rectangle(Width * (1 - scaleWidth) / 2, 0, Width * scaleWidth, Height);
+ }
+ PerformLayout();
+ }
+
private void OnPostRender(GPUContext context, ref RenderContext renderContext)
{
// Debug Draw shapes
@@ -372,6 +492,53 @@ namespace FlaxEditor.Windows
resolutionValue.ValueChanged += () => _viewport.ResolutionScale = resolutionValue.Value;
}
+ // Viewport aspect ratio
+ {
+ // Create default scaling options if they dont exist from deserialization.
+ if (_defaultViewportScaling.Count == 0)
+ {
+ _defaultViewportScaling.Add(new ViewportScaleOptions
+ {
+ Label = "Free Aspect",
+ ScaleType = ViewportScaleType.Aspect,
+ Size = new Int2(1, 1),
+ Active = true,
+ });
+ _defaultViewportScaling.Add(new ViewportScaleOptions
+ {
+ Label = "16:9 Aspect",
+ ScaleType = ViewportScaleType.Aspect,
+ Size = new Int2(16, 9),
+ Active = false,
+ });
+ _defaultViewportScaling.Add(new ViewportScaleOptions
+ {
+ Label = "16:10 Aspect",
+ ScaleType = ViewportScaleType.Aspect,
+ Size = new Int2(16, 10),
+ Active = false,
+ });
+ _defaultViewportScaling.Add(new ViewportScaleOptions
+ {
+ Label = "1920x1080 Resolution",
+ ScaleType = ViewportScaleType.Resolution,
+ Size = new Int2(1920, 1080),
+ Active = false,
+ });
+ _defaultViewportScaling.Add(new ViewportScaleOptions
+ {
+ Label = "2560x1440 Resolution",
+ ScaleType = ViewportScaleType.Resolution,
+ Size = new Int2(2560, 1440),
+ Active = false,
+ });
+ }
+
+ var vsMenu = menu.AddChildMenu("Viewport Size").ContextMenu;
+
+ CreateViewportSizingContextMenu(vsMenu);
+ }
+
// Take Screenshot
{
var takeScreenshot = menu.AddButton("Take Screenshot");
@@ -400,6 +567,243 @@ namespace FlaxEditor.Windows
menu.AddSeparator();
}
+ private void CreateViewportSizingContextMenu(ContextMenu vsMenu)
+ {
+ // Add default viewport sizing options
+ for (int i = 0; i < _defaultViewportScaling.Count; i++)
+ {
+ var viewportScale = _defaultViewportScaling[i];
+ var button = vsMenu.AddButton(viewportScale.Label);
+ button.CloseMenuOnClick = false;
+ button.Icon = viewportScale.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
+ button.Tag = viewportScale;
+ if (viewportScale.Active)
+ ChangeViewportRatio(viewportScale);
+
+ button.Clicked += () =>
+ {
+ if (button.Tag == null)
+ return;
+
+ // Reset selected icon on all buttons
+ foreach (var child in vsMenu.Items)
+ {
+ if (child is ContextMenuButton cmb && cmb.Tag is ViewportScaleOptions v)
+ {
+ if (cmb == button)
+ {
+ v.Active = true;
+ button.Icon = Style.Current.CheckBoxTick;
+ ChangeViewportRatio(v);
+ }
+ else if (v.Active)
+ {
+ cmb.Icon = SpriteHandle.Invalid;
+ v.Active = false;
+ }
+ }
+ }
+ };
+ }
+ if (_defaultViewportScaling.Count != 0)
+ vsMenu.AddSeparator();
+
+ // Add custom viewport options
+ for (int i = 0; i < _customViewportScaling.Count; i++)
+ {
+ var viewportScale = _customViewportScaling[i];
+ var childCM = vsMenu.AddChildMenu(viewportScale.Label);
+ childCM.CloseMenuOnClick = false;
+ childCM.Icon = viewportScale.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
+ childCM.Tag = viewportScale;
+ if (viewportScale.Active)
+ ChangeViewportRatio(viewportScale);
+
+ var applyButton = childCM.ContextMenu.AddButton("Apply");
+ applyButton.Tag = childCM.Tag = viewportScale;
+ applyButton.CloseMenuOnClick = false;
+ applyButton.Clicked += () =>
+ {
+ if (childCM.Tag == null)
+ return;
+
+ // Reset selected icon on all buttons
+ foreach (var child in vsMenu.Items)
+ {
+ if (child is ContextMenuButton cmb && cmb.Tag is ViewportScaleOptions v)
+ {
+ if (child == childCM)
+ {
+ v.Active = true;
+ childCM.Icon = Style.Current.CheckBoxTick;
+ ChangeViewportRatio(v);
+ }
+ else if (v.Active)
+ {
+ cmb.Icon = SpriteHandle.Invalid;
+ v.Active = false;
+ }
+ }
+ }
+ };
+
+ var deleteButton = childCM.ContextMenu.AddButton("Delete");
+ deleteButton.CloseMenuOnClick = false;
+ deleteButton.Clicked += () =>
+ {
+ if (childCM.Tag == null)
+ return;
+
+ var v = (ViewportScaleOptions)childCM.Tag;
+ if (v.Active)
+ {
+ v.Active = false;
+ _defaultViewportScaling[0].Active = true;
+ ChangeViewportRatio(_defaultViewportScaling[0]);
+ }
+ _customViewportScaling.Remove(v);
+ vsMenu.DisposeAllItems();
+ CreateViewportSizingContextMenu(vsMenu);
+ vsMenu.PerformLayout();
+ };
+ }
+ if (_customViewportScaling.Count != 0)
+ vsMenu.AddSeparator();
+
+ // Add button
+ var add = vsMenu.AddButton("Add...");
+ add.CloseMenuOnClick = false;
+ add.Clicked += () =>
+ {
+ var popup = new ContextMenuBase
+ {
+ Size = new Float2(230, 125),
+ ClipChildren = false,
+ CullChildren = false,
+ };
+ popup.Show(add, new Float2(add.Width, 0));
+
+ var nameLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Name",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ nameLabel.LocalX += 10;
+ nameLabel.LocalY += 10;
+
+ var nameTextBox = new TextBox
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ IsMultiline = false,
+ };
+ nameTextBox.LocalX += 100;
+ nameTextBox.LocalY += 10;
+
+ var typeLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Type",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ typeLabel.LocalX += 10;
+ typeLabel.LocalY += 35;
+
+ var typeDropdown = new Dropdown
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Items = { "Aspect", "Resolution" },
+ SelectedItem = "Aspect",
+ Width = nameTextBox.Width
+ };
+ typeDropdown.LocalY += 35;
+ typeDropdown.LocalX += 100;
+
+ var whLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Width & Height",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ whLabel.LocalX += 10;
+ whLabel.LocalY += 60;
+
+ var wValue = new IntValueBox(16)
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ MinValue = 1,
+ Width = 55,
+ };
+ wValue.LocalY += 60;
+ wValue.LocalX += 100;
+
+ var hValue = new IntValueBox(9)
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ MinValue = 1,
+ Width = 55,
+ };
+ hValue.LocalY += 60;
+ hValue.LocalX += 165;
+
+ var submitButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Submit",
+ Width = 70,
+ };
+ submitButton.LocalX += 40;
+ submitButton.LocalY += 90;
+
+ submitButton.Clicked += () =>
+ {
+ Enum.TryParse(typeDropdown.SelectedItem, out ViewportScaleType type);
+
+ var combineString = type == ViewportScaleType.Aspect ? ":" : "x";
+ var name = nameTextBox.Text + " (" + wValue.Value + combineString + hValue.Value + ") " + typeDropdown.SelectedItem;
+
+ var newViewportOption = new ViewportScaleOptions
+ {
+ ScaleType = type,
+ Label = name,
+ Size = new Int2(wValue.Value, hValue.Value),
+ };
+
+ _customViewportScaling.Add(newViewportOption);
+ vsMenu.DisposeAllItems();
+ CreateViewportSizingContextMenu(vsMenu);
+ vsMenu.PerformLayout();
+ };
+
+ var cancelButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Cancel",
+ Width = 70,
+ };
+ cancelButton.LocalX += 120;
+ cancelButton.LocalY += 90;
+
+ cancelButton.Clicked += () =>
+ {
+ nameTextBox.Clear();
+ typeDropdown.SelectedItem = "Aspect";
+ hValue.Value = 9;
+ wValue.Value = 16;
+ popup.Hide();
+ };
+ };
+ }
+
///
public override void Draw()
{
@@ -471,7 +875,7 @@ namespace FlaxEditor.Windows
Screen.CursorVisible = true;
if (Screen.CursorLock == CursorLockMode.Clipped)
Screen.CursorLock = CursorLockMode.None;
-
+
// Defocus
_isUnlockingMouse = true;
Focus(null);
@@ -624,6 +1028,8 @@ namespace FlaxEditor.Windows
{
writer.WriteAttributeString("ShowGUI", ShowGUI.ToString());
writer.WriteAttributeString("ShowDebugDraw", ShowDebugDraw.ToString());
+ writer.WriteAttributeString("DefaultViewportScaling", JsonSerializer.Serialize(_defaultViewportScaling));
+ writer.WriteAttributeString("CustomViewportScaling", JsonSerializer.Serialize(_customViewportScaling));
}
///
@@ -633,6 +1039,23 @@ namespace FlaxEditor.Windows
ShowGUI = value1;
if (bool.TryParse(node.GetAttribute("ShowDebugDraw"), out value1))
ShowDebugDraw = value1;
+ if (node.HasAttribute("CustomViewportScaling"))
+ _customViewportScaling = JsonSerializer.Deserialize>(node.GetAttribute("CustomViewportScaling"));
+
+ for (int i = 0; i < _customViewportScaling.Count; i++)
+ {
+ if (_customViewportScaling[i].Active)
+ ChangeViewportRatio(_customViewportScaling[i]);
+ }
+
+ if (node.HasAttribute("DefaultViewportScaling"))
+ _defaultViewportScaling = JsonSerializer.Deserialize>(node.GetAttribute("DefaultViewportScaling"));
+
+ for (int i = 0; i < _defaultViewportScaling.Count; i++)
+ {
+ if (_defaultViewportScaling[i].Active)
+ ChangeViewportRatio(_defaultViewportScaling[i]);
+ }
}
///
diff --git a/Source/Engine/Animations/AnimEvent.cpp b/Source/Engine/Animations/AnimEvent.cpp
index 8a867861e..a3ec94861 100644
--- a/Source/Engine/Animations/AnimEvent.cpp
+++ b/Source/Engine/Animations/AnimEvent.cpp
@@ -17,7 +17,7 @@ void AnimEvent::Serialize(SerializeStream& stream, const void* otherObj)
#if !COMPILE_WITHOUT_CSHARP
// Handle C# objects data serialization
- if (Flags & ObjectFlags::IsManagedType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
{
stream.JKEY("V");
if (other)
@@ -32,7 +32,7 @@ void AnimEvent::Serialize(SerializeStream& stream, const void* otherObj)
#endif
// Handle custom scripting objects data serialization
- if (Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
{
stream.JKEY("D");
_type.Module->SerializeObject(stream, this, other);
@@ -43,7 +43,7 @@ void AnimEvent::Deserialize(DeserializeStream& stream, ISerializeModifier* modif
{
#if !COMPILE_WITHOUT_CSHARP
// Handle C# objects data serialization
- if (Flags & ObjectFlags::IsManagedType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
{
auto* const v = SERIALIZE_FIND_MEMBER(stream, "V");
if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
@@ -54,7 +54,7 @@ void AnimEvent::Deserialize(DeserializeStream& stream, ISerializeModifier* modif
#endif
// Handle custom scripting objects data serialization
- if (Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
{
auto* const v = SERIALIZE_FIND_MEMBER(stream, "D");
if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
index 96f6a0008..9b74ff347 100644
--- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
+++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
@@ -1517,7 +1517,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
const uint16 idx = stateData.Transitions[transitionIndex];
ASSERT(idx < data.Graph->StateTransitions.Count());
auto& transition = data.Graph->StateTransitions[idx];
- const bool useDefaultRule = (transition.Flags & AnimGraphStateTransition::FlagTypes::UseDefaultRule) != 0;
+ const bool useDefaultRule = EnumHasAnyFlags(transition.Flags, AnimGraphStateTransition::FlagTypes::UseDefaultRule);
if (transition.RuleGraph && !useDefaultRule)
{
// Execute transition rule
@@ -1569,7 +1569,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
// Skip after Solo transition
// TODO: don't load transitions after first enabled Solo transition and remove this check here
- if ((transition.Flags & AnimGraphStateTransition::FlagTypes::Solo) != 0)
+ if (EnumHasAnyFlags(transition.Flags, AnimGraphStateTransition::FlagTypes::Solo))
break;
transitionIndex++;
diff --git a/Source/Engine/Content/Assets/Material.cpp b/Source/Engine/Content/Assets/Material.cpp
index be532e64c..76ed34b80 100644
--- a/Source/Engine/Content/Assets/Material.cpp
+++ b/Source/Engine/Content/Assets/Material.cpp
@@ -424,8 +424,8 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
const bool useDistortion =
(info.Domain == MaterialDomain::Surface || info.Domain == MaterialDomain::Deformable || info.Domain == MaterialDomain::Particle) &&
info.BlendMode != MaterialBlendMode::Opaque &&
- (info.UsageFlags & MaterialUsageFlags::UseRefraction) != 0 &&
- (info.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0;
+ EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseRefraction) &&
+ (info.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None;
// @formatter:off
static const char* Numbers[] =
@@ -438,22 +438,22 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
options.Macros.Add({ "MATERIAL_DOMAIN", Numbers[(int32)info.Domain] });
options.Macros.Add({ "MATERIAL_BLEND", Numbers[(int32)info.BlendMode] });
options.Macros.Add({ "MATERIAL_SHADING_MODEL", Numbers[(int32)info.ShadingModel] });
- options.Macros.Add({ "MATERIAL_MASKED", Numbers[info.UsageFlags & MaterialUsageFlags::UseMask ? 1 : 0] });
+ options.Macros.Add({ "MATERIAL_MASKED", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseMask) ? 1 : 0] });
options.Macros.Add({ "DECAL_BLEND_MODE", Numbers[(int32)info.DecalBlendingMode] });
- options.Macros.Add({ "USE_EMISSIVE", Numbers[info.UsageFlags & MaterialUsageFlags::UseEmissive ? 1 : 0] });
- options.Macros.Add({ "USE_NORMAL", Numbers[info.UsageFlags & MaterialUsageFlags::UseNormal ? 1 : 0] });
- options.Macros.Add({ "USE_POSITION_OFFSET", Numbers[info.UsageFlags & MaterialUsageFlags::UsePositionOffset ? 1 : 0] });
- options.Macros.Add({ "USE_VERTEX_COLOR", Numbers[info.UsageFlags & MaterialUsageFlags::UseVertexColor ? 1 : 0] });
- options.Macros.Add({ "USE_DISPLACEMENT", Numbers[info.UsageFlags & MaterialUsageFlags::UseDisplacement ? 1 : 0] });
- options.Macros.Add({ "USE_DITHERED_LOD_TRANSITION", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::DitheredLODTransition ? 1 : 0] });
+ options.Macros.Add({ "USE_EMISSIVE", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseEmissive) ? 1 : 0] });
+ options.Macros.Add({ "USE_NORMAL", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseNormal) ? 1 : 0] });
+ options.Macros.Add({ "USE_POSITION_OFFSET", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UsePositionOffset) ? 1 : 0] });
+ options.Macros.Add({ "USE_VERTEX_COLOR", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseVertexColor) ? 1 : 0] });
+ options.Macros.Add({ "USE_DISPLACEMENT", Numbers[EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseDisplacement) ? 1 : 0] });
+ options.Macros.Add({ "USE_DITHERED_LOD_TRANSITION", Numbers[EnumHasAnyFlags(info.FeaturesFlags, MaterialFeaturesFlags::DitheredLODTransition) ? 1 : 0] });
options.Macros.Add({ "USE_GBUFFER_CUSTOM_DATA", Numbers[useCustomData ? 1 : 0] });
- options.Macros.Add({ "USE_REFLECTIONS", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::DisableReflections ? 0 : 1] });
- if (!(info.FeaturesFlags & MaterialFeaturesFlags::DisableReflections) && info.FeaturesFlags & MaterialFeaturesFlags::ScreenSpaceReflections)
+ options.Macros.Add({ "USE_REFLECTIONS", Numbers[EnumHasAnyFlags(info.FeaturesFlags, MaterialFeaturesFlags::DisableReflections) ? 0 : 1] });
+ if (!(info.FeaturesFlags & MaterialFeaturesFlags::DisableReflections) && EnumHasAnyFlags(info.FeaturesFlags, MaterialFeaturesFlags::ScreenSpaceReflections))
options.Macros.Add({ "MATERIAL_REFLECTIONS", Numbers[1] });
- options.Macros.Add({ "USE_FOG", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::DisableFog ? 0 : 1] });
+ options.Macros.Add({ "USE_FOG", Numbers[EnumHasAnyFlags(info.FeaturesFlags, MaterialFeaturesFlags::DisableFog) ? 0 : 1] });
if (useForward)
{
- options.Macros.Add({ "USE_PIXEL_NORMAL_OFFSET_REFRACTION", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::PixelNormalOffsetRefraction ? 1 : 0] });
+ options.Macros.Add({ "USE_PIXEL_NORMAL_OFFSET_REFRACTION", Numbers[EnumHasAnyFlags(info.FeaturesFlags, MaterialFeaturesFlags::PixelNormalOffsetRefraction) ? 1 : 0] });
switch (info.TransparentLightingMode)
{
case MaterialTransparentLightingMode::Surface:
diff --git a/Source/Engine/Content/Cache/AssetsCache.cpp b/Source/Engine/Content/Cache/AssetsCache.cpp
index 8138fc94e..ddb7159f9 100644
--- a/Source/Engine/Content/Cache/AssetsCache.cpp
+++ b/Source/Engine/Content/Cache/AssetsCache.cpp
@@ -97,7 +97,7 @@ void AssetsCache::Init()
stream->Read(tmp1);
#endif
- if (flags & AssetsCacheFlags::RelativePaths && e.Info.Path.HasChars())
+ if (EnumHasAnyFlags(flags, AssetsCacheFlags::RelativePaths) && e.Info.Path.HasChars())
{
// Convert to absolute path
e.Info.Path = Globals::StartupFolder / e.Info.Path;
@@ -125,7 +125,7 @@ void AssetsCache::Init()
String mappedPath;
stream->ReadString(&mappedPath, i + 73);
- if (flags & AssetsCacheFlags::RelativePaths && mappedPath.HasChars())
+ if (EnumHasAnyFlags(flags, AssetsCacheFlags::RelativePaths) && mappedPath.HasChars())
{
// Convert to absolute path
mappedPath = Globals::StartupFolder / mappedPath;
diff --git a/Source/Engine/Content/Storage/FlaxStorage.cpp b/Source/Engine/Content/Storage/FlaxStorage.cpp
index fd64d872c..fd964daaf 100644
--- a/Source/Engine/Content/Storage/FlaxStorage.cpp
+++ b/Source/Engine/Content/Storage/FlaxStorage.cpp
@@ -651,7 +651,7 @@ bool FlaxStorage::LoadAssetChunk(FlaxChunk* chunk)
// Load data
auto size = chunk->LocationInFile.Size;
- if (chunk->Flags & FlaxChunkFlags::CompressedLZ4)
+ if (EnumHasAnyFlags(chunk->Flags, FlaxChunkFlags::CompressedLZ4))
{
// Compressed
size -= sizeof(int32); // Don't count original size int
@@ -861,7 +861,7 @@ bool FlaxStorage::Create(WriteStream* stream, const AssetInitData* data, int32 d
for (int32 i = 0; i < chunksCount; i++)
{
const FlaxChunk* chunk = chunks[i];
- if (chunk->Flags & FlaxChunkFlags::CompressedLZ4)
+ if (EnumHasAnyFlags(chunk->Flags, FlaxChunkFlags::CompressedLZ4))
{
PROFILE_CPU_NAMED("CompressLZ4");
const int32 srcSize = chunk->Data.Length();
diff --git a/Source/Engine/Core/Object.h b/Source/Engine/Core/Object.h
index 901118dc5..db08a0155 100644
--- a/Source/Engine/Core/Object.h
+++ b/Source/Engine/Core/Object.h
@@ -42,7 +42,6 @@ public:
///
/// Gets the string representation of this object.
///
- /// The string.
virtual String ToString() const = 0;
///
diff --git a/Source/Engine/Core/ObjectsRemovalService.cpp b/Source/Engine/Core/ObjectsRemovalService.cpp
index 567f621c1..61ac1b748 100644
--- a/Source/Engine/Core/ObjectsRemovalService.cpp
+++ b/Source/Engine/Core/ObjectsRemovalService.cpp
@@ -113,7 +113,7 @@ void ObjectsRemovalService::Flush(float dt, float gameDelta)
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
{
auto obj = i->Key;
- const float ttl = i->Value - (obj->Flags & ObjectFlags::UseGameTimeForDelete ? gameDelta : dt);
+ const float ttl = i->Value - ((obj->Flags & ObjectFlags::UseGameTimeForDelete) != ObjectFlags::None ? gameDelta : dt);
if (ttl <= ZeroTolerance)
{
Pool.Remove(i);
diff --git a/Source/Engine/Core/Types/BaseTypes.h b/Source/Engine/Core/Types/BaseTypes.h
index 40fc84505..9db3020e1 100644
--- a/Source/Engine/Core/Types/BaseTypes.h
+++ b/Source/Engine/Core/Types/BaseTypes.h
@@ -141,13 +141,28 @@ struct Color32;
// Declares full set of operators for the enum type (using binary operation on integer values)
#define DECLARE_ENUM_OPERATORS(T) \
- inline constexpr T operator~ (T a) { return (T)~(int)a; } \
- inline constexpr T operator| (T a, T b) { return (T)((int)a | (int)b); } \
- inline constexpr int operator& (T a, T b) { return ((int)a & (int)b); } \
- inline constexpr T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } \
- inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); } \
- inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } \
- inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
+ inline constexpr bool operator!(T a) { return !(__underlying_type(T))a; } \
+ inline constexpr T operator~(T a) { return (T)~(__underlying_type(T))a; } \
+ inline constexpr T operator|(T a, T b) { return (T)((__underlying_type(T))a | (__underlying_type(T))b); } \
+ inline constexpr T operator&(T a, T b) { return (T)((__underlying_type(T))a & (__underlying_type(T))b); } \
+ inline constexpr T operator^(T a, T b) { return (T)((__underlying_type(T))a ^ (__underlying_type(T))b); } \
+ inline T& operator|=(T& a, T b) { return a = (T)((__underlying_type(T))a | (__underlying_type(T))b); } \
+ inline T& operator&=(T& a, T b) { return a = (T)((__underlying_type(T))a & (__underlying_type(T))b); } \
+ inline T& operator^=(T& a, T b) { return a = (T)((__underlying_type(T))a ^ (__underlying_type(T))b); }
+
+// Returns true if given enum value has one or more enum flags set
+template
+constexpr bool EnumHasAnyFlags(T value, T flags)
+{
+ return ((__underlying_type(T))value & (__underlying_type(T))flags) != 0;
+}
+
+// Returns true if given enum value has all of the enum flags set
+template
+constexpr bool EnumHasAllFlags(T value, T flags)
+{
+ return ((__underlying_type(T))value & (__underlying_type(T))flags) == (__underlying_type(T))flags;
+}
// Returns byte offset from the object pointer in vtable to the begin of the given inherited type implementation
#define VTABLE_OFFSET(type, baseType) (((intptr)static_cast((type*)1))-1)
diff --git a/Source/Engine/Engine/Base/GameBase.cpp b/Source/Engine/Engine/Base/GameBase.cpp
index f0cd7043c..26bc9c267 100644
--- a/Source/Engine/Engine/Base/GameBase.cpp
+++ b/Source/Engine/Engine/Base/GameBase.cpp
@@ -109,7 +109,7 @@ bool GameBase::Init()
PROFILE_CPU();
// Preload splash screen texture
- if (GameBaseImpl::HeaderFlags & GameHeaderFlags::ShowSplashScreen)
+ if (EnumHasAnyFlags(GameBaseImpl::HeaderFlags, GameHeaderFlags::ShowSplashScreen))
{
LOG(Info, "Loading splash screen");
if (GameBaseImpl::SplashScreenId)
diff --git a/Source/Engine/Engine/RandomStream.cs b/Source/Engine/Engine/RandomStream.cs
new file mode 100644
index 000000000..90be3bd2c
--- /dev/null
+++ b/Source/Engine/Engine/RandomStream.cs
@@ -0,0 +1,198 @@
+// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+
+using System.Runtime.CompilerServices;
+
+#pragma warning disable 675
+
+namespace FlaxEngine
+{
+ ///
+ /// Very basic pseudo numbers generator.
+ ///
+ [HideInEditor]
+ public class RandomStream
+ {
+ ///
+ /// Holds the initial seed.
+ ///
+ private int _initialSeed;
+
+ ///
+ /// Holds the current seed.
+ ///
+ private int _seed;
+
+ ///
+ /// Init
+ ///
+ public RandomStream()
+ {
+ _initialSeed = 0;
+ _seed = 0;
+ }
+
+ ///
+ /// Creates and initializes a new random stream from the specified seed value.
+ ///
+ /// The seed value.
+ public RandomStream(int seed)
+ {
+ _initialSeed = seed;
+ _seed = seed;
+ }
+
+ ///
+ /// Gets initial seed value
+ ///
+ public int GetInitialSeed()
+ {
+ return _initialSeed;
+ }
+
+
+ ///
+ /// Gets the current seed.
+ ///
+ public int GetCurrentSeed()
+ {
+ return _seed;
+ }
+
+ ///
+ /// Initializes this random stream with the specified seed value.
+ ///
+ /// The seed value.
+ public void Initialize(int seed)
+ {
+ _initialSeed = seed;
+ _seed = seed;
+ }
+
+ ///
+ /// Resets this random stream to the initial seed value.
+ ///
+ public void Reset()
+ {
+ _seed = _initialSeed;
+ }
+
+ ///
+ /// Generates a new random seed.
+ ///
+ public void GenerateNewSeed()
+ {
+ Initialize(new System.Random().Next());
+ }
+
+ ///
+ /// Returns a random boolean.
+ ///
+ public unsafe bool GetBool()
+ {
+ MutateSeed();
+ fixed (int* seedPtr = &_seed)
+ return *seedPtr < (uint.MaxValue / 2);
+ }
+
+ ///
+ /// Returns a random number between 0 and uint.MaxValue.
+ ///
+ public unsafe uint GetUnsignedInt()
+ {
+ MutateSeed();
+ fixed (int* seedPtr = &_seed)
+ return (uint)*seedPtr;
+ }
+
+ ///
+ /// Returns a random number between 0 and 1.
+ ///
+ public unsafe float GetFraction()
+ {
+ MutateSeed();
+ float temp = 1.0f;
+ float result = 0.0f;
+ *(int*)&result = (int)((*(int*)&temp & 0xff800000) | (_seed & 0x007fffff));
+ return Mathf.Frac(result);
+ }
+
+ ///
+ /// Returns a random number between 0 and 1.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public float Rand()
+ {
+ return GetFraction();
+ }
+
+ ///
+ /// Returns a random vector of unit size.
+ ///
+ public Float3 GetUnitVector()
+ {
+ Float3 result;
+ float l;
+ do
+ {
+ result.X = GetFraction() * 2.0f - 1.0f;
+ result.Y = GetFraction() * 2.0f - 1.0f;
+ result.Z = GetFraction() * 2.0f - 1.0f;
+ l = result.LengthSquared;
+ } while (l > 1.0f || l < Mathf.Epsilon);
+ return Float3.Normalize(result);
+ }
+
+ ///
+ /// Gets a random with components in a range between [0;1].
+ ///
+ public Vector3 GetVector3()
+ {
+ return new Vector3(GetFraction(), GetFraction(), GetFraction());
+ }
+
+ ///
+ /// Helper function for rand implementations.
+ ///
+ /// Top border
+ /// A random number in [0..A)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int RandHelper(int a)
+ {
+ return a > 0 ? Mathf.FloorToInt(GetFraction() * ((float)a - Mathf.Epsilon)) : 0;
+ }
+
+ ///
+ /// Helper function for rand implementations
+ ///
+ /// Minimum value
+ /// Maximum value
+ /// A random number in [min; max] range
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int RandRange(int min, int max)
+ {
+ int range = max - min + 1;
+ return min + RandHelper(range);
+ }
+
+ ///
+ /// Helper function for rand implementations
+ ///
+ /// Minimum value
+ /// Maximum value
+ /// A random number in [min; max] range
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public float RandRange(float min, float max)
+ {
+ return min + (max - min) * Rand();
+ }
+
+ ///
+ /// Mutates the current seed into the next seed.
+ ///
+ protected void MutateSeed()
+ {
+ // This can be modified to provide better randomization
+ _seed = _seed * 196314165 + 907633515;
+ }
+ }
+}
diff --git a/Source/Engine/Engine/RandomUtil.cs b/Source/Engine/Engine/RandomUtil.cs
new file mode 100644
index 000000000..41682dc53
--- /dev/null
+++ b/Source/Engine/Engine/RandomUtil.cs
@@ -0,0 +1,25 @@
+// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace FlaxEngine
+{
+ ///
+ /// Basic pseudo numbers generator utility.
+ ///
+ public static class RandomUtil
+ {
+ private static readonly Random _random = new Random();
+
+ ///
+ /// Generates a pseudo-random number from normalized range [0;1].
+ ///
+ /// The random number.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Rand()
+ {
+ return _random.Next(0, int.MaxValue) / (float)int.MaxValue;
+ }
+ }
+}
diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp
index fe000f5e7..97688e196 100644
--- a/Source/Engine/Foliage/Foliage.cpp
+++ b/Source/Engine/Foliage/Foliage.cpp
@@ -22,7 +22,7 @@
#include "Engine/Serialization/Serialization.h"
#include "Engine/Utilities/Encryption.h"
-#define FOLIAGE_GET_DRAW_MODES(renderContext, type) static_cast(type.DrawModes & renderContext.View.Pass & (int32)renderContext.View.GetShadowsDrawPassMask(type.ShadowsMode))
+#define FOLIAGE_GET_DRAW_MODES(renderContext, type) (type.DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(type.ShadowsMode))
#define FOLIAGE_CAN_DRAW(renderContext, type) (type.IsReady() && FOLIAGE_GET_DRAW_MODES(renderContext, type) != DrawPass::None && type.Model->CanBeRendered())
Foliage::Foliage(const SpawnParams& params)
@@ -115,7 +115,7 @@ void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instan
e = &result[key];
ASSERT_LOW_LAYER(key.Mat);
e->DrawCall.Material = key.Mat;
- e->DrawCall.Surface.Lightmap = _staticFlags & StaticFlags::Lightmap ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
+ e->DrawCall.Surface.Lightmap = EnumHasAnyFlags(_staticFlags, StaticFlags::Lightmap) ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
}
// Add instance to the draw batch
@@ -450,9 +450,9 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
continue;
// Select draw modes
- const auto shadowsMode = static_cast(entry.ShadowsMode & slot.ShadowsMode);
- const auto drawModes = static_cast(typeDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode)) & material->GetDrawModes();
- if (drawModes == 0)
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = typeDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & material->GetDrawModes();
+ if (drawModes == DrawPass::None)
continue;
drawCall.DrawCall.Material = material;
@@ -472,8 +472,8 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
const auto& mesh = *e.Key.Geo;
const auto& entry = type.Entries[mesh.GetMaterialSlotIndex()];
const MaterialSlot& slot = type.Model->MaterialSlots[mesh.GetMaterialSlotIndex()];
- const auto shadowsMode = static_cast(entry.ShadowsMode & slot.ShadowsMode);
- const auto drawModes = (DrawPass)(static_cast(typeDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode)) & batch.DrawCall.Material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = typeDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & batch.DrawCall.Material->GetDrawModes();
// Setup draw call
mesh.GetDrawCallGeometry(batch.DrawCall);
@@ -493,7 +493,7 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
batch.DrawCall.Surface.Skinning = nullptr;
batch.DrawCall.WorldDeterminantSign = 1;
- if (drawModes & DrawPass::Forward)
+ if (EnumHasAnyFlags(drawModes, DrawPass::Forward))
{
// Transparency requires sorting by depth so convert back the batched draw call into normal draw calls (RenderList impl will handle this)
DrawCall drawCall = batch.DrawCall;
@@ -518,22 +518,22 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
const int32 batchIndex = renderContext.List->BatchedDrawCalls.Add(MoveTemp(batch));
// Add draw call to proper draw lists
- if (drawModes & DrawPass::Depth)
+ if (EnumHasAnyFlags(drawModes, DrawPass::Depth))
{
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::Depth].PreBatchedDrawCalls.Add(batchIndex);
}
- if (drawModes & DrawPass::GBuffer)
+ if (EnumHasAnyFlags(drawModes, DrawPass::GBuffer))
{
if (entry.ReceiveDecals)
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBuffer].PreBatchedDrawCalls.Add(batchIndex);
else
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBufferNoDecals].PreBatchedDrawCalls.Add(batchIndex);
}
- if (drawModes & DrawPass::Distortion)
+ if (EnumHasAnyFlags(drawModes, DrawPass::Distortion))
{
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::Distortion].PreBatchedDrawCalls.Add(batchIndex);
}
- if (drawModes & DrawPass::MotionVectors && (_staticFlags & StaticFlags::Transform) == 0)
+ if (EnumHasAnyFlags(drawModes, DrawPass::MotionVectors) && (_staticFlags & StaticFlags::Transform) == StaticFlags::None)
{
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::MotionVectors].PreBatchedDrawCalls.Add(batchIndex);
}
@@ -1053,7 +1053,7 @@ bool Foliage::Intersects(const Ray& ray, Real& distance, Vector3& normal, int32&
Real tmpDistance;
Vector3 tmpNormal;
FoliageInstance* tmpInstance;
- for (auto& type : FoliageTypes)
+ for (const auto& type : FoliageTypes)
{
if (type.Root && type.Root->Intersects(this, ray, tmpDistance, tmpNormal, tmpInstance) && tmpDistance < distance)
{
@@ -1155,7 +1155,7 @@ void Foliage::Draw(RenderContext& renderContext)
#endif
return;
}
- if (renderContext.View.Pass & DrawPass::GlobalSurfaceAtlas)
+ if (EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GlobalSurfaceAtlas))
{
// Draw single foliage instance projection into Global Surface Atlas
auto& instance = *(FoliageInstance*)GlobalSurfaceAtlasPass::Instance()->GetCurrentActorObject();
@@ -1181,7 +1181,7 @@ void Foliage::Draw(RenderContext& renderContext)
draw.DrawState = &instance.DrawState;
draw.Bounds = instance.Bounds;
draw.PerInstanceRandom = instance.Random;
- draw.DrawModes = static_cast(type.DrawModes & view.Pass & (int32)view.GetShadowsDrawPassMask(type.ShadowsMode));
+ draw.DrawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode);
type.Model->Draw(renderContext, draw);
return;
}
@@ -1216,7 +1216,7 @@ void Foliage::Draw(RenderContextBatch& renderContextBatch)
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
// Run async job for each foliage type
const RenderView& view = renderContextBatch.GetMainContext().View;
- if ((view.Pass & DrawPass::GBuffer) && !(view.Pass & (DrawPass::GlobalSDF | DrawPass::GlobalSurfaceAtlas)) && renderContextBatch.EnableAsync)
+ if (EnumHasAnyFlags(view.Pass, DrawPass::GBuffer) && !(view.Pass & (DrawPass::GlobalSDF | DrawPass::GlobalSurfaceAtlas)) && renderContextBatch.EnableAsync)
{
// Cache data per foliage instance type
for (FoliageType& type : FoliageTypes)
diff --git a/Source/Engine/Graphics/GPUBuffer.cpp b/Source/Engine/Graphics/GPUBuffer.cpp
index 72cfd1cf6..a38c88dd0 100644
--- a/Source/Engine/Graphics/GPUBuffer.cpp
+++ b/Source/Engine/Graphics/GPUBuffer.cpp
@@ -2,6 +2,7 @@
#include "GPUBuffer.h"
#include "GPUDevice.h"
+#include "GPUResourceProperty.h"
#include "GPUBufferDescription.h"
#include "PixelFormatExtensions.h"
#include "Async/Tasks/GPUCopyResourceTask.h"
@@ -10,9 +11,8 @@
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Debug/Exceptions/InvalidOperationException.h"
#include "Engine/Debug/Exceptions/ArgumentNullException.h"
-#include "Engine/Threading/ThreadPoolTask.h"
-#include "Engine/Graphics/GPUResourceProperty.h"
#include "Engine/Debug/Exceptions/ArgumentOutOfRangeException.h"
+#include "Engine/Threading/ThreadPoolTask.h"
#include "Engine/Threading/Threading.h"
GPUBufferDescription GPUBufferDescription::Buffer(uint32 size, GPUBufferFlags flags, PixelFormat format, const void* initData, uint32 stride, GPUResourceUsage usage)
@@ -91,7 +91,7 @@ String GPUBufferDescription::ToString() const
{
// TODO: create tool to auto convert flag enums to string
-#define CONVERT_FLAGS_FLAGS_2_STR(value) if(Flags & GPUBufferFlags::value) { if (flags.HasChars()) flags += TEXT('|'); flags += TEXT(#value); }
+#define CONVERT_FLAGS_FLAGS_2_STR(value) if (EnumHasAnyFlags(Flags, GPUBufferFlags::value)) { if (flags.HasChars()) flags += TEXT('|'); flags += TEXT(#value); }
CONVERT_FLAGS_FLAGS_2_STR(ShaderResource);
CONVERT_FLAGS_FLAGS_2_STR(VertexBuffer);
CONVERT_FLAGS_FLAGS_2_STR(IndexBuffer);
@@ -149,7 +149,7 @@ bool GPUBuffer::Init(const GPUBufferDescription& desc)
&& Math::IsInRange(desc.Stride, 0, 1024));
// Validate description
- if (desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(desc.Flags, GPUBufferFlags::Structured))
{
if (desc.Stride <= 0)
{
@@ -157,7 +157,7 @@ bool GPUBuffer::Init(const GPUBufferDescription& desc)
return true;
}
}
- if (desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(desc.Flags, GPUBufferFlags::RawBuffer))
{
if (desc.Format != PixelFormat::R32_Typeless)
{
diff --git a/Source/Engine/Graphics/GPUBufferDescription.h b/Source/Engine/Graphics/GPUBufferDescription.h
index 34b0b8e17..62dc527a6 100644
--- a/Source/Engine/Graphics/GPUBufferDescription.h
+++ b/Source/Engine/Graphics/GPUBufferDescription.h
@@ -124,7 +124,7 @@ public:
///
FORCE_INLINE bool IsShaderResource() const
{
- return (Flags & GPUBufferFlags::ShaderResource) != 0;
+ return (Flags & GPUBufferFlags::ShaderResource) != GPUBufferFlags::None;
}
///
@@ -132,7 +132,7 @@ public:
///
FORCE_INLINE bool IsUnorderedAccess() const
{
- return (Flags & GPUBufferFlags::UnorderedAccess) != 0;
+ return (Flags & GPUBufferFlags::UnorderedAccess) != GPUBufferFlags::None;
}
public:
diff --git a/Source/Engine/Graphics/GPULimits.h b/Source/Engine/Graphics/GPULimits.h
index b613d6ade..11da5aca3 100644
--- a/Source/Engine/Graphics/GPULimits.h
+++ b/Source/Engine/Graphics/GPULimits.h
@@ -173,12 +173,6 @@ API_ENUM(Attributes="Flags") enum class FormatSupport : int32
DECLARE_ENUM_OPERATORS(FormatSupport);
-// Helper macro to check if given format does not support a given set of feature flags
-#define FORMAT_FEATURES_ARE_NOT_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & (formatSupportFlags)) != static_cast(formatSupportFlags))
-
-// Helper macro to check if given format does support a given set of feature flags
-#define FORMAT_FEATURES_ARE_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & (formatSupportFlags)) == static_cast(formatSupportFlags))
-
///
/// The features exposed for a particular format.
///
diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
index d531f757a..9e5f43957 100644
--- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
@@ -101,7 +101,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
+ const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -137,8 +137,8 @@ void DeferredMaterialShader::Unload()
bool DeferredMaterialShader::Load()
{
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
+ psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
@@ -206,7 +206,7 @@ bool DeferredMaterialShader::Load()
psDesc.HS = nullptr;
psDesc.DS = nullptr;
GPUShaderProgramVS* instancedDepthPassVS;
- if ((_info.UsageFlags & (MaterialUsageFlags::UseMask | MaterialUsageFlags::UsePositionOffset)) != 0)
+ if (EnumHasAnyFlags(_info.UsageFlags, MaterialUsageFlags::UseMask | MaterialUsageFlags::UsePositionOffset))
{
// Materials with masking need full vertex buffer to get texcoord used to sample textures for per pixel masking.
// Materials with world pos offset need full VB to apply offset using texcoord etc.
diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
index b2b3eceef..83bfc457b 100644
--- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
@@ -82,7 +82,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
+ const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0)
{
@@ -112,8 +112,8 @@ bool DeformableMaterialShader::Load()
{
_drawModes = DrawPass::Depth | DrawPass::QuadOverdraw;
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
+ psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
index 427128b1e..a1646a154 100644
--- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
@@ -51,7 +51,7 @@ void ForwardMaterialShader::Bind(BindParameters& params)
int32 srv = 2;
// Setup features
- if (_info.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination)
+ if ((_info.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination) != MaterialFeaturesFlags::None)
GlobalIlluminationFeature::Bind(params, cb, srv);
ForwardShadingFeature::Bind(params, cb, srv);
@@ -92,7 +92,7 @@ void ForwardMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
+ const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != MaterialFeaturesFlags::None || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -130,8 +130,8 @@ bool ForwardMaterialShader::Load()
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
auto psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
+ psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
diff --git a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp
index 063b663e8..795d16311 100644
--- a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp
@@ -84,7 +84,7 @@ void GUIMaterialShader::Unload()
bool GUIMaterialShader::Load()
{
GPUPipelineState::Description psDesc0 = GPUPipelineState::Description::DefaultFullscreenTriangle;
- psDesc0.Wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0;
+ psDesc0.Wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe);
psDesc0.VS = _shader->GetVS("VS_GUI");
psDesc0.PS = _shader->GetPS("PS_GUI");
psDesc0.BlendMode = BlendingMode::AlphaBlend;
diff --git a/Source/Engine/Graphics/Materials/MaterialParams.cpp b/Source/Engine/Graphics/Materials/MaterialParams.cpp
index 45f720aeb..5baf611ff 100644
--- a/Source/Engine/Graphics/Materials/MaterialParams.cpp
+++ b/Source/Engine/Graphics/Materials/MaterialParams.cpp
@@ -10,7 +10,6 @@
#include "Engine/Serialization/MemoryWriteStream.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/GPUDevice.h"
-#include "Engine/Graphics/GPULimits.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
#include "Engine/Streaming/Streaming.h"
@@ -36,42 +35,42 @@ MaterialInfo9::MaterialInfo9(const MaterialInfo8& other)
BlendMode = other.BlendMode;
ShadingModel = other.ShadingModel;
UsageFlags = MaterialUsageFlags::None;
- if (other.Flags & MaterialFlags_Deprecated::UseMask)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseMask))
UsageFlags |= MaterialUsageFlags::UseMask;
- if (other.Flags & MaterialFlags_Deprecated::UseEmissive)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseEmissive))
UsageFlags |= MaterialUsageFlags::UseEmissive;
- if (other.Flags & MaterialFlags_Deprecated::UsePositionOffset)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UsePositionOffset))
UsageFlags |= MaterialUsageFlags::UsePositionOffset;
- if (other.Flags & MaterialFlags_Deprecated::UseVertexColor)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseVertexColor))
UsageFlags |= MaterialUsageFlags::UseVertexColor;
- if (other.Flags & MaterialFlags_Deprecated::UseNormal)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseNormal))
UsageFlags |= MaterialUsageFlags::UseNormal;
- if (other.Flags & MaterialFlags_Deprecated::UseDisplacement)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseDisplacement))
UsageFlags |= MaterialUsageFlags::UseDisplacement;
- if (other.Flags & MaterialFlags_Deprecated::UseRefraction)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseRefraction))
UsageFlags |= MaterialUsageFlags::UseRefraction;
FeaturesFlags = MaterialFeaturesFlags::None;
- if (other.Flags & MaterialFlags_Deprecated::Wireframe)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::Wireframe))
FeaturesFlags |= MaterialFeaturesFlags::Wireframe;
- if (other.Flags & MaterialFlags_Deprecated::TransparentDisableDepthTest && BlendMode != MaterialBlendMode::Opaque)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::TransparentDisableDepthTest) && BlendMode != MaterialBlendMode::Opaque)
FeaturesFlags |= MaterialFeaturesFlags::DisableDepthTest;
- if (other.Flags & MaterialFlags_Deprecated::TransparentDisableFog && BlendMode != MaterialBlendMode::Opaque)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::TransparentDisableFog) && BlendMode != MaterialBlendMode::Opaque)
FeaturesFlags |= MaterialFeaturesFlags::DisableFog;
- if (other.Flags & MaterialFlags_Deprecated::TransparentDisableReflections && BlendMode != MaterialBlendMode::Opaque)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::TransparentDisableReflections) && BlendMode != MaterialBlendMode::Opaque)
FeaturesFlags |= MaterialFeaturesFlags::DisableReflections;
- if (other.Flags & MaterialFlags_Deprecated::DisableDepthWrite)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::DisableDepthWrite))
FeaturesFlags |= MaterialFeaturesFlags::DisableDepthWrite;
- if (other.Flags & MaterialFlags_Deprecated::TransparentDisableDistortion && BlendMode != MaterialBlendMode::Opaque)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::TransparentDisableDistortion) && BlendMode != MaterialBlendMode::Opaque)
FeaturesFlags |= MaterialFeaturesFlags::DisableDistortion;
- if (other.Flags & MaterialFlags_Deprecated::InputWorldSpaceNormal)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::InputWorldSpaceNormal))
FeaturesFlags |= MaterialFeaturesFlags::InputWorldSpaceNormal;
- if (other.Flags & MaterialFlags_Deprecated::UseDitheredLODTransition)
+ if (EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::UseDitheredLODTransition))
FeaturesFlags |= MaterialFeaturesFlags::DitheredLODTransition;
if (other.BlendMode != MaterialBlendMode::Opaque && other.TransparentLighting == MaterialTransparentLighting_Deprecated::None)
ShadingModel = MaterialShadingModel::Unlit;
DecalBlendingMode = other.DecalBlendingMode;
PostFxLocation = other.PostFxLocation;
- CullMode = other.Flags & MaterialFlags_Deprecated::TwoSided ? ::CullMode::TwoSided : ::CullMode::Normal;
+ CullMode = EnumHasAnyFlags(other.Flags, MaterialFlags_Deprecated::TwoSided) ? ::CullMode::TwoSided : ::CullMode::Normal;
MaskThreshold = other.MaskThreshold;
OpacityThreshold = other.OpacityThreshold;
TessellationMode = other.TessellationMode;
@@ -441,7 +440,7 @@ void MaterialParameter::Bind(BindMeta& meta) const
case MaterialSceneTextures::SceneDepth:
case MaterialSceneTextures::WorldPosition:
view = meta.CanSampleDepth
- ? meta.Buffers->DepthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView
+ ? EnumHasAnyFlags(meta.Buffers->DepthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView)
? meta.Buffers->DepthBuffer->ViewReadOnlyDepth()
: meta.Buffers->DepthBuffer->View()
: GPUDevice::Instance->GetDefaultWhiteTexture()->View();
diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp
index 2d9de90d2..b3069b4db 100644
--- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp
+++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp
@@ -127,7 +127,7 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, Span& c
auto& drawCall = *params.FirstDrawCall;
ASSERT_LOW_LAYER(cb.Length() >= sizeof(Data));
- const bool useLightmap = params.RenderContext.View.Flags & ViewFlags::GI
+ const bool useLightmap = EnumHasAnyFlags(params.RenderContext.View.Flags, ViewFlags::GI)
#if USE_EDITOR
&& EnableLightmapsUsage
#endif
@@ -157,7 +157,7 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa
ASSERT_LOW_LAYER(cb.Length() >= sizeof(Data));
bool useGI = false;
- if (params.RenderContext.View.Flags & ViewFlags::GI)
+ if (EnumHasAnyFlags(params.RenderContext.View.Flags, ViewFlags::GI))
{
switch (params.RenderContext.List->Settings.GlobalIllumination.Mode)
{
diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
index 65bbca71f..43dd9d447 100644
--- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp
@@ -56,7 +56,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
int32 srv = 2;
// Setup features
- if (_info.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination)
+ if (EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::GlobalIllumination))
GlobalIlluminationFeature::Bind(params, cb, srv);
ForwardShadingFeature::Bind(params, cb, srv);
@@ -117,7 +117,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
+ bool wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe) || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
PipelineStateCache* psCache = nullptr;
switch (drawCall.Particle.Module->TypeID)
@@ -189,8 +189,8 @@ bool ParticleMaterialShader::Load()
{
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
+ psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
auto vsSprite = _shader->GetVS("VS_Sprite");
auto vsMesh = _shader->GetVS("VS_Model");
diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
index 7323950c8..7c25a12fc 100644
--- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
@@ -100,7 +100,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
}
// Select pipeline state based on current pass and render mode
- const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;
+ const bool wireframe = EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::Wireframe) || view.Mode == ViewMode::Wireframe;
CullMode cullMode = view.Pass == DrawPass::Depth ? CullMode::TwoSided : _info.CullMode;
#if USE_EDITOR
if (IsRunningRadiancePass)
@@ -133,8 +133,8 @@ void TerrainMaterialShader::Unload()
bool TerrainMaterialShader::Load()
{
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
- psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
- psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
+ psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
+ psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp
index 63648b375..9dfcd72e8 100644
--- a/Source/Engine/Graphics/Models/Mesh.cpp
+++ b/Source/Engine/Graphics/Models/Mesh.cpp
@@ -468,8 +468,8 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
return;
// Check if skip rendering
- const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode);
- const auto drawModes = (DrawPass)((uint32)info.DrawModes & (uint32)renderContext.View.Pass & (uint32)renderContext.View.GetShadowsDrawPassMask(shadowsMode) & (uint32)material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = info.DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & material->GetDrawModes();
if (drawModes == DrawPass::None)
return;
@@ -499,7 +499,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
drawCall.ObjectPosition = drawCall.World.GetTranslation();
drawCall.Surface.GeometrySize = _box.GetSize();
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
- drawCall.Surface.Lightmap = info.Flags & StaticFlags::Lightmap ? info.Lightmap : nullptr;
+ drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty;
drawCall.Surface.Skinning = nullptr;
drawCall.Surface.LODDitherFactor = lodDitherFactor;
@@ -559,7 +559,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
drawCall.ObjectPosition = drawCall.World.GetTranslation();
drawCall.Surface.GeometrySize = _box.GetSize();
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
- drawCall.Surface.Lightmap = info.Flags & StaticFlags::Lightmap ? info.Lightmap : nullptr;
+ drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty;
drawCall.Surface.Skinning = nullptr;
drawCall.Surface.LODDitherFactor = lodDitherFactor;
@@ -572,8 +572,8 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
#endif
// Push draw call to the render lists
- const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode);
- const DrawPass drawModes = (DrawPass)(info.DrawModes & material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = info.DrawModes & material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, info.Flags, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals);
}
diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
index 8a222bfbc..979d9e250 100644
--- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp
+++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
@@ -172,8 +172,8 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
return;
// Check if skip rendering
- const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode);
- const auto drawModes = (DrawPass)((uint32)info.DrawModes & (uint32)renderContext.View.Pass & (uint32)renderContext.View.GetShadowsDrawPassMask(shadowsMode) & (uint32)material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = info.DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & material->GetDrawModes();
if (drawModes == DrawPass::None)
return;
@@ -276,8 +276,8 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
drawCall.PerInstanceRandom = info.PerInstanceRandom;
// Push draw call to the render lists
- const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode);
- const DrawPass drawModes = (DrawPass)(info.DrawModes & material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = info.DrawModes & material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals);
}
diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp
index df328d065..59b29e893 100644
--- a/Source/Engine/Graphics/RenderTask.cpp
+++ b/Source/Engine/Graphics/RenderTask.cpp
@@ -192,11 +192,11 @@ void SceneRenderTask::CollectPostFxVolumes(RenderContext& renderContext)
// Cache WorldPosition used for PostFx volumes blending (RenderView caches it later on)
renderContext.View.WorldPosition = renderContext.View.Origin + renderContext.View.Position;
- if ((ActorsSource & ActorsSources::Scenes) != 0)
+ if (EnumHasAllFlags(ActorsSource, ActorsSources::Scenes))
{
Level::CollectPostFxVolumes(renderContext);
}
- if ((ActorsSource & ActorsSources::CustomActors) != 0)
+ if (EnumHasAllFlags(ActorsSource , ActorsSources::CustomActors))
{
for (Actor* a : CustomActors)
{
@@ -262,7 +262,7 @@ void SceneRenderTask::OnCollectDrawCalls(RenderContextBatch& renderContextBatch,
}
// Draw actors (collect draw calls)
- if ((ActorsSource & ActorsSources::CustomActors) != 0)
+ if (EnumHasAllFlags(ActorsSource, ActorsSources::CustomActors))
{
if (category == SceneRendering::DrawCategory::PreRender)
{
@@ -276,7 +276,7 @@ void SceneRenderTask::OnCollectDrawCalls(RenderContextBatch& renderContextBatch,
ASSERT_LOW_LAYER(_customActorsScene);
_customActorsScene->Draw(renderContextBatch, (SceneRendering::DrawCategory)category);
}
- if ((ActorsSource & ActorsSources::Scenes) != 0)
+ if (EnumHasAllFlags(ActorsSource, ActorsSources::Scenes))
{
Level::DrawActors(renderContextBatch, category);
}
diff --git a/Source/Engine/Graphics/Textures/GPUTexture.cpp b/Source/Engine/Graphics/Textures/GPUTexture.cpp
index af19f5750..921941304 100644
--- a/Source/Engine/Graphics/Textures/GPUTexture.cpp
+++ b/Source/Engine/Graphics/Textures/GPUTexture.cpp
@@ -168,7 +168,7 @@ String GPUTextureDescription::ToString() const
{
// TODO: create tool to auto convert flag enums to string
-#define CONVERT_FLAGS_FLAGS_2_STR(value) if(Flags & GPUTextureFlags::value) { if (flags.HasChars()) flags += TEXT('|'); flags += TEXT(#value); }
+#define CONVERT_FLAGS_FLAGS_2_STR(value) if (EnumHasAnyFlags(Flags, GPUTextureFlags::value)) { if (flags.HasChars()) flags += TEXT('|'); flags += TEXT(#value); }
CONVERT_FLAGS_FLAGS_2_STR(ShaderResource);
CONVERT_FLAGS_FLAGS_2_STR(RenderTarget);
CONVERT_FLAGS_FLAGS_2_STR(UnorderedAccess);
@@ -385,7 +385,7 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot create texture. Depth Stencil texture cannot be used as a Render Target. Description: {0}", desc.ToString());
return true;
}
- if (desc.Flags & GPUTextureFlags::ReadOnlyDepthView && !device->Limits.HasReadOnlyDepth)
+ if (EnumHasAnyFlags(desc.Flags, GPUTextureFlags::ReadOnlyDepthView) && !device->Limits.HasReadOnlyDepth)
{
LOG(Warning, "Cannot create texture. The current graphics platform does not support read-only Depth Stencil texture. Description: {0}", desc.ToString());
return true;
@@ -393,7 +393,7 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
}
else
{
- if (desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
{
LOG(Warning, "Cannot create texture. Cannot create read-only Depth Stencil texture that is not a Depth Stencil texture. Add DepthStencil flag. Description: {0}", desc.ToString());
return true;
diff --git a/Source/Engine/Graphics/Textures/GPUTextureDescription.h b/Source/Engine/Graphics/Textures/GPUTextureDescription.h
index 307496a4f..2302b2faf 100644
--- a/Source/Engine/Graphics/Textures/GPUTextureDescription.h
+++ b/Source/Engine/Graphics/Textures/GPUTextureDescription.h
@@ -148,7 +148,7 @@ public:
///
FORCE_INLINE bool IsRenderTarget() const
{
- return (Flags & GPUTextureFlags::RenderTarget) != 0;
+ return (Flags & GPUTextureFlags::RenderTarget) != GPUTextureFlags::None;
}
///
@@ -156,7 +156,7 @@ public:
///
FORCE_INLINE bool IsDepthStencil() const
{
- return (Flags & GPUTextureFlags::DepthStencil) != 0;
+ return (Flags & GPUTextureFlags::DepthStencil) != GPUTextureFlags::None;
}
///
@@ -164,7 +164,7 @@ public:
///
FORCE_INLINE bool IsShaderResource() const
{
- return (Flags & GPUTextureFlags::ShaderResource) != 0;
+ return (Flags & GPUTextureFlags::ShaderResource) != GPUTextureFlags::None;
}
///
@@ -172,7 +172,7 @@ public:
///
FORCE_INLINE bool IsUnorderedAccess() const
{
- return (Flags & GPUTextureFlags::UnorderedAccess) != 0;
+ return (Flags & GPUTextureFlags::UnorderedAccess) != GPUTextureFlags::None;
}
///
@@ -180,7 +180,7 @@ public:
///
FORCE_INLINE bool HasPerMipViews() const
{
- return (Flags & GPUTextureFlags::PerMipViews) != 0;
+ return (Flags & GPUTextureFlags::PerMipViews) != GPUTextureFlags::None;
}
///
@@ -188,7 +188,7 @@ public:
///
FORCE_INLINE bool HasPerSliceViews() const
{
- return (Flags & GPUTextureFlags::PerSliceViews) != 0;
+ return (Flags & GPUTextureFlags::PerSliceViews) != GPUTextureFlags::None;
}
///
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp
index 2c0e5a342..e3ff0befe 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp
@@ -76,21 +76,20 @@ bool GPUBufferDX11::OnInit()
bufferDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- //
- if (_desc.Flags & GPUBufferFlags::VertexBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer))
bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER;
- if (_desc.Flags & GPUBufferFlags::IndexBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::IndexBuffer))
bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER;
if (useSRV)
bufferDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
if (useUAV)
bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
- //
- if (_desc.Flags & GPUBufferFlags::Argument)
+
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Argument))
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
{
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
bufferDesc.StructureByteStride = _desc.Stride;
@@ -115,7 +114,7 @@ bool GPUBufferDX11::OnInit()
if (useSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
{
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
@@ -125,7 +124,7 @@ bool GPUBufferDX11::OnInit()
}
else
{
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
else
srvDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(_desc.Format, false));
@@ -144,13 +143,13 @@ bool GPUBufferDX11::OnInit()
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = numElements;
uavDesc.Buffer.Flags = 0;
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
- if (_desc.Flags & GPUBufferFlags::Append)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Append))
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_APPEND;
- if (_desc.Flags & GPUBufferFlags::Counter)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Counter))
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_COUNTER;
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
else
uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format));
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
index 9ec5784b8..06f666e12 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
@@ -472,7 +472,7 @@ void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCo
void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
const auto bufferForArgsDX11 = static_cast(bufferForArgs);
@@ -483,7 +483,7 @@ void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs
void GPUContextDX11::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
const auto bufferForArgsDX11 = static_cast(bufferForArgs);
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
index e7faaa27a..19b42074f 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
@@ -494,7 +494,7 @@ void GPUTextureDX11::initHandles()
}
// Read-only depth-stencil
- if (_desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(_desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
{
CLEAR_VIEWS();
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp
index dde8c849d..0f389a9c3 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp
@@ -172,7 +172,7 @@ bool GPUBufferDX12::OnInit()
}
// Check if need to use a counter
- if (_desc.Flags & GPUBufferFlags::Counter || _desc.Flags & GPUBufferFlags::Append)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Counter) || EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Append))
{
#if GPU_ENABLE_RESOURCE_NAMING
String name = String(GetName()) + TEXT(".Counter");
@@ -192,7 +192,7 @@ bool GPUBufferDX12::OnInit()
if (useSRV)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
srvDesc.Format = RenderToolsDX::ToDxgiFormat(_desc.Format);
else
srvDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(_desc.Format, false));
@@ -201,7 +201,7 @@ bool GPUBufferDX12::OnInit()
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = numElements;
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
{
srvDesc.Buffer.StructureByteStride = _desc.Stride;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
@@ -210,7 +210,7 @@ bool GPUBufferDX12::OnInit()
{
srvDesc.Buffer.StructureByteStride = 0;
}
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW;
_view.SetSRV(srvDesc);
}
@@ -223,11 +223,11 @@ bool GPUBufferDX12::OnInit()
uavDesc.Buffer.CounterOffsetInBytes = 0;
uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
uavDesc.Buffer.NumElements = numElements;
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
uavDesc.Buffer.StructureByteStride = _desc.Stride;
- if (_desc.Flags & GPUBufferFlags::RawBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer))
uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
- if (_desc.Flags & GPUBufferFlags::Structured)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Structured))
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
else
uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format));
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
index ede3ec464..b8af1178b 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
@@ -1100,7 +1100,7 @@ void GPUContextDX12::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCo
void GPUContextDX12::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
auto bufferForArgsDX12 = (GPUBufferDX12*)bufferForArgs;
auto signature = _device->DrawIndirectCommandSignature->GetSignature();
@@ -1113,7 +1113,7 @@ void GPUContextDX12::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs
void GPUContextDX12::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
auto bufferForArgsDX12 = (GPUBufferDX12*)bufferForArgs;
auto signature = _device->DrawIndexedIndirectCommandSignature->GetSignature();
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
index badef2591..fb8642c86 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
@@ -691,7 +691,7 @@ void GPUTextureDX12::initHandles()
}
// Read-only depth-stencil
- if (_desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(_desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
{
_handleReadOnlyDepth.Init(this, _device, this, format, msaa);
_handleReadOnlyDepth.ReadOnlyDepthView = true;
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
index ca822228e..c423dc415 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
@@ -197,7 +197,7 @@ public:
// [IShaderResourceDX12]
bool IsDepthStencilResource() const override
{
- return (_desc.Flags & GPUTextureFlags::DepthStencil) != 0;
+ return (_desc.Flags & GPUTextureFlags::DepthStencil) != GPUTextureFlags::None;
}
D3D12_CPU_DESCRIPTOR_HANDLE SRV() const override
{
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
index 17c8816bf..1f5704f8b 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
@@ -100,19 +100,19 @@ bool GPUBufferVulkan::OnInit()
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
if (useSRV && !(_desc.Flags & GPUBufferFlags::Structured))
bufferInfo.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
- if (useUAV || _desc.Flags & GPUBufferFlags::RawBuffer || _desc.Flags & GPUBufferFlags::Structured)
+ if (useUAV || EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::RawBuffer | GPUBufferFlags::Structured))
bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (useUAV && useSRV)
bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
- if (_desc.Flags & GPUBufferFlags::Argument)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Argument))
bufferInfo.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
- if (_desc.Flags & GPUBufferFlags::Argument && useUAV)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Argument) && useUAV)
bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; // For some reason, glslang marks indirect uav buffers (UpdateProbesInitArgs, IndirectArgsBuffer) as Storage Texel Buffers
- if (_desc.Flags & GPUBufferFlags::VertexBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer))
bufferInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- if (_desc.Flags & GPUBufferFlags::IndexBuffer)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::IndexBuffer))
bufferInfo.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- if (IsStaging() || _desc.Flags & GPUBufferFlags::UnorderedAccess)
+ if (IsStaging() || EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::UnorderedAccess))
bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
// Create buffer
@@ -162,7 +162,7 @@ bool GPUBufferVulkan::OnInit()
}
// Check if need to use a counter
- if (_desc.Flags & GPUBufferFlags::Counter || _desc.Flags & GPUBufferFlags::Append)
+ if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Counter | GPUBufferFlags::Append))
{
#if GPU_ENABLE_RESOURCE_NAMING
String name = String(GetName()) + TEXT(".Counter");
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
index d9dafcdfb..5c13dd896 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
@@ -1215,7 +1215,7 @@ void GPUContextVulkan::DrawIndexedInstanced(uint32 indicesCount, uint32 instance
void GPUContextVulkan::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
@@ -1226,7 +1226,7 @@ void GPUContextVulkan::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 of
void GPUContextVulkan::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
- ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
+ ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
index 3a31e47a4..aa7cd53ee 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
@@ -1322,19 +1322,19 @@ PixelFormat GPUDeviceVulkan::GetClosestSupportedPixelFormat(PixelFormat format,
{
// Collect features to use
VkFormatFeatureFlags wantedFeatureFlags = 0;
- if (flags & GPUTextureFlags::ShaderResource)
+ if (EnumHasAnyFlags(flags, GPUTextureFlags::ShaderResource))
wantedFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
- if (flags & GPUTextureFlags::RenderTarget)
+ if (EnumHasAnyFlags(flags, GPUTextureFlags::RenderTarget))
wantedFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
- if (flags & GPUTextureFlags::DepthStencil)
+ if (EnumHasAnyFlags(flags, GPUTextureFlags::DepthStencil))
wantedFeatureFlags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
- if (flags & GPUTextureFlags::UnorderedAccess)
+ if (EnumHasAnyFlags(flags, GPUTextureFlags::UnorderedAccess))
wantedFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
if (!IsVkFormatSupported(RenderToolsVulkan::ToVulkanFormat(format), wantedFeatureFlags, optimalTiling))
{
// Special case for depth-stencil formats
- if (flags & GPUTextureFlags::DepthStencil)
+ if (EnumHasAnyFlags(flags, GPUTextureFlags::DepthStencil))
{
const bool hasStencil = PixelFormatExtensions::HasStencil(format);
@@ -1749,7 +1749,7 @@ bool GPUDeviceVulkan::Init()
//VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT
// Multi-sampling support
- if (support & FormatSupport::Texture2D)
+ if (EnumHasAnyFlags(support, FormatSupport::Texture2D))
msaa = maxMsaa;
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
index cf4fa2e75..977ba4863 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
@@ -216,7 +216,7 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
if (resultFormat != PixelFormat::Unknown)
{
bool found = false;
- if (FORMAT_FEATURES_ARE_SUPPORTED(_device->FeaturesPerFormat[(int32)resultFormat].Support, FormatSupport::RenderTarget))
+ if (EnumHasAllFlags(_device->FeaturesPerFormat[(int32)resultFormat].Support, FormatSupport::RenderTarget))
{
const VkFormat requested = RenderToolsVulkan::ToVulkanFormat(resultFormat);
for (int32 i = 0; i < surfaceFormats.Count(); i++)
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
index 7d4942887..1e28cc32f 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
@@ -420,7 +420,7 @@ void GPUTextureVulkan::initHandles()
}
// Read-only depth-stencil
- if (_desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(_desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
{
_handleReadOnlyDepth.Init(_device, this, _image, mipLevels, format, msaa, extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, 0, 1, 0, true);
}
diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h
index 557d35408..3e8d5232f 100644
--- a/Source/Engine/Level/Actor.h
+++ b/Source/Engine/Level/Actor.h
@@ -350,7 +350,7 @@ public:
///
FORCE_INLINE bool IsTransformStatic() const
{
- return (_staticFlags & StaticFlags::Transform) != 0;
+ return (_staticFlags & StaticFlags::Transform) != StaticFlags::None;
}
///
@@ -373,7 +373,7 @@ public:
///
FORCE_INLINE bool HasStaticFlag(StaticFlags flag) const
{
- return (_staticFlags & flag) == (int)flag;
+ return EnumHasAllFlags(_staticFlags, flag);
}
///
@@ -391,7 +391,7 @@ public:
/// The flags to remove.
FORCE_INLINE void RemoveStaticFlags(StaticFlags flags)
{
- SetStaticFlags(static_cast(_staticFlags & ~flags));
+ SetStaticFlags(_staticFlags & ~flags);
}
///
@@ -401,7 +401,7 @@ public:
/// The target value of the flag.
FORCE_INLINE void SetStaticFlag(StaticFlags flag, bool value)
{
- SetStaticFlags(static_cast(_staticFlags & ~flag) | (value ? flag : StaticFlags::None));
+ SetStaticFlags((_staticFlags & ~flag) | (value ? flag : StaticFlags::None));
}
public:
diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp
index 9be5e718a..ecaed39cb 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.cpp
+++ b/Source/Engine/Level/Actors/AnimatedModel.cpp
@@ -730,7 +730,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
draw.World = &world;
draw.DrawState = &_drawState;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
- draw.DrawModes = (DrawPass)(DrawModes & renderContext.View.GetShadowsDrawPassMask(ShadowsMode));
+ draw.DrawModes = DrawModes & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
draw.Bounds = _sphere;
draw.Bounds.Center -= renderContext.View.Origin;
@@ -785,7 +785,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
// TODO: maybe deserialize ShadowsMode into ModelInstanceBuffer entries options?
for (auto& e : renderContextBatch.Contexts)
{
- draw.DrawModes = (DrawPass)(DrawModes & e.View.GetShadowsDrawPassMask(ShadowsMode));
+ draw.DrawModes = DrawModes & e.View.GetShadowsDrawPassMask(ShadowsMode);
SkinnedModel->Draw(e, draw);
}
}
diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp
index 6c199e6fa..064d6344a 100644
--- a/Source/Engine/Level/Actors/Camera.cpp
+++ b/Source/Engine/Level/Actors/Camera.cpp
@@ -275,7 +275,7 @@ bool Camera::HasContentLoaded() const
void Camera::Draw(RenderContext& renderContext)
{
- if (renderContext.View.Flags & ViewFlags::EditorSprites
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::EditorSprites)
&& _previewModel
&& _previewModel->IsLoaded())
{
@@ -291,7 +291,7 @@ void Camera::Draw(RenderContext& renderContext)
draw.Lightmap = nullptr;
draw.LightmapUVs = nullptr;
draw.Flags = StaticFlags::Transform;
- draw.DrawModes = (DrawPass)((DrawPass::Depth | DrawPass::GBuffer | DrawPass::Forward) & renderContext.View.Pass);
+ draw.DrawModes = (DrawPass::Depth | DrawPass::GBuffer | DrawPass::Forward) & renderContext.View.Pass;
BoundingSphere::FromBox(_previewModelBox, draw.Bounds);
draw.Bounds.Center -= renderContext.View.Origin;
draw.PerInstanceRandom = GetPerInstanceRandom();
diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp
index d744c4c32..31f8d59f4 100644
--- a/Source/Engine/Level/Actors/Decal.cpp
+++ b/Source/Engine/Level/Actors/Decal.cpp
@@ -69,8 +69,8 @@ void Decal::OnLayerChanged()
void Decal::Draw(RenderContext& renderContext)
{
- if ((renderContext.View.Flags & ViewFlags::Decals) != 0 &&
- renderContext.View.Pass & DrawPass::GBuffer &&
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Decals) &&
+ EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer) &&
Material &&
Material->IsLoaded() &&
Material->IsDecal())
diff --git a/Source/Engine/Level/Actors/DirectionalLight.cpp b/Source/Engine/Level/Actors/DirectionalLight.cpp
index 478098abf..43450fd8e 100644
--- a/Source/Engine/Level/Actors/DirectionalLight.cpp
+++ b/Source/Engine/Level/Actors/DirectionalLight.cpp
@@ -20,8 +20,8 @@ void DirectionalLight::Draw(RenderContext& renderContext)
AdjustBrightness(renderContext.View, brightness);
const Float3 position = GetPosition() - renderContext.View.Origin;
if (Brightness > ZeroTolerance
- && (renderContext.View.Flags & ViewFlags::DirectionalLights) != 0
- && renderContext.View.Pass & DrawPass::GBuffer
+ && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::DirectionalLights)
+ && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& (ViewDistance < ZeroTolerance || Float3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance))
{
RendererDirectionalLightData data;
diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.cpp b/Source/Engine/Level/Actors/EnvironmentProbe.cpp
index 08e870942..1b1a400d4 100644
--- a/Source/Engine/Level/Actors/EnvironmentProbe.cpp
+++ b/Source/Engine/Level/Actors/EnvironmentProbe.cpp
@@ -178,8 +178,8 @@ void EnvironmentProbe::UpdateBounds()
void EnvironmentProbe::Draw(RenderContext& renderContext)
{
if (Brightness > ZeroTolerance &&
- (renderContext.View.Flags & ViewFlags::Reflections) != 0 &&
- renderContext.View.Pass & DrawPass::GBuffer)
+ EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Reflections) &&
+ EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer))
{
if (UpdateMode == ProbeUpdateMode::Realtime)
ProbesRenderer::Bake(this, 0.0f);
diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
index 5f01916f5..74b14369d 100644
--- a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
+++ b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
@@ -35,8 +35,8 @@ void ExponentialHeightFog::Draw(RenderContext& renderContext)
{
// Render only when shader is valid and fog can be rendered
// Do not render exponential fog in orthographic views
- if ((renderContext.View.Flags & ViewFlags::Fog) != 0
- && renderContext.View.Pass & DrawPass::GBuffer
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Fog)
+ && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& _shader
&& _shader->IsLoaded()
&& renderContext.View.IsPerspectiveProjection())
diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp
index de2c0070b..49c0f4c88 100644
--- a/Source/Engine/Level/Actors/PointLight.cpp
+++ b/Source/Engine/Level/Actors/PointLight.cpp
@@ -83,9 +83,9 @@ void PointLight::Draw(RenderContext& renderContext)
AdjustBrightness(renderContext.View, brightness);
const Float3 position = GetPosition() - renderContext.View.Origin;
const float radius = GetScaledRadius();
- if ((renderContext.View.Flags & ViewFlags::PointLights) != 0
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::PointLights)
+ && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& brightness > ZeroTolerance
- && renderContext.View.Pass & DrawPass::GBuffer
&& radius > ZeroTolerance
&& (ViewDistance < ZeroTolerance || Vector3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance))
{
diff --git a/Source/Engine/Level/Actors/Sky.cpp b/Source/Engine/Level/Actors/Sky.cpp
index 3d3b83d30..f0ccf84b4 100644
--- a/Source/Engine/Level/Actors/Sky.cpp
+++ b/Source/Engine/Level/Actors/Sky.cpp
@@ -184,7 +184,7 @@ void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureV
data.ViewOffset = renderContext.View.Origin + GetPosition();
InitConfig(data.Fog);
data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
- bool useSpecularLight = (renderContext.View.Flags & ViewFlags::SpecularLight) != 0;
+ bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
if (!useSpecularLight)
{
data.Fog.AtmosphericFogSunDiscScale = 0;
@@ -223,7 +223,7 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
data.ViewOffset = renderContext.View.Origin + GetPosition();
InitConfig(data.Fog);
//data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
- bool useSpecularLight = (renderContext.View.Flags & ViewFlags::SpecularLight) != 0;
+ bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
if (!useSpecularLight)
{
// Hide sun disc if specular light is disabled
diff --git a/Source/Engine/Level/Actors/SkyLight.cpp b/Source/Engine/Level/Actors/SkyLight.cpp
index 2b3d4498c..93e2a8276 100644
--- a/Source/Engine/Level/Actors/SkyLight.cpp
+++ b/Source/Engine/Level/Actors/SkyLight.cpp
@@ -106,8 +106,8 @@ void SkyLight::Draw(RenderContext& renderContext)
float brightness = Brightness;
AdjustBrightness(renderContext.View, brightness);
const Float3 position = GetPosition() - renderContext.View.Origin;
- if ((renderContext.View.Flags & ViewFlags::SkyLights) != 0
- && renderContext.View.Pass & DrawPass::GBuffer
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SkyLights)
+ && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& brightness > ZeroTolerance
&& (ViewDistance < ZeroTolerance || Vector3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance))
{
diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp
index cbd56d70d..8606b179e 100644
--- a/Source/Engine/Level/Actors/Skybox.cpp
+++ b/Source/Engine/Level/Actors/Skybox.cpp
@@ -33,7 +33,7 @@ void Skybox::Draw(RenderContext& renderContext)
bool isReady;
if (CustomMaterial)
{
- isReady = CustomMaterial->IsLoaded() && CustomMaterial->IsSurface() && CustomMaterial->GetDrawModes() & DrawPass::GBuffer;
+ isReady = CustomMaterial->IsLoaded() && CustomMaterial->IsSurface() && EnumHasAnyFlags(CustomMaterial->GetDrawModes(), DrawPass::GBuffer);
}
else
{
diff --git a/Source/Engine/Level/Actors/SplineModel.cpp b/Source/Engine/Level/Actors/SplineModel.cpp
index 0f27f672b..08dc5ddea 100644
--- a/Source/Engine/Level/Actors/SplineModel.cpp
+++ b/Source/Engine/Level/Actors/SplineModel.cpp
@@ -348,7 +348,7 @@ bool SplineModel::HasContentLoaded() const
void SplineModel::Draw(RenderContext& renderContext)
{
- const DrawPass actorDrawModes = (DrawPass)(DrawModes & renderContext.View.Pass);
+ const DrawPass actorDrawModes = DrawModes & renderContext.View.Pass;
if (!_spline || !Model || !Model->IsLoaded() || !Model->CanBeRendered() || actorDrawModes == DrawPass::None)
return;
auto model = Model.Get();
@@ -428,8 +428,8 @@ void SplineModel::Draw(RenderContext& renderContext)
continue;
// Check if skip rendering
- const auto shadowsMode = static_cast(entry.ShadowsMode & slot.ShadowsMode);
- const auto drawModes = static_cast(actorDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & (uint32)material->GetDrawModes());
+ const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
+ const auto drawModes = actorDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & material->GetDrawModes();
if (drawModes == DrawPass::None)
continue;
diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp
index c72a20777..26f1700d5 100644
--- a/Source/Engine/Level/Actors/SpotLight.cpp
+++ b/Source/Engine/Level/Actors/SpotLight.cpp
@@ -132,8 +132,8 @@ void SpotLight::Draw(RenderContext& renderContext)
const Float3 position = GetPosition() - renderContext.View.Origin;
const float radius = GetScaledRadius();
const float outerConeAngle = GetOuterConeAngle();
- if ((renderContext.View.Flags & ViewFlags::SpotLights) != 0
- && renderContext.View.Pass & DrawPass::GBuffer
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpotLights)
+ && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& brightness > ZeroTolerance
&& radius > ZeroTolerance
&& outerConeAngle > ZeroTolerance
diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp
index e06a03ff9..ef6446874 100644
--- a/Source/Engine/Level/Actors/StaticModel.cpp
+++ b/Source/Engine/Level/Actors/StaticModel.cpp
@@ -262,13 +262,13 @@ void StaticModel::Draw(RenderContext& renderContext)
return;
if (renderContext.View.Pass == DrawPass::GlobalSDF)
{
- if (DrawModes & DrawPass::GlobalSDF)
+ if (EnumHasAnyFlags(DrawModes, DrawPass::GlobalSDF))
GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, Model->SDF, _transform, _box);
return;
}
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
{
- if (DrawModes & DrawPass::GlobalSurfaceAtlas)
+ if (EnumHasAnyFlags(DrawModes, DrawPass::GlobalSurfaceAtlas))
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, Model->LODs.Last().GetBox());
return;
}
diff --git a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
index e438345cb..908fa88c0 100644
--- a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
+++ b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
@@ -184,7 +184,7 @@ void PrefabInstanceData::CollectPrefabInstances(Array& prefa
for (int32 instanceIndex = 0; instanceIndex < instances.Count(); instanceIndex++)
{
const auto instance = instances[instanceIndex];
- if ((instance->Flags & ObjectFlags::WasMarkedToDelete) != 0)
+ if (EnumHasAnyFlags(instance->Flags, ObjectFlags::WasMarkedToDelete))
continue;
if (instance != defaultInstance && targetActor != instance && !targetActor->HasActorInHierarchy(instance))
usedCount++;
@@ -195,7 +195,7 @@ void PrefabInstanceData::CollectPrefabInstances(Array& prefa
{
// Skip default instance because it will be recreated, skip input actor because it needs just to be linked
Actor* instance = instances[instanceIndex];
- if ((instance->Flags & ObjectFlags::WasMarkedToDelete) != 0)
+ if (EnumHasAnyFlags(instance->Flags, ObjectFlags::WasMarkedToDelete))
continue;
if (instance != defaultInstance && targetActor != instance && !targetActor->HasActorInHierarchy(instance))
{
@@ -268,7 +268,7 @@ bool PrefabInstanceData::SynchronizePrefabInstances(Array& p
// If prefab object root was changed during changes apply then update the TargetActor to point a valid object
Actor* oldTargetActor = instance.TargetActor;
- if (!oldTargetActor || (oldTargetActor->Flags & ObjectFlags::WasMarkedToDelete) != 0)
+ if (!oldTargetActor || EnumHasAnyFlags(oldTargetActor->Flags, ObjectFlags::WasMarkedToDelete))
continue;
Actor* newTargetActor = FindActorWithPrefabObjectId(instance.TargetActor, defaultInstance->GetID());
if (!newTargetActor)
@@ -670,7 +670,7 @@ bool Prefab::ApplyAll(Actor* targetActor)
for (int32 i = 0; i < nestedPrefabIds.Count(); i++)
{
const auto nestedPrefab = Content::LoadAsync(nestedPrefabIds[i]);
- if (nestedPrefab && nestedPrefab != this && (nestedPrefab->Flags & ObjectFlags::WasMarkedToDelete) == 0)
+ if (nestedPrefab && nestedPrefab != this && (nestedPrefab->Flags & ObjectFlags::WasMarkedToDelete) == ObjectFlags::None)
{
allPrefabs.Add(nestedPrefab);
}
diff --git a/Source/Engine/Level/Prefabs/PrefabManager.cpp b/Source/Engine/Level/Prefabs/PrefabManager.cpp
index 138b6b401..9f35b9fdc 100644
--- a/Source/Engine/Level/Prefabs/PrefabManager.cpp
+++ b/Source/Engine/Level/Prefabs/PrefabManager.cpp
@@ -298,7 +298,7 @@ bool PrefabManager::CreatePrefab(Actor* targetActor, const StringView& outputPat
LOG(Error, "Cannot create prefab from scene actor.");
return true;
}
- if ((targetActor->HideFlags & HideFlags::DontSave) != 0)
+ if (EnumHasAnyFlags(targetActor->HideFlags, HideFlags::DontSave))
{
LOG(Error, "Cannot create prefab from actor marked with HideFlags.DontSave.");
return true;
diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp
index 8d629a23e..7f3d32ecc 100644
--- a/Source/Engine/Level/Scene/SceneRendering.cpp
+++ b/Source/Engine/Level/Scene/SceneRendering.cpp
@@ -85,10 +85,10 @@ void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory c
}
#if USE_EDITOR
- if (view.Pass & DrawPass::GBuffer && category == SceneDraw)
+ if (EnumHasAnyFlags(view.Pass, DrawPass::GBuffer) && category == SceneDraw)
{
// Draw physics shapes
- if (view.Flags & ViewFlags::PhysicsDebug || view.Mode == ViewMode::PhysicsColliders)
+ if (EnumHasAnyFlags(view.Flags, ViewFlags::PhysicsDebug) || view.Mode == ViewMode::PhysicsColliders)
{
const PhysicsDebugCallback* physicsDebugData = PhysicsDebug.Get();
for (int32 i = 0; i < PhysicsDebug.Count(); i++)
@@ -203,7 +203,7 @@ void SceneRendering::DrawActorsJob(int32)
// Offline pass with additional static flags culling
FOR_EACH_BATCH_ACTOR
e.Bounds.Center -= view.Origin;
- if (CHECK_ACTOR && e.Actor->GetStaticFlags() & view.StaticFlagsMask)
+ if (CHECK_ACTOR && (e.Actor->GetStaticFlags() & view.StaticFlagsMask) != StaticFlags::None)
{
DRAW_ACTOR(*_drawBatch);
}
diff --git a/Source/Engine/Level/SceneObject.cpp b/Source/Engine/Level/SceneObject.cpp
index e3568e92f..989cd2c09 100644
--- a/Source/Engine/Level/SceneObject.cpp
+++ b/Source/Engine/Level/SceneObject.cpp
@@ -119,7 +119,7 @@ void SceneObject::Serialize(SerializeStream& stream, const void* otherObj)
#if !COMPILE_WITHOUT_CSHARP
// Handle C# objects data serialization
- if (Flags & ObjectFlags::IsManagedType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
{
stream.JKEY("V");
if (other)
@@ -134,7 +134,7 @@ void SceneObject::Serialize(SerializeStream& stream, const void* otherObj)
#endif
// Handle custom scripting objects data serialization
- if (Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
{
stream.JKEY("D");
_type.Module->SerializeObject(stream, this, other);
@@ -150,7 +150,7 @@ void SceneObject::Deserialize(DeserializeStream& stream, ISerializeModifier* mod
#if !COMPILE_WITHOUT_CSHARP
// Handle C# objects data serialization
- if (Flags & ObjectFlags::IsManagedType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
{
auto* const v = SERIALIZE_FIND_MEMBER(stream, "V");
if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
@@ -161,7 +161,7 @@ void SceneObject::Deserialize(DeserializeStream& stream, ISerializeModifier* mod
#endif
// Handle custom scripting objects data serialization
- if (Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
{
auto* const v = SERIALIZE_FIND_MEMBER(stream, "D");
if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
diff --git a/Source/Engine/Level/SceneObject.h b/Source/Engine/Level/SceneObject.h
index ce957591f..0425a3a76 100644
--- a/Source/Engine/Level/SceneObject.h
+++ b/Source/Engine/Level/SceneObject.h
@@ -99,7 +99,7 @@ public:
///
API_PROPERTY() FORCE_INLINE bool IsDuringPlay() const
{
- return (Flags & ObjectFlags::IsDuringPlay) != 0;
+ return (Flags & ObjectFlags::IsDuringPlay) == ObjectFlags::IsDuringPlay;
}
///
diff --git a/Source/Engine/Level/SceneQuery.cpp b/Source/Engine/Level/SceneQuery.cpp
index 0afd9f8be..b990daaa8 100644
--- a/Source/Engine/Level/SceneQuery.cpp
+++ b/Source/Engine/Level/SceneQuery.cpp
@@ -54,7 +54,7 @@ void SceneQuery::GetAllSceneObjects(Actor* root, Array& objects)
bool GetAllSerializableSceneObjectsQuery(Actor* actor, Array& objects)
{
- if ((actor->HideFlags & HideFlags::DontSave) != 0)
+ if (EnumHasAnyFlags(actor->HideFlags, HideFlags::DontSave))
return false;
objects.Add(actor);
diff --git a/Source/Engine/Networking/Components/NetworkTransform.cpp b/Source/Engine/Networking/Components/NetworkTransform.cpp
index 59368569a..58c6481f6 100644
--- a/Source/Engine/Networking/Components/NetworkTransform.cpp
+++ b/Source/Engine/Networking/Components/NetworkTransform.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
// Interpolation and prediction logic based on https://www.gabrielgambetta.com/client-server-game-architecture.html
@@ -162,51 +162,51 @@ void NetworkTransform::Serialize(NetworkStream* stream)
data.HasSequenceIndex = Mode == ReplicationModes::Prediction;
data.Components = Components;
stream->Write(data);
- if ((data.Components & ReplicationComponents::All) == (int)ReplicationComponents::All)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::All))
{
stream->Write(transform);
}
else
{
- if ((data.Components & ReplicationComponents::Position) == (int)ReplicationComponents::Position)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Position))
{
stream->Write(transform.Translation);
}
- else if (data.Components & ReplicationComponents::Position)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Position))
{
- if (data.Components & ReplicationComponents::PositionX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionX))
stream->Write(transform.Translation.X);
- if (data.Components & ReplicationComponents::PositionY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionY))
stream->Write(transform.Translation.X);
- if (data.Components & ReplicationComponents::PositionZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionZ))
stream->Write(transform.Translation.X);
}
- if ((data.Components & ReplicationComponents::Scale) == (int)ReplicationComponents::Scale)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Scale))
{
stream->Write(transform.Scale);
}
- else if (data.Components & ReplicationComponents::Scale)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Scale))
{
- if (data.Components & ReplicationComponents::ScaleX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleX))
stream->Write(transform.Scale.X);
- if (data.Components & ReplicationComponents::ScaleY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleY))
stream->Write(transform.Scale.X);
- if (data.Components & ReplicationComponents::ScaleZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleZ))
stream->Write(transform.Scale.X);
}
- if ((data.Components & ReplicationComponents::Rotation) == (int)ReplicationComponents::Rotation)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Rotation))
{
const Float3 rotation = transform.Orientation.GetEuler();
stream->Write(rotation);
}
- else if (data.Components & ReplicationComponents::Rotation)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Rotation))
{
const Float3 rotation = transform.Orientation.GetEuler();
- if (data.Components & ReplicationComponents::RotationX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationX))
stream->Write(rotation.X);
- if (data.Components & ReplicationComponents::RotationY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationY))
stream->Write(rotation.Y);
- if (data.Components & ReplicationComponents::RotationZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationZ))
stream->Write(rotation.Z);
}
}
@@ -227,52 +227,52 @@ void NetworkTransform::Deserialize(NetworkStream* stream)
// Decode data
Data data;
stream->Read(data);
- if ((data.Components & ReplicationComponents::All) == (int)ReplicationComponents::All)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::All))
{
stream->Read(transform);
}
else
{
- if ((data.Components & ReplicationComponents::Position) == (int)ReplicationComponents::Position)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Position))
{
stream->Read(transform.Translation);
}
- else if (data.Components & ReplicationComponents::Position)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Position))
{
- if (data.Components & ReplicationComponents::PositionX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionX))
stream->Read(transform.Translation.X);
- if (data.Components & ReplicationComponents::PositionY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionY))
stream->Read(transform.Translation.X);
- if (data.Components & ReplicationComponents::PositionZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::PositionZ))
stream->Read(transform.Translation.X);
}
- if ((data.Components & ReplicationComponents::Scale) == (int)ReplicationComponents::Scale)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Scale))
{
stream->Read(transform.Scale);
}
- else if (data.Components & ReplicationComponents::Scale)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Scale))
{
- if (data.Components & ReplicationComponents::ScaleX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleX))
stream->Read(transform.Scale.X);
- if (data.Components & ReplicationComponents::ScaleY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleY))
stream->Read(transform.Scale.X);
- if (data.Components & ReplicationComponents::ScaleZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::ScaleZ))
stream->Read(transform.Scale.X);
}
- if ((data.Components & ReplicationComponents::Rotation) == (int)ReplicationComponents::Rotation)
+ if (EnumHasAllFlags(data.Components, ReplicationComponents::Rotation))
{
Float3 rotation;
stream->Read(rotation);
transform.Orientation = Quaternion::Euler(rotation);
}
- else if (data.Components & ReplicationComponents::Rotation)
+ else if (EnumHasAnyFlags(data.Components, ReplicationComponents::Rotation))
{
Float3 rotation = transform.Orientation.GetEuler();
- if (data.Components & ReplicationComponents::RotationX)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationX))
stream->Read(rotation.X);
- if (data.Components & ReplicationComponents::RotationY)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationY))
stream->Read(rotation.Y);
- if (data.Components & ReplicationComponents::RotationZ)
+ if (EnumHasAnyFlags(data.Components, ReplicationComponents::RotationZ))
stream->Read(rotation.Z);
transform.Orientation = Quaternion::Euler(rotation);
}
diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp
index 635b4c0a0..9162102dd 100644
--- a/Source/Engine/Networking/NetworkReplicator.cpp
+++ b/Source/Engine/Networking/NetworkReplicator.cpp
@@ -843,11 +843,6 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
item.Role = localRole;
SendObjectRoleMessage(item);
}
- else
- {
- // Object is the owner
- CHECK(localRole == NetworkObjectRole::OwnedAuthoritative);
- }
}
else
{
diff --git a/Source/Engine/Networking/NetworkReplicator.h b/Source/Engine/Networking/NetworkReplicator.h
index 706aee97e..0957094d0 100644
--- a/Source/Engine/Networking/NetworkReplicator.h
+++ b/Source/Engine/Networking/NetworkReplicator.h
@@ -146,7 +146,7 @@ public:
/// The new owner. Set to NetworkManager::LocalClientId for local client to be owner (server might reject it).
/// The local role to assign for the object.
/// True if apply the ownership to all child objects of this object (eg. all child actors and scripts attached to the networked actor).
- API_FUNCTION() static void SetObjectOwnership(ScriptingObject* obj, uint32 ownerClientId, NetworkObjectRole localRole = NetworkObjectRole::Replicated, bool hierarchical = false);
+ API_FUNCTION() static void SetObjectOwnership(ScriptingObject* obj, uint32 ownerClientId, NetworkObjectRole localRole = NetworkObjectRole::Replicated, bool hierarchical = true);
///
/// Marks the object dirty to perform immediate replication to the other clients.
diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp
index 8e0477cd9..8e3756a19 100644
--- a/Source/Engine/Particles/Particles.cpp
+++ b/Source/Engine/Particles/Particles.cpp
@@ -409,7 +409,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
{
const auto material = (MaterialBase*)module->Assets[0].Get();
const auto moduleDrawModes = module->Values.Count() > 3 ? (DrawPass)module->Values[3].AsInt : DrawPass::Default;
- auto dp = (DrawPass)(drawModes & moduleDrawModes & (uint32)material->GetDrawModes());
+ auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
if (dp == DrawPass::None)
break;
drawCall.Material = material;
@@ -427,7 +427,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
const auto model = (Model*)module->Assets[0].Get();
const auto material = (MaterialBase*)module->Assets[1].Get();
const auto moduleDrawModes = module->Values.Count() > 4 ? (DrawPass)module->Values[4].AsInt : DrawPass::Default;
- auto dp = (DrawPass)(drawModes & moduleDrawModes & (uint32)material->GetDrawModes());
+ auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
if (dp == DrawPass::None)
break;
drawCall.Material = material;
@@ -457,7 +457,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
break;
const auto material = (MaterialBase*)module->Assets[0].Get();
const auto moduleDrawModes = module->Values.Count() > 6 ? (DrawPass)module->Values[6].AsInt : DrawPass::Default;
- auto dp = (DrawPass)(drawModes & moduleDrawModes & (uint32)material->GetDrawModes());
+ auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
if (dp == DrawPass::None)
break;
drawCall.Material = material;
@@ -820,7 +820,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
{
const auto material = (MaterialBase*)module->Assets[0].Get();
const auto moduleDrawModes = module->Values.Count() > 3 ? (DrawPass)module->Values[3].AsInt : DrawPass::Default;
- auto dp = (DrawPass)(drawModes & moduleDrawModes & (uint32)material->GetDrawModes());
+ auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
drawCall.Material = material;
// Submit draw call
@@ -840,7 +840,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
const auto model = (Model*)module->Assets[0].Get();
const auto material = (MaterialBase*)module->Assets[1].Get();
const auto moduleDrawModes = module->Values.Count() > 4 ? (DrawPass)module->Values[4].AsInt : DrawPass::Default;
- auto dp = (DrawPass)(drawModes & moduleDrawModes & (uint32)material->GetDrawModes());
+ auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
drawCall.Material = material;
// TODO: model LOD picking for particles?
@@ -887,7 +887,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
{
// Setup
auto& view = renderContext.View;
- const auto drawModes = static_cast(view.Pass & effect->DrawModes);
+ const auto drawModes = view.Pass & effect->DrawModes;
if (drawModes == DrawPass::None || SpriteRenderer.Init())
return;
Matrix worlds[2];
@@ -937,11 +937,11 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
case 400:
{
const auto material = (MaterialBase*)module->Assets[0].Get();
- const auto moduleDrawModes = module->Values.Count() > 3 ? module->Values[3].AsInt : (int32)DrawPass::Default;
+ const auto moduleDrawModes = module->Values.Count() > 3 ? (DrawPass)module->Values[3].AsInt : DrawPass::Default;
if (!material ||
!material->IsReady() ||
!material->IsParticle() ||
- (view.Pass & material->GetDrawModes() & moduleDrawModes) == 0
+ (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None
)
break;
renderModulesIndices.Add(moduleIndex);
@@ -951,7 +951,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
case 403:
{
const auto model = (Model*)module->Assets[0].Get();
- const auto moduleDrawModes = module->Values.Count() > 4 ? module->Values[4].AsInt : (int32)DrawPass::Default;
+ const auto moduleDrawModes = module->Values.Count() > 4 ? (DrawPass)module->Values[4].AsInt : DrawPass::Default;
if (!model ||
!model->IsLoaded() ||
!model->CanBeRendered())
@@ -960,7 +960,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
if (!material ||
!material->IsReady() ||
!material->IsParticle() ||
- (view.Pass & material->GetDrawModes() & moduleDrawModes) == 0
+ (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None
)
break;
renderModulesIndices.Add(moduleIndex);
@@ -970,11 +970,11 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
case 404:
{
const auto material = (MaterialBase*)module->Assets[0].Get();
- const auto moduleDrawModes = module->Values.Count() > 6 ? module->Values[6].AsInt : (int32)DrawPass::Default;
+ const auto moduleDrawModes = module->Values.Count() > 6 ? (DrawPass)module->Values[6].AsInt : DrawPass::Default;
if (!material ||
!material->IsReady() ||
!material->IsParticle() ||
- (view.Pass & material->GetDrawModes() & moduleDrawModes) == 0
+ (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None
)
break;
renderModulesIndices.Add(moduleIndex);
@@ -987,7 +987,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
if (!material ||
!material->IsReady() ||
material->GetInfo().Domain != MaterialDomain::VolumeParticle ||
- (view.Flags & ViewFlags::Fog) == 0
+ (view.Flags & ViewFlags::Fog) == ViewFlags::None
)
break;
renderModulesIndices.Add(moduleIndex);
diff --git a/Source/Engine/Physics/Joints/DistanceJoint.cpp b/Source/Engine/Physics/Joints/DistanceJoint.cpp
index 96419f86b..c7115199e 100644
--- a/Source/Engine/Physics/Joints/DistanceJoint.cpp
+++ b/Source/Engine/Physics/Joints/DistanceJoint.cpp
@@ -79,13 +79,13 @@ void DistanceJoint::OnDebugDrawSelected()
dir *= 1.0f / len;
Vector3 start = source, end = target;
float max = 0, min = 0;
- if (_flags & DistanceJointFlag::MinDistance)
+ if (EnumHasAnyFlags(_flags, DistanceJointFlag::MinDistance))
{
min = Math::Min(_minDistance, len);
start += dir * min;
DEBUG_DRAW_LINE(source, start, Color::Red * 0.6f, 0, false);
}
- if (_flags & DistanceJointFlag::MaxDistance)
+ if (EnumHasAnyFlags(_flags, DistanceJointFlag::MaxDistance))
{
max = Math::Min(_maxDistance, len - min);
end -= dir * max;
diff --git a/Source/Engine/Physics/Joints/HingeJoint.cpp b/Source/Engine/Physics/Joints/HingeJoint.cpp
index 0d8557f10..7f85941ef 100644
--- a/Source/Engine/Physics/Joints/HingeJoint.cpp
+++ b/Source/Engine/Physics/Joints/HingeJoint.cpp
@@ -65,7 +65,7 @@ void HingeJoint::OnDebugDrawSelected()
const Color color = Color::Green.AlphaMultiplied(0.6f);
DEBUG_DRAW_WIRE_ARROW(source, sourceRotation, size / 100.0f * 0.5f, Color::Red, 0, false);
DEBUG_DRAW_WIRE_ARROW(target, targetRotation, size / 100.0f * 0.5f, Color::Blue, 0, false);
- if (_flags & HingeJointFlag::Limit)
+ if (EnumHasAnyFlags(_flags, HingeJointFlag::Limit))
{
const float upper = Math::Max(_limit.Upper, _limit.Lower);
const float range = Math::Abs(upper - _limit.Lower);
diff --git a/Source/Engine/Physics/Joints/SliderJoint.cpp b/Source/Engine/Physics/Joints/SliderJoint.cpp
index 4f33154ff..f7fc9ae2b 100644
--- a/Source/Engine/Physics/Joints/SliderJoint.cpp
+++ b/Source/Engine/Physics/Joints/SliderJoint.cpp
@@ -49,7 +49,7 @@ void SliderJoint::OnDebugDrawSelected()
const Vector3 source = GetPosition();
const Vector3 normal = GetOrientation() * Vector3::Right;
float min = -100.0f, max = 100.0f;
- if (_flags & SliderJointFlag::Limit)
+ if (EnumHasAnyFlags(_flags, SliderJointFlag::Limit))
{
min = _limit.Lower;
max = _limit.Upper;
diff --git a/Source/Engine/Physics/Joints/SphericalJoint.cpp b/Source/Engine/Physics/Joints/SphericalJoint.cpp
index 63aff4477..c44d4bc6e 100644
--- a/Source/Engine/Physics/Joints/SphericalJoint.cpp
+++ b/Source/Engine/Physics/Joints/SphericalJoint.cpp
@@ -40,7 +40,7 @@ void SphericalJoint::OnDebugDrawSelected()
const float size = 15.0f;
const Color color = Color::Green.AlphaMultiplied(0.6f);
DEBUG_DRAW_WIRE_ARROW(source, GetOrientation(), size / 100.0f * 0.5f, Color::Red, 0, false);
- if (_flags & SphericalJointFlag::Limit)
+ if (EnumHasAnyFlags(_flags, SphericalJointFlag::Limit))
{
DEBUG_DRAW_CONE(source, GetOrientation(), size, _limit.YLimitAngle * DegreesToRadians, _limit.ZLimitAngle * DegreesToRadians, color, 0, false);
}
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 9b0c3a9f9..097ca4853 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -569,16 +569,16 @@ bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& outpu
desc.vertexLimit = CONVEX_VERTEX_MAX;
else
desc.vertexLimit = (PxU16)Math::Clamp(input.ConvexVertexLimit, CONVEX_VERTEX_MIN, CONVEX_VERTEX_MAX);
- if (input.ConvexFlags & ConvexMeshGenerationFlags::SkipValidation)
+ if (EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::SkipValidation))
desc.flags |= PxConvexFlag::Enum::eDISABLE_MESH_VALIDATION;
- if (input.ConvexFlags & ConvexMeshGenerationFlags::UsePlaneShifting)
+ if (EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::UsePlaneShifting))
desc.flags |= PxConvexFlag::Enum::ePLANE_SHIFTING;
- if (input.ConvexFlags & ConvexMeshGenerationFlags::UseFastInteriaComputation)
+ if (EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::UseFastInteriaComputation))
desc.flags |= PxConvexFlag::Enum::eFAST_INERTIA_COMPUTATION;
- if (input.ConvexFlags & ConvexMeshGenerationFlags::ShiftVertices)
+ if (EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::ShiftVertices))
desc.flags |= PxConvexFlag::Enum::eSHIFT_VERTICES;
PxCookingParams cookingParams = cooking->getParams();
- cookingParams.suppressTriangleMeshRemapTable = input.ConvexFlags & ConvexMeshGenerationFlags::SuppressFaceRemapTable;
+ cookingParams.suppressTriangleMeshRemapTable = EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::SuppressFaceRemapTable);
cooking->setParams(cookingParams);
// Perform cooking
@@ -612,7 +612,7 @@ bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& out
desc.triangles.data = input.IndexData;
desc.flags = input.Is16bitIndexData ? PxMeshFlag::e16_BIT_INDICES : (PxMeshFlag::Enum)0;
PxCookingParams cookingParams = cooking->getParams();
- cookingParams.suppressTriangleMeshRemapTable = input.ConvexFlags & ConvexMeshGenerationFlags::SuppressFaceRemapTable;
+ cookingParams.suppressTriangleMeshRemapTable = EnumHasAnyFlags(input.ConvexFlags, ConvexMeshGenerationFlags::SuppressFaceRemapTable);
cooking->setParams(cookingParams);
// Perform cooking
@@ -1628,9 +1628,9 @@ void PhysicsBackend::SetActorFlags(void* actor, ActorFlags value)
#if WITH_PVD
flags |= PxActorFlag::eVISUALIZATION;
#endif
- if (value & ActorFlags::NoGravity)
+ if (EnumHasAnyFlags(value, ActorFlags::NoGravity))
flags |= PxActorFlag::eDISABLE_GRAVITY;
- if (value & ActorFlags::NoSimulation)
+ if (EnumHasAnyFlags(value, ActorFlags::NoSimulation))
flags |= PxActorFlag::eDISABLE_SIMULATION;
actorPhysX->setActorFlags(flags);
}
@@ -1697,9 +1697,9 @@ void PhysicsBackend::SetRigidDynamicActorFlags(void* actor, RigidDynamicFlags va
{
auto actorPhysX = (PxRigidDynamic*)actor;
auto flags = (PxRigidBodyFlags)0;
- if (value & RigidDynamicFlags::Kinematic)
+ if (EnumHasAnyFlags(value, RigidDynamicFlags::Kinematic))
flags |= PxRigidBodyFlag::eKINEMATIC;
- if (value & RigidDynamicFlags::CCD)
+ if (EnumHasAnyFlags(value, RigidDynamicFlags::CCD))
flags |= PxRigidBodyFlag::eENABLE_CCD;
actorPhysX->setRigidBodyFlags(flags);
}
@@ -2089,7 +2089,7 @@ bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Qu
void PhysicsBackend::SetJointFlags(void* joint, JointFlags value)
{
auto jointPhysX = (PxJoint*)joint;
- jointPhysX->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED, value & JointFlags::Collision);
+ jointPhysX->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED, EnumHasAnyFlags(value, JointFlags::Collision));
}
void PhysicsBackend::SetJointActors(void* joint, void* actors0, void* actor1)
@@ -2235,9 +2235,9 @@ void PhysicsBackend::SetHingeJointFlags(void* joint, HingeJointFlag value, bool
{
auto jointPhysX = (PxRevoluteJoint*)joint;
PxRevoluteJointFlags flags = (PxRevoluteJointFlags)0;
- if (value & HingeJointFlag::Limit)
+ if (EnumHasAnyFlags(value, HingeJointFlag::Limit))
flags |= PxRevoluteJointFlag::eLIMIT_ENABLED;
- if (value & HingeJointFlag::Drive)
+ if (EnumHasAnyFlags(value, HingeJointFlag::Drive))
flags |= PxRevoluteJointFlag::eDRIVE_ENABLED;
if (driveFreeSpin)
flags |= PxRevoluteJointFlag::eDRIVE_FREESPIN;
@@ -2279,7 +2279,7 @@ float PhysicsBackend::GetHingeJointVelocity(void* joint)
void PhysicsBackend::SetSliderJointFlags(void* joint, SliderJointFlag value)
{
auto jointPhysX = (PxPrismaticJoint*)joint;
- jointPhysX->setPrismaticJointFlag(PxPrismaticJointFlag::eLIMIT_ENABLED, (value & SliderJointFlag::Limit) != 0);
+ jointPhysX->setPrismaticJointFlag(PxPrismaticJointFlag::eLIMIT_ENABLED, EnumHasAnyFlags(value, SliderJointFlag::Limit));
}
void PhysicsBackend::SetSliderJointLimit(void* joint, const LimitLinearRange& value)
@@ -2308,7 +2308,7 @@ float PhysicsBackend::GetSliderJointVelocity(void* joint)
void PhysicsBackend::SetSphericalJointFlags(void* joint, SphericalJointFlag value)
{
auto jointPhysX = (PxSphericalJoint*)joint;
- jointPhysX->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, (value & SphericalJointFlag::Limit) != 0);
+ jointPhysX->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, EnumHasAnyFlags(value, SphericalJointFlag::Limit));
}
void PhysicsBackend::SetSphericalJointLimit(void* joint, const LimitConeRange& value)
diff --git a/Source/Engine/Render2D/FontAsset.cpp b/Source/Engine/Render2D/FontAsset.cpp
index 062479b97..5fa07771f 100644
--- a/Source/Engine/Render2D/FontAsset.cpp
+++ b/Source/Engine/Render2D/FontAsset.cpp
@@ -116,7 +116,7 @@ Font* FontAsset::CreateFont(int32 size)
FontAsset* FontAsset::GetBold()
{
ScopeLock lock(Locker);
- if (_options.Flags & FontFlags::Bold)
+ if (EnumHasAnyFlags(_options.Flags, FontFlags::Bold))
return this;
if (!_virtualBold)
{
@@ -132,7 +132,7 @@ FontAsset* FontAsset::GetBold()
FontAsset* FontAsset::GetItalic()
{
ScopeLock lock(Locker);
- if (_options.Flags & FontFlags::Italic)
+ if (EnumHasAnyFlags(_options.Flags, FontFlags::Italic))
return this;
if (!_virtualItalic)
{
diff --git a/Source/Engine/Render2D/FontManager.cpp b/Source/Engine/Render2D/FontManager.cpp
index 21443fa9d..578e28409 100644
--- a/Source/Engine/Render2D/FontManager.cpp
+++ b/Source/Engine/Render2D/FontManager.cpp
@@ -125,7 +125,8 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
// Set load flags
uint32 glyphFlags = FT_LOAD_NO_BITMAP;
- if (options.Flags & FontFlags::AntiAliasing)
+ const bool useAA = EnumHasAnyFlags(options.Flags, FontFlags::AntiAliasing);
+ if (useAA)
{
switch (options.Hinting)
{
@@ -164,18 +165,18 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
}
// Handle special effects
- if (options.Flags & FontFlags::Bold)
+ if (EnumHasAnyFlags(options.Flags, FontFlags::Bold))
{
FT_GlyphSlot_Embolden(face->glyph);
}
- if (options.Flags & FontFlags::Italic)
+ if (EnumHasAnyFlags(options.Flags, FontFlags::Italic))
{
FT_GlyphSlot_Oblique(face->glyph);
}
// Render glyph to the bitmap
FT_GlyphSlot glyph = face->glyph;
- FT_Render_Glyph(glyph, options.Flags & FontFlags::AntiAliasing ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
+ FT_Render_Glyph(glyph, useAA ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
FT_Bitmap* bitmap = &glyph->bitmap;
FT_Bitmap tmpBitmap;
diff --git a/Source/Engine/Renderer/AmbientOcclusionPass.cpp b/Source/Engine/Renderer/AmbientOcclusionPass.cpp
index 76fa41ce8..17dac35c2 100644
--- a/Source/Engine/Renderer/AmbientOcclusionPass.cpp
+++ b/Source/Engine/Renderer/AmbientOcclusionPass.cpp
@@ -206,20 +206,12 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext)
if (renderContext.List == nullptr)
return;
auto& aoSettings = renderContext.List->Settings.AmbientOcclusion;
- if (aoSettings.Enabled == false || (renderContext.View.Flags & ViewFlags::AO) == 0)
+ if (aoSettings.Enabled == false ||
+ (renderContext.View.Flags & ViewFlags::AO) == ViewFlags::None ||
+ renderContext.View.IsOrthographicProjection() || // TODO: add support for SSAO in ortho projection
+ Math::Min(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight()) < 16 ||
+ checkIfSkipPass())
return;
-
- // TODO: add support for SSAO in ortho projection
- if (renderContext.View.IsOrthographicProjection())
- return;
-
- // Ensure to have valid data
- if (checkIfSkipPass())
- {
- // Resources are missing. Do not perform rendering.
- return;
- }
-
PROFILE_GPU_CPU("Ambient Occlusion");
settings.Radius = aoSettings.Radius * 0.006f;
diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp
index 89da9ebb4..fbfa4eae6 100644
--- a/Source/Engine/Renderer/ColorGradingPass.cpp
+++ b/Source/Engine/Renderer/ColorGradingPass.cpp
@@ -62,7 +62,7 @@ bool ColorGradingPass::Init()
formatSupportFlags |= FormatSupport::Texture3D;
else
formatSupportFlags |= FormatSupport::Texture2D;
- if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(formatSupport, formatSupportFlags))
+ if (!EnumHasAllFlags(formatSupport, formatSupportFlags))
{
// Fallback to format that is supported on every washing machine
_lutFormat = PixelFormat::R8G8B8A8_UNorm;
diff --git a/Source/Engine/Renderer/DepthOfFieldPass.cpp b/Source/Engine/Renderer/DepthOfFieldPass.cpp
index ae467fafb..e5d772aba 100644
--- a/Source/Engine/Renderer/DepthOfFieldPass.cpp
+++ b/Source/Engine/Renderer/DepthOfFieldPass.cpp
@@ -209,7 +209,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
const auto depthBuffer = renderContext.Buffers->DepthBuffer;
const auto shader = _shader->GetShader();
DepthOfFieldSettings& dofSettings = renderContext.List->Settings.DepthOfField;
- const bool useDoF = _platformSupportsDoF && (renderContext.View.Flags & ViewFlags::DepthOfField) != 0 && dofSettings.Enabled;
+ const bool useDoF = _platformSupportsDoF && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::DepthOfField) && dofSettings.Enabled;
if (!useDoF)
return;
PROFILE_GPU_CPU("Depth Of Field");
diff --git a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp
index a09a8ede3..71ab624cb 100644
--- a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp
+++ b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp
@@ -150,7 +150,7 @@ void MaterialComplexityMaterialShader::Draw(RenderContext& renderContext, GPUCon
// Draw transparency into Light buffer to include it into complexity drawing
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* readOnlyDepthBuffer = depthBuffer->View();
- if (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView))
readOnlyDepthBuffer = depthBuffer->ViewReadOnlyDepth();
context->SetRenderTarget(readOnlyDepthBuffer, lightBuffer);
auto& distortionList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::Distortion];
@@ -196,7 +196,7 @@ void MaterialComplexityMaterialShader::DebugOverrideDrawCallsMaterial(DrawCall&
switch (domain)
{
case MaterialDomain::Surface:
- wrapperIndex = drawCall.Material->GetDrawModes() & DrawPass::Forward ? 1 : 0;
+ wrapperIndex = EnumHasAnyFlags(drawCall.Material->GetDrawModes(), DrawPass::Forward) ? 1 : 0;
break;
case MaterialDomain::Terrain:
wrapperIndex = 2;
diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
index 7acb6ddb4..319bc4924 100644
--- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
+++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
@@ -93,7 +93,7 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context,
}
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* readOnlyDepthBuffer = depthBuffer->View();
- if (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView))
readOnlyDepthBuffer = depthBuffer->ViewReadOnlyDepth();
context->ResetSR();
context->ResetRenderTarget();
diff --git a/Source/Engine/Renderer/EyeAdaptationPass.cpp b/Source/Engine/Renderer/EyeAdaptationPass.cpp
index 1b0829b1c..12b26ea41 100644
--- a/Source/Engine/Renderer/EyeAdaptationPass.cpp
+++ b/Source/Engine/Renderer/EyeAdaptationPass.cpp
@@ -47,7 +47,7 @@ void EyeAdaptationPass::Render(RenderContext& renderContext, GPUTexture* colorBu
renderContext.Buffers->LastEyeAdaptationTime = 0.0f;
// Optionally skip the rendering
- if (checkIfSkipPass() || (view.Flags & ViewFlags::EyeAdaptation) == 0 || settings.Mode == EyeAdaptationMode::None)
+ if (checkIfSkipPass() || (view.Flags & ViewFlags::EyeAdaptation) == ViewFlags::None || settings.Mode == EyeAdaptationMode::None)
{
return;
}
diff --git a/Source/Engine/Renderer/ForwardPass.cpp b/Source/Engine/Renderer/ForwardPass.cpp
index 95b1904e1..0eb637eea 100644
--- a/Source/Engine/Renderer/ForwardPass.cpp
+++ b/Source/Engine/Renderer/ForwardPass.cpp
@@ -85,7 +85,7 @@ void ForwardPass::Render(RenderContext& renderContext, GPUTexture* input, GPUTex
// Try to use read-only depth if supported
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferHandle = depthBuffer->View();
- if (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView)
+ if (EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView))
depthBufferHandle = depthBuffer->ViewReadOnlyDepth();
// Check if there is no objects to render or no resources ready
diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp
index 01a642e37..87ddf1bf2 100644
--- a/Source/Engine/Renderer/GBufferPass.cpp
+++ b/Source/Engine/Renderer/GBufferPass.cpp
@@ -116,7 +116,7 @@ void DebugOverrideDrawCallsMaterial(const RenderContext& renderContext, IMateria
IMaterial::InstancingHandler handler;
const bool canUseInstancing = material->CanUseInstancing(handler);
const auto drawModes = material->GetDrawModes();
- if (drawModes & DrawPass::GBuffer)
+ if (EnumHasAnyFlags(drawModes, DrawPass::GBuffer))
{
auto& drawCallsList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBuffer];
for (int32 i : drawCallsList.Indices)
@@ -129,7 +129,7 @@ void DebugOverrideDrawCallsMaterial(const RenderContext& renderContext, IMateria
}
drawCallsList.CanUseInstancing &= canUseInstancing;
}
- if (drawModes & DrawPass::GBuffer)
+ if (EnumHasAnyFlags(drawModes, DrawPass::GBuffer))
{
auto& drawCallsList = renderContext.List->DrawCallsLists[(int32)DrawCallsListType::GBufferNoDecals];
for (int32 i : drawCallsList.Indices)
@@ -473,18 +473,18 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
int32 count = 2;
targetBuffers[0] = buffers->GBuffer0->View();
targetBuffers[1] = buffers->GBuffer2->View();
- if (info.UsageFlags & MaterialUsageFlags::UseEmissive)
+ if (EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseEmissive))
{
count++;
targetBuffers[2] = lightBuffer;
- if (info.UsageFlags & MaterialUsageFlags::UseNormal)
+ if (EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseNormal))
{
count++;
targetBuffers[3] = buffers->GBuffer1->View();
}
}
- else if (info.UsageFlags & MaterialUsageFlags::UseNormal)
+ else if (EnumHasAnyFlags(info.UsageFlags, MaterialUsageFlags::UseNormal))
{
count++;
targetBuffers[2] = buffers->GBuffer1->View();
diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
index 64f571049..d4ac81f98 100644
--- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
+++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
@@ -820,7 +820,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
{
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
lightData.LastFrameUsed = currentFrame;
- uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
+ uint32 redrawFramesCount = EnumHasAnyFlags(light.StaticFlags, StaticFlags::Lightmap) ? 120 : 4;
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
continue;
lightData.LastFrameUpdated = currentFrame;
@@ -828,7 +828,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
// Mark all objects to shade
allLightingDirty = true;
}
- if (renderContext.View.Flags & ViewFlags::GI && (renderContext.List->DirectionalLights.Count() != 1 || renderContext.List->DirectionalLights[0].StaticFlags & StaticFlags::Lightmap))
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::GI) && (renderContext.List->DirectionalLights.Count() != 1 || EnumHasAnyFlags(renderContext.List->DirectionalLights[0].StaticFlags, StaticFlags::Lightmap)))
{
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
@@ -855,7 +855,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
{
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
lightData.LastFrameUsed = currentFrame;
- uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
+ uint32 redrawFramesCount = EnumHasAnyFlags(light.StaticFlags, StaticFlags::Lightmap) ? 120 : 4;
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
continue;
lightData.LastFrameUpdated = currentFrame;
@@ -877,7 +877,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
{
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
lightData.LastFrameUsed = currentFrame;
- uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
+ uint32 redrawFramesCount = EnumHasAnyFlags(light.StaticFlags, StaticFlags::Lightmap) ? 120 : 4;
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
continue;
lightData.LastFrameUpdated = currentFrame;
@@ -1028,7 +1028,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
}
// Draw draw indirect light from Global Illumination
- if (renderContext.View.Flags & ViewFlags::GI)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::GI))
{
switch (giSettings.Mode)
{
@@ -1081,7 +1081,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output)
{
// Render all dependant effects before
- if (renderContext.View.Flags & ViewFlags::GI)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::GI))
{
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
index 3d378421e..fb3b9ee39 100644
--- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
+++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
@@ -30,7 +30,7 @@
#define GLOBAL_SDF_MIP_FLOODS 5 // Amount of flood fill passes for mip.
#define GLOBAL_SDF_DEBUG_CHUNKS 0
#define GLOBAL_SDF_DEBUG_FORCE_REDRAW 0 // Forces to redraw all SDF cascades every frame
-#define GLOBAL_SDF_ACTOR_IS_STATIC(actor) ((actor->GetStaticFlags() & (StaticFlags::Lightmap | StaticFlags::Transform)) == (int32)(StaticFlags::Lightmap | StaticFlags::Transform))
+#define GLOBAL_SDF_ACTOR_IS_STATIC(actor) EnumHasAllFlags(actor->GetStaticFlags(), StaticFlags::Lightmap | StaticFlags::Transform)
static_assert(GLOBAL_SDF_RASTERIZE_MODEL_MAX_COUNT % 4 == 0, "Must be multiple of 4 due to data packing for GPU constant buffer.");
#if GLOBAL_SDF_DEBUG_CHUNKS
@@ -272,7 +272,7 @@ bool GlobalSignDistanceFieldPass::Init()
// Check platform support
const auto device = GPUDevice::Instance;
_supported = device->GetFeatureLevel() >= FeatureLevel::SM5 && device->Limits.HasCompute && device->Limits.HasTypedUAVLoad
- && FORMAT_FEATURES_ARE_SUPPORTED(device->GetFormatFeatures(GLOBAL_SDF_FORMAT).Support, FormatSupport::ShaderSample | FormatSupport::Texture3D);
+ && EnumHasAllFlags(device->GetFormatFeatures(GLOBAL_SDF_FORMAT).Support, FormatSupport::ShaderSample | FormatSupport::Texture3D);
return false;
}
diff --git a/Source/Engine/Renderer/LightPass.cpp b/Source/Engine/Renderer/LightPass.cpp
index 0a8a145bb..0b98067d7 100644
--- a/Source/Engine/Renderer/LightPass.cpp
+++ b/Source/Engine/Renderer/LightPass.cpp
@@ -50,7 +50,7 @@ bool LightPass::Init()
#endif
auto format = PixelFormat::R8G8_UNorm;
- if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(format).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
+ if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
{
format = PixelFormat::B8G8R8A8_UNorm;
}
@@ -171,8 +171,8 @@ void LightPass::RenderLight(RenderContextBatch& renderContextBatch, GPUTextureVi
auto& view = renderContext.View;
auto mainCache = renderContext.List;
const auto lightShader = _shader->GetShader();
- const bool useShadows = ShadowsPass::Instance()->IsReady() && ((view.Flags & ViewFlags::Shadows) != 0);
- const bool disableSpecular = (view.Flags & ViewFlags::SpecularLight) == 0;
+ const bool useShadows = ShadowsPass::Instance()->IsReady() && EnumHasAnyFlags(view.Flags, ViewFlags::Shadows);
+ const bool disableSpecular = (view.Flags & ViewFlags::SpecularLight) == ViewFlags::None;
// Check if debug lights
if (renderContext.View.Mode == ViewMode::LightBuffer)
@@ -210,7 +210,7 @@ void LightPass::RenderLight(RenderContextBatch& renderContextBatch, GPUTextureVi
// Bind output
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
- const bool depthBufferReadOnly = (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView) != 0;
+ const bool depthBufferReadOnly = EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView);
GPUTextureView* depthBufferRTV = depthBufferReadOnly ? depthBuffer->ViewReadOnlyDepth() : nullptr;
GPUTextureView* depthBufferSRV = depthBufferReadOnly ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetRenderTarget(depthBufferRTV, lightBuffer);
diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp
index aed53ce15..e5f622fc5 100644
--- a/Source/Engine/Renderer/MotionBlurPass.cpp
+++ b/Source/Engine/Renderer/MotionBlurPass.cpp
@@ -62,11 +62,11 @@ bool MotionBlurPass::Init()
// Prepare formats for the buffers
auto format = PixelFormat::R16G16_Float;
- if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(format).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
+ if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
{
- if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
+ if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
format = PixelFormat::R32G32_Float;
- else if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
+ else if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
format = PixelFormat::R16G16B16A16_Float;
else
format = PixelFormat::R32G32B32A32_Float;
@@ -269,7 +269,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& frame, GP
const int32 screenHeight = frame->Height();
const int32 motionVectorsWidth = screenWidth / static_cast(settings.MotionVectorsResolution);
const int32 motionVectorsHeight = screenHeight / static_cast(settings.MotionVectorsResolution);
- if ((renderContext.View.Flags & ViewFlags::MotionBlur) == 0 ||
+ if ((renderContext.View.Flags & ViewFlags::MotionBlur) == ViewFlags::None ||
!_hasValidResources ||
isCameraCut ||
screenWidth < 16 ||
diff --git a/Source/Engine/Renderer/PostProcessingPass.cpp b/Source/Engine/Renderer/PostProcessingPass.cpp
index 905abb039..058ceabab 100644
--- a/Source/Engine/Renderer/PostProcessingPass.cpp
+++ b/Source/Engine/Renderer/PostProcessingPass.cpp
@@ -200,10 +200,10 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
// Cache data
PostProcessSettings& settings = renderContext.List->Settings;
- bool useBloom = (view.Flags & ViewFlags::Bloom) != 0 && settings.Bloom.Enabled && settings.Bloom.Intensity > 0.0f;
- bool useToneMapping = (view.Flags & ViewFlags::ToneMapping) != 0;
- bool useCameraArtifacts = (view.Flags & ViewFlags::CameraArtifacts) != 0;
- bool useLensFlares = (view.Flags & ViewFlags::LensFlares) != 0 && settings.LensFlares.Intensity > 0.0f && useBloom;
+ bool useBloom = EnumHasAnyFlags(view.Flags, ViewFlags::Bloom) && settings.Bloom.Enabled && settings.Bloom.Intensity > 0.0f;
+ bool useToneMapping = EnumHasAnyFlags(view.Flags, ViewFlags::ToneMapping);
+ bool useCameraArtifacts = EnumHasAnyFlags(view.Flags, ViewFlags::CameraArtifacts);
+ bool useLensFlares = EnumHasAnyFlags(view.Flags, ViewFlags::LensFlares) && settings.LensFlares.Intensity > 0.0f && useBloom;
// Ensure to have valid data and if at least one effect should be applied
if (!(useBloom || useToneMapping || useCameraArtifacts))
diff --git a/Source/Engine/Renderer/ReflectionsPass.cpp b/Source/Engine/Renderer/ReflectionsPass.cpp
index f00247446..d419742b4 100644
--- a/Source/Engine/Renderer/ReflectionsPass.cpp
+++ b/Source/Engine/Renderer/ReflectionsPass.cpp
@@ -370,9 +370,9 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
// Cache data
auto& view = renderContext.View;
- bool useReflections = ((view.Flags & ViewFlags::Reflections) != 0);
- bool useSSR = ((view.Flags & ViewFlags::SSR) != 0) && (renderContext.List->Settings.ScreenSpaceReflections.Intensity > ZeroTolerance);
- int32 probesCount = (int32)renderContext.List->EnvironmentProbes.Count();
+ bool useReflections = EnumHasAnyFlags(view.Flags, ViewFlags::Reflections);
+ bool useSSR = EnumHasAnyFlags(view.Flags, ViewFlags::SSR) && renderContext.List->Settings.ScreenSpaceReflections.Intensity > ZeroTolerance;
+ int32 probesCount = renderContext.List->EnvironmentProbes.Count();
bool renderProbes = probesCount > 0;
auto shader = _shader->GetShader();
auto cb = shader->GetCB(0);
@@ -404,7 +404,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
context->SetRenderTarget(*reflectionsBuffer);
// Sort probes by the radius
- Sorting::QuickSort(renderContext.List->EnvironmentProbes.Get(), (int32)renderContext.List->EnvironmentProbes.Count(), &sortProbes);
+ Sorting::QuickSort(renderContext.List->EnvironmentProbes.Get(), renderContext.List->EnvironmentProbes.Count(), &sortProbes);
// TODO: don't render too far probes, check area of the screen and apply culling!
diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp
index 9e9bcb9ff..2f8fba76f 100644
--- a/Source/Engine/Renderer/RenderList.cpp
+++ b/Source/Engine/Renderer/RenderList.cpp
@@ -218,7 +218,7 @@ void RenderList::RunPostFxPass(GPUContext* context, RenderContext& renderContext
needTempTarget = true;
}
}
- if (renderContext.View.Flags & ViewFlags::CustomPostProcess)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::CustomPostProcess))
{
for (const PostProcessEffect* fx : renderContext.List->PostFx)
{
@@ -259,7 +259,7 @@ void RenderList::RunPostFxPass(GPUContext* context, RenderContext& renderContext
Swap(output, input);
}
}
- if (renderContext.View.Flags & ViewFlags::CustomPostProcess)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::CustomPostProcess))
{
for (PostProcessEffect* fx : renderContext.List->PostFx)
{
@@ -328,7 +328,7 @@ void RenderList::RunCustomPostFxPass(GPUContext* context, RenderContext& renderC
bool RenderList::HasAnyPostFx(const RenderContext& renderContext, PostProcessEffectLocation postProcess) const
{
- if (renderContext.View.Flags & ViewFlags::CustomPostProcess)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::CustomPostProcess))
{
for (const PostProcessEffect* fx : renderContext.List->PostFx)
{
@@ -443,26 +443,26 @@ void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawMo
const int32 index = DrawCalls.Add(drawCall);
// Add draw call to proper draw lists
- if (drawModes & DrawPass::Depth)
+ if ((drawModes & DrawPass::Depth) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Depth].Indices.Add(index);
}
- if (drawModes & (DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas))
+ if ((drawModes & (DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas)) != DrawPass::None)
{
if (receivesDecals)
DrawCallsLists[(int32)DrawCallsListType::GBuffer].Indices.Add(index);
else
DrawCallsLists[(int32)DrawCallsListType::GBufferNoDecals].Indices.Add(index);
}
- if (drawModes & DrawPass::Forward)
+ if ((drawModes & DrawPass::Forward) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Forward].Indices.Add(index);
}
- if (drawModes & DrawPass::Distortion)
+ if ((drawModes & DrawPass::Distortion) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Distortion].Indices.Add(index);
}
- if (drawModes & DrawPass::MotionVectors && (staticFlags & StaticFlags::Transform) == 0)
+ if ((drawModes & DrawPass::MotionVectors) != DrawPass::None && (staticFlags & StaticFlags::Transform) == StaticFlags::None)
{
DrawCallsLists[(int32)DrawCallsListType::MotionVectors].Indices.Add(index);
}
@@ -482,30 +482,30 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
const int32 index = DrawCalls.Add(drawCall);
// Add draw call to proper draw lists
- DrawPass modes = (DrawPass)(drawModes & mainRenderContext.View.GetShadowsDrawPassMask(shadowsMode));
- drawModes = (DrawPass)(modes & mainRenderContext.View.Pass);
+ DrawPass modes = drawModes & mainRenderContext.View.GetShadowsDrawPassMask(shadowsMode);
+ drawModes = modes & mainRenderContext.View.Pass;
if (drawModes != DrawPass::None && mainRenderContext.View.CullingFrustum.Intersects(bounds))
{
- if (drawModes & DrawPass::Depth)
+ if ((drawModes & DrawPass::Depth) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Depth].Indices.Add(index);
}
- if (drawModes & (DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas))
+ if ((drawModes & (DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas)) != DrawPass::None)
{
if (receivesDecals)
DrawCallsLists[(int32)DrawCallsListType::GBuffer].Indices.Add(index);
else
DrawCallsLists[(int32)DrawCallsListType::GBufferNoDecals].Indices.Add(index);
}
- if (drawModes & DrawPass::Forward)
+ if ((drawModes & DrawPass::Forward) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Forward].Indices.Add(index);
}
- if (drawModes & DrawPass::Distortion)
+ if ((drawModes & DrawPass::Distortion) != DrawPass::None)
{
DrawCallsLists[(int32)DrawCallsListType::Distortion].Indices.Add(index);
}
- if (drawModes & DrawPass::MotionVectors && (staticFlags & StaticFlags::Transform) == 0)
+ if ((drawModes & DrawPass::MotionVectors) != DrawPass::None && (staticFlags & StaticFlags::Transform) == StaticFlags::None)
{
DrawCallsLists[(int32)DrawCallsListType::MotionVectors].Indices.Add(index);
}
diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp
index af8d1adcb..295a2ea77 100644
--- a/Source/Engine/Renderer/Renderer.cpp
+++ b/Source/Engine/Renderer/Renderer.cpp
@@ -297,7 +297,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
// Perform postFx volumes blending and query before rendering
task->CollectPostFxVolumes(renderContext);
renderContext.List->BlendSettings();
- auto aaMode = (renderContext.View.Flags & ViewFlags::AntiAliasing) != 0 ? renderContext.List->Settings.AntiAliasing.Mode : AntialiasingMode::None;
+ auto aaMode = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::AntiAliasing) ? renderContext.List->Settings.AntiAliasing.Mode : AntialiasingMode::None;
if (aaMode == AntialiasingMode::TemporalAntialiasing && view.IsOrthographicProjection())
aaMode = AntialiasingMode::None; // TODO: support TAA in ortho projection (see RenderView::Prepare to jitter projection matrix better)
renderContext.List->Settings.AntiAliasing.Mode = aaMode;
@@ -317,10 +317,11 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
{
const MotionBlurSettings& motionBlurSettings = renderContext.List->Settings.MotionBlur;
const ScreenSpaceReflectionsSettings ssrSettings = renderContext.List->Settings.ScreenSpaceReflections;
- setup.UseMotionVectors = ((renderContext.View.Flags & ViewFlags::MotionBlur) != 0 && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) ||
- renderContext.View.Mode == ViewMode::MotionVectors ||
- (ssrSettings.TemporalEffect && renderContext.View.Flags & ViewFlags::SSR) ||
- renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing;
+ setup.UseMotionVectors =
+ (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::MotionBlur) && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) ||
+ renderContext.View.Mode == ViewMode::MotionVectors ||
+ (ssrSettings.TemporalEffect && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SSR)) ||
+ renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing;
}
setup.UseTemporalAAJitter = aaMode == AntialiasingMode::TemporalAntialiasing;
@@ -344,7 +345,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
view.Pass |= DrawPass::MotionVectors;
renderContextBatch.GetMainContext() = renderContext; // Sync render context in batch with the current value
- bool drawShadows = !isGBufferDebug && ((view.Flags & ViewFlags::Shadows) != 0) && ShadowsPass::Instance()->IsReady();
+ bool drawShadows = !isGBufferDebug && EnumHasAnyFlags(view.Flags, ViewFlags::Shadows) && ShadowsPass::Instance()->IsReady();
switch (renderContext.View.Mode)
{
case ViewMode::QuadOverdraw:
@@ -415,7 +416,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
#endif
// Global SDF rendering (can be used by materials later on)
- if (graphicsSettings->EnableGlobalSDF && view.Flags & ViewFlags::GlobalSDF)
+ if (graphicsSettings->EnableGlobalSDF && EnumHasAnyFlags(view.Flags, ViewFlags::GlobalSDF))
{
GlobalSignDistanceFieldPass::BindingData bindingData;
GlobalSignDistanceFieldPass::Instance()->Render(renderContext, context, bindingData);
@@ -470,7 +471,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
// Render lighting
renderContextBatch.GetMainContext() = renderContext; // Sync render context in batch with the current value
LightPass::Instance()->RenderLight(renderContextBatch, *lightBuffer);
- if (renderContext.View.Flags & ViewFlags::GI)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::GI))
{
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
index 69b0f3289..80bacf650 100644
--- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
+++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
@@ -275,7 +275,7 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
GlobalSignDistanceFieldPass::BindingData bindingDataSDF;
GlobalSurfaceAtlasPass::BindingData bindingDataSurfaceAtlas;
if (settings.TraceMode == ReflectionsTraceMode::SoftwareTracing &&
- view.Flags & ViewFlags::GI &&
+ EnumHasAnyFlags(view.Flags, ViewFlags::GI) &&
renderContext.List->Settings.GlobalIllumination.Mode == GlobalIlluminationMode::DDGI)
{
if (!GlobalSignDistanceFieldPass::Instance()->Render(renderContext, context, bindingDataSDF) &&
diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp
index 7eeacadf1..b22effdc9 100644
--- a/Source/Engine/Renderer/ShadowsPass.cpp
+++ b/Source/Engine/Renderer/ShadowsPass.cpp
@@ -84,8 +84,8 @@ bool ShadowsPass::Init()
const auto formatTexture = PixelFormatExtensions::FindShaderResourceFormat(SHADOW_MAPS_FORMAT, false);
const auto formatFeaturesDepth = GPUDevice::Instance->GetFormatFeatures(SHADOW_MAPS_FORMAT);
const auto formatFeaturesTexture = GPUDevice::Instance->GetFormatFeatures(formatTexture);
- _supportsShadows = FORMAT_FEATURES_ARE_SUPPORTED(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D)
- && FORMAT_FEATURES_ARE_SUPPORTED(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison);
+ _supportsShadows = EnumHasAllFlags(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D)
+ && EnumHasAllFlags(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison);
if (!_supportsShadows)
{
LOG(Warning, "GPU doesn't support shadows rendering");
@@ -640,7 +640,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererP
context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
- GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
+ GPUTextureView* depthBufferSRV = EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
@@ -655,7 +655,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererP
sperLight.LightShadow = shadowData.Constants;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
- sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;
+ sperLight.ContactShadowsLength = EnumHasAnyFlags(view.Flags, ViewFlags::ContactShadows) ? light.ContactShadowsLength : 0.0f;
// Calculate world view projection matrix for the light sphere
Matrix world, wvp, matrix;
@@ -718,7 +718,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererS
context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
- GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
+ GPUTextureView* depthBufferSRV = EnumHasAllFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
@@ -733,7 +733,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererS
sperLight.LightShadow = shadowData.Constants;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
- sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;
+ sperLight.ContactShadowsLength = EnumHasAnyFlags(view.Flags, ViewFlags::ContactShadows) ? light.ContactShadowsLength : 0.0f;
// Calculate world view projection matrix for the light sphere
Matrix world, wvp, matrix;
@@ -787,7 +787,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererD
context->ResetSR();
context->ResetRenderTarget();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
- GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
+ GPUTextureView* depthBufferSRV = EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(renderContext.Task->GetViewport());
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
@@ -803,7 +803,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererD
sperLight.LightShadow = shadowData.Constants;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
- sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;
+ sperLight.ContactShadowsLength = EnumHasAnyFlags(view.Flags, ViewFlags::ContactShadows) ? light.ContactShadowsLength : 0.0f;
// Render shadow in screen space
auto shader = _shader->GetShader();
diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp
index 42ddd36d9..6d0adef01 100644
--- a/Source/Engine/Renderer/VolumetricFogPass.cpp
+++ b/Source/Engine/Renderer/VolumetricFogPass.cpp
@@ -120,7 +120,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
}
// Check if skip rendering
- if (fog == nullptr || (view.Flags & ViewFlags::Fog) == 0 || !_isSupported || checkIfSkipPass())
+ if (fog == nullptr || (view.Flags & ViewFlags::Fog) == ViewFlags::None || !_isSupported || checkIfSkipPass())
{
RenderTargetPool::Release(renderContext.Buffers->VolumetricFog);
renderContext.Buffers->VolumetricFog = nullptr;
@@ -459,7 +459,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
// Init GI data
bool useDDGI = false;
DynamicDiffuseGlobalIlluminationPass::BindingData bindingDataDDGI;
- if (renderContext.View.Flags & ViewFlags::GI)
+ if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::GI))
{
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
diff --git a/Source/Engine/Scripting/Attributes/Editor/AssetReferenceAttribute.cs b/Source/Engine/Scripting/Attributes/Editor/AssetReferenceAttribute.cs
index 15c037f82..62040d224 100644
--- a/Source/Engine/Scripting/Attributes/Editor/AssetReferenceAttribute.cs
+++ b/Source/Engine/Scripting/Attributes/Editor/AssetReferenceAttribute.cs
@@ -12,7 +12,7 @@ namespace FlaxEngine
public class AssetReferenceAttribute : Attribute
{
///
- /// The full name of the asset type to link. Use null or empty to skip it.
+ /// The full name of the asset type to link. Use null or empty to skip it. Can be used as file extension filter if starts with a dot and used over string property.
///
public string TypeName;
@@ -45,7 +45,7 @@ namespace FlaxEngine
///
/// Initializes a new instance of the class.
///
- /// The full name of the asset type to link. Use null or empty to skip it.
+ /// The full name of the asset type to link. Use null or empty to skip it. Can be used as file extension filter if starts with a dot and used over string property.
/// True if use asset picker with a smaller height (single line), otherwise will use with full icon.
public AssetReferenceAttribute(string typeName = null, bool useSmallPicker = false)
{
diff --git a/Source/Engine/Scripting/Script.cpp b/Source/Engine/Scripting/Script.cpp
index 1ffb38210..16931b14d 100644
--- a/Source/Engine/Scripting/Script.cpp
+++ b/Source/Engine/Scripting/Script.cpp
@@ -265,7 +265,7 @@ void Script::Initialize()
{
ASSERT(!IsDuringPlay());
- if (Flags & ObjectFlags::IsManagedType || Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType | ObjectFlags::IsCustomScriptingType))
SetupType();
// Use lazy creation for the managed instance, just register the object
diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp
index e7267dae1..3cef7e420 100644
--- a/Source/Engine/Scripting/ScriptingObject.cpp
+++ b/Source/Engine/Scripting/ScriptingObject.cpp
@@ -45,7 +45,7 @@ ScriptingObject::~ScriptingObject()
ASSERT(_gcHandle == 0);
// Handle custom scripting objects removing
- if (Flags & ObjectFlags::IsCustomScriptingType)
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
{
_type.Module->OnObjectDeleted(this);
}
diff --git a/Source/Engine/Scripting/ScriptingObject.h b/Source/Engine/Scripting/ScriptingObject.h
index d972cc75c..efaa5eb90 100644
--- a/Source/Engine/Scripting/ScriptingObject.h
+++ b/Source/Engine/Scripting/ScriptingObject.h
@@ -206,7 +206,7 @@ public:
///
FORCE_INLINE bool IsRegistered() const
{
- return (Flags & ObjectFlags::IsRegistered) != 0;
+ return (Flags & ObjectFlags::IsRegistered) != ObjectFlags::None;
}
///
diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
index fdba37efd..9cef81b20 100644
--- a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
+++ b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h
@@ -433,7 +433,7 @@ namespace ShaderProcessing
}
// Check if use this shader program
- if ((current.Flags & ShaderFlags::Hidden) == false && current.MinFeatureLevel <= parser->GetFeatureLevel())
+ if ((current.Flags & ShaderFlags::Hidden) == (ShaderFlags)0 && current.MinFeatureLevel <= parser->GetFeatureLevel())
{
// Cache read function
ShaderMetaReaderType::_cache.Add(current);
diff --git a/Source/Engine/ShadersCompilation/ShaderCompiler.cpp b/Source/Engine/ShadersCompilation/ShaderCompiler.cpp
index 1b868dc44..291910b11 100644
--- a/Source/Engine/ShadersCompilation/ShaderCompiler.cpp
+++ b/Source/Engine/ShadersCompilation/ShaderCompiler.cpp
@@ -259,7 +259,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->VS.Count(); i++)
{
auto& shader = meta->VS[i];
- ASSERT(shader.GetStage() == ShaderStage::Vertex && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Vertex && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader, &WriteCustomDataVS))
{
@@ -272,7 +272,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->HS.Count(); i++)
{
auto& shader = meta->HS[i];
- ASSERT(shader.GetStage() == ShaderStage::Hull && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Hull && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader, &WriteCustomDataHS))
{
@@ -285,7 +285,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->DS.Count(); i++)
{
auto& shader = meta->DS[i];
- ASSERT(shader.GetStage() == ShaderStage::Domain && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Domain && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader))
{
@@ -298,7 +298,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->GS.Count(); i++)
{
auto& shader = meta->GS[i];
- ASSERT(shader.GetStage() == ShaderStage::Geometry && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Geometry && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader))
{
@@ -311,7 +311,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->PS.Count(); i++)
{
auto& shader = meta->PS[i];
- ASSERT(shader.GetStage() == ShaderStage::Pixel && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Pixel && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader))
{
@@ -324,7 +324,7 @@ bool ShaderCompiler::CompileShaders()
for (int32 i = 0; i < meta->CS.Count(); i++)
{
auto& shader = meta->CS[i];
- ASSERT(shader.GetStage() == ShaderStage::Compute && (shader.Flags & ShaderFlags::Hidden) == 0);
+ ASSERT(shader.GetStage() == ShaderStage::Compute && (shader.Flags & ShaderFlags::Hidden) == (ShaderFlags)0);
PROFILE_COMPILE_SHADER(shader);
if (CompileShader(shader))
{
diff --git a/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp b/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
index 5c7e89c81..ed6ecbf9c 100644
--- a/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
+++ b/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
@@ -24,7 +24,7 @@ bool canUseMaterialWithLightmap(MaterialBase* material, ShadowsOfMordor::Builder
bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildCache* scene)
{
ShadowsOfMordor::Builder::GeometryEntry entry;
- const bool useLightmap = actor->GetIsActive() && (actor->GetStaticFlags() & StaticFlags::Lightmap);
+ const bool useLightmap = actor->GetIsActive() && actor->HasStaticFlag(StaticFlags::Lightmap);
auto& results = scene->Entries;
// Switch actor type
diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp
index b16a440bf..f347e3732 100644
--- a/Source/Engine/Terrain/Terrain.cpp
+++ b/Source/Engine/Terrain/Terrain.cpp
@@ -505,13 +505,13 @@ void Terrain::RemovePatch(const Int2& patchCoord)
void Terrain::Draw(RenderContext& renderContext)
{
- DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass);
+ const DrawPass drawModes = DrawModes & renderContext.View.Pass;
if (drawModes == DrawPass::None)
return;
PROFILE_CPU();
if (renderContext.View.Pass == DrawPass::GlobalSDF)
{
- if ((DrawModes & DrawPass::GlobalSDF) == 0)
+ if ((DrawModes & DrawPass::GlobalSDF) == DrawPass::None)
return;
const float chunkSize = TERRAIN_UNITS_PER_VERTEX * (float)_chunkSize;
const float posToUV = 0.25f / chunkSize;
@@ -531,7 +531,7 @@ void Terrain::Draw(RenderContext& renderContext)
}
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
{
- if ((DrawModes & DrawPass::GlobalSurfaceAtlas) == 0)
+ if ((DrawModes & DrawPass::GlobalSurfaceAtlas) == DrawPass::None)
return;
for (TerrainPatch* patch : _patches)
{
diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp
index 626da9d73..be145ae43 100644
--- a/Source/Engine/Terrain/TerrainChunk.cpp
+++ b/Source/Engine/Terrain/TerrainChunk.cpp
@@ -101,7 +101,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
drawCall.Terrain.NeighborLOD.W = (float)Math::Clamp(_neighbors[3]->_cachedDrawLOD, lod, minLod);
const auto scene = _patch->_terrain->GetScene();
const auto flags = _patch->_terrain->_staticFlags;
- if (flags & StaticFlags::Lightmap && scene)
+ if ((flags & StaticFlags::Lightmap) != StaticFlags::None && scene)
{
drawCall.Terrain.Lightmap = scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex);
drawCall.Terrain.LightmapUVsArea = Lightmap.UVsArea;
@@ -121,7 +121,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
//drawCall.TerrainData.HeightmapUVScaleBias.W += halfTexelOffset;
// Submit draw call
- auto drawModes = (DrawPass)(_patch->_terrain->DrawModes & renderContext.View.Pass & (uint32)drawCall.Material->GetDrawModes());
+ const DrawPass drawModes = _patch->_terrain->DrawModes & renderContext.View.Pass & drawCall.Material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, true);
}
@@ -157,7 +157,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
drawCall.Terrain.NeighborLOD.W = (float)lod;
const auto scene = _patch->_terrain->GetScene();
const auto flags = _patch->_terrain->_staticFlags;
- if (flags & StaticFlags::Lightmap && scene)
+ if ((flags & StaticFlags::Lightmap) != StaticFlags::None && scene)
{
drawCall.Terrain.Lightmap = scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex);
drawCall.Terrain.LightmapUVsArea = Lightmap.UVsArea;
@@ -177,7 +177,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
//drawCall.TerrainData.HeightmapUVScaleBias.W += halfTexelOffset;
// Submit draw call
- auto drawModes = (DrawPass)(_patch->_terrain->DrawModes & renderContext.View.Pass & (uint32)drawCall.Material->GetDrawModes());
+ const DrawPass drawModes = _patch->_terrain->DrawModes & renderContext.View.Pass & drawCall.Material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, true);
}
diff --git a/Source/Engine/Tests/TestPropertyNameUI.cs b/Source/Engine/Tests/TestPropertyNameUI.cs
index ef7ecaa41..e51905ff2 100644
--- a/Source/Engine/Tests/TestPropertyNameUI.cs
+++ b/Source/Engine/Tests/TestPropertyNameUI.cs
@@ -11,10 +11,10 @@ namespace FlaxEditor.Tests
[Test]
public void TestFormatting()
{
- Assert.AreEqual("property", Utils.GetPropertyNameUI("property"));
- Assert.AreEqual("property", Utils.GetPropertyNameUI("_property"));
- Assert.AreEqual("property", Utils.GetPropertyNameUI("m_property"));
- Assert.AreEqual("property", Utils.GetPropertyNameUI("g_property"));
+ Assert.AreEqual("Property", Utils.GetPropertyNameUI("property"));
+ Assert.AreEqual("Property", Utils.GetPropertyNameUI("_property"));
+ Assert.AreEqual("Property", Utils.GetPropertyNameUI("m_property"));
+ Assert.AreEqual("Property", Utils.GetPropertyNameUI("g_property"));
Assert.AreEqual("Property", Utils.GetPropertyNameUI("Property"));
Assert.AreEqual("Property 1", Utils.GetPropertyNameUI("Property1"));
Assert.AreEqual("Property Name", Utils.GetPropertyNameUI("PropertyName"));
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
index 98a9e7c87..103101bec 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
@@ -459,6 +459,8 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
}
// Sample Texture
case 9:
+ // Procedural Texture Sample
+ case 17:
{
enum CommonSamplerType
{
@@ -479,7 +481,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
// Get input boxes
auto textureBox = node->GetBox(0);
auto uvsBox = node->GetBox(1);
- auto levelBox = node->GetBox(2);
+ auto levelBox = node->TryGetBox(2);
auto offsetBox = node->GetBox(3);
if (!textureBox->HasConnection())
{
@@ -519,7 +521,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
// Get other inputs
const auto level = tryGetValue(levelBox, node->Values[1]);
- const bool useLevel = levelBox->HasConnection() || (int32)node->Values[1] != -1;
+ const bool useLevel = (levelBox && levelBox->HasConnection()) || (int32)node->Values[1] != -1;
const bool useOffset = offsetBox->HasConnection();
const auto offset = useOffset ? eatBox(offsetBox->GetParent(), offsetBox->FirstConnection()) : Value::Zero;
const Char* samplerName;
@@ -539,32 +541,78 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
return;
}
- // Pick a property format string
- const Char* format;
- if (useLevel || !canUseSample)
+ // Create texture sampling code
+ if (node->TypeID == 9)
{
- if (useOffset)
- format = TEXT("{0}.SampleLevel({1}, {2}, {3}, {4})");
+ // Sample Texture
+ const Char* format;
+ if (useLevel || !canUseSample)
+ {
+ if (useOffset)
+ format = TEXT("{0}.SampleLevel({1}, {2}, {3}, {4})");
+ else
+ format = TEXT("{0}.SampleLevel({1}, {2}, {3})");
+ }
else
- format = TEXT("{0}.SampleLevel({1}, {2}, {3})");
+ {
+ if (useOffset)
+ format = TEXT("{0}.Sample({1}, {2}, {4})");
+ else
+ format = TEXT("{0}.Sample({1}, {2})");
+ }
+ const String sampledValue = String::Format(format, texture.Value, samplerName, uvs.Value, level.Value, offset.Value);
+ textureBox->Cache = writeLocal(VariantType::Float4, sampledValue, node);
}
else
{
- if (useOffset)
- format = TEXT("{0}.Sample({1}, {2}, {4})");
- else
- format = TEXT("{0}.Sample({1}, {2})");
- }
+ // Procedural Texture Sample
+ textureBox->Cache = writeLocal(Value::InitForZero(ValueType::Float4), node);
+ createGradients(node);
+ auto proceduralSample = String::Format(TEXT(
+ " {{\n"
+ " float3 weights;\n"
+ " float2 vertex1, vertex2, vertex3;\n"
+ " float2 uv = {0} * 3.464; // 2 * sqrt (3);\n"
+ " float2 uv1, uv2, uv3;\n"
+ " const float2x2 gridToSkewedGrid = float2x2(1.0, 0.0, -0.57735027, 1.15470054);\n"
+ " float2 skewedCoord = mul(gridToSkewedGrid, uv);\n"
+ " int2 baseId = int2(floor(skewedCoord));\n"
+ " float3 temp = float3(frac(skewedCoord), 0);\n"
+ " temp.z = 1.0 - temp.x - temp.y;\n"
+ " if (temp.z > 0.0)\n"
+ " {{\n"
+ " weights = float3(temp.z, temp.y, temp.x);\n"
+ " vertex1 = baseId;\n"
+ " vertex2 = baseId + int2(0, 1);\n"
+ " vertex3 = baseId + int2(1, 0);\n"
+ " }}\n"
+ " else\n"
+ " {{\n"
+ " weights = float3(-temp.z, 1.0 - temp.y, 1.0 - temp.x);\n"
+ " vertex1 = baseId + int2(1, 1);\n"
+ " vertex2 = baseId + int2(1, 0);\n"
+ " vertex3 = baseId + int2(0, 1);\n"
+ " }}\n"
+ " uv1 = {0} + frac(sin(mul(float2x2(127.1, 311.7, 269.5, 183.3), vertex1)) * 43758.5453);\n"
+ " uv2 = {0} + frac(sin(mul(float2x2(127.1, 311.7, 269.5, 183.3), vertex2)) * 43758.5453);\n"
+ " uv3 = {0} + frac(sin(mul(float2x2(127.1, 311.7, 269.5, 183.3), vertex3)) * 43758.5453);\n"
+ " float4 tex1 = {1}.SampleGrad({4}, uv1, {2}, {3}, {6}) * weights.x;\n"
+ " float4 tex2 = {1}.SampleGrad({4}, uv2, {2}, {3}, {6}) * weights.y;\n"
+ " float4 tex3 = {1}.SampleGrad({4}, uv3, {2}, {3}, {6}) * weights.z;\n"
+ " {5} = tex1 + tex2 + tex3;\n"
+ " }}\n"
+ ),
+ uvs.Value, // {0}
+ texture.Value, // {1}
+ _ddx.Value, // {2}
+ _ddy.Value, // {3}
+ samplerName, // {4}
+ textureBox->Cache.Value, // {5}
+ offset.Value // {6}
+ );
- // Sample texture
- const String sampledValue = String::Format(format,
- texture.Value, // {0}
- samplerName, // {1}
- uvs.Value, // {2}
- level.Value, // {3}
- offset.Value // {4}
- );
- textureBox->Cache = writeLocal(VariantType::Float4, sampledValue, node);
+ _writer.Write(*proceduralSample);
+ }
// Decode normal map vector
if (isNormalMap)
@@ -627,7 +675,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
auto textureBox = node->GetBox(0);
auto scaleBox = node->GetBox(1);
auto blendBox = node->GetBox(2);
-
+
if (!textureBox->HasConnection())
{
// No texture to sample
@@ -660,10 +708,10 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
" {3} += {0}.Sample(SamplerLinearWrap, worldPos.xy) * normal.z;\n"
" }}\n"
),
- texture.Value, // {0}
- scale.Value, // {1}
- blend.Value, // {2}
- result.Value // {3}
+ texture.Value, // {0}
+ scale.Value, // {1}
+ blend.Value, // {2}
+ result.Value // {3}
);
_writer.Write(*triplanarTexture);
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
index 6de5c6cf9..b1aab0049 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp
@@ -195,9 +195,9 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
ADD_FEATURE(LightmapFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(DeferredShadingFeature);
- if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
+ if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None)
ADD_FEATURE(DistortionFeature);
- if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination) != 0)
+ if (materialInfo.BlendMode != MaterialBlendMode::Opaque && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::GlobalIllumination))
ADD_FEATURE(GlobalIlluminationFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
ADD_FEATURE(ForwardShadingFeature);
@@ -209,9 +209,9 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
ADD_FEATURE(DeferredShadingFeature);
break;
case MaterialDomain::Particle:
- if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
+ if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None)
ADD_FEATURE(DistortionFeature);
- if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination) != 0)
+ if (materialInfo.BlendMode != MaterialBlendMode::Opaque && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::GlobalIllumination))
ADD_FEATURE(GlobalIlluminationFeature);
ADD_FEATURE(ForwardShadingFeature);
break;
@@ -330,15 +330,15 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
// Normalize and transform to world space if need to
_writer.Write(TEXT("\t{0}.TangentNormal = normalize({0}.TangentNormal);\n"), materialVarPS.Value);
- if ((baseLayer->FeaturesFlags & MaterialFeaturesFlags::InputWorldSpaceNormal) == 0)
- {
- _writer.Write(TEXT("\t{0}.WorldNormal = normalize(TransformTangentVectorToWorld(input, {0}.TangentNormal));\n"), materialVarPS.Value);
- }
- else
+ if (EnumHasAllFlags(baseLayer->FeaturesFlags, MaterialFeaturesFlags::InputWorldSpaceNormal))
{
_writer.Write(TEXT("\t{0}.WorldNormal = {0}.TangentNormal;\n"), materialVarPS.Value);
_writer.Write(TEXT("\t{0}.TangentNormal = normalize(TransformWorldVectorToTangent(input, {0}.WorldNormal));\n"), materialVarPS.Value);
}
+ else
+ {
+ _writer.Write(TEXT("\t{0}.WorldNormal = normalize(TransformTangentVectorToWorld(input, {0}.TangentNormal));\n"), materialVarPS.Value);
+ }
// Clamp values
_writer.Write(TEXT("\t{0}.Metalness = saturate({0}.Metalness);\n"), materialVarPS.Value);
@@ -421,7 +421,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
_writer.Write(TEXT("#define MATERIAL_MASK_THRESHOLD ({0})\n"), baseLayer->MaskThreshold);
_writer.Write(TEXT("#define CUSTOM_VERTEX_INTERPOLATORS_COUNT ({0})\n"), _vsToPsInterpolants.Count());
_writer.Write(TEXT("#define MATERIAL_OPACITY_THRESHOLD ({0})\n"), baseLayer->OpacityThreshold);
- if (materialInfo.BlendMode != MaterialBlendMode::Opaque && !(materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableReflections) && materialInfo.FeaturesFlags & MaterialFeaturesFlags::ScreenSpaceReflections)
+ if (materialInfo.BlendMode != MaterialBlendMode::Opaque && !(materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableReflections) && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::ScreenSpaceReflections))
{
// Inject depth and color buffers for Screen Space Reflections used by transparent material
auto sceneDepthTexture = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index 2aaeb9040..beaa60b87 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -352,7 +352,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
}
// Blend Indices and Blend Weights
- if (aMesh->mNumBones > 0 && aMesh->mBones && result.Types & ImportDataTypes::Skeleton)
+ if (aMesh->mNumBones > 0 && aMesh->mBones && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton))
{
const int32 vertexCount = mesh.Positions.Count();
mesh.BlendIndices.Resize(vertexCount);
@@ -433,7 +433,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
}
// Blend Shapes
- if (aMesh->mNumAnimMeshes > 0 && result.Types & ImportDataTypes::Skeleton && data.Options.ImportBlendShapes)
+ if (aMesh->mNumAnimMeshes > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes)
{
mesh.BlendShapes.EnsureCapacity(aMesh->mNumAnimMeshes);
for (unsigned int animMeshIndex = 0; animMeshIndex < aMesh->mNumAnimMeshes; animMeshIndex++)
@@ -524,7 +524,7 @@ bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String
materialSlot.Name = String(aName.C_Str()).TrimTrailing();
materialSlot.AssetID = Guid::Empty;
- if (result.Types & ImportDataTypes::Materials)
+ if (EnumHasAnyFlags(result.Types, ImportDataTypes::Materials))
{
aiColor3D aColor;
if (aMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aColor) == AI_SUCCESS)
@@ -536,7 +536,7 @@ bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String
if (aMaterial->Get(AI_MATKEY_OPACITY, aFloat) == AI_SUCCESS)
materialSlot.Opacity.Value = aFloat;
- if (result.Types & ImportDataTypes::Textures)
+ if (EnumHasAnyFlags(result.Types, ImportDataTypes::Textures))
{
ImportMaterialTexture(result, data, aMaterial, aiTextureType_DIFFUSE, materialSlot.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB);
ImportMaterialTexture(result, data, aMaterial, aiTextureType_EMISSIVE, materialSlot.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB);
@@ -641,8 +641,8 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
AssimpInited = true;
LOG(Info, "Assimp {0}.{1}.{2}", aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
}
- bool importMeshes = (data.Types & ImportDataTypes::Geometry) != 0;
- bool importAnimations = (data.Types & ImportDataTypes::Animations) != 0;
+ bool importMeshes = EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry);
+ bool importAnimations = EnumHasAnyFlags(data.Types, ImportDataTypes::Animations);
context = New(path, options);
// Setup import flags
@@ -704,7 +704,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
}
// Import geometry
- if (data.Types & ImportDataTypes::Geometry && context->Scene->HasMeshes())
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->HasMeshes())
{
const int meshCount = context->Scene->mNumMeshes;
if (options.SplitObjects && options.ObjectIndex == -1)
@@ -747,7 +747,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
}
// Import skeleton
- if (data.Types & ImportDataTypes::Skeleton)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton))
{
data.Skeleton.Nodes.Resize(context->Nodes.Count(), false);
for (int32 i = 0; i < context->Nodes.Count(); i++)
@@ -777,7 +777,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
}
// Import animations
- if (data.Types & ImportDataTypes::Animations && context->Scene->HasAnimations())
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations) && context->Scene->HasAnimations())
{
const int32 animCount = (int32)context->Scene->mNumAnimations;
if (options.SplitObjects && options.ObjectIndex == -1)
@@ -825,7 +825,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
}
// Import nodes
- if (data.Types & ImportDataTypes::Nodes)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Nodes))
{
data.Nodes.Resize(context->Nodes.Count());
for (int32 i = 0; i < context->Nodes.Count(); i++)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
index 688cf2bfd..002c84b09 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
@@ -219,11 +219,11 @@ struct OpenFbxImporterData
if (mat)
material.Name = String(mat->name).TrimTrailing();
- if (mat && result.Types & ImportDataTypes::Materials)
+ if (mat && EnumHasAnyFlags(result.Types, ImportDataTypes::Materials))
{
material.Diffuse.Color = ToColor(mat->getDiffuseColor());
- if (result.Types & ImportDataTypes::Textures)
+ if (EnumHasAnyFlags(result.Types, ImportDataTypes::Textures))
{
ImportMaterialTexture(result, mat, ofbx::Texture::DIFFUSE, material.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB);
ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB);
@@ -698,7 +698,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
}
// Blend Indices and Blend Weights
- if (skin && skin->getClusterCount() > 0 && result.Types & ImportDataTypes::Skeleton)
+ if (skin && skin->getClusterCount() > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton))
{
mesh.BlendIndices.Resize(vertexCount);
mesh.BlendWeights.Resize(vertexCount);
@@ -764,7 +764,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
}
// Blend Shapes
- if (blendShape && blendShape->getBlendShapeChannelCount() > 0 && result.Types & ImportDataTypes::Skeleton && data.Options.ImportBlendShapes)
+ if (blendShape && blendShape->getBlendShapeChannelCount() > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes)
{
mesh.BlendShapes.EnsureCapacity(blendShape->getBlendShapeChannelCount());
for (int32 channelIndex = 0; channelIndex < blendShape->getBlendShapeChannelCount(); channelIndex++)
@@ -1130,7 +1130,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
return true;
}
ofbx::u64 loadFlags = 0;
- if (data.Types & ImportDataTypes::Geometry)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry))
loadFlags |= (ofbx::u64)ofbx::LoadFlags::TRIANGULATE;
else
loadFlags |= (ofbx::u64)ofbx::LoadFlags::IGNORE_GEOMETRY;
@@ -1160,7 +1160,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
LOG(Info, "Imported scene: Up={0}, Front={1}, Right={2}", context->Up, context->Front, context->Right);
// Extract embedded textures
- if (data.Types & ImportDataTypes::Textures)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Textures))
{
String outputPath;
for (int i = 0, c = scene->getEmbeddedDataCount(); i < c; i++)
@@ -1229,7 +1229,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
DeleteMe contextCleanup(options.SplitContext ? nullptr : context);
// Build final skeleton bones hierarchy before importing meshes
- if (data.Types & ImportDataTypes::Skeleton)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton))
{
if (ImportBones(*context, errorMsg))
{
@@ -1241,7 +1241,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
}
// Import geometry (meshes and materials)
- if (data.Types & ImportDataTypes::Geometry && context->Scene->getMeshCount() > 0)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->getMeshCount() > 0)
{
const int meshCount = context->Scene->getMeshCount();
if (options.SplitObjects && options.ObjectIndex == -1)
@@ -1284,7 +1284,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
}
// Import skeleton
- if (data.Types & ImportDataTypes::Skeleton)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton))
{
data.Skeleton.Nodes.Resize(context->Nodes.Count(), false);
for (int32 i = 0; i < context->Nodes.Count(); i++)
@@ -1324,7 +1324,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
}
// Import animations
- if (data.Types & ImportDataTypes::Animations)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations))
{
const int animCount = context->Scene->getAnimationStackCount();
if (options.SplitObjects && options.ObjectIndex == -1)
@@ -1367,7 +1367,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
}
// Import nodes
- if (data.Types & ImportDataTypes::Nodes)
+ if (EnumHasAnyFlags(data.Types, ImportDataTypes::Nodes))
{
data.Nodes.Resize(context->Nodes.Count());
for (int32 i = 0; i < context->Nodes.Count(); i++)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index 8f8753a9a..103d2187a 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -482,7 +482,7 @@ bool ModelTool::ImportData(const String& path, ImportedModelData& data, Options&
}
// Flip normals of the imported geometry
- if (options.FlipNormals && data.Types & ImportDataTypes::Geometry)
+ if (options.FlipNormals && EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry))
{
for (auto& lod : data.LODs)
{
@@ -795,7 +795,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
auto& texture = data.Textures[i];
// Auto-import textures
- if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Textures) == 0 || texture.FilePath.IsEmpty())
+ if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Textures) == ImportDataTypes::None || texture.FilePath.IsEmpty())
continue;
String filename = StringUtils::GetFileNameWithoutExtension(texture.FilePath);
for (int32 j = filename.Length() - 1; j >= 0; j--)
@@ -842,7 +842,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
material.Name = TEXT("Material ") + StringUtils::ToString(i);
// Auto-import materials
- if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Materials) == 0 || !material.UsesProperties())
+ if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Materials) == ImportDataTypes::None || !material.UsesProperties())
continue;
auto filename = material.Name;
for (int32 j = filename.Length() - 1; j >= 0; j--)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.h b/Source/Engine/Tools/ModelTool/ModelTool.h
index 048ea4eb9..7d767bc77 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.h
+++ b/Source/Engine/Tools/ModelTool/ModelTool.h
@@ -19,6 +19,8 @@ class JsonWriter;
///
enum class ImportDataTypes : int32
{
+ None = 0,
+
///
/// Imports materials and meshes.
///
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index e1f41a5ff..0e0d29615 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -205,6 +205,15 @@ namespace FlaxEngine.GUI
BorderColorHighlighted = BorderColor;
}
+ ///
+ public override void ClearState()
+ {
+ base.ClearState();
+
+ if (_isPressed)
+ OnPressEnd();
+ }
+
///
public override void DrawSelf()
{
diff --git a/Source/Engine/UI/GUI/ContainerControl.cs b/Source/Engine/UI/GUI/ContainerControl.cs
index 9e226edb5..365889cbf 100644
--- a/Source/Engine/UI/GUI/ContainerControl.cs
+++ b/Source/Engine/UI/GUI/ContainerControl.cs
@@ -750,6 +750,20 @@ namespace FlaxEngine.GUI
}
}
+ ///
+ public override void ClearState()
+ {
+ base.ClearState();
+
+ // Clear state for any nested controls
+ for (int i = 0; i < _children.Count; i++)
+ {
+ var child = _children[i];
+ //if (child.Enabled && child.Enabled)
+ child.ClearState();
+ }
+ }
+
///
/// Draw the control and the children.
///
diff --git a/Source/Engine/UI/GUI/Control.cs b/Source/Engine/UI/GUI/Control.cs
index 027dd0267..d7b226cd1 100644
--- a/Source/Engine/UI/GUI/Control.cs
+++ b/Source/Engine/UI/GUI/Control.cs
@@ -131,6 +131,7 @@ namespace FlaxEngine.GUI
else
{
oldParentSize = Float2.Zero;
+ ClearState();
}
_parent = value;
@@ -214,20 +215,8 @@ namespace FlaxEngine.GUI
if (_isEnabled != value)
{
_isEnabled = value;
-
- // Check if control has been disabled
if (!_isEnabled)
- {
- Defocus();
-
- // Clear flags
- if (_isMouseOver)
- OnMouseLeave();
- if (_isDragOver)
- OnDragLeave();
- while (_touchOvers != null && _touchOvers.Count != 0)
- OnTouchLeave(_touchOvers[0]);
- }
+ ClearState();
}
}
}
@@ -259,20 +248,8 @@ namespace FlaxEngine.GUI
if (_isVisible != value)
{
_isVisible = value;
-
- // Check on control hide event
if (!_isVisible)
- {
- Defocus();
-
- // Clear flags
- if (_isMouseOver)
- OnMouseLeave();
- if (_isDragOver)
- OnDragLeave();
- while (_touchOvers != null && _touchOvers.Count != 0)
- OnTouchLeave(_touchOvers[0]);
- }
+ ClearState();
OnVisibleChanged();
_parent?.PerformLayout();
@@ -453,6 +430,20 @@ namespace FlaxEngine.GUI
{
}
+ ///
+ /// Called to clear UI state. For example, removes mouse over state or drag and drop when control gets disabled or hidden (including hierarchy).
+ ///
+ public virtual void ClearState()
+ {
+ Defocus();
+ if (_isMouseOver)
+ OnMouseLeave();
+ if (_isDragOver)
+ OnDragLeave();
+ while (_touchOvers != null && _touchOvers.Count != 0)
+ OnTouchLeave(_touchOvers[0]);
+ }
+
#region Focus
///
@@ -1338,6 +1329,12 @@ namespace FlaxEngine.GUI
///
protected virtual void OnVisibleChanged()
{
+ // Clear state when control gets hidden
+ if (!_isVisible && _isMouseOver)
+ {
+ OnMouseLeave();
+ }
+
VisibleChanged?.Invoke(this);
}
diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp
index 6631824f9..c1d173870 100644
--- a/Source/Engine/UI/TextRender.cpp
+++ b/Source/Engine/UI/TextRender.cpp
@@ -349,7 +349,7 @@ void TextRender::Draw(RenderContext& renderContext)
renderContext.View.GetWorldMatrix(_transform, world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
- const DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass & (uint32)renderContext.View.GetShadowsDrawPassMask(ShadowsMode));
+ const DrawPass drawModes = DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
if (_vb0.Data.Count() > 0 && drawModes != DrawPass::None)
{
// Flush buffers
@@ -386,13 +386,13 @@ void TextRender::Draw(RenderContext& renderContext)
// Submit draw calls
for (const auto& e : _drawChunks)
{
- auto chunkDrawModes = drawModes & e.Material->GetDrawModes();
- if (chunkDrawModes == 0)
+ const DrawPass chunkDrawModes = drawModes & e.Material->GetDrawModes();
+ if (chunkDrawModes == DrawPass::None)
continue;
drawCall.Draw.IndicesCount = e.IndicesCount;
drawCall.Draw.StartIndex = e.StartIndex;
drawCall.Material = e.Material;
- renderContext.List->AddDrawCall(renderContext, (DrawPass)chunkDrawModes, GetStaticFlags(), drawCall, true);
+ renderContext.List->AddDrawCall(renderContext, chunkDrawModes, GetStaticFlags(), drawCall, true);
}
}
diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs
index a3d70997b..266097a3f 100644
--- a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs
+++ b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs
@@ -81,6 +81,8 @@ namespace Flax.Build.Projects.VisualStudio
csProjectFileContent.AppendLine(" 7.3");
csProjectFileContent.AppendLine(" 512");
csProjectFileContent.AppendLine(" ");
+ if (Version >= VisualStudioVersion.VisualStudio2022)
+ csProjectFileContent.AppendLine(" false");
csProjectFileContent.AppendLine(" ");
diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs
index d82de4066..a4b19f79e 100644
--- a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs
+++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs
@@ -103,7 +103,8 @@ namespace Flax.Build.Projects.VisualStudio
vcProjectFileContent.AppendLine(" Native");
vcProjectFileContent.AppendLine(" Unicode");
vcProjectFileContent.AppendLine(" MakeFileProj");
- vcProjectFileContent.AppendLine(" false");
+ if (Version >= VisualStudioVersion.VisualStudio2022)
+ vcProjectFileContent.AppendLine(" false");
vcProjectFileContent.AppendLine(" ");
// Default properties