Merge branch '1.5' into dotnet7
# Conflicts: # Content/Shaders/GI/DDGI.flax # Content/Shaders/GI/GlobalSurfaceAtlas.flax # Content/Shaders/TAA.flax # Content/Shaders/VolumetricFog.flax # Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs
This commit is contained in:
@@ -36,6 +36,7 @@ namespace FlaxEditor.Content
|
||||
/// A <see cref="SceneAnimation"/> asset proxy object.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||
[ContentContextMenu("New/Animation/Scene Animation")]
|
||||
public class SceneAnimationProxy : BinaryAssetProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); };
|
||||
|
||||
@@ -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<AssetPicker> _element;
|
||||
private AssetPicker _picker;
|
||||
private ScriptType _valueType;
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -42,46 +41,59 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
if (!HasDifferentTypes)
|
||||
if (HasDifferentTypes)
|
||||
return;
|
||||
_picker = layout.Custom<AssetPicker>().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<AssetPicker>();
|
||||
_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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LayersAndTagsSettings>();
|
||||
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<TreeNode>();
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected item.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected content item path.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected asset object.
|
||||
/// </summary>
|
||||
@@ -117,16 +158,12 @@ namespace FlaxEditor.GUI
|
||||
_selectedItem = item;
|
||||
_selected = value;
|
||||
_selectedItem?.AddReference(this);
|
||||
|
||||
// Update tooltip
|
||||
TooltipText = _selectedItem?.NamePath;
|
||||
|
||||
OnSelectedItemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 <see cref="ScriptType.Null"/> for generic file picker.
|
||||
/// </summary>
|
||||
public ScriptType AssetType
|
||||
{
|
||||
@@ -144,6 +181,25 @@ namespace FlaxEditor.GUI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content items extensions filter. Null if unused.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when selected item gets changed.
|
||||
/// </summary>
|
||||
@@ -154,24 +210,32 @@ namespace FlaxEditor.GUI
|
||||
/// </summary>
|
||||
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
|
||||
/// </summary>
|
||||
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
|
||||
/// <inheritdoc />
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,40 +8,38 @@ using FlaxEngine.GUI;
|
||||
namespace FlaxEditor.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu" />
|
||||
public class AssetSearchPopup : ItemsListContextMenu
|
||||
public class ContentSearchPopup : ItemsListContextMenu
|
||||
{
|
||||
/// <summary>
|
||||
/// The asset item.
|
||||
/// The content item.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu.Item" />
|
||||
public class AssetItemView : Item, IContentItemOwner
|
||||
public class ContentItemView : Item, IContentItemOwner
|
||||
{
|
||||
private AssetItem _asset;
|
||||
|
||||
/// <summary>
|
||||
/// The icon size (in pixels).
|
||||
/// </summary>
|
||||
public const float IconSize = 28;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset.
|
||||
/// Gets the item.
|
||||
/// </summary>
|
||||
public AssetItem Asset => _asset;
|
||||
public ContentItem ContentItem;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetItemView"/> class.
|
||||
/// Initializes a new instance of the <see cref="ContentItemView"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset.</param>
|
||||
public AssetItemView(AssetItem asset)
|
||||
/// <param name="item">The item.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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
|
||||
/// <inheritdoc />
|
||||
public void OnItemRenamed(ContentItem item)
|
||||
{
|
||||
Name = _asset.ShortName;
|
||||
Name = ContentItem.ShortName;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -99,12 +97,118 @@ namespace FlaxEditor.GUI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if the given content item can be used to pick it.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>True if is valid.</returns>
|
||||
public delegate bool IsValidDelegate(ContentItem item);
|
||||
|
||||
private IsValidDelegate _isValid;
|
||||
private Action<ContentItem> _selected;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected ContentSearchPopup()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected ContentSearchPopup(IsValidDelegate isValid, Action<ContentItem> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the popup.
|
||||
/// </summary>
|
||||
/// <param name="showTarget">The show target.</param>
|
||||
/// <param name="showTargetLocation">The show target location.</param>
|
||||
/// <param name="isValid">Event called to check if a given content item is valid to be used.</param>
|
||||
/// <param name="selected">Event called on content item pick.</param>
|
||||
/// <returns>The dialog.</returns>
|
||||
public static ContentSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<ContentItem> selected)
|
||||
{
|
||||
var popup = new ContentSearchPopup(isValid, selected);
|
||||
popup.Show(showTarget, showTargetLocation);
|
||||
return popup;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_isValid = null;
|
||||
_selected = null;
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Popup that shows the list of assets to pick. Supports searching and basic items filtering.
|
||||
/// </summary>
|
||||
public class AssetSearchPopup : ContentSearchPopup
|
||||
{
|
||||
/// <summary>
|
||||
/// The asset item.
|
||||
/// </summary>
|
||||
public class AssetItemView : ContentItemView
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the asset.
|
||||
/// </summary>
|
||||
public AssetItem AssetItem => (AssetItem)ContentItem;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetItemView"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset.</param>
|
||||
public AssetItemView(AssetItem asset)
|
||||
: base(asset)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if the given asset item can be used to pick it.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset.</param>
|
||||
/// <returns>True if is valid.</returns>
|
||||
public delegate bool IsValidDelegate(AssetItem asset);
|
||||
public new delegate bool IsValidDelegate(AssetItem asset);
|
||||
|
||||
private IsValidDelegate _isValid;
|
||||
private Action<AssetItem> _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)
|
||||
|
||||
169
Source/Editor/GUI/Popups/AutoSavePopup.cs
Normal file
169
Source/Editor/GUI/Popups/AutoSavePopup.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup menu for reminding of an upcoming auto save.
|
||||
/// </summary>
|
||||
public class AutoSavePopup : ContainerControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value for if the user has manually closed this popup.
|
||||
/// </summary>
|
||||
public bool UserClosed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The save now button. Used to skip the last remaining auto save time.
|
||||
/// </summary>
|
||||
public Button SaveNowButton => _saveNowButton;
|
||||
|
||||
/// <summary>
|
||||
/// Button that should be used to cancel the auto save.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the AutoSavePopup.
|
||||
/// </summary>
|
||||
/// <param name="initialTime">The initial time to set the time label to.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the time label
|
||||
/// </summary>
|
||||
/// <param name="time">The time to change the label to.</param>
|
||||
public void UpdateTime(float time)
|
||||
{
|
||||
_timeRemaining = Mathf.CeilToInt(time);
|
||||
if (_timeLabel != null)
|
||||
_timeLabel.Text = "Auto Save in: " + _timeRemaining;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and shows the AutoSavePopup
|
||||
/// </summary>
|
||||
/// <param name="parentControl">The parent control.</param>
|
||||
/// <param name="initialTime">The time to start at.</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the popup by changing its visibility
|
||||
/// </summary>
|
||||
public void ShowPopup()
|
||||
{
|
||||
Visible = true;
|
||||
UserClosed = false;
|
||||
_saveNowButton.TextColor = _defaultTextColor;
|
||||
_cancelSaveButton.TextColor = _defaultTextColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides the popup by changing its visibility
|
||||
/// </summary>
|
||||
public void HidePopup()
|
||||
{
|
||||
Visible = false;
|
||||
if (_containsFocus)
|
||||
Defocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,11 @@ namespace FlaxEditor.GUI
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status text color
|
||||
/// </summary>
|
||||
public Color TextColor { get; set; } = Style.Current.Foreground;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StatusBar"/> class.
|
||||
/// </summary>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace FlaxEditor.Modules
|
||||
handler.ProgressStart += HandlerOnProgressStart;
|
||||
handler.ProgressChanged += HandlerOnProgressChanged;
|
||||
handler.ProgressEnd += HandlerOnProgressEnd;
|
||||
handler.ProgressFailed += HandlerOnProgressFail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,10 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
private Label _progressLabel;
|
||||
private ProgressBar _progressBar;
|
||||
private Button _outputLogButton;
|
||||
private List<KeyValuePair<string, DateTime>> _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();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the time before the auto save that the popup shows (in seconds).
|
||||
/// </summary>
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether enable auto saves for scenes.
|
||||
/// </summary>
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether enable auto saves for content.
|
||||
/// </summary>
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace FlaxEditor.Progress
|
||||
/// </summary>
|
||||
/// <param name="handler">The calling handler.</param>
|
||||
public delegate void ProgressDelegate(ProgressHandler handler);
|
||||
|
||||
/// <summary>
|
||||
/// Progress failed handler event delegate
|
||||
/// </summary>
|
||||
public delegate void ProgressFailedDelegate(ProgressHandler handler, string message);
|
||||
|
||||
private float _progress;
|
||||
private bool _isActive;
|
||||
@@ -51,6 +56,11 @@ namespace FlaxEditor.Progress
|
||||
/// </summary>
|
||||
public event ProgressDelegate ProgressEnd;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the progress fails
|
||||
/// </summary>
|
||||
public event ProgressFailedDelegate ProgressFailed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this handler action can be cancelled.
|
||||
/// </summary>
|
||||
@@ -109,5 +119,19 @@ namespace FlaxEditor.Progress
|
||||
ProgressChanged?.Invoke(this);
|
||||
ProgressEnd?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when progress action fails
|
||||
/// </summary>
|
||||
protected virtual void OnFail(string message)
|
||||
{
|
||||
if (!_isActive)
|
||||
throw new InvalidOperationException("Already ended.");
|
||||
|
||||
_isActive = false;
|
||||
_progress = 0;
|
||||
_infoText = string.Empty;
|
||||
ProgressFailed?.Invoke(this, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
/// <returns>The processed name path.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -308,6 +308,14 @@ namespace FlaxEditor.Windows.Assets
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drops any loaded asset data and refreshes the UI state.
|
||||
/// </summary>
|
||||
public void RefreshAsset()
|
||||
{
|
||||
_isWaitingForLoaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads the asset (window will receive <see cref="OnAssetLoaded"/> or <see cref="OnAssetLoadFailed"/> events).
|
||||
/// </summary>
|
||||
|
||||
@@ -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<ViewportScaleOptions> _defaultViewportScaling = new List<ViewportScaleOptions>();
|
||||
private List<ViewportScaleOptions> _customViewportScaling = new List<ViewportScaleOptions>();
|
||||
private float _viewportAspectRatio = 1;
|
||||
private float _windowAspectRatio = 1;
|
||||
private bool _useAspect = false;
|
||||
private bool _freeAspect = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the viewport.
|
||||
/// </summary>
|
||||
@@ -106,6 +115,35 @@ namespace FlaxEditor.Windows
|
||||
/// </summary>
|
||||
public bool FocusOnPlay { get; set; }
|
||||
|
||||
private enum ViewportScaleType
|
||||
{
|
||||
Resolution = 0,
|
||||
Aspect = 1,
|
||||
}
|
||||
|
||||
private class ViewportScaleOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The name.
|
||||
/// </summary>
|
||||
public string Label;
|
||||
|
||||
/// <summary>
|
||||
/// The Type of scaling to do.
|
||||
/// </summary>
|
||||
public ViewportScaleType ScaleType;
|
||||
|
||||
/// <summary>
|
||||
/// The width and height to scale by.
|
||||
/// </summary>
|
||||
public Int2 Size;
|
||||
|
||||
/// <summary>
|
||||
/// If the scaling is active.
|
||||
/// </summary>
|
||||
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();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -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<List<ViewportScaleOptions>>(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<List<ViewportScaleOptions>>(node.GetAttribute("DefaultViewportScaling"));
|
||||
|
||||
for (int i = 0; i < _defaultViewportScaling.Count; i++)
|
||||
{
|
||||
if (_defaultViewportScaling[i].Active)
|
||||
ChangeViewportRatio(_defaultViewportScaling[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -42,7 +42,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
virtual String ToString() const = 0;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<typename T>
|
||||
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<typename T>
|
||||
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<baseType*>((type*)1))-1)
|
||||
|
||||
@@ -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)
|
||||
|
||||
198
Source/Engine/Engine/RandomStream.cs
Normal file
198
Source/Engine/Engine/RandomStream.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#pragma warning disable 675
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Very basic pseudo numbers generator.
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public class RandomStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the initial seed.
|
||||
/// </summary>
|
||||
private int _initialSeed;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the current seed.
|
||||
/// </summary>
|
||||
private int _seed;
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
public RandomStream()
|
||||
{
|
||||
_initialSeed = 0;
|
||||
_seed = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initializes a new random stream from the specified seed value.
|
||||
/// </summary>
|
||||
/// <param name="seed">The seed value.</param>
|
||||
public RandomStream(int seed)
|
||||
{
|
||||
_initialSeed = seed;
|
||||
_seed = seed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets initial seed value
|
||||
/// </summary>
|
||||
public int GetInitialSeed()
|
||||
{
|
||||
return _initialSeed;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current seed.
|
||||
/// </summary>
|
||||
public int GetCurrentSeed()
|
||||
{
|
||||
return _seed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this random stream with the specified seed value.
|
||||
/// </summary>
|
||||
/// <param name="seed">The seed value.</param>
|
||||
public void Initialize(int seed)
|
||||
{
|
||||
_initialSeed = seed;
|
||||
_seed = seed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets this random stream to the initial seed value.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_seed = _initialSeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new random seed.
|
||||
/// </summary>
|
||||
public void GenerateNewSeed()
|
||||
{
|
||||
Initialize(new System.Random().Next());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random boolean.
|
||||
/// </summary>
|
||||
public unsafe bool GetBool()
|
||||
{
|
||||
MutateSeed();
|
||||
fixed (int* seedPtr = &_seed)
|
||||
return *seedPtr < (uint.MaxValue / 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and uint.MaxValue.
|
||||
/// </summary>
|
||||
public unsafe uint GetUnsignedInt()
|
||||
{
|
||||
MutateSeed();
|
||||
fixed (int* seedPtr = &_seed)
|
||||
return (uint)*seedPtr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and 1.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0 and 1.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float Rand()
|
||||
{
|
||||
return GetFraction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random vector of unit size.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random <see cref="Vector3"/> with components in a range between [0;1].
|
||||
/// </summary>
|
||||
public Vector3 GetVector3()
|
||||
{
|
||||
return new Vector3(GetFraction(), GetFraction(), GetFraction());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for rand implementations.
|
||||
/// </summary>
|
||||
/// <param name="a">Top border</param>
|
||||
/// <returns>A random number in [0..A)</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int RandHelper(int a)
|
||||
{
|
||||
return a > 0 ? Mathf.FloorToInt(GetFraction() * ((float)a - Mathf.Epsilon)) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for rand implementations
|
||||
/// </summary>
|
||||
/// <param name="min">Minimum value</param>
|
||||
/// <param name="max">Maximum value</param>
|
||||
/// <returns>A random number in [min; max] range</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int RandRange(int min, int max)
|
||||
{
|
||||
int range = max - min + 1;
|
||||
return min + RandHelper(range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for rand implementations
|
||||
/// </summary>
|
||||
/// <param name="min">Minimum value</param>
|
||||
/// <param name="max">Maximum value</param>
|
||||
/// <returns>A random number in [min; max] range</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float RandRange(float min, float max)
|
||||
{
|
||||
return min + (max - min) * Rand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mutates the current seed into the next seed.
|
||||
/// </summary>
|
||||
protected void MutateSeed()
|
||||
{
|
||||
// This can be modified to provide better randomization
|
||||
_seed = _seed * 196314165 + 907633515;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Source/Engine/Engine/RandomUtil.cs
Normal file
25
Source/Engine/Engine/RandomUtil.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic pseudo numbers generator utility.
|
||||
/// </summary>
|
||||
public static class RandomUtil
|
||||
{
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Generates a pseudo-random number from normalized range [0;1].
|
||||
/// </summary>
|
||||
/// <returns>The random number.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float Rand()
|
||||
{
|
||||
return _random.Next(0, int.MaxValue) / (float)int.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
|
||||
#define FOLIAGE_GET_DRAW_MODES(renderContext, type) static_cast<DrawPass>(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<ShadowsCastingMode>(entry.ShadowsMode & slot.ShadowsMode);
|
||||
const auto drawModes = static_cast<DrawPass>(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<ShadowsCastingMode>(entry.ShadowsMode & slot.ShadowsMode);
|
||||
const auto drawModes = (DrawPass)(static_cast<DrawPass>(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<DrawPass>(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)
|
||||
|
||||
@@ -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<uint32>(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)
|
||||
{
|
||||
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsShaderResource() const
|
||||
{
|
||||
return (Flags & GPUBufferFlags::ShaderResource) != 0;
|
||||
return (Flags & GPUBufferFlags::ShaderResource) != GPUBufferFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsUnorderedAccess() const
|
||||
{
|
||||
return (Flags & GPUBufferFlags::UnorderedAccess) != 0;
|
||||
return (Flags & GPUBufferFlags::UnorderedAccess) != GPUBufferFlags::None;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -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<int>(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<int>(formatSupportFlags))
|
||||
|
||||
/// <summary>
|
||||
/// The features exposed for a particular format.
|
||||
/// </summary>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -127,7 +127,7 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, Span<byte>& 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)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsRenderTarget() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::RenderTarget) != 0;
|
||||
return (Flags & GPUTextureFlags::RenderTarget) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsDepthStencil() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::DepthStencil) != 0;
|
||||
return (Flags & GPUTextureFlags::DepthStencil) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsShaderResource() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::ShaderResource) != 0;
|
||||
return (Flags & GPUTextureFlags::ShaderResource) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsUnorderedAccess() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::UnorderedAccess) != 0;
|
||||
return (Flags & GPUTextureFlags::UnorderedAccess) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool HasPerMipViews() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::PerMipViews) != 0;
|
||||
return (Flags & GPUTextureFlags::PerMipViews) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool HasPerSliceViews() const
|
||||
{
|
||||
return (Flags & GPUTextureFlags::PerSliceViews) != 0;
|
||||
return (Flags & GPUTextureFlags::PerSliceViews) != GPUTextureFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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<GPUBufferDX11*>(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<GPUBufferDX11*>(bufferForArgs);
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ void GPUTextureDX11::initHandles()
|
||||
}
|
||||
|
||||
// Read-only depth-stencil
|
||||
if (_desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
|
||||
if (EnumHasAnyFlags(_desc.Flags, GPUTextureFlags::ReadOnlyDepthView))
|
||||
{
|
||||
CLEAR_VIEWS();
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsTransformStatic() const
|
||||
{
|
||||
return (_staticFlags & StaticFlags::Transform) != 0;
|
||||
return (_staticFlags & StaticFlags::Transform) != StaticFlags::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -373,7 +373,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE bool HasStaticFlag(StaticFlags flag) const
|
||||
{
|
||||
return (_staticFlags & flag) == (int)flag;
|
||||
return EnumHasAllFlags(_staticFlags, flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -391,7 +391,7 @@ public:
|
||||
/// <param name="flags">The flags to remove.</param>
|
||||
FORCE_INLINE void RemoveStaticFlags(StaticFlags flags)
|
||||
{
|
||||
SetStaticFlags(static_cast<StaticFlags>(_staticFlags & ~flags));
|
||||
SetStaticFlags(_staticFlags & ~flags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -401,7 +401,7 @@ public:
|
||||
/// <param name="value">The target value of the flag.</param>
|
||||
FORCE_INLINE void SetStaticFlag(StaticFlags flag, bool value)
|
||||
{
|
||||
SetStaticFlags(static_cast<StaticFlags>(_staticFlags & ~flag) | (value ? flag : StaticFlags::None));
|
||||
SetStaticFlags((_staticFlags & ~flag) | (value ? flag : StaticFlags::None));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<ShadowsCastingMode>(entry.ShadowsMode & slot.ShadowsMode);
|
||||
const auto drawModes = static_cast<DrawPass>(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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ void PrefabInstanceData::CollectPrefabInstances(Array<PrefabInstanceData>& 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<PrefabInstanceData>& 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<PrefabInstanceData>& 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<Prefab>(nestedPrefabIds[i]);
|
||||
if (nestedPrefab && nestedPrefab != this && (nestedPrefab->Flags & ObjectFlags::WasMarkedToDelete) == 0)
|
||||
if (nestedPrefab && nestedPrefab != this && (nestedPrefab->Flags & ObjectFlags::WasMarkedToDelete) == ObjectFlags::None)
|
||||
{
|
||||
allPrefabs.Add(nestedPrefab);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE bool IsDuringPlay() const
|
||||
{
|
||||
return (Flags & ObjectFlags::IsDuringPlay) != 0;
|
||||
return (Flags & ObjectFlags::IsDuringPlay) == ObjectFlags::IsDuringPlay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -54,7 +54,7 @@ void SceneQuery::GetAllSceneObjects(Actor* root, Array<SceneObject*>& objects)
|
||||
|
||||
bool GetAllSerializableSceneObjectsQuery(Actor* actor, Array<SceneObject*>& objects)
|
||||
{
|
||||
if ((actor->HideFlags & HideFlags::DontSave) != 0)
|
||||
if (EnumHasAnyFlags(actor->HideFlags, HideFlags::DontSave))
|
||||
return false;
|
||||
|
||||
objects.Add(actor);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
/// <param name="ownerClientId">The new owner. Set to NetworkManager::LocalClientId for local client to be owner (server might reject it).</param>
|
||||
/// <param name="localRole">The local role to assign for the object.</param>
|
||||
/// <param name="hierarchical">True if apply the ownership to all child objects of this object (eg. all child actors and scripts attached to the networked actor).</param>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// Marks the object dirty to perform immediate replication to the other clients.
|
||||
|
||||
@@ -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<DrawPass>(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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user