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