From 0a516ac98d86464eef859a3752a57601a7cf2a65 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sat, 14 Sep 2024 15:33:07 +0200 Subject: [PATCH 001/137] make it possible to pan editor when rmb down on node --- Source/Editor/Surface/SurfaceNode.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs index c5c011db0..09ab04c8a 100644 --- a/Source/Editor/Surface/SurfaceNode.cs +++ b/Source/Editor/Surface/SurfaceNode.cs @@ -146,6 +146,8 @@ namespace FlaxEditor.Surface /// protected virtual Color FooterColor => GroupArchetype.Color; + private Float2 mouseDownMousePosition; + /// /// Calculates the size of the node including header, footer, and margins. /// @@ -1093,7 +1095,7 @@ namespace FlaxEditor.Surface if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location)) return true; if (button == MouseButton.Right) - return true; + mouseDownMousePosition = Input.Mouse.Position; return false; } @@ -1114,6 +1116,9 @@ namespace FlaxEditor.Surface // Secondary Context Menu if (button == MouseButton.Right) { + if (mouseDownMousePosition != Input.Mouse.Position) + return true; + if (!IsSelected) Surface.Select(this); var tmp = PointToParent(ref location); From e665cc75003022173fd1cbdc78361e7397f5d31f Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Mon, 16 Sep 2024 15:43:46 +0200 Subject: [PATCH 002/137] add safe margin 4 pixels seemed a bit much, smaller adjustments could lead to the menu still showing --- Source/Editor/Surface/SurfaceNode.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs index 09ab04c8a..f763eceb5 100644 --- a/Source/Editor/Surface/SurfaceNode.cs +++ b/Source/Editor/Surface/SurfaceNode.cs @@ -1116,7 +1116,8 @@ namespace FlaxEditor.Surface // Secondary Context Menu if (button == MouseButton.Right) { - if (mouseDownMousePosition != Input.Mouse.Position) + float distance = Float2.Distance(mouseDownMousePosition, Input.Mouse.Position); + if (distance > 2.5f) return true; if (!IsSelected) From 9b495bbc6830c2f8f666adb1f620839ead0e4261 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Thu, 13 Mar 2025 17:18:11 +0100 Subject: [PATCH 003/137] improve how ColorValueBoxes draw transparent colors --- Source/Editor/GUI/Input/ColorValueBox.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Source/Editor/GUI/Input/ColorValueBox.cs b/Source/Editor/GUI/Input/ColorValueBox.cs index 1531266e3..1416ccc58 100644 --- a/Source/Editor/GUI/Input/ColorValueBox.cs +++ b/Source/Editor/GUI/Input/ColorValueBox.cs @@ -129,11 +129,20 @@ namespace FlaxEditor.GUI.Input { base.Draw(); - var style = Style.Current; - var r = new Rectangle(0, 0, Width, Height); + bool isTransparent = _value.A < 1; - Render2D.FillRectangle(r, _value); - Render2D.DrawRectangle(r, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black); + var style = Style.Current; + var fullRect = new Rectangle(0, 0, Width, Height); + var colorRect = new Rectangle(0, 0, isTransparent ? Width * 0.7f : Width, Height); + + if (isTransparent) + { + var alphaRect = new Rectangle(colorRect.Right, 0, Width - colorRect.Right, Height); + Render2D.FillRectangle(alphaRect, _value); + } + + Render2D.FillRectangle(colorRect, _value with { A = 1 }); + Render2D.DrawRectangle(fullRect, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black); } /// From 051d3633588d5694cc88f6202e8ef2f0f406c642 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 14 Mar 2025 15:51:36 +0100 Subject: [PATCH 004/137] add alpha grid background --- Source/Editor/EditorAssets.cs | 5 +++++ Source/Editor/GUI/Input/ColorValueBox.cs | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs index bdfc7dfa6..d30ca91c0 100644 --- a/Source/Editor/EditorAssets.cs +++ b/Source/Editor/EditorAssets.cs @@ -134,6 +134,11 @@ namespace FlaxEditor /// public static string FlaxIconBlueTexture = "Engine/Textures/FlaxIconBlue"; + /// + /// The checkboard material used as a background for displaying transparent colors. + /// + public static string ColorAlphaBackgroundGrid = "Editor/AlphaBackgroundGrid"; + /// /// The icon lists used by editor from the SegMDL2 font. /// diff --git a/Source/Editor/GUI/Input/ColorValueBox.cs b/Source/Editor/GUI/Input/ColorValueBox.cs index 1416ccc58..1893c4124 100644 --- a/Source/Editor/GUI/Input/ColorValueBox.cs +++ b/Source/Editor/GUI/Input/ColorValueBox.cs @@ -14,7 +14,12 @@ namespace FlaxEditor.GUI.Input [HideInEditor] public class ColorValueBox : Control { + private const String ScaleParamName = "Scale"; + // 4.8 is a magic number that makes the grid fit perfect in the color value box + private const float GridScale = 4.8f; + private bool _isMouseDown; + private MaterialBase checkerMaterial; /// /// Delegate function used for the color picker events handling. @@ -101,6 +106,9 @@ namespace FlaxEditor.GUI.Input public ColorValueBox() : base(0, 0, 32, 18) { + checkerMaterial = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.ColorAlphaBackgroundGrid); + checkerMaterial = checkerMaterial.CreateVirtualInstance(); + checkerMaterial.SetParameterValue(ScaleParamName, GridScale); } /// @@ -138,6 +146,7 @@ namespace FlaxEditor.GUI.Input if (isTransparent) { var alphaRect = new Rectangle(colorRect.Right, 0, Width - colorRect.Right, Height); + Render2D.DrawMaterial(checkerMaterial, alphaRect); Render2D.FillRectangle(alphaRect, _value); } From 0b7550e5caa8dcc665e7773b8544faccbe91195a Mon Sep 17 00:00:00 2001 From: Andre Mohren Date: Wed, 2 Apr 2025 15:10:11 +0200 Subject: [PATCH 005/137] Implement creation of new projects from within the editor gui. --- Source/Editor/Editor.cs | 22 +++++++++++++++++++++- Source/Editor/Modules/UIModule.cs | 12 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index ee9251a69..c577c4055 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -51,6 +51,7 @@ namespace FlaxEditor private readonly List _modules = new List(16); private bool _isAfterInit, _areModulesInited, _areModulesAfterInitEnd, _isHeadlessMode, _autoExit; private string _projectToOpen; + private bool _projectIsNew; private float _lastAutoSaveTimer, _autoExitTimeout = 0.1f; private Button _saveNowButton; private Button _cancelSaveButton; @@ -731,11 +732,12 @@ namespace FlaxEditor var procSettings = new CreateProcessSettings { FileName = Platform.ExecutableFilePath, - Arguments = string.Format("-project \"{0}\"", _projectToOpen), + Arguments = string.Format("-project \"{0}\"" + (_projectIsNew ? " -new" : string.Empty), _projectToOpen), ShellExecute = true, WaitForEnd = false, HiddenWindow = false, }; + _projectIsNew = false; _projectToOpen = null; Platform.CreateProcess(ref procSettings); } @@ -784,6 +786,24 @@ namespace FlaxEditor } } + /// + /// Creates the given project. Afterwards closes this project with running editor and opens the given project. + /// + /// The project file path. + public void NewProject(string projectFilePath) + { + if (projectFilePath == null) + { + MessageBox.Show("Missing project"); + return; + } + + // Cache project path and start editor exit (it will open new instance on valid closing) + _projectToOpen = StringUtils.NormalizePath(Path.GetDirectoryName(projectFilePath)); + _projectIsNew = true; + Windows.MainWindow.Close(ClosingReason.User); + } + /// /// Closes this project with running editor and opens the given project. /// diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index 67df5a2e8..1eb62c13c 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -536,6 +536,7 @@ namespace FlaxEditor.Modules _menuFileGenerateScriptsProjectFiles = cm.AddButton("Generate scripts project files", inputOptions.GenerateScriptsProject, Editor.ProgressReporting.GenerateScriptsProjectFiles.RunAsync); _menuFileRecompileScripts = cm.AddButton("Recompile scripts", inputOptions.RecompileScripts, ScriptsBuilder.Compile); cm.AddSeparator(); + cm.AddButton("New project", NewProject); cm.AddButton("Open project...", OpenProject); cm.AddButton("Reload project", ReloadProject); cm.AddButton("Open project folder", () => FileSystem.ShowFileExplorer(Editor.Instance.GameProject.ProjectFolderPath)); @@ -827,6 +828,17 @@ namespace FlaxEditor.Modules MasterPanel.Offsets = new Margin(0, 0, ToolStrip.Bottom, StatusBar.Height); } + private void NewProject() + { + // Ask user to create project file + if (FileSystem.ShowSaveFileDialog(Editor.Windows.MainWindow, null, "Project files (*.flaxproj)\0*.flaxproj\0All files (*.*)\0*.*\0", false, "Create project file", out var files)) + return; + if (files != null && files.Length > 0) + { + Editor.NewProject(files[0]); + } + } + private void OpenProject() { // Ask user to select project file From 2e48be97b67c14d322e9b523c0da257eab8f70ef Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 17:24:13 +0200 Subject: [PATCH 006/137] add getter for steering --- Source/Engine/Physics/Actors/WheeledVehicle.cpp | 5 +++++ Source/Engine/Physics/Actors/WheeledVehicle.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index 010add151..3aa7ff5ce 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -200,6 +200,11 @@ void WheeledVehicle::SetSteering(float value) _steering = Math::Clamp(value, -1.0f, 1.0f); } +float WheeledVehicle::GetSteering() +{ + return _steering; +} + void WheeledVehicle::SetBrake(float value) { value = Math::Saturate(value); diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index fe518a41d..bbb3026db 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -553,6 +553,12 @@ public: /// The value (-1,1 range). API_FUNCTION() void SetSteering(float value); + /// + /// Gets the vehicle steering. Steer is the analog steer value in range (-1,1) where -1 represents the steering wheel at left lock and +1 represents the steering wheel at right lock. + /// + /// The vehicle steering. + API_FUNCTION() float GetSteering(); + /// /// Sets the input for vehicle brakes. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state. /// From dd281bbca8583f3ca433d8c903ba9b14d5163a1d Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 19:12:36 +0200 Subject: [PATCH 007/137] add wheel information debug draw --- .../Engine/Physics/Actors/WheeledVehicle.cpp | 6 +++++ Source/Engine/Physics/Actors/WheeledVehicle.h | 25 ++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index 3aa7ff5ce..08141e75e 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -424,6 +424,12 @@ void WheeledVehicle::OnDebugDrawSelected() { DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(data.State.TireContactPoint, 5.0f), Color::Green, 0, false); } + + if (DisplayWheelInfo) + { + const String text = String::Format(TEXT("Index: {}\nCollider: {}"), wheelIndex, wheel.Collider->GetName()); + DEBUG_DRAW_TEXT(text, currentPos, WheelInfoColor, 10, 0); + } } } diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index bbb3026db..a3d66ff29 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -5,6 +5,7 @@ #include "Engine/Physics/Actors/RigidBody.h" #include "Engine/Physics/Colliders/Collider.h" #include "Engine/Scripting/ScriptingObjectReference.h" +#include "Engine/Core/Math/Color.h" /// /// Representation of the car vehicle that uses wheels. Built on top of the RigidBody with collider representing its chassis shape and wheels. @@ -464,10 +465,22 @@ public: API_FIELD(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") bool UseAnalogSteering = false; + /// + /// If checked, will draw some useful information about the wheels at the position of their colliders. + /// + API_FIELD(Attributes ="EditorOrder(2), EditorDisplay(\"Vehicle\")") + bool DisplayWheelInfo = false; + + /// + /// If checked, will draw some useful information about the wheels at the position of their colliders. + /// + API_FIELD(Attributes = "EditorOrder(3), EditorDisplay(\"Vehicle\"), VisibleIf(\"DisplayWheelInfo\")") + Color WheelInfoColor = Color::White; + /// /// Gets the vehicle driving model type. /// - API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const; + API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const; /// /// Sets the vehicle driving model type. @@ -477,12 +490,12 @@ public: /// /// Gets the vehicle wheels settings. /// - API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const; + API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const; /// /// Gets the vehicle drive control settings. /// - API_PROPERTY(Attributes = "EditorOrder(5), EditorDisplay(\"Vehicle\")") DriveControlSettings GetDriveControl() const; + API_PROPERTY(Attributes = "EditorOrder(6), EditorDisplay(\"Vehicle\")") DriveControlSettings GetDriveControl() const; /// /// Sets the vehicle drive control settings. @@ -497,7 +510,7 @@ public: /// /// Gets the vehicle engine settings. /// - API_PROPERTY(Attributes="EditorOrder(6), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const; + API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const; /// /// Sets the vehicle engine settings. @@ -507,7 +520,7 @@ public: /// /// Gets the vehicle differential settings. /// - API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const; + API_PROPERTY(Attributes="EditorOrder(8), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const; /// /// Sets the vehicle differential settings. @@ -517,7 +530,7 @@ public: /// /// Gets the vehicle gearbox settings. /// - API_PROPERTY(Attributes="EditorOrder(8), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const; + API_PROPERTY(Attributes="EditorOrder(9), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const; /// /// Sets the vehicle gearbox settings. From 59ac8a3f602f226036ec4075a57b5738a9a39e7b Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 19:21:24 +0200 Subject: [PATCH 008/137] move anti roll bars into Vehicle display group --- Source/Engine/Physics/Actors/WheeledVehicle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index a3d66ff29..dec7b75cd 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -540,7 +540,7 @@ public: // /// Sets axles anti roll bars to increase vehicle stability. /// - API_PROPERTY() void SetAntiRollBars(const Array& value); + API_PROPERTY(Attributes="EditorOrder(10), EditorDisplay(\"Vehicle\")") void SetAntiRollBars(const Array& value); // /// Gets axles anti roll bars. From a0b80c6096a569ece0b26291f450453d7218aeb7 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 19:29:11 +0200 Subject: [PATCH 009/137] add getters for more commonly used vehicle fields --- Source/Engine/Physics/Actors/WheeledVehicle.cpp | 10 ++++++++++ Source/Engine/Physics/Actors/WheeledVehicle.h | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index 08141e75e..b3b0473f1 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -213,11 +213,21 @@ void WheeledVehicle::SetBrake(float value) _tankRightBrake = value; } +float WheeledVehicle::GetBrake() +{ + return _brake; +} + void WheeledVehicle::SetHandbrake(float value) { _handBrake = Math::Saturate(value); } +float WheeledVehicle::GetHandbrake() +{ + return _handBrake; +} + void WheeledVehicle::SetTankLeftThrottle(float value) { _tankLeftThrottle = Math::Clamp(value, -1.0f, 1.0f); diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index dec7b75cd..3e93f47ec 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -578,12 +578,24 @@ public: /// The value (0,1 range). API_FUNCTION() void SetBrake(float value); + /// + /// Gets the vehicle brakes. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state. + /// + /// The vehicle brake. + API_FUNCTION() float GetBrake(); + /// /// Sets the input for vehicle handbrake. Handbrake is the analog handbrake value in range (0,1) where 1 represents the handbrake fully engaged and 0 represents the handbrake in its rest state. /// /// The value (0,1 range). API_FUNCTION() void SetHandbrake(float value); + /// + /// Gets the vehicle handbrake. Handbrake is the analog handbrake value in range (0,1) where 1 represents the handbrake fully engaged and 0 represents the handbrake in its rest state. + /// + /// The vehicle handbrake. + API_FUNCTION() float GetHandbrake(); + /// /// Sets the input for tank left track throttle. It is the analog accelerator pedal value in range (-1,1) where 1 represents the pedal fully pressed to move to forward, 0 to represents the /// pedal in its rest state and -1 represents the pedal fully pressed to move to backward. The track direction will be inverted if the vehicle current gear is rear. From 68ef6f08c6cfe6cdf09795a4fc591a009e8d65aa Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 19:40:27 +0200 Subject: [PATCH 010/137] minor style fixes --- Source/Engine/Physics/Actors/WheeledVehicle.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index 3e93f47ec..a9efb204d 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -468,13 +468,13 @@ public: /// /// If checked, will draw some useful information about the wheels at the position of their colliders. /// - API_FIELD(Attributes ="EditorOrder(2), EditorDisplay(\"Vehicle\")") + API_FIELD(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") bool DisplayWheelInfo = false; /// /// If checked, will draw some useful information about the wheels at the position of their colliders. /// - API_FIELD(Attributes = "EditorOrder(3), EditorDisplay(\"Vehicle\"), VisibleIf(\"DisplayWheelInfo\")") + API_FIELD(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\"), VisibleIf(\"DisplayWheelInfo\")") Color WheelInfoColor = Color::White; /// From 1dfd717093b53a5e1f618fca821524c8e92bd80c Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 2 Apr 2025 23:38:04 +0200 Subject: [PATCH 011/137] serialize display info and color --- Source/Engine/Physics/Actors/WheeledVehicle.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index b3b0473f1..799f4a5d4 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -471,6 +471,8 @@ void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_GET_OTHER_OBJ(WheeledVehicle); + SERIALIZE_MEMBER(DisplayWheelInfo, DisplayWheelInfo); + SERIALIZE_MEMBER(WheelInfoColor, WheelInfoColor); SERIALIZE_MEMBER(DriveType, _driveType); SERIALIZE_MEMBER(Wheels, _wheels); SERIALIZE_MEMBER(DriveControl, _driveControl); @@ -486,6 +488,8 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* { RigidBody::Deserialize(stream, modifier); + DESERIALIZE(DisplayWheelInfo); + DESERIALIZE(WheelInfoColor); DESERIALIZE_MEMBER(DriveType, _driveType); DESERIALIZE_MEMBER(Wheels, _wheels); DESERIALIZE_MEMBER(DriveControl, _driveControl); From 78dffc9ad11c524799ab8cbdaf76285fee85268f Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 5 Apr 2025 15:24:19 +0300 Subject: [PATCH 012/137] Add override for building CMake project with custom configuration --- Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs | 2 +- Source/Tools/Flax.Build/Deps/Dependency.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs index 7be41423f..9719a7ec2 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs @@ -195,7 +195,7 @@ namespace Flax.Deps.Dependencies RunCmake(cmakeFolder, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + cmakeArgs, envVars); // Run build - BuildCmake(cmakeFolder, envVars); + BuildCmake(cmakeFolder, envVars: envVars); // Deploy binaries var libs = new[] diff --git a/Source/Tools/Flax.Build/Deps/Dependency.cs b/Source/Tools/Flax.Build/Deps/Dependency.cs index 848f2a2a9..2405cc991 100644 --- a/Source/Tools/Flax.Build/Deps/Dependency.cs +++ b/Source/Tools/Flax.Build/Deps/Dependency.cs @@ -251,10 +251,11 @@ namespace Flax.Deps /// Builds the cmake project. /// /// The path. + /// The configuration preset. /// Custom environment variables to pass to the child process. - public static void BuildCmake(string path, Dictionary envVars = null) + public static void BuildCmake(string path, string config = "Release", Dictionary envVars = null) { - Utilities.Run("cmake", "--build . --config Release", null, path, Utilities.RunOptions.DefaultTool, envVars); + Utilities.Run("cmake", $"--build . --config {config}", null, path, Utilities.RunOptions.DefaultTool, envVars); } /// From 643fe639e52b837a5843fee03bfdc8c2c07ea889 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 5 Apr 2025 13:47:42 +0300 Subject: [PATCH 013/137] Update OpenAL to 1.24.3 --- Source/ThirdParty/OpenAL/al.h | 325 +++++---- Source/ThirdParty/OpenAL/alc.h | 113 ++-- Source/ThirdParty/OpenAL/alext.h | 621 +++++++++++++++--- Source/ThirdParty/OpenAL/efx-presets.h | 2 + Source/ThirdParty/OpenAL/efx.h | 134 ++-- .../Flax.Build/Deps/Dependencies/OpenAL.cs | 17 +- 6 files changed, 860 insertions(+), 352 deletions(-) diff --git a/Source/ThirdParty/OpenAL/al.h b/Source/ThirdParty/OpenAL/al.h index 5071fa5e3..a4e3ad515 100644 --- a/Source/ThirdParty/OpenAL/al.h +++ b/Source/ThirdParty/OpenAL/al.h @@ -1,8 +1,40 @@ #ifndef AL_AL_H #define AL_AL_H +/* NOLINTBEGIN */ #ifdef __cplusplus extern "C" { + +#ifdef _MSVC_LANG +#define AL_CPLUSPLUS _MSVC_LANG +#else +#define AL_CPLUSPLUS __cplusplus +#endif + +#ifndef AL_DISABLE_NOEXCEPT +#if AL_CPLUSPLUS >= 201103L +#define AL_API_NOEXCEPT noexcept +#else +#define AL_API_NOEXCEPT +#endif +#if AL_CPLUSPLUS >= 201703L +#define AL_API_NOEXCEPT17 noexcept +#else +#define AL_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 +#endif + +#undef AL_CPLUSPLUS + +#else /* __cplusplus */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 #endif #ifndef AL_API @@ -455,220 +487,221 @@ typedef void ALvoid; #ifndef AL_NO_PROTOTYPES /* Renderer State management. */ -AL_API void AL_APIENTRY alEnable(ALenum capability); -AL_API void AL_APIENTRY alDisable(ALenum capability); -AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); +AL_API void AL_APIENTRY alEnable(ALenum capability) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDisable(ALenum capability) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) AL_API_NOEXCEPT; /* Context state setting. */ -AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); -AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); -AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); +AL_API void AL_APIENTRY alDopplerFactor(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel) AL_API_NOEXCEPT; /* Context state retrieval. */ -AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); -AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); -AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); -AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); -AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); -AL_API ALint AL_APIENTRY alGetInteger(ALenum param); -AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); -AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); +AL_API const ALchar* AL_APIENTRY alGetString(ALenum param) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param) AL_API_NOEXCEPT; +AL_API ALint AL_APIENTRY alGetInteger(ALenum param) AL_API_NOEXCEPT; +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param) AL_API_NOEXCEPT; +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param) AL_API_NOEXCEPT; /** * Obtain the first error generated in the AL context since the last call to * this function. */ -AL_API ALenum AL_APIENTRY alGetError(void); +AL_API ALenum AL_APIENTRY alGetError(void) AL_API_NOEXCEPT; /** Query for the presence of an extension on the AL context. */ -AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname) AL_API_NOEXCEPT; /** * Retrieve the address of a function. The returned function may be context- * specific. */ -AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); +AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname) AL_API_NOEXCEPT; /** * Retrieve the value of an enum. The returned value may be context-specific. */ -AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename) AL_API_NOEXCEPT; /* Set listener parameters. */ -AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); -AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); -AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); +AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get listener parameters. */ -AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values) AL_API_NOEXCEPT; /** Create source objects. */ -AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); +AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources) AL_API_NOEXCEPT; /** Delete source objects. */ -AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Verify an ID is for a valid source. */ -AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) AL_API_NOEXCEPT; /* Set source parameters. */ -AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); -AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); +AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get source parameters. */ -AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; /** Play, restart, or resume a source, setting its state to AL_PLAYING. */ -AL_API void AL_APIENTRY alSourcePlay(ALuint source); +AL_API void AL_APIENTRY alSourcePlay(ALuint source) AL_API_NOEXCEPT; /** Stop a source, setting its state to AL_STOPPED if playing or paused. */ -AL_API void AL_APIENTRY alSourceStop(ALuint source); +AL_API void AL_APIENTRY alSourceStop(ALuint source) AL_API_NOEXCEPT; /** Rewind a source, setting its state to AL_INITIAL. */ -AL_API void AL_APIENTRY alSourceRewind(ALuint source); +AL_API void AL_APIENTRY alSourceRewind(ALuint source) AL_API_NOEXCEPT; /** Pause a source, setting its state to AL_PAUSED if playing. */ -AL_API void AL_APIENTRY alSourcePause(ALuint source); +AL_API void AL_APIENTRY alSourcePause(ALuint source) AL_API_NOEXCEPT; /** Play, restart, or resume a list of sources atomically. */ -AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Stop a list of sources atomically. */ -AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Rewind a list of sources atomically. */ -AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Pause a list of sources atomically. */ -AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Queue buffers onto a source */ -AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); +AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; /** Unqueue processed buffers from a source */ -AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); +AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; /** Create buffer objects */ -AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); +AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; /** Delete buffer objects */ -AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); +AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; /** Verify an ID is a valid buffer (including the NULL buffer) */ -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) AL_API_NOEXCEPT; /** * Copies data into the buffer, interpreting it using the specified format and * samplerate. */ -AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; /* Set buffer parameters. */ -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); -AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get buffer parameters. */ -AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; #endif /* AL_NO_PROTOTYPES */ /* Pointer-to-function types, useful for storing dynamically loaded AL entry * points. */ -typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); -typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); -typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); -typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); -typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); -typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); -typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); -typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); -typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); -typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); -typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); -typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); -typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); -typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); -typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); -typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); -typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); -typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); +typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERROR)(void) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel) AL_API_NOEXCEPT17; #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_AL_H */ diff --git a/Source/ThirdParty/OpenAL/alc.h b/Source/ThirdParty/OpenAL/alc.h index 6d2103335..d048ca04d 100644 --- a/Source/ThirdParty/OpenAL/alc.h +++ b/Source/ThirdParty/OpenAL/alc.h @@ -1,8 +1,40 @@ #ifndef AL_ALC_H #define AL_ALC_H +/* NOLINTBEGIN */ #ifdef __cplusplus extern "C" { + +#ifdef _MSVC_LANG +#define ALC_CPLUSPLUS _MSVC_LANG +#else +#define ALC_CPLUSPLUS __cplusplus +#endif + +#ifndef AL_DISABLE_NOEXCEPT +#if ALC_CPLUSPLUS >= 201103L +#define ALC_API_NOEXCEPT noexcept +#else +#define ALC_API_NOEXCEPT +#endif +#if ALC_CPLUSPLUS >= 201703L +#define ALC_API_NOEXCEPT17 noexcept +#else +#define ALC_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 +#endif + +#undef ALC_CPLUSPLUS + +#else /* __cplusplus */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 #endif #ifndef ALC_API @@ -172,34 +204,34 @@ typedef void ALCvoid; /* Context management. */ /** Create and attach a context to the given device. */ -ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist); +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT; /** * Makes the given context the active process-wide context. Passing NULL clears * the active context. */ -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) ALC_API_NOEXCEPT; /** Resumes processing updates for the given context. */ -ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Suspends updates for the given context. */ -ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Remove a context from its device and destroys it. */ -ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Returns the currently active context. */ -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) ALC_API_NOEXCEPT; /** Returns the device that a particular context is attached to. */ -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context) ALC_API_NOEXCEPT; /* Device management. */ /** Opens the named playback device. */ -ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename) ALC_API_NOEXCEPT; /** Closes the given playback device. */ -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; /* Error support. */ /** Obtain the most recent Device error. */ -ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) ALC_API_NOEXCEPT; /* Extension support. */ @@ -207,24 +239,24 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); * Query for the presence of an extension on the device. Pass a NULL device to * query a device-inspecific extension. */ -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT; /** * Retrieve the address of a function. Given a non-NULL device, the returned * function may be device-specific. */ -ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT; /** * Retrieve the value of an enum. Given a non-NULL device, the returned value * may be device-specific. */ -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT; /* Query functions. */ /** Returns information about the device, and error strings. */ -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT; /** Returns information about the device and the version of OpenAL. */ -ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT; /* Capture functions. */ @@ -232,43 +264,44 @@ ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum pa * Opens the named capture device with the given frequency, format, and buffer * size. */ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT; /** Closes the given capture device. */ -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; /** Starts capturing samples into the device buffer. */ -ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) ALC_API_NOEXCEPT; /** Stops capturing samples. Samples in the device buffer remain available. */ -ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) ALC_API_NOEXCEPT; /** Reads samples from the device buffer. */ -ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT; #endif /* ALC_NO_PROTOTYPES */ /* Pointer-to-function types, useful for storing dynamically loaded ALC entry * points. */ -typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); -typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); -typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); -typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); -typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); -typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); -typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); -typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); -typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); -typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); -typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); -typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT17; +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT17; +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT17; #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_ALC_H */ diff --git a/Source/ThirdParty/OpenAL/alext.h b/Source/ThirdParty/OpenAL/alext.h index d313a999a..3908e1940 100644 --- a/Source/ThirdParty/OpenAL/alext.h +++ b/Source/ThirdParty/OpenAL/alext.h @@ -1,6 +1,7 @@ #ifndef AL_ALEXT_H #define AL_ALEXT_H +/* NOLINTBEGIN */ #include /* Define int64 and uint64 types */ #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ @@ -25,6 +26,8 @@ typedef uint64_t _alsoft_uint64_t; extern "C" { #endif +struct _GUID; + #ifndef AL_LOKI_IMA_ADPCM_format #define AL_LOKI_IMA_ADPCM_format 1 #define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 @@ -141,9 +144,9 @@ extern "C" { #ifndef AL_EXT_STATIC_BUFFER #define AL_EXT_STATIC_BUFFER 1 -typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALuint,ALenum,ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALuint,ALenum,ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq); +void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; #endif #endif @@ -159,11 +162,11 @@ void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid * #ifndef ALC_EXT_thread_local_context #define ALC_EXT_thread_local_context 1 -typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); +typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) ALC_API_NOEXCEPT; +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) ALC_API_NOEXCEPT; #endif #endif @@ -176,9 +179,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); #define AL_SOFT_buffer_sub_data 1 #define AL_BYTE_RW_OFFSETS_SOFT 0x1031 #define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); +AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) AL_API_NOEXCEPT; #endif #endif @@ -195,12 +198,12 @@ AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const AL #define AL_FOLDBACK_EVENT_STOP 0x4113 #define AL_FOLDBACK_MODE_MONO 0x4101 #define AL_FOLDBACK_MODE_STEREO 0x4102 -typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); +typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); -AL_API void AL_APIENTRY alRequestFoldbackStop(void); +AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alRequestFoldbackStop(void) AL_API_NOEXCEPT; #endif #endif @@ -263,15 +266,15 @@ AL_API void AL_APIENTRY alRequestFoldbackStop(void); #define AL_SAMPLE_LENGTH_SOFT 0x200A #define AL_SEC_LENGTH_SOFT 0x200B -typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); -typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) AL_API_NOEXCEPT; #endif #endif @@ -302,13 +305,13 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); #define ALC_6POINT1_SOFT 0x1505 #define ALC_7POINT1_SOFT 0x1506 -typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); -typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); -typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); +typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); -ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) AL_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) AL_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) AL_API_NOEXCEPT; #endif #endif @@ -328,31 +331,31 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe #define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 typedef _alsoft_int64_t ALint64SOFT; typedef _alsoft_uint64_t ALuint64SOFT; -typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); +typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); -AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); -AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); -AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); -AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); -AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); -AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); -AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); -AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); -AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); -AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); -AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); +AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; #endif #endif @@ -364,11 +367,11 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64 #ifndef AL_SOFT_deferred_updates #define AL_SOFT_deferred_updates 1 #define AL_DEFERRED_UPDATES_SOFT 0xC002 -typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); -typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); +typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alDeferUpdatesSOFT(void); -AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); +AL_API void AL_APIENTRY alDeferUpdatesSOFT(void) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alProcessUpdatesSOFT(void) AL_API_NOEXCEPT; #endif #endif @@ -400,11 +403,11 @@ AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); #ifndef ALC_SOFT_pause_device #define ALC_SOFT_pause_device 1 -typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); -typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); +typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) ALC_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) ALC_API_NOEXCEPT; #endif #endif @@ -448,11 +451,11 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); #define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 #define ALC_HRTF_SPECIFIER_SOFT 0x1995 #define ALC_HRTF_ID_SOFT 0x1996 -typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); -typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); +typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); -ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT; #endif #endif @@ -467,9 +470,9 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi #define AL_DEFAULT_RESAMPLER_SOFT 0x1211 #define AL_SOURCE_RESAMPLER_SOFT 0x1212 #define AL_RESAMPLER_NAME_SOFT 0x1213 -typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index); +typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index); +AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index) AL_API_NOEXCEPT; #endif #endif @@ -493,9 +496,9 @@ typedef _alsoft_uint64_t ALCuint64SOFT; #define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 #define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 #define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 -typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT; #endif #endif @@ -552,27 +555,26 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, #define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5 #define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6 typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param, - ALsizei length, const ALchar *message, - void *userParam); -typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable); -typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam); -typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname); -typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values); + ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable); -AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam); -AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname); -AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values); +AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values) AL_API_NOEXCEPT; #endif #endif #ifndef ALC_SOFT_reopen_device #define ALC_SOFT_reopen_device typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device, - const ALCchar *deviceName, const ALCint *attribs); + const ALCchar *deviceName, const ALCint *attribs) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, - const ALCint *attribs); + const ALCint *attribs) ALC_API_NOEXCEPT; #endif #endif @@ -580,16 +582,16 @@ ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *de #define AL_SOFT_callback_buffer #define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 #define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 -typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); -typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value); -typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values); +typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); -AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); -AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); +AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; #endif #endif @@ -640,16 +642,451 @@ AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid #ifndef AL_SOFT_source_start_delay #define AL_SOFT_source_start_delay -typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMESOFT)(ALuint source, ALint64SOFT start_time); -typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMEVSOFT)(ALsizei n, const ALuint *sources, ALint64SOFT start_time); +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMESOFT)(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMEVSOFT)(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time); -void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time); +void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; #endif #endif +#ifndef ALC_EXT_debug +#define ALC_EXT_debug +#define ALC_CONTEXT_FLAGS_EXT 0x19CF +#define ALC_CONTEXT_DEBUG_BIT_EXT 0x0001 +#endif + +#ifndef AL_EXT_debug +#define AL_EXT_debug +#define AL_DONT_CARE_EXT 0x0002 +#define AL_DEBUG_OUTPUT_EXT 0x19B2 +#define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 +#define AL_DEBUG_CALLBACK_USER_PARAM_EXT 0x19B4 +#define AL_DEBUG_SOURCE_API_EXT 0x19B5 +#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT 0x19B6 +#define AL_DEBUG_SOURCE_THIRD_PARTY_EXT 0x19B7 +#define AL_DEBUG_SOURCE_APPLICATION_EXT 0x19B8 +#define AL_DEBUG_SOURCE_OTHER_EXT 0x19B9 +#define AL_DEBUG_TYPE_ERROR_EXT 0x19BA +#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT 0x19BB +#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT 0x19BC +#define AL_DEBUG_TYPE_PORTABILITY_EXT 0x19BD +#define AL_DEBUG_TYPE_PERFORMANCE_EXT 0x19BE +#define AL_DEBUG_TYPE_MARKER_EXT 0x19BF +#define AL_DEBUG_TYPE_PUSH_GROUP_EXT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_EXT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_EXT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_EXT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_EXT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_EXT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_EXT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_EXT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB +#define AL_MAX_LABEL_LENGTH_EXT 0x19CC +#define AL_STACK_OVERFLOW_EXT 0x19CD +#define AL_STACK_UNDERFLOW_EXT 0x19CE +#define AL_CONTEXT_FLAGS_EXT 0x19CF +#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ +#define AL_SOURCE_EXT 0x19D0 +#define AL_FILTER_EXT 0x19D1 +#define AL_EFFECT_EXT 0x19D2 +#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 + +typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTEREXT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVEXT)(ALenum pname, void **values) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerEXT(ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervEXT(ALenum pname, void **values) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef ALC_SOFT_system_events +#define ALC_SOFT_system_events +#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 +#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 +#define ALC_EVENT_SUPPORTED_SOFT 0x19D9 +#define ALC_EVENT_NOT_SUPPORTED_SOFT 0x19DA +typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, + ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY*LPALCEVENTISSUPPORTEDSOFT)(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT; +ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; +void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_EXT_direct_context +#define AL_EXT_direct_context +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS2)(ALCdevice *device, const ALCchar *funcname) AL_API_NOEXCEPT17; + +typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +/* ALC_EXT_EFX */ +typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +/* AL_EXT_BUFFER_DATA_STATIC */ +typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; +/* AL_EXT_debug */ +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERDIRECTEXT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVDIRECTEXT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_EXT_FOLDBACK */ +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_buffer_sub_data */ +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; +/* AL_SOFT_source_latency */ +typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +/* AL_SOFT_deferred_updates */ +typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_source_resampler */ +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT17; +/* AL_SOFT_events */ +typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_SOFT_callback_buffer */ +typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; +/* AL_SOFT_source_start_delay */ +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; +/* EAX */ +typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCvoid* ALC_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALCchar *funcName) AL_API_NOEXCEPT; + +void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; + +void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT; +ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT; + +void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT; +void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; + +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectEXT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectEXT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; +void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT; + +void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_bformat_hoa +#define AL_SOFT_bformat_hoa +#define AL_UNPACK_AMBISONIC_ORDER_SOFT 0x199D +#endif + #ifdef __cplusplus } #endif +/* NOLINTEND */ #endif diff --git a/Source/ThirdParty/OpenAL/efx-presets.h b/Source/ThirdParty/OpenAL/efx-presets.h index 8539fd517..acd5bf398 100644 --- a/Source/ThirdParty/OpenAL/efx-presets.h +++ b/Source/ThirdParty/OpenAL/efx-presets.h @@ -2,6 +2,7 @@ #ifndef EFX_PRESETS_H #define EFX_PRESETS_H +/* NOLINTBEGIN */ #ifndef EFXEAXREVERBPROPERTIES_DEFINED #define EFXEAXREVERBPROPERTIES_DEFINED @@ -399,4 +400,5 @@ typedef struct { #define EFX_REVERB_PRESET_SMALLWATERROOM \ { 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } +/* NOLINTEND */ #endif /* EFX_PRESETS_H */ diff --git a/Source/ThirdParty/OpenAL/efx.h b/Source/ThirdParty/OpenAL/efx.h index 5ab64a64d..1e93bf222 100644 --- a/Source/ThirdParty/OpenAL/efx.h +++ b/Source/ThirdParty/OpenAL/efx.h @@ -1,6 +1,7 @@ #ifndef AL_EFX_H #define AL_EFX_H +/* NOLINTBEGIN */ #include #include "alc.h" @@ -204,80 +205,80 @@ extern "C" { /* Effect object function types. */ -typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); -typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Filter object function types. */ -typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); -typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Auxiliary Effect Slot object function types. */ -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); -AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); -AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); -AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; -AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); -AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); -AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); -AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; -AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); -AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); -AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); -AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; #endif /* Filter ranges and defaults. */ @@ -758,5 +759,6 @@ AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum par #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_EFX_H */ diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs index f13449192..aa4584135 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs @@ -49,7 +49,9 @@ namespace Flax.Deps.Dependencies public override void Build(BuildOptions options) { var root = options.IntermediateFolder; - var version = "1.23.1"; + var version = "1.24.3"; + string configuration = "Release"; + int concurrency = Math.Min(Math.Max(1, (int)(Environment.ProcessorCount * Configuration.ConcurrencyProcessorScale)), Configuration.MaxConcurrency); var dstIncludePath = Path.Combine(options.ThirdPartyFolder, "OpenAL"); foreach (var platform in options.Platforms) @@ -65,11 +67,9 @@ namespace Flax.Deps.Dependencies "OpenAL32.dll", }; - string configuration = "Release"; - // Get the source CloneGitRepo(root, "https://github.com/kcat/openal-soft.git"); - GitCheckout(root, "master", "d3875f333fb6abe2f39d82caca329414871ae53b"); // 1.23.1 + GitCheckout(root, "master", "dc7d7054a5b4f3bec1dc23a42fd616a0847af948"); // 1.24.3 // Build for Win64 and ARM64 foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 }) @@ -121,8 +121,9 @@ namespace Flax.Deps.Dependencies }; var envVars = new Dictionary { - { "CC", "clang-7" }, - { "CC_FOR_BUILD", "clang-7" } + { "CC", "clang" }, + { "CC_FOR_BUILD", "clang" }, + { "CMAKE_BUILD_PARALLEL_LEVEL", concurrency.ToString() }, }; var config = "-DALSOFT_REQUIRE_ALSA=ON -DALSOFT_REQUIRE_OSS=ON -DALSOFT_REQUIRE_PORTAUDIO=ON -DALSOFT_REQUIRE_PULSEAUDIO=ON -DALSOFT_REQUIRE_JACK=ON -DALSOFT_EMBED_HRTF_DATA=YES"; @@ -138,8 +139,8 @@ namespace Flax.Deps.Dependencies SetupDirectory(buildDir, true); // Build for Linux - Utilities.Run("cmake", "-G \"Unix Makefiles\" -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DLIBTYPE=STATIC " + config + " ..", null, buildDir, Utilities.RunOptions.ConsoleLogOutput, envVars); - Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.ConsoleLogOutput, envVars); + Utilities.Run("cmake", $"-G \"Unix Makefiles\" -DCMAKE_BUILD_TYPE={configuration} -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DLIBTYPE=STATIC {config} ..", null, buildDir, Utilities.RunOptions.ConsoleLogOutput, envVars); + BuildCmake(buildDir, configuration, envVars); var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64); foreach (var file in binariesToCopy) Utilities.FileCopy(Path.Combine(buildDir, file), Path.Combine(depsFolder, file)); From 36c1909111cf197a77289e2e393a318de08e13c0 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 5 Apr 2025 13:48:16 +0300 Subject: [PATCH 014/137] Build OpenAL with PipeWire backend enabled --- Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs index aa4584135..3bc9611e8 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs @@ -125,7 +125,13 @@ namespace Flax.Deps.Dependencies { "CC_FOR_BUILD", "clang" }, { "CMAKE_BUILD_PARALLEL_LEVEL", concurrency.ToString() }, }; - var config = "-DALSOFT_REQUIRE_ALSA=ON -DALSOFT_REQUIRE_OSS=ON -DALSOFT_REQUIRE_PORTAUDIO=ON -DALSOFT_REQUIRE_PULSEAUDIO=ON -DALSOFT_REQUIRE_JACK=ON -DALSOFT_EMBED_HRTF_DATA=YES"; + var config = $"-DALSOFT_REQUIRE_ALSA=ON " + + $"-DALSOFT_REQUIRE_OSS=ON " + + $"-DALSOFT_REQUIRE_PORTAUDIO=ON " + + $"-DALSOFT_REQUIRE_PULSEAUDIO=ON " + + $"-DALSOFT_REQUIRE_JACK=ON " + + $"-DALSOFT_REQUIRE_PIPEWIRE=ON " + + $"-DALSOFT_EMBED_HRTF_DATA=YES "; // Get the source var packagePath = Path.Combine(root, "package.zip"); From fc96b248cb169ebd012fa37eb84887b767913054 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 5 Apr 2025 13:51:23 +0300 Subject: [PATCH 015/137] Ignore invalid VelocityChanged velocity values in audio backend --- Source/Engine/Audio/AudioBackend.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioBackend.h b/Source/Engine/Audio/AudioBackend.h index ee94e21a3..b7ab87759 100644 --- a/Source/Engine/Audio/AudioBackend.h +++ b/Source/Engine/Audio/AudioBackend.h @@ -4,6 +4,8 @@ #include "Config.h" #include "Types.h" + +#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Types/BaseTypes.h" /// @@ -83,7 +85,8 @@ public: FORCE_INLINE static void VelocityChanged(const Vector3& velocity) { - Instance->Listener_VelocityChanged(velocity); + if (!velocity.IsNanOrInfinity()) + Instance->Listener_VelocityChanged(velocity); } FORCE_INLINE static void TransformChanged(const Vector3& position, const Quaternion& orientation) From 40dae18b7659b7af3ed7eb79a9911fa7d6ebcad5 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Thu, 24 Apr 2025 18:48:29 -0500 Subject: [PATCH 016/137] Add new issue and request templates. --- .github/ISSUE_TEMPLATE/1-bug.yaml | 42 +++++++++++++++++++ .github/ISSUE_TEMPLATE/2-feature-request.yaml | 22 ++++++++++ ISSUE_TEMPLATE.md | 19 --------- 3 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/1-bug.yaml create mode 100644 .github/ISSUE_TEMPLATE/2-feature-request.yaml delete mode 100644 ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE/1-bug.yaml b/.github/ISSUE_TEMPLATE/1-bug.yaml new file mode 100644 index 000000000..acae26c00 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug.yaml @@ -0,0 +1,42 @@ +name: Bug Report +description: File a bug report. +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! Please attach any minimal repoduction projects! + - type: textarea + id: description-area + attributes: + label: Description + description: Please provide a description and what you expected to happen. + validations: + required: true + - type: textarea + id: steps-area + attributes: + label: Steps to reproduce + description: Please provide an repoduction steps. + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of Flax are you running? + options: + - 1.8 + - 1.9 + - 1.10 + - 1.11 + - master branch + default: 2 + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant logs + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.yaml b/.github/ISSUE_TEMPLATE/2-feature-request.yaml new file mode 100644 index 000000000..235c863e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-feature-request.yaml @@ -0,0 +1,22 @@ +name: Feature Request +description: File a feature request. +title: "[Request]: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out a feature request! + - type: textarea + id: description-area + attributes: + label: Description + description: Please provide a description of the feature! + validations: + required: true + - type: textarea + id: benifits-area + attributes: + label: Benifits + description: Please provide what benifits this feature would provide to the engine! + validations: + required: true \ No newline at end of file diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 798f210ef..000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,19 +0,0 @@ - - -**Issue description:** - - - -**Steps to reproduce:** - - - -**Minimal reproduction project:** - - - -**Flax version:** - - From 47a6da9e40d57c59e3eae1c051cf0fb6ce430397 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sun, 27 Apr 2025 15:56:34 +0200 Subject: [PATCH 017/137] add editor option for disabled transform gizmo brightness --- .../Editor/Gizmo/TransformGizmoBase.Draw.cs | 91 +++++++++++-------- Source/Editor/Options/VisualOptions.cs | 7 ++ 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index bb9684869..8523b9378 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -21,13 +21,17 @@ namespace FlaxEditor.Gizmo private MaterialInstance _materialAxisY; private MaterialInstance _materialAxisZ; private MaterialInstance _materialAxisFocus; - private MaterialInstance _materialAxisLocked; private MaterialBase _materialSphere; // Material Parameter Names const String _brightnessParamName = "Brightness"; const String _opacityParamName = "Opacity"; + /// + /// Used for example when the selection can't be moved because one actor is static. + /// + private bool _isDisabled; + private void InitDrawing() { // Axis Models @@ -42,7 +46,6 @@ namespace FlaxEditor.Gizmo _materialAxisY = FlaxEngine.Content.LoadAsyncInternal("Editor/Gizmo/MaterialAxisY"); _materialAxisZ = FlaxEngine.Content.LoadAsyncInternal("Editor/Gizmo/MaterialAxisZ"); _materialAxisFocus = FlaxEngine.Content.LoadAsyncInternal("Editor/Gizmo/MaterialAxisFocus"); - _materialAxisLocked = FlaxEngine.Content.LoadAsyncInternal("Editor/Gizmo/MaterialAxisLocked"); _materialSphere = FlaxEngine.Content.LoadAsyncInternal("Editor/Gizmo/MaterialSphere"); // Ensure that every asset was loaded @@ -67,17 +70,41 @@ namespace FlaxEditor.Gizmo private void OnEditorOptionsChanged(EditorOptions options) { - float brightness = options.Visual.TransformGizmoBrightness; - _materialAxisX.SetParameterValue(_brightnessParamName, brightness); - _materialAxisY.SetParameterValue(_brightnessParamName, brightness); - _materialAxisZ.SetParameterValue(_brightnessParamName, brightness); - _materialAxisLocked.SetParameterValue(_brightnessParamName, brightness); - + UpdateGizmoBrightness(options); + float opacity = options.Visual.TransformGizmoOpacity; _materialAxisX.SetParameterValue(_opacityParamName, opacity); _materialAxisY.SetParameterValue(_opacityParamName, opacity); _materialAxisZ.SetParameterValue(_opacityParamName, opacity); - _materialAxisLocked.SetParameterValue(_opacityParamName, opacity); + } + + private void UpdateGizmoBrightness(EditorOptions options) + { + _isDisabled = ShouldGizmoBeLocked(); + + float brightness = _isDisabled ? options.Visual.TransformGizmoBrighnessDisabled : options.Visual.TransformGizmoBrightness; + _materialAxisX.SetParameterValue(_brightnessParamName, brightness); + _materialAxisY.SetParameterValue(_brightnessParamName, brightness); + _materialAxisZ.SetParameterValue(_brightnessParamName, brightness); + } + + private bool ShouldGizmoBeLocked() + { + bool gizmoLocked = false; + + if (Editor.Instance.StateMachine.IsPlayMode) + { + foreach (SceneGraphNode obj in Editor.Instance.SceneEditing.Selection) + { + if (obj.CanTransform == false) + { + gizmoLocked = true; + break; + } + } + } + + return gizmoLocked; } /// @@ -88,20 +115,8 @@ namespace FlaxEditor.Gizmo if (!_modelCube || !_modelCube.IsLoaded) return; - // Find out if any of the selected objects can not be moved - bool gizmoLocked = false; - if (Editor.Instance.StateMachine.IsPlayMode) - { - for (int i = 0; i < SelectionCount; i++) - { - var obj = GetSelectedObject(i); - if (obj.CanTransform == false) - { - gizmoLocked = true; - break; - } - } - } + // Update the gizmo brightness every frame to ensure it updates correctly + UpdateGizmoBrightness(Editor.Instance.Options.Options); // As all axisMesh have the same pivot, add a little offset to the x axisMesh, this way SortDrawCalls is able to sort the draw order // https://github.com/FlaxEngine/FlaxEngine/issues/680 @@ -136,37 +151,37 @@ namespace FlaxEditor.Gizmo // X axis Matrix.RotationY(-Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance xAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX); + MaterialInstance xAxisMaterialTransform = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; transAxisMesh.Draw(ref renderContext, xAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Y axis Matrix.RotationX(Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance yAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY); + MaterialInstance yAxisMaterialTransform = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; transAxisMesh.Draw(ref renderContext, yAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Z axis Matrix.RotationX(Mathf.Pi, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance zAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ); + MaterialInstance zAxisMaterialTransform = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; transAxisMesh.Draw(ref renderContext, zAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // XY plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance xyPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX); + MaterialInstance xyPlaneMaterialTransform = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX; cubeMesh.Draw(ref renderContext, xyPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // ZX plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance zxPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisY); + MaterialInstance zxPlaneMaterialTransform = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisY; cubeMesh.Draw(ref renderContext, zxPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // YZ plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance yzPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisZ); + MaterialInstance yzPlaneMaterialTransform = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; cubeMesh.Draw(ref renderContext, yzPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Center sphere @@ -186,17 +201,17 @@ namespace FlaxEditor.Gizmo // X axis Matrix.RotationZ(Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX); + MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; rotationAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Y axis - MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY); + MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; rotationAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m1, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Z axis Matrix.RotationX(-Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ); + MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; rotationAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Center box @@ -216,37 +231,37 @@ namespace FlaxEditor.Gizmo // X axis Matrix.RotationY(-Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref mx1, out m3); - MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX); + MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; scaleAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Y axis Matrix.RotationX(Mathf.PiOverTwo, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY); + MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; scaleAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Z axis Matrix.RotationX(Mathf.Pi, out m2); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ); + MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; scaleAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // XY plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance xyPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX); + MaterialInstance xyPlaneMaterialScale = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX; cubeMesh.Draw(ref renderContext, xyPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // ZX plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance zxPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ); + MaterialInstance zxPlaneMaterialScale = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; cubeMesh.Draw(ref renderContext, zxPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // YZ plane m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale)); Matrix.Multiply(ref m2, ref m1, out m3); - MaterialInstance yzPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY); + MaterialInstance yzPlaneMaterialScale = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisY; cubeMesh.Draw(ref renderContext, yzPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); // Center box diff --git a/Source/Editor/Options/VisualOptions.cs b/Source/Editor/Options/VisualOptions.cs index 3a12dd0c5..45a1f1b13 100644 --- a/Source/Editor/Options/VisualOptions.cs +++ b/Source/Editor/Options/VisualOptions.cs @@ -81,6 +81,13 @@ namespace FlaxEditor.Options [EditorDisplay("Transform Gizmo", "Gizmo Opacity"), EditorOrder(211)] public float TransformGizmoOpacity { get; set; } = 1f; + /// + /// Gets or set a value indicating how bright the transform gizmo is when it is disabled, for example when one of the selected actors is static in play mode. Use a value of 0 to make the gizmo fully gray. Value over 1 will result in the gizmo emitting light. + /// + [DefaultValue(0.25f), Range(0f, 5f)] + [EditorDisplay("Transform Gizmo", "Disabled Gizmo Brightness"), EditorOrder(212)] + public float TransformGizmoBrighnessDisabled { get; set; } = 0.25f; + /// /// Gets or sets a value indicating whether enable MSAA for DebugDraw primitives rendering. Helps with pixel aliasing but reduces performance. /// From f71bdd09625cea8964ef2e9515648b7cab061e00 Mon Sep 17 00:00:00 2001 From: Norite SC <162097313+cNori@users.noreply.github.com> Date: Tue, 13 May 2025 01:13:16 +0200 Subject: [PATCH 018/137] Create GPUTextureEditor.cs --- Source/Editor/GUI/GPUTextureEditor.cs | 112 ++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Source/Editor/GUI/GPUTextureEditor.cs diff --git a/Source/Editor/GUI/GPUTextureEditor.cs b/Source/Editor/GUI/GPUTextureEditor.cs new file mode 100644 index 000000000..5dd672941 --- /dev/null +++ b/Source/Editor/GUI/GPUTextureEditor.cs @@ -0,0 +1,112 @@ +#if FLAX_EDITOR +using FlaxEditor.CustomEditors; +using FlaxEditor.CustomEditors.Editors; +using FlaxEditor.CustomEditors.Elements; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.Scripting; +using FlaxEditor.Tools.Foliage; +using FlaxEngine; +using FlaxEngine.GUI; +using FlaxEngine.Utilities; + +namespace FlaxEditor.GUI +{ + /// + /// basic custom property editor for GPUTexture + /// + [CustomEditor(typeof(GPUTexture))] + public class GPUTexturePropertyEditor : GenericEditor + { + public override DisplayStyle Style => DisplayStyle.Inline; + + ImageElement imageElement; + GroupElement group; + /// + /// + /// + public override void Initialize(LayoutElementsContainer layout) + { + imageElement = (group = layout.Group("")).Image(SpriteHandle.Default); + + //todo fix the AddSettingsButton func + //shit is buged + //the code below (until the Paint) is untested the Clear might not work + group.AddSettingsButton(); + group.SetupContextMenu += (ContextMenu.ContextMenu cxm, DropPanel dp) => + { + cxm.AddButton("Clear", (ContextMenuButton bt) => + { + SetValue(null); + }); + + cxm.AddSeparator(); + + //todo + //editor is needed + //cxm.AddButton("Display Full Texture", (ContextMenuButton bt) => + //{ + //}); + + //todo + // + //cxm.AddButton("Save To Asset", (ContextMenuButton bt) => + //{ + //}); + }; + Paint(); + group.Panel.Close(); + } + /// + /// + public override void Refresh() + { + Paint(); + base.Refresh(); + } + private void Paint() + { + string name = null; + string tt = null; + if (Values[0] is GPUTexture gputex) + { + name = gputex.Name; + tt += "Type: " + gputex.ResourceType.ToString() + "\n"; + tt += "Memory Usage: " + gputex.MemoryUsage + "B" + "\n"; + tt += "Format: " + gputex.Format.ToString() + "\n"; + //shorten the name it is a full path + if (name.EndsWith(".flax")) + { + if (name != ".flax")//sanity guard + { + var nameStartIndexWithEx = Globals.ProjectFolder.Length + 9 /* +9 to remove the "/Content/" */; + name = name.Substring + ( + nameStartIndexWithEx, + nameStartIndexWithEx - 5 /* -5 to remove the .flax */ + 2 + ); + + tt += "Path: " + gputex.Name.Remove(0, Globals.ProjectFolder.Length + 1); + } + } + + if (imageElement.Image.Brush is GPUTextureBrush brush) + { + brush.Texture = gputex; + imageElement.Control.Size = new Float2(group.Control.Width); + } + else + { + imageElement.Image.Brush = new GPUTextureBrush(); + Paint(); + } + } + name ??= "..."; + + DropPanel p = group.Control as DropPanel; + + p.HeaderText = name; + p.TooltipText = tt; + } + } +} +#endif From 608839b6a5eb547929dfe0c270c0a1f6cf0697ae Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Mon, 2 Jun 2025 22:33:22 +0200 Subject: [PATCH 019/137] set width of command suggestions based on longest command --- Source/Editor/Windows/OutputLogWindow.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs index 6fc0659d7..5c6e9a27e 100644 --- a/Source/Editor/Windows/OutputLogWindow.cs +++ b/Source/Editor/Windows/OutputLogWindow.cs @@ -233,7 +233,10 @@ namespace FlaxEditor.Windows else cm.ClearItems(); + float longestItemWidth = 0.0f; + // Add items + var font = Style.Current.FontMedium; ItemsListContextMenu.Item lastItem = null; foreach (var command in commands) { @@ -244,7 +247,7 @@ namespace FlaxEditor.Windows }); var flags = DebugCommands.GetCommandFlags(command); if (flags.HasFlag(DebugCommands.CommandFlags.Exec)) - lastItem.TintColor = new Color(0.85f, 0.85f, 1.0f, 1.0f); + lastItem.TintColor = new Color(0.75f, 0.75f, 1.0f, 1.0f); else if (flags.HasFlag(DebugCommands.CommandFlags.Read) && !flags.HasFlag(DebugCommands.CommandFlags.Write)) lastItem.TintColor = new Color(0.85f, 0.85f, 0.85f, 1.0f); lastItem.Focused += item => @@ -252,6 +255,10 @@ namespace FlaxEditor.Windows // Set command Set(item.Name); }; + + float width = font.MeasureText(command).X; + if (width > longestItemWidth) + longestItemWidth = width; } cm.ItemClicked += item => { @@ -262,6 +269,10 @@ namespace FlaxEditor.Windows // Setup popup var count = commands.Count(); var totalHeight = count * lastItem.Height + cm.ItemsPanel.Margin.Height + cm.ItemsPanel.Spacing * (count - 1); + + // Account for scroll bars taking up a part of the width + longestItemWidth += 25f; + cm.Width = longestItemWidth; cm.Height = 220; if (cm.Height > totalHeight) cm.Height = totalHeight; // Limit popup height if list is small From c9fe9213b33835e79432d5a4c801efd83c4aba62 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Mon, 2 Jun 2025 23:25:50 +0200 Subject: [PATCH 020/137] add showing all commands if prompt is whitespace(s) --- Source/Editor/Windows/OutputLogWindow.cs | 11 ++++++++--- Source/Engine/Debug/DebugCommands.cpp | 11 +++++++++++ Source/Engine/Debug/DebugCommands.h | 7 +++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs index 5c6e9a27e..7d3dfa644 100644 --- a/Source/Editor/Windows/OutputLogWindow.cs +++ b/Source/Editor/Windows/OutputLogWindow.cs @@ -325,12 +325,17 @@ namespace FlaxEditor.Windows // Show commands search popup based on current text input var text = Text.Trim(); - if (text.Length != 0) + bool isWhitespaceOnly = string.IsNullOrWhiteSpace(Text) && !string.IsNullOrEmpty(Text); + if (text.Length != 0 || isWhitespaceOnly) { DebugCommands.Search(text, out var matches); - if (matches.Length != 0) + if (matches.Length != 0 || isWhitespaceOnly) { - ShowPopup(ref _searchPopup, matches, text); + string[] commands = []; + if (isWhitespaceOnly) + DebugCommands.GetAllCommands(out commands); + + ShowPopup(ref _searchPopup, isWhitespaceOnly ? commands : matches, isWhitespaceOnly ? commands[0] : text); return; } } diff --git a/Source/Engine/Debug/DebugCommands.cpp b/Source/Engine/Debug/DebugCommands.cpp index 5d94cf557..9c66341ab 100644 --- a/Source/Engine/Debug/DebugCommands.cpp +++ b/Source/Engine/Debug/DebugCommands.cpp @@ -435,6 +435,17 @@ void DebugCommands::InitAsync() AsyncTask = Task::StartNew(InitCommands); } +void DebugCommands::GetAllCommands(Array& commands) +{ + EnsureInited(); + ScopeLock lock(Locker); + + for (auto& command : Commands) + { + commands.Add(command.Name); + } +} + DebugCommands::CommandFlags DebugCommands::GetCommandFlags(StringView command) { CommandFlags result = CommandFlags::None; diff --git a/Source/Engine/Debug/DebugCommands.h b/Source/Engine/Debug/DebugCommands.h index 73b2def69..6028ab9d8 100644 --- a/Source/Engine/Debug/DebugCommands.h +++ b/Source/Engine/Debug/DebugCommands.h @@ -46,6 +46,13 @@ public: /// API_FUNCTION() static void InitAsync(); + /// + /// Gets all available commands. + /// + /// The output list of all commands (unsorted). + /// TODO. + API_FUNCTION() static void GetAllCommands(API_PARAM(Out) Array& commands); + /// /// Returns flags of the command. /// From c4130aa20f649b64649d4c3e901c6546a1f50afd Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 4 Jun 2025 15:23:42 +0200 Subject: [PATCH 021/137] fix and improve show all commands on " " behavior --- Source/Editor/Windows/OutputLogWindow.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs index 7d3dfa644..f1efebeb4 100644 --- a/Source/Editor/Windows/OutputLogWindow.cs +++ b/Source/Editor/Windows/OutputLogWindow.cs @@ -335,7 +335,15 @@ namespace FlaxEditor.Windows if (isWhitespaceOnly) DebugCommands.GetAllCommands(out commands); - ShowPopup(ref _searchPopup, isWhitespaceOnly ? commands : matches, isWhitespaceOnly ? commands[0] : text); + ShowPopup(ref _searchPopup, isWhitespaceOnly ? commands : matches, text); + + if (isWhitespaceOnly) + { + // Scroll to and select first item for consistent behaviour + var firstItem = _searchPopup.ItemsPanel.Children[0] as Item; + _searchPopup.ScrollToAndHighlightItemByName(firstItem.Name); + } + return; } } From 6997cbeb477a34b92383b39d9dc4d7adfe3a5044 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Wed, 11 Jun 2025 13:08:59 +0200 Subject: [PATCH 022/137] add options for viewport icons --- Source/Editor/Options/ViewportOptions.cs | 21 +++++++++++++++++++ .../Utilities/ViewportIconsRenderer.cpp | 9 ++++---- .../Editor/Utilities/ViewportIconsRenderer.h | 15 +++++++++++++ Source/Editor/Viewport/EditorViewport.cs | 5 +++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Source/Editor/Options/ViewportOptions.cs b/Source/Editor/Options/ViewportOptions.cs index 13ab2a8b0..aed633672 100644 --- a/Source/Editor/Options/ViewportOptions.cs +++ b/Source/Editor/Options/ViewportOptions.cs @@ -150,5 +150,26 @@ namespace FlaxEditor.Options [DefaultValue(typeof(Color), "0.5,0.5,0.5,1.0")] [EditorDisplay("Grid"), EditorOrder(310), Tooltip("The color for the viewport grid.")] public Color ViewportGridColor { get; set; } = new Color(0.5f, 0.5f, 0.5f, 1.0f); + + /// + /// Gets or sets the minimum size used for viewport icons. + /// + [DefaultValue(7.0f), Limit(1.0f, 1000.0f, 5.0f)] + [EditorDisplay("Viewport Icons"), EditorOrder(400)] + public float IconsMinimumSize { get; set; } = 7.0f; + + /// + /// Gets or sets the maximum size used for viewport icons. + /// + [DefaultValue(30.0f), Limit(1.0f, 1000.0f, 5.0f)] + [EditorDisplay("Viewport Icons"), EditorOrder(410)] + public float IconsMaximumSize { get; set; } = 30.0f; + + /// + /// Gets or sets the distance towards the camera at which the max icon scale will be applied. Set to 0 to disable scaling the icons based on the distance to the camera. + /// + [DefaultValue(1000.0f), Limit(0.0f, 20000.0f, 5.0f)] + [EditorDisplay("Viewport Icons"), EditorOrder(410)] + public float MaxSizeDistance { get; set; } = 1000.0f; } } diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 1f721d289..690c55424 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -65,13 +65,14 @@ public: ViewportIconsRendererService ViewportIconsRendererServiceInstance; float ViewportIconsRenderer::Scale = 1.0f; +Real ViewportIconsRenderer::MinSize = 7.0f; +Real ViewportIconsRenderer::MaxSize = 30.0f; +Real ViewportIconsRenderer::MaxSizeDistance = 1000.0f; void ViewportIconsRenderer::GetBounds(const Vector3& position, const Vector3& viewPosition, BoundingSphere& bounds) { - constexpr Real minSize = 7.0; - constexpr Real maxSize = 30.0; - Real scale = Math::Square(Vector3::Distance(position, viewPosition) / 1000.0f); - Real radius = minSize + Math::Min(scale, 1.0f) * (maxSize - minSize); + Real scale = Math::Square(Vector3::Distance(position, viewPosition) / MaxSizeDistance); + Real radius = MinSize + Math::Min(scale, 1.0f) * (MaxSize - MinSize); bounds = BoundingSphere(position, radius * Scale); } diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.h b/Source/Editor/Utilities/ViewportIconsRenderer.h index c7bf7e1c3..a1e1538b8 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.h +++ b/Source/Editor/Utilities/ViewportIconsRenderer.h @@ -22,6 +22,21 @@ public: /// API_FIELD() static float Scale; + /// + /// The minimum size of the icons. + /// + API_FIELD() static Real MinSize; + + /// + /// The maximum size of the icons. + /// + API_FIELD() static Real MaxSize; + + /// + /// The distance to the camera at which the icons will be drawn at their maximum size. + /// + API_FIELD() static Real MaxSizeDistance; + /// /// Draws the icons for the actors in the given scene (or actor tree). /// diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index b4af43281..0f9fce7c0 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -1292,6 +1292,11 @@ namespace FlaxEditor.Viewport _mouseSensitivity = options.Viewport.MouseSensitivity; _maxSpeedSteps = options.Viewport.TotalCameraSpeedSteps; _cameraEasingDegree = options.Viewport.CameraEasingDegree; + + ViewportIconsRenderer.MinSize = options.Viewport.IconsMinimumSize; + ViewportIconsRenderer.MaxSize = options.Viewport.IconsMaximumSize; + ViewportIconsRenderer.MaxSizeDistance = options.Viewport.MaxSizeDistance; + OnCameraMovementProgressChanged(); } From ec154b4998415c218dc5017a72813ab43407ae15 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Thu, 12 Jun 2025 19:31:32 +0200 Subject: [PATCH 023/137] remove unnecessary returns xml doc comment --- Source/Engine/Debug/DebugCommands.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Engine/Debug/DebugCommands.h b/Source/Engine/Debug/DebugCommands.h index 6028ab9d8..cfe70db73 100644 --- a/Source/Engine/Debug/DebugCommands.h +++ b/Source/Engine/Debug/DebugCommands.h @@ -50,7 +50,6 @@ public: /// Gets all available commands. /// /// The output list of all commands (unsorted). - /// TODO. API_FUNCTION() static void GetAllCommands(API_PARAM(Out) Array& commands); /// From f40c67ddf0c21a269685c640d83d7428466e0698 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 13 Jun 2025 22:05:57 +0200 Subject: [PATCH 024/137] add support to move visject socket connections --- Source/Editor/Surface/Elements/Box.cs | 12 +++- .../Surface/VisjectSurface.Connecting.cs | 37 +++++++----- .../Surface/VisjectSurface.ContextMenu.cs | 9 +-- Source/Editor/Surface/VisjectSurface.Draw.cs | 56 ++++++++++--------- Source/Editor/Surface/VisjectSurface.Input.cs | 8 +-- .../Surface/VisjectSurface.Serialization.cs | 2 +- Source/Editor/Surface/VisjectSurface.cs | 8 +-- 7 files changed, 77 insertions(+), 55 deletions(-) diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs index 16b6b3c16..54ea0292d 100644 --- a/Source/Editor/Surface/Elements/Box.cs +++ b/Source/Editor/Surface/Elements/Box.cs @@ -552,7 +552,17 @@ namespace FlaxEditor.Surface.Elements _isMouseDown = false; if (Surface.CanEdit) { - if (!IsOutput && HasSingleConnection) + if (Input.GetKey(KeyboardKeys.Control)) + { + List connectedBoxes = new List(Connections); + + for (int i = 0; i < connectedBoxes.Count; i++) + { + BreakConnection(connectedBoxes[i]); + Surface.ConnectingStart(connectedBoxes[i], true); + } + } + else if (!IsOutput && HasSingleConnection) { var connectedBox = Connections[0]; if (Surface.Undo != null && Surface.Undo.Enabled) diff --git a/Source/Editor/Surface/VisjectSurface.Connecting.cs b/Source/Editor/Surface/VisjectSurface.Connecting.cs index dbc2b7fb5..d733c7a0e 100644 --- a/Source/Editor/Surface/VisjectSurface.Connecting.cs +++ b/Source/Editor/Surface/VisjectSurface.Connecting.cs @@ -1,5 +1,6 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System.Collections.Generic; using FlaxEditor.Scripting; using FlaxEngine; @@ -233,11 +234,15 @@ namespace FlaxEditor.Surface /// Begins connecting surface objects action. /// /// The connection instigator (eg. start box). - public void ConnectingStart(IConnectionInstigator instigator) + /// If the instigator should be added to the list of instigators. + public void ConnectingStart(IConnectionInstigator instigator, bool additive = false) { if (instigator != null && instigator != _connectionInstigator) { - _connectionInstigator = instigator; + if (!additive) + _connectionInstigator.Clear(); + + _connectionInstigator.Add(instigator); StartMouseCapture(); } } @@ -257,22 +262,26 @@ namespace FlaxEditor.Surface /// The end object (eg. end box). public void ConnectingEnd(IConnectionInstigator end) { - // Ensure that there was a proper start box - if (_connectionInstigator == null) + // Ensure that there is at least one connection instigator + if (_connectionInstigator.Count == 0) return; - var start = _connectionInstigator; - _connectionInstigator = null; - - // Check if boxes are different and end box is specified - if (start == end || end == null) - return; - - // Connect them - if (start.CanConnectWith(end)) + List instigators = new List(_connectionInstigator); + for (int i = 0; i < instigators.Count; i++) { - start.Connect(end); + var start = _connectionInstigator[i]; + + // Check if boxes are different and end box is specified + if (start == end || end == null) + return; + + // Connect them + if (start.CanConnectWith(end)) + start.Connect(end); } + + // Reset instigator list + _connectionInstigator.Clear(); } } } diff --git a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs index ee7dd33e5..98221ce6f 100644 --- a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs +++ b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs @@ -290,7 +290,7 @@ namespace FlaxEditor.Surface _cmStartPos = location; // Offset added in case the user doesn't like the box and wants to quickly get rid of it by clicking - OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, _connectionInstigator as Box); + OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, _connectionInstigator[0] as Box); if (!string.IsNullOrEmpty(input)) { @@ -475,9 +475,7 @@ namespace FlaxEditor.Surface private void OnPrimaryMenuVisibleChanged(Control primaryMenu) { if (!primaryMenu.Visible) - { - _connectionInstigator = null; - } + _connectionInstigator.Clear(); } /// @@ -555,8 +553,7 @@ namespace FlaxEditor.Surface } // If the user is patiently waiting for his box to get connected to the newly created one fulfill his wish! - - _connectionInstigator = startBox; + _connectionInstigator[0] = startBox; if (!IsConnecting) { diff --git a/Source/Editor/Surface/VisjectSurface.Draw.cs b/Source/Editor/Surface/VisjectSurface.Draw.cs index 5a63fe4de..dcf5e8108 100644 --- a/Source/Editor/Surface/VisjectSurface.Draw.cs +++ b/Source/Editor/Surface/VisjectSurface.Draw.cs @@ -1,5 +1,6 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System.Collections.Generic; using FlaxEditor.Surface.Elements; using FlaxEngine; @@ -126,40 +127,45 @@ namespace FlaxEditor.Surface /// Called only when user is connecting nodes. protected virtual void DrawConnectingLine() { - // Get start position - var startPos = _connectionInstigator.ConnectionOrigin; - - // Check if mouse is over any of box var cmVisible = _activeVisjectCM != null && _activeVisjectCM.Visible; var endPos = cmVisible ? _rootControl.PointFromParent(ref _cmStartPos) : _rootControl.PointFromParent(ref _mousePos); Color lineColor = Style.Colors.Connecting; - if (_lastInstigatorUnderMouse != null && !cmVisible) - { - // Check if can connect objects - bool canConnect = _connectionInstigator.CanConnectWith(_lastInstigatorUnderMouse); - lineColor = canConnect ? Style.Colors.ConnectingValid : Style.Colors.ConnectingInvalid; - endPos = _lastInstigatorUnderMouse.ConnectionOrigin; - } - Float2 actualStartPos = startPos; - Float2 actualEndPos = endPos; - - if (_connectionInstigator is Archetypes.Tools.RerouteNode) + List instigators = new List(_connectionInstigator); + for (int i = 0; i < instigators.Count; i++) { - if (endPos.X < startPos.X && _lastInstigatorUnderMouse is null or Box { IsOutput: true }) + IConnectionInstigator currentInstigator = instigators[i]; + Float2 currentStartPosition = currentInstigator.ConnectionOrigin; + + // Check if mouse is over any of box + if (_lastInstigatorUnderMouse != null && !cmVisible) + { + // Check if can connect objects + bool canConnect = currentInstigator.CanConnectWith(_lastInstigatorUnderMouse); + lineColor = canConnect ? Style.Colors.ConnectingValid : Style.Colors.ConnectingInvalid; + endPos = _lastInstigatorUnderMouse.ConnectionOrigin; + } + + Float2 actualStartPos = currentStartPosition; + Float2 actualEndPos = endPos; + + if (currentInstigator is Archetypes.Tools.RerouteNode) + { + if (endPos.X < currentStartPosition.X && _lastInstigatorUnderMouse is null or Box { IsOutput: true }) + { + actualStartPos = endPos; + actualEndPos = currentStartPosition; + } + } + else if (currentInstigator is Box { IsOutput: false }) { actualStartPos = endPos; - actualEndPos = startPos; + actualEndPos = currentStartPosition; } - } - else if (_connectionInstigator is Box { IsOutput: false }) - { - actualStartPos = endPos; - actualEndPos = startPos; - } - // Draw connection - _connectionInstigator.DrawConnectingLine(ref actualStartPos, ref actualEndPos, ref lineColor); + // Draw connection + currentInstigator.DrawConnectingLine(ref actualStartPos, ref actualEndPos, ref lineColor); + } } /// diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs index a874db681..25fdfe7e4 100644 --- a/Source/Editor/Surface/VisjectSurface.Input.cs +++ b/Source/Editor/Surface/VisjectSurface.Input.cs @@ -268,7 +268,7 @@ namespace FlaxEditor.Surface if (_leftMouseDown) { // Connecting - if (_connectionInstigator != null) + if (_connectionInstigator.Count > 0) { } // Moving @@ -438,7 +438,7 @@ namespace FlaxEditor.Surface public override bool OnMouseDown(Float2 location, MouseButton button) { // Check if user is connecting boxes - if (_connectionInstigator != null) + if (_connectionInstigator.Count > 0) return true; // Base @@ -560,7 +560,7 @@ namespace FlaxEditor.Surface _movingNodesDelta = Float2.Zero; } // Connecting - else if (_connectionInstigator != null) + else if (_connectionInstigator.Count > 0) { } // Selecting @@ -632,7 +632,7 @@ namespace FlaxEditor.Surface ShowPrimaryMenu(_cmStartPos); } // Letting go of a connection or right clicking while creating a connection - else if (!_isMovingSelection && _connectionInstigator != null && !IsPrimaryMenuOpened) + else if (!_isMovingSelection && _connectionInstigator.Count > 0 && !IsPrimaryMenuOpened) { _cmStartPos = location; Cursor = CursorType.Default; diff --git a/Source/Editor/Surface/VisjectSurface.Serialization.cs b/Source/Editor/Surface/VisjectSurface.Serialization.cs index e490d1550..cf5af9a4f 100644 --- a/Source/Editor/Surface/VisjectSurface.Serialization.cs +++ b/Source/Editor/Surface/VisjectSurface.Serialization.cs @@ -33,7 +33,7 @@ namespace FlaxEditor.Surface Enabled = false; // Clean data - _connectionInstigator = null; + _connectionInstigator.Clear(); _lastInstigatorUnderMouse = null; var failed = RootContext.Load(); diff --git a/Source/Editor/Surface/VisjectSurface.cs b/Source/Editor/Surface/VisjectSurface.cs index faecebbd3..19413ad48 100644 --- a/Source/Editor/Surface/VisjectSurface.cs +++ b/Source/Editor/Surface/VisjectSurface.cs @@ -121,7 +121,7 @@ namespace FlaxEditor.Surface /// /// The connection start. /// - protected IConnectionInstigator _connectionInstigator; + protected List _connectionInstigator = new List(); /// /// The last connection instigator under mouse. @@ -234,17 +234,17 @@ namespace FlaxEditor.Surface /// /// Gets a value indicating whether user is selecting nodes. /// - public bool IsSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigator == null; + public bool IsSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigator.Count == 0; /// /// Gets a value indicating whether user is moving selected nodes. /// - public bool IsMovingSelection => _leftMouseDown && _isMovingSelection && _connectionInstigator == null; + public bool IsMovingSelection => _leftMouseDown && _isMovingSelection && _connectionInstigator.Count == 0; /// /// Gets a value indicating whether user is connecting nodes. /// - public bool IsConnecting => _connectionInstigator != null; + public bool IsConnecting => _connectionInstigator.Count > 0; /// /// Gets a value indicating whether the left mouse button is down. From b44d4107c02ec12f39d02751c8c896590cd2b947 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Fri, 13 Jun 2025 22:25:02 +0200 Subject: [PATCH 025/137] fixes --- Source/Editor/Surface/VisjectSurface.Connecting.cs | 14 +++++++------- .../Editor/Surface/VisjectSurface.ContextMenu.cs | 7 ++++--- Source/Editor/Surface/VisjectSurface.Draw.cs | 2 +- Source/Editor/Surface/VisjectSurface.Input.cs | 8 ++++---- .../Editor/Surface/VisjectSurface.Serialization.cs | 2 +- Source/Editor/Surface/VisjectSurface.cs | 8 ++++---- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Source/Editor/Surface/VisjectSurface.Connecting.cs b/Source/Editor/Surface/VisjectSurface.Connecting.cs index d733c7a0e..9b5ce1cf8 100644 --- a/Source/Editor/Surface/VisjectSurface.Connecting.cs +++ b/Source/Editor/Surface/VisjectSurface.Connecting.cs @@ -237,12 +237,12 @@ namespace FlaxEditor.Surface /// If the instigator should be added to the list of instigators. public void ConnectingStart(IConnectionInstigator instigator, bool additive = false) { - if (instigator != null && instigator != _connectionInstigator) + if (instigator != null && instigator != _connectionInstigators) { if (!additive) - _connectionInstigator.Clear(); + _connectionInstigators.Clear(); - _connectionInstigator.Add(instigator); + _connectionInstigators.Add(instigator); StartMouseCapture(); } } @@ -263,13 +263,13 @@ namespace FlaxEditor.Surface public void ConnectingEnd(IConnectionInstigator end) { // Ensure that there is at least one connection instigator - if (_connectionInstigator.Count == 0) + if (_connectionInstigators.Count == 0) return; - List instigators = new List(_connectionInstigator); + List instigators = new List(_connectionInstigators); for (int i = 0; i < instigators.Count; i++) { - var start = _connectionInstigator[i]; + var start = _connectionInstigators[i]; // Check if boxes are different and end box is specified if (start == end || end == null) @@ -281,7 +281,7 @@ namespace FlaxEditor.Surface } // Reset instigator list - _connectionInstigator.Clear(); + _connectionInstigators.Clear(); } } } diff --git a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs index 98221ce6f..36ef020d3 100644 --- a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs +++ b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs @@ -290,7 +290,8 @@ namespace FlaxEditor.Surface _cmStartPos = location; // Offset added in case the user doesn't like the box and wants to quickly get rid of it by clicking - OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, _connectionInstigator[0] as Box); + Box startBox = _connectionInstigators.Count > 0 ? _connectionInstigators[0] as Box : null; + OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, startBox); if (!string.IsNullOrEmpty(input)) { @@ -475,7 +476,7 @@ namespace FlaxEditor.Surface private void OnPrimaryMenuVisibleChanged(Control primaryMenu) { if (!primaryMenu.Visible) - _connectionInstigator.Clear(); + _connectionInstigators.Clear(); } /// @@ -553,7 +554,7 @@ namespace FlaxEditor.Surface } // If the user is patiently waiting for his box to get connected to the newly created one fulfill his wish! - _connectionInstigator[0] = startBox; + _connectionInstigators[0] = startBox; if (!IsConnecting) { diff --git a/Source/Editor/Surface/VisjectSurface.Draw.cs b/Source/Editor/Surface/VisjectSurface.Draw.cs index dcf5e8108..5f8a7284a 100644 --- a/Source/Editor/Surface/VisjectSurface.Draw.cs +++ b/Source/Editor/Surface/VisjectSurface.Draw.cs @@ -131,7 +131,7 @@ namespace FlaxEditor.Surface var endPos = cmVisible ? _rootControl.PointFromParent(ref _cmStartPos) : _rootControl.PointFromParent(ref _mousePos); Color lineColor = Style.Colors.Connecting; - List instigators = new List(_connectionInstigator); + List instigators = new List(_connectionInstigators); for (int i = 0; i < instigators.Count; i++) { IConnectionInstigator currentInstigator = instigators[i]; diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs index 25fdfe7e4..dda112b20 100644 --- a/Source/Editor/Surface/VisjectSurface.Input.cs +++ b/Source/Editor/Surface/VisjectSurface.Input.cs @@ -268,7 +268,7 @@ namespace FlaxEditor.Surface if (_leftMouseDown) { // Connecting - if (_connectionInstigator.Count > 0) + if (_connectionInstigators.Count > 0) { } // Moving @@ -438,7 +438,7 @@ namespace FlaxEditor.Surface public override bool OnMouseDown(Float2 location, MouseButton button) { // Check if user is connecting boxes - if (_connectionInstigator.Count > 0) + if (_connectionInstigators.Count > 0) return true; // Base @@ -560,7 +560,7 @@ namespace FlaxEditor.Surface _movingNodesDelta = Float2.Zero; } // Connecting - else if (_connectionInstigator.Count > 0) + else if (_connectionInstigators.Count > 0) { } // Selecting @@ -632,7 +632,7 @@ namespace FlaxEditor.Surface ShowPrimaryMenu(_cmStartPos); } // Letting go of a connection or right clicking while creating a connection - else if (!_isMovingSelection && _connectionInstigator.Count > 0 && !IsPrimaryMenuOpened) + else if (!_isMovingSelection && _connectionInstigators.Count > 0 && !IsPrimaryMenuOpened) { _cmStartPos = location; Cursor = CursorType.Default; diff --git a/Source/Editor/Surface/VisjectSurface.Serialization.cs b/Source/Editor/Surface/VisjectSurface.Serialization.cs index cf5af9a4f..5bf7a9e34 100644 --- a/Source/Editor/Surface/VisjectSurface.Serialization.cs +++ b/Source/Editor/Surface/VisjectSurface.Serialization.cs @@ -33,7 +33,7 @@ namespace FlaxEditor.Surface Enabled = false; // Clean data - _connectionInstigator.Clear(); + _connectionInstigators.Clear(); _lastInstigatorUnderMouse = null; var failed = RootContext.Load(); diff --git a/Source/Editor/Surface/VisjectSurface.cs b/Source/Editor/Surface/VisjectSurface.cs index 19413ad48..f886682e4 100644 --- a/Source/Editor/Surface/VisjectSurface.cs +++ b/Source/Editor/Surface/VisjectSurface.cs @@ -121,7 +121,7 @@ namespace FlaxEditor.Surface /// /// The connection start. /// - protected List _connectionInstigator = new List(); + protected List _connectionInstigators = new List(); /// /// The last connection instigator under mouse. @@ -234,17 +234,17 @@ namespace FlaxEditor.Surface /// /// Gets a value indicating whether user is selecting nodes. /// - public bool IsSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigator.Count == 0; + public bool IsSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigators.Count == 0; /// /// Gets a value indicating whether user is moving selected nodes. /// - public bool IsMovingSelection => _leftMouseDown && _isMovingSelection && _connectionInstigator.Count == 0; + public bool IsMovingSelection => _leftMouseDown && _isMovingSelection && _connectionInstigators.Count == 0; /// /// Gets a value indicating whether user is connecting nodes. /// - public bool IsConnecting => _connectionInstigator.Count > 0; + public bool IsConnecting => _connectionInstigators.Count > 0; /// /// Gets a value indicating whether the left mouse button is down. From baba151d8a5a095c2b250038ec13b9717f705136 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sat, 14 Jun 2025 00:54:16 +0200 Subject: [PATCH 026/137] fix context menu --- Source/Editor/Surface/AnimGraphSurface.cs | 6 +- Source/Editor/Surface/BehaviorTreeSurface.cs | 4 +- .../Editor/Surface/ContextMenu/VisjectCM.cs | 34 ++++++----- .../Surface/VisjectSurface.ContextMenu.cs | 59 +++++++++---------- Source/Editor/Surface/VisualScriptSurface.cs | 4 +- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/Source/Editor/Surface/AnimGraphSurface.cs b/Source/Editor/Surface/AnimGraphSurface.cs index 40cb1fd9a..237e9d019 100644 --- a/Source/Editor/Surface/AnimGraphSurface.cs +++ b/Source/Editor/Surface/AnimGraphSurface.cs @@ -229,20 +229,20 @@ namespace FlaxEditor.Surface } /// - protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, Box startBox) + protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, List startBoxes) { // Check if show additional nodes in the current surface context if (activeCM != _cmStateMachineMenu) { _nodesCache.Get(activeCM); - base.OnShowPrimaryMenu(activeCM, location, startBox); + base.OnShowPrimaryMenu(activeCM, location, startBoxes); activeCM.VisibleChanged += OnActiveContextMenuVisibleChanged; } else { - base.OnShowPrimaryMenu(activeCM, location, startBox); + base.OnShowPrimaryMenu(activeCM, location, startBoxes); } } diff --git a/Source/Editor/Surface/BehaviorTreeSurface.cs b/Source/Editor/Surface/BehaviorTreeSurface.cs index 9adcc9949..cf6d7b19a 100644 --- a/Source/Editor/Surface/BehaviorTreeSurface.cs +++ b/Source/Editor/Surface/BehaviorTreeSurface.cs @@ -101,12 +101,12 @@ namespace FlaxEditor.Surface } /// - protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, Box startBox) + protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, List startBoxes) { activeCM.ShowExpanded = true; _nodesCache.Get(activeCM); - base.OnShowPrimaryMenu(activeCM, location, startBox); + base.OnShowPrimaryMenu(activeCM, location, startBoxes); activeCM.VisibleChanged += OnActiveContextMenuVisibleChanged; } diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index 94b411fc2..de9261356 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -24,8 +24,8 @@ namespace FlaxEditor.Surface.ContextMenu /// Visject context menu item clicked delegate. /// /// The item that was clicked - /// The currently user-selected box. Can be null. - public delegate void ItemClickedDelegate(VisjectCMItem clickedItem, Elements.Box selectedBox); + /// The currently user-selected boxes. Can be empty/ null. + public delegate void ItemClickedDelegate(VisjectCMItem clickedItem, List selectedBoxes); /// /// Visject Surface node archetype spawn ability checking delegate. @@ -53,7 +53,7 @@ namespace FlaxEditor.Surface.ContextMenu private Panel _panel1; private VerticalPanel _groupsPanel; private readonly ParameterGetterDelegate _parametersGetter; - private Elements.Box _selectedBox; + private List _selectedBoxes = new List(); private NodeArchetype _parameterGetNodeArchetype; private NodeArchetype _parameterSetNodeArchetype; @@ -411,7 +411,8 @@ namespace FlaxEditor.Surface.ContextMenu if (!IsLayoutLocked) { group.UnlockChildrenRecursive(); - if (_contextSensitiveSearchEnabled && _selectedBox != null) + // TODO: Improve filtering to be based on boxes with the most common things instead of first box + if (_contextSensitiveSearchEnabled && _selectedBoxes[0] != null) UpdateFilters(); else SortGroups(); @@ -425,7 +426,8 @@ namespace FlaxEditor.Surface.ContextMenu } else if (_contextSensitiveSearchEnabled) { - group.EvaluateVisibilityWithBox(_selectedBox); + // TODO: Filtering could be improved here as well + group.EvaluateVisibilityWithBox(_selectedBoxes[0]); } Profiler.EndEvent(); @@ -461,7 +463,7 @@ namespace FlaxEditor.Surface.ContextMenu }; } if (_contextSensitiveSearchEnabled) - group.EvaluateVisibilityWithBox(_selectedBox); + group.EvaluateVisibilityWithBox(_selectedBoxes[0]); group.SortChildren(); if (ShowExpanded) group.Open(false); @@ -474,7 +476,7 @@ namespace FlaxEditor.Surface.ContextMenu if (!isLayoutLocked) { - if (_contextSensitiveSearchEnabled && _selectedBox != null) + if (_contextSensitiveSearchEnabled && _selectedBoxes[0] != null) UpdateFilters(); else SortGroups(); @@ -583,7 +585,7 @@ namespace FlaxEditor.Surface.ContextMenu private void UpdateFilters() { - if (string.IsNullOrEmpty(_searchBox.Text) && _selectedBox == null) + if (string.IsNullOrEmpty(_searchBox.Text) && _selectedBoxes[0] == null) { ResetView(); Profiler.EndEvent(); @@ -592,7 +594,7 @@ namespace FlaxEditor.Surface.ContextMenu // Update groups LockChildrenRecursive(); - var contextSensitiveSelectedBox = _contextSensitiveSearchEnabled ? _selectedBox : null; + var contextSensitiveSelectedBox = _contextSensitiveSearchEnabled ? _selectedBoxes[0] : null; for (int i = 0; i < _groups.Count; i++) { _groups[i].UpdateFilter(_searchBox.Text, contextSensitiveSelectedBox); @@ -640,7 +642,7 @@ namespace FlaxEditor.Surface.ContextMenu public void OnClickItem(VisjectCMItem item) { Hide(); - ItemClicked?.Invoke(item, _selectedBox); + ItemClicked?.Invoke(item, _selectedBoxes); } /// @@ -666,12 +668,12 @@ namespace FlaxEditor.Surface.ContextMenu for (int i = 0; i < _groups.Count; i++) { _groups[i].ResetView(); - if (_contextSensitiveSearchEnabled) - _groups[i].EvaluateVisibilityWithBox(_selectedBox); + if (_contextSensitiveSearchEnabled && _selectedBoxes.Count > 0) + _groups[i].EvaluateVisibilityWithBox(_selectedBoxes[0]); } UnlockChildrenRecursive(); - if (_contextSensitiveSearchEnabled && _selectedBox != null) + if (_contextSensitiveSearchEnabled && _selectedBoxes.Count > 0 && _selectedBoxes[0] != null) UpdateFilters(); else SortGroups(); @@ -772,10 +774,10 @@ namespace FlaxEditor.Surface.ContextMenu /// /// Parent control to attach to it. /// Popup menu origin location in parent control coordinates. - /// The currently selected box that the new node will get connected to. Can be null - public void Show(Control parent, Float2 location, Elements.Box startBox) + /// The currently selected boxes that the new node will get connected to. Can be empty/ null + public void Show(Control parent, Float2 location, List startBoxes) { - _selectedBox = startBox; + _selectedBoxes = startBoxes; base.Show(parent, location); } diff --git a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs index 36ef020d3..6505b4f64 100644 --- a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs +++ b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs @@ -252,10 +252,10 @@ namespace FlaxEditor.Surface /// /// The active context menu to show. /// The display location on the surface control. - /// The start box. - protected virtual void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, Box startBox) + /// The start boxes. + protected virtual void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, List startBoxes) { - activeCM.Show(this, location, startBox); + activeCM.Show(this, location, startBoxes); } /// @@ -289,9 +289,10 @@ namespace FlaxEditor.Surface _cmStartPos = location; - // Offset added in case the user doesn't like the box and wants to quickly get rid of it by clicking - Box startBox = _connectionInstigators.Count > 0 ? _connectionInstigators[0] as Box : null; - OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, startBox); + List startBoxes = new List(_connectionInstigators.Cast()); + + // Position offset added so the user can quickly close the menu by clicking + OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, startBoxes); if (!string.IsNullOrEmpty(input)) { @@ -483,8 +484,8 @@ namespace FlaxEditor.Surface /// Handles Visject CM item click event by spawning the selected item. /// /// The item. - /// The selected box. - protected virtual void OnPrimaryMenuButtonClick(VisjectCMItem visjectCmItem, Box selectedBox) + /// The selected boxes. + protected virtual void OnPrimaryMenuButtonClick(VisjectCMItem visjectCmItem, List selectedBoxes) { if (!CanEdit) return; @@ -511,34 +512,36 @@ namespace FlaxEditor.Surface // Auto select new node Select(node); - if (selectedBox != null) + for (int i = 0; i < selectedBoxes.Count; i++) { - Box endBox = null; - foreach (var box in node.GetBoxes().Where(box => box.IsOutput != selectedBox.IsOutput)) + Box currentBox = selectedBoxes[i]; + if (currentBox != null) { - if (selectedBox.IsOutput) + Box endBox = null; + foreach (var box in node.GetBoxes().Where(box => box.IsOutput != currentBox.IsOutput)) { - if (box.CanUseType(selectedBox.CurrentType)) + if (currentBox.IsOutput) { - endBox = box; - break; + if (box.CanUseType(currentBox.CurrentType)) + { + endBox = box; + break; + } } - } - else - { - if (selectedBox.CanUseType(box.CurrentType)) + else { - endBox = box; - break; + if (currentBox.CanUseType(box.CurrentType)) + { + endBox = box; + break; + } } - } - if (endBox == null && selectedBox.CanUseType(box.CurrentType)) - { - endBox = box; + if (endBox == null && currentBox.CanUseType(box.CurrentType)) + endBox = box; } + TryConnect(currentBox, endBox); } - TryConnect(selectedBox, endBox); } } @@ -554,12 +557,8 @@ namespace FlaxEditor.Surface } // If the user is patiently waiting for his box to get connected to the newly created one fulfill his wish! - _connectionInstigators[0] = startBox; - if (!IsConnecting) - { ConnectingStart(startBox); - } ConnectingEnd(endBox); // Smart-Select next box diff --git a/Source/Editor/Surface/VisualScriptSurface.cs b/Source/Editor/Surface/VisualScriptSurface.cs index 0c11e54ff..2f70ee340 100644 --- a/Source/Editor/Surface/VisualScriptSurface.cs +++ b/Source/Editor/Surface/VisualScriptSurface.cs @@ -212,7 +212,7 @@ namespace FlaxEditor.Surface } /// - protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, Box startBox) + protected override void OnShowPrimaryMenu(VisjectCM activeCM, Float2 location, List startBoxes) { // Update nodes for method overrides Profiler.BeginEvent("Overrides"); @@ -268,7 +268,7 @@ namespace FlaxEditor.Surface // Update nodes for invoke methods (async) _nodesCache.Get(activeCM); - base.OnShowPrimaryMenu(activeCM, location, startBox); + base.OnShowPrimaryMenu(activeCM, location, startBoxes); activeCM.VisibleChanged += OnActiveContextMenuVisibleChanged; } From 2e0c35e6e4eca5c0770aa1623f997f9b5e16888f Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sat, 14 Jun 2025 01:04:35 +0200 Subject: [PATCH 027/137] fix out of range error when searching visject cm --- Source/Editor/Surface/ContextMenu/VisjectCM.cs | 2 +- Source/Editor/Surface/VisjectSurface.Draw.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index de9261356..42c863789 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -594,7 +594,7 @@ namespace FlaxEditor.Surface.ContextMenu // Update groups LockChildrenRecursive(); - var contextSensitiveSelectedBox = _contextSensitiveSearchEnabled ? _selectedBoxes[0] : null; + var contextSensitiveSelectedBox = _contextSensitiveSearchEnabled && _selectedBoxes.Count > 0 ? _selectedBoxes[0] : null; for (int i = 0; i < _groups.Count; i++) { _groups[i].UpdateFilter(_searchBox.Text, contextSensitiveSelectedBox); diff --git a/Source/Editor/Surface/VisjectSurface.Draw.cs b/Source/Editor/Surface/VisjectSurface.Draw.cs index 5f8a7284a..b413ae032 100644 --- a/Source/Editor/Surface/VisjectSurface.Draw.cs +++ b/Source/Editor/Surface/VisjectSurface.Draw.cs @@ -137,7 +137,7 @@ namespace FlaxEditor.Surface IConnectionInstigator currentInstigator = instigators[i]; Float2 currentStartPosition = currentInstigator.ConnectionOrigin; - // Check if mouse is over any of box + // Check if mouse is over any box if (_lastInstigatorUnderMouse != null && !cmVisible) { // Check if can connect objects From 92edb996f21df755f25613952cf52b98f7475159 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sat, 14 Jun 2025 17:20:28 +0200 Subject: [PATCH 028/137] properly handle connecting to a box that already has a connection --- Source/Editor/Surface/Elements/Box.cs | 18 ++++++------------ .../Surface/VisjectSurface.Connecting.cs | 7 ++++++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs index 54ea0292d..964b3cc69 100644 --- a/Source/Editor/Surface/Elements/Box.cs +++ b/Source/Editor/Surface/Elements/Box.cs @@ -544,15 +544,13 @@ namespace FlaxEditor.Surface.Elements public override void OnMouseLeave() { if (_originalTooltipText != null) - { TooltipText = _originalTooltipText; - } if (_isMouseDown) { _isMouseDown = false; if (Surface.CanEdit) { - if (Input.GetKey(KeyboardKeys.Control)) + if (IsOutput && Input.GetKey(KeyboardKeys.Control)) { List connectedBoxes = new List(Connections); @@ -564,25 +562,21 @@ namespace FlaxEditor.Surface.Elements } else if (!IsOutput && HasSingleConnection) { - var connectedBox = Connections[0]; + var otherBox = Connections[0]; if (Surface.Undo != null && Surface.Undo.Enabled) { - var action = new ConnectBoxesAction((InputBox)this, (OutputBox)connectedBox, false); - BreakConnection(connectedBox); + var action = new ConnectBoxesAction((InputBox)this, (OutputBox)otherBox, false); + BreakConnection(otherBox); action.End(); Surface.AddBatchedUndoAction(action); Surface.MarkAsEdited(); } else - { - BreakConnection(connectedBox); - } - Surface.ConnectingStart(connectedBox); + BreakConnection(otherBox); + Surface.ConnectingStart(otherBox); } else - { Surface.ConnectingStart(this); - } } } base.OnMouseLeave(); diff --git a/Source/Editor/Surface/VisjectSurface.Connecting.cs b/Source/Editor/Surface/VisjectSurface.Connecting.cs index 9b5ce1cf8..6f60ca2e2 100644 --- a/Source/Editor/Surface/VisjectSurface.Connecting.cs +++ b/Source/Editor/Surface/VisjectSurface.Connecting.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using FlaxEditor.Scripting; +using FlaxEditor.Surface.Elements; using FlaxEngine; namespace FlaxEditor.Surface @@ -269,11 +270,15 @@ namespace FlaxEditor.Surface List instigators = new List(_connectionInstigators); for (int i = 0; i < instigators.Count; i++) { - var start = _connectionInstigators[i]; + var start = instigators[i]; // Check if boxes are different and end box is specified if (start == end || end == null) return; + + // Properly handle connecting to a socket that already has a connection + if (end is Box e && !e.IsOutput && start is Box s && e.AreConnected(s)) + e.BreakConnection(s); // Connect them if (start.CanConnectWith(end)) From a4d3ede368222f87bcba6df8add9d668f848c868 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sun, 15 Jun 2025 02:08:47 +0200 Subject: [PATCH 029/137] fix context menu on reroute node --- Source/Editor/Surface/VisjectSurface.ContextMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs index 6505b4f64..5870125d4 100644 --- a/Source/Editor/Surface/VisjectSurface.ContextMenu.cs +++ b/Source/Editor/Surface/VisjectSurface.ContextMenu.cs @@ -289,7 +289,7 @@ namespace FlaxEditor.Surface _cmStartPos = location; - List startBoxes = new List(_connectionInstigators.Cast()); + List startBoxes = new List(_connectionInstigators.Where(c => c is Box).Cast()); // Position offset added so the user can quickly close the menu by clicking OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, startBoxes); From 53d4ea51af4ae620df77879b681969184fea49a5 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 27 Jun 2025 21:18:53 -0500 Subject: [PATCH 030/137] Add prefab UI viewport scaling. --- Source/Editor/Gizmo/UIEditorGizmo.cs | 10 + Source/Editor/Modules/UIModule.cs | 100 ++++++ .../Editor/Viewport/PrefabWindowViewport.cs | 311 +++++++++++++++++- Source/Editor/Windows/Assets/PrefabWindow.cs | 10 + Source/Editor/Windows/GameWindow.cs | 186 ++++------- 5 files changed, 501 insertions(+), 116 deletions(-) diff --git a/Source/Editor/Gizmo/UIEditorGizmo.cs b/Source/Editor/Gizmo/UIEditorGizmo.cs index bdc1c56ca..765893bed 100644 --- a/Source/Editor/Gizmo/UIEditorGizmo.cs +++ b/Source/Editor/Gizmo/UIEditorGizmo.cs @@ -155,6 +155,16 @@ namespace FlaxEditor private List _widgets; private Widget _activeWidget; + /// + /// Sets the view size. + /// + /// The new size. + public void SetViewSize(Float2 size) + { + _view.Size = size; + _view.PerformLayout(); + } + /// /// True if enable displaying UI editing background and grid elements. /// diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index 19a0c1142..e62dd6b6e 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -37,6 +37,53 @@ namespace FlaxEditor.Modules private bool _progressFailed; ContextMenuSingleSelectGroup _numberOfClientsGroup = new ContextMenuSingleSelectGroup(); + + /// + /// Defines a viewport scaling option. + /// + public class ViewportScaleOption + { + /// + /// Defines the viewport scale type. + /// + public enum ViewportScaleType + { + /// + /// Resolution. + /// + Resolution = 0, + + /// + /// Aspect Ratio. + /// + Aspect = 1, + } + + /// + /// The name. + /// + public string Label; + + /// + /// The Type of scaling to do. + /// + public ViewportScaleType ScaleType; + + /// + /// The width and height to scale by. + /// + public Int2 Size; + } + + /// + /// The default viewport scaling options. + /// + public List DefaultViewportScaleOptions = new List(); + + /// + /// The user defined viewport scaling options. + /// + public List CustomViewportScaleOptions = new List(); private ContextMenuButton _menuFileSaveScenes; private ContextMenuButton _menuFileReloadScenes; @@ -371,6 +418,8 @@ namespace FlaxEditor.Modules // Update window background mainWindow.BackgroundColor = Style.Current.Background; + + InitViewportScaleOptions(); InitSharedMenus(); InitMainMenu(mainWindow); @@ -392,6 +441,57 @@ namespace FlaxEditor.Modules } } + private void InitViewportScaleOptions() + { + if (DefaultViewportScaleOptions.Count == 0) + { + DefaultViewportScaleOptions.Add(new ViewportScaleOption + { + Label = "Free Aspect", + ScaleType = ViewportScaleOption.ViewportScaleType.Aspect, + Size = new Int2(1, 1), + }); + DefaultViewportScaleOptions.Add(new ViewportScaleOption + { + Label = "16:9 Aspect", + ScaleType = ViewportScaleOption.ViewportScaleType.Aspect, + Size = new Int2(16, 9), + }); + DefaultViewportScaleOptions.Add(new ViewportScaleOption + { + Label = "16:10 Aspect", + ScaleType = ViewportScaleOption.ViewportScaleType.Aspect, + Size = new Int2(16, 10), + }); + DefaultViewportScaleOptions.Add(new ViewportScaleOption + { + Label = "1920x1080 Resolution (Full HD)", + ScaleType = ViewportScaleOption.ViewportScaleType.Resolution, + Size = new Int2(1920, 1080), + }); + DefaultViewportScaleOptions.Add(new ViewportScaleOption + { + Label = "2560x1440 Resolution (2K)", + ScaleType = ViewportScaleOption.ViewportScaleType.Resolution, + Size = new Int2(2560, 1440), + }); + } + + if (Editor.Instance.ProjectCache.TryGetCustomData("CustomViewportScalingOptions", out string data)) + { + CustomViewportScaleOptions = JsonSerializer.Deserialize>(data); + } + } + + /// + /// Saves the custom viewport scaling options. + /// + public void SaveCustomViewportScalingOptions() + { + var customOptions = JsonSerializer.Serialize(CustomViewportScaleOptions); + Editor.Instance.ProjectCache.SetCustomData("CustomViewportScalingOptions", customOptions); + } + /// public override void OnUpdate() { diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index 2efe7c95f..f7c496703 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -6,6 +6,8 @@ using System.Linq; using FlaxEditor.Content; using FlaxEditor.Gizmo; using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Input; +using FlaxEditor.Modules; using FlaxEditor.SceneGraph; using FlaxEditor.Scripting; using FlaxEditor.Viewport.Cameras; @@ -13,6 +15,7 @@ using FlaxEditor.Viewport.Previews; using FlaxEditor.Windows.Assets; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEngine.Json; using Utils = FlaxEditor.Utilities.Utils; namespace FlaxEditor.Viewport @@ -71,7 +74,10 @@ namespace FlaxEditor.Viewport private PrefabUIEditorRoot _uiRoot; private bool _showUI = false; + private int _defaultScaleActiveIndex = 0; + private int _customScaleActiveIndex = -1; private ContextMenuButton _uiModeButton; + private ContextMenu _uiViewCM; /// /// Event fired when the UI Mode is toggled. @@ -213,7 +219,7 @@ namespace FlaxEditor.Viewport _uiModeButton = ViewWidgetShowMenu.AddButton("UI Mode", (button) => ShowUI = button.Checked); _uiModeButton.AutoCheck = true; _uiModeButton.VisibleChanged += control => (control as ContextMenuButton).Checked = ShowUI; - + EditorGizmoViewport.AddGizmoViewportWidgets(this, TransformGizmo); // Setup input actions @@ -222,6 +228,309 @@ namespace FlaxEditor.Viewport SetUpdate(ref _update, OnUpdate); } + /// + /// Creates the view scaling options. Needs to be called after a Prefab is valid and loaded. + /// + public void CreateViewScalingOptions() + { + // View Scaling + var uiViewCM = ViewWidgetButtonMenu.AddChildMenu("UI View Scaling"); + LoadCustomUIScalingOption(); + CreateUIViewScalingContextMenu(uiViewCM.ContextMenu); + } + + private void ChangeUIView(UIModule.ViewportScaleOption uiViewScaleOption) + { + _uiRoot.SetViewSize((Float2)uiViewScaleOption.Size); + } + + private void CreateUIViewScalingContextMenu(ContextMenu vsMenu) + { + // Add default viewport sizing options + var defaultOptions = Editor.Instance.UI.DefaultViewportScaleOptions; + for (int i = 0; i < defaultOptions.Count; i++) + { + var viewportScale = defaultOptions[i]; + + // Skip aspect ratio types in prefab + if (viewportScale.ScaleType == UIModule.ViewportScaleOption.ViewportScaleType.Aspect) + continue; + + var button = vsMenu.AddButton(viewportScale.Label); + button.CloseMenuOnClick = false; + button.Tag = viewportScale; + + // No default index is active. + if (_defaultScaleActiveIndex == -1) + { + button.Icon = SpriteHandle.Invalid; + } + // This is the active index. + else if (_defaultScaleActiveIndex == i) + { + button.Icon = Style.Current.CheckBoxTick; + ChangeUIView(viewportScale); + } + + button.Clicked += () => + { + if (button.Tag == null) + return; + + // Reset selected icon on all buttons + foreach (var child in vsMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) + { + if (cmb == button) + { + var index = defaultOptions.FindIndex(x => x == v); + _defaultScaleActiveIndex = index; + _customScaleActiveIndex = -1; // Reset custom index because default was chosen. + button.Icon = Style.Current.CheckBoxTick; + ChangeUIView(v); + } + else if (cmb.Icon != SpriteHandle.Invalid) + { + cmb.Icon = SpriteHandle.Invalid; + } + } + } + }; + } + if (defaultOptions.Count != 0) + vsMenu.AddSeparator(); + + // Add custom viewport options + var customOptions = Editor.Instance.UI.CustomViewportScaleOptions; + for (int i = 0; i < customOptions.Count; i++) + { + var viewportScale = customOptions[i]; + + // Skip aspect ratio types for prefabs + if (viewportScale.ScaleType == UIModule.ViewportScaleOption.ViewportScaleType.Aspect) + continue; + + var childCM = vsMenu.AddChildMenu(viewportScale.Label); + childCM.CloseMenuOnClick = false; + childCM.Tag = viewportScale; + + // No custom index is active. + if (_customScaleActiveIndex == -1) + { + childCM.Icon = SpriteHandle.Invalid; + } + // This is the active index. + else if (_customScaleActiveIndex == i) + { + childCM.Icon = Style.Current.CheckBoxTick; + ChangeUIView(viewportScale); + } + + var applyButton = childCM.ContextMenu.AddButton("Apply"); + applyButton.Tag = childCM.Tag = viewportScale; + applyButton.CloseMenuOnClick = false; + applyButton.Clicked += () => + { + if (childCM.Tag == null) + return; + + // Reset selected icon on all buttons + foreach (var child in vsMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) + { + if (child == childCM) + { + var index = customOptions.FindIndex(x => x == v); + _defaultScaleActiveIndex = -1; // Reset default index because custom was chosen. + _customScaleActiveIndex = index; + childCM.Icon = Style.Current.CheckBoxTick; + ChangeUIView(v); + } + else if (cmb.Icon != SpriteHandle.Invalid) + { + cmb.Icon = SpriteHandle.Invalid; + } + } + } + }; + + var deleteButton = childCM.ContextMenu.AddButton("Delete"); + deleteButton.CloseMenuOnClick = false; + deleteButton.Clicked += () => + { + if (childCM.Tag == null) + return; + + var v = (UIModule.ViewportScaleOption)childCM.Tag; + if (childCM.Icon != SpriteHandle.Invalid) + { + _customScaleActiveIndex = -1; + _defaultScaleActiveIndex = 0; + ChangeUIView(defaultOptions[0]); + } + customOptions.Remove(v); + Editor.Instance.UI.SaveCustomViewportScalingOptions(); + vsMenu.DisposeAllItems(); + CreateUIViewScalingContextMenu(vsMenu); + vsMenu.PerformLayout(); + }; + } + if (customOptions.Count != 0) + vsMenu.AddSeparator(); + + // Add button + var add = vsMenu.AddButton("Add..."); + add.CloseMenuOnClick = false; + add.Clicked += () => + { + var popup = new ContextMenuBase + { + Size = new Float2(230, 95), + 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 whLabel = new Label + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Text = "Width & Height", + HorizontalAlignment = TextAlignment.Near, + }; + whLabel.LocalX += 10; + whLabel.LocalY += 30; + + var wValue = new IntValueBox(1920) + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + MinValue = 1, + Width = 55, + }; + wValue.LocalY += 30; + wValue.LocalX += 100; + + var hValue = new IntValueBox(1080) + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + MinValue = 1, + Width = 55, + }; + hValue.LocalY += 30; + hValue.LocalX += 165; + + var submitButton = new Button + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Text = "Submit", + Width = 70, + }; + submitButton.LocalX += 40; + submitButton.LocalY += 60; + + submitButton.Clicked += () => + { + var name = nameTextBox.Text + " (" + wValue.Value + "x" + hValue.Value + ")"; + + var newViewportOption = new UIModule.ViewportScaleOption + { + Label = name, + ScaleType = UIModule.ViewportScaleOption.ViewportScaleType.Resolution, + Size = new Int2(wValue.Value, hValue.Value), + }; + + customOptions.Add(newViewportOption); + Editor.Instance.UI.SaveCustomViewportScalingOptions(); + vsMenu.DisposeAllItems(); + CreateUIViewScalingContextMenu(vsMenu); + vsMenu.PerformLayout(); + }; + + var cancelButton = new Button + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Text = "Cancel", + Width = 70, + }; + cancelButton.LocalX += 120; + cancelButton.LocalY += 60; + + cancelButton.Clicked += () => + { + nameTextBox.Clear(); + hValue.Value = 9; + wValue.Value = 16; + popup.Hide(); + }; + }; + } + + /// + /// Saves the active ui scaling option. + /// + public void SaveActiveUIScalingOption() + { + var defaultKey = $"{Prefab.ID}:DefaultViewportScalingIndex"; + Editor.Instance.ProjectCache.SetCustomData(defaultKey, _defaultScaleActiveIndex.ToString()); + var customKey = $"{Prefab.ID}:CustomViewportScalingIndex"; + Editor.Instance.ProjectCache.SetCustomData(customKey, _customScaleActiveIndex.ToString()); + } + + private void LoadCustomUIScalingOption() + { + Prefab.WaitForLoaded(); + var defaultKey = $"{Prefab.ID}:DefaultViewportScalingIndex"; + if (Editor.Instance.ProjectCache.TryGetCustomData(defaultKey, out string defaultData)) + { + if (int.TryParse(defaultData, out var index)) + { + _defaultScaleActiveIndex = index; + if (index != -1) + { + ChangeUIView(Editor.Instance.UI.DefaultViewportScaleOptions[index]); + } + } + } + + var customKey = $"{Prefab.ID}:CustomViewportScalingIndex"; + if (Editor.Instance.ProjectCache.TryGetCustomData(customKey, out string data)) + { + if (int.TryParse(data, out var index)) + { + _customScaleActiveIndex = index; + if (index != -1) + { + ChangeUIView(Editor.Instance.UI.CustomViewportScaleOptions[index]); + } + } + } + } + private void OnUpdate(float deltaTime) { for (int i = 0; i < Gizmos.Count; i++) diff --git a/Source/Editor/Windows/Assets/PrefabWindow.cs b/Source/Editor/Windows/Assets/PrefabWindow.cs index 44c21d863..8202577d0 100644 --- a/Source/Editor/Windows/Assets/PrefabWindow.cs +++ b/Source/Editor/Windows/Assets/PrefabWindow.cs @@ -368,6 +368,7 @@ namespace FlaxEditor.Windows.Assets else _viewport.SetInitialUIMode(_viewport._hasUILinked); _viewport.UIModeToggled += OnUIModeToggled; + _viewport.CreateViewScalingOptions(); Graph.MainActor = _viewport.Instance; Selection.Clear(); Select(Graph.Main); @@ -564,6 +565,15 @@ namespace FlaxEditor.Windows.Assets Graph.Dispose(); } + /// + protected override void OnClose() + { + // Save current UI view size state. + _viewport.SaveActiveUIScalingOption(); + + base.OnClose(); + } + /// public EditorViewport PresenterViewport => _viewport; diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index e05f0d2db..1f5399926 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -6,6 +6,7 @@ using System.Xml; using FlaxEditor.Gizmo; using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Input; +using FlaxEditor.Modules; using FlaxEditor.Options; using FlaxEngine; using FlaxEngine.GUI; @@ -34,8 +35,8 @@ namespace FlaxEditor.Windows private CursorLockMode _cursorLockMode = CursorLockMode.None; // Viewport scaling variables - private List _defaultViewportScaling = new List(); - private List _customViewportScaling = new List(); + private int _defaultScaleActiveIndex = 0; + private int _customScaleActiveIndex = -1; private float _viewportAspectRatio = 1; private float _windowAspectRatio = 1; private bool _useAspect = false; @@ -234,35 +235,6 @@ namespace FlaxEditor.Windows /// public InterfaceOptions.PlayModeFocus FocusOnPlayOption { get; set; } - private enum ViewportScaleType - { - Resolution = 0, - Aspect = 1, - } - - private class ViewportScaleOptions - { - /// - /// The name. - /// - public string Label; - - /// - /// The Type of scaling to do. - /// - public ViewportScaleType ScaleType; - - /// - /// The width and height to scale by. - /// - public Int2 Size; - - /// - /// If the scaling is active. - /// - public bool Active; - } - private class PlayModeFocusOptions { /// @@ -408,7 +380,7 @@ namespace FlaxEditor.Windows InputActions.Add(options => options.FocusConsoleCommand, () => Editor.Instance.Windows.OutputLogWin.FocusCommand()); } - private void ChangeViewportRatio(ViewportScaleOptions v) + private void ChangeViewportRatio(UIModule.ViewportScaleOption v) { if (v == null) return; @@ -427,11 +399,11 @@ namespace FlaxEditor.Windows { switch (v.ScaleType) { - case ViewportScaleType.Aspect: + case UIModule.ViewportScaleOption.ViewportScaleType.Aspect: _useAspect = true; _freeAspect = false; break; - case ViewportScaleType.Resolution: + case UIModule.ViewportScaleOption.ViewportScaleType.Resolution: _useAspect = false; _freeAspect = false; break; @@ -629,45 +601,6 @@ namespace FlaxEditor.Windows // Viewport aspect ratio { // Create default scaling options if they dont exist from deserialization. - if (_defaultViewportScaling.Count == 0) - { - _defaultViewportScaling.Add(new ViewportScaleOptions - { - Label = "Free Aspect", - ScaleType = ViewportScaleType.Aspect, - Size = new Int2(1, 1), - Active = true, - }); - _defaultViewportScaling.Add(new ViewportScaleOptions - { - Label = "16:9 Aspect", - ScaleType = ViewportScaleType.Aspect, - Size = new Int2(16, 9), - Active = false, - }); - _defaultViewportScaling.Add(new ViewportScaleOptions - { - Label = "16:10 Aspect", - ScaleType = ViewportScaleType.Aspect, - Size = new Int2(16, 10), - Active = false, - }); - _defaultViewportScaling.Add(new ViewportScaleOptions - { - Label = "1920x1080 Resolution (Full HD)", - ScaleType = ViewportScaleType.Resolution, - Size = new Int2(1920, 1080), - Active = false, - }); - _defaultViewportScaling.Add(new ViewportScaleOptions - { - Label = "2560x1440 Resolution (2K)", - ScaleType = ViewportScaleType.Resolution, - Size = new Int2(2560, 1440), - Active = false, - }); - } - var vsMenu = menu.AddChildMenu("Viewport Size").ContextMenu; CreateViewportSizingContextMenu(vsMenu); @@ -771,15 +704,25 @@ namespace FlaxEditor.Windows private void CreateViewportSizingContextMenu(ContextMenu vsMenu) { // Add default viewport sizing options - for (int i = 0; i < _defaultViewportScaling.Count; i++) + var defaultOptions = Editor.UI.DefaultViewportScaleOptions; + for (int i = 0; i < defaultOptions.Count; i++) { - var viewportScale = _defaultViewportScaling[i]; + var viewportScale = defaultOptions[i]; var button = vsMenu.AddButton(viewportScale.Label); button.CloseMenuOnClick = false; - button.Icon = viewportScale.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; button.Tag = viewportScale; - if (viewportScale.Active) + + // No default index is active. + if (_defaultScaleActiveIndex == -1) + { + button.Icon = SpriteHandle.Invalid; + } + // This is the active index. + else if (_defaultScaleActiveIndex == i) + { + button.Icon = Style.Current.CheckBoxTick; ChangeViewportRatio(viewportScale); + } button.Clicked += () => { @@ -789,36 +732,47 @@ namespace FlaxEditor.Windows // Reset selected icon on all buttons foreach (var child in vsMenu.Items) { - if (child is ContextMenuButton cmb && cmb.Tag is ViewportScaleOptions v) + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) { if (cmb == button) { - v.Active = true; + var index = defaultOptions.FindIndex(x => x == v); + _defaultScaleActiveIndex = index; + _customScaleActiveIndex = -1; // Reset custom index because default was chosen. button.Icon = Style.Current.CheckBoxTick; ChangeViewportRatio(v); } - else if (v.Active) + else if (cmb.Icon != SpriteHandle.Invalid) { cmb.Icon = SpriteHandle.Invalid; - v.Active = false; } } } }; } - if (_defaultViewportScaling.Count != 0) + if (defaultOptions.Count != 0) vsMenu.AddSeparator(); // Add custom viewport options - for (int i = 0; i < _customViewportScaling.Count; i++) + var customOptions = Editor.UI.CustomViewportScaleOptions; + for (int i = 0; i < customOptions.Count; i++) { - var viewportScale = _customViewportScaling[i]; + var viewportScale = customOptions[i]; var childCM = vsMenu.AddChildMenu(viewportScale.Label); childCM.CloseMenuOnClick = false; - childCM.Icon = viewportScale.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; childCM.Tag = viewportScale; - if (viewportScale.Active) + + // No custom index is active. + if (_customScaleActiveIndex == -1) + { + childCM.Icon = SpriteHandle.Invalid; + } + // This is the active index. + else if (_customScaleActiveIndex == i) + { + childCM.Icon = Style.Current.CheckBoxTick; ChangeViewportRatio(viewportScale); + } var applyButton = childCM.ContextMenu.AddButton("Apply"); applyButton.Tag = childCM.Tag = viewportScale; @@ -831,18 +785,19 @@ namespace FlaxEditor.Windows // Reset selected icon on all buttons foreach (var child in vsMenu.Items) { - if (child is ContextMenuButton cmb && cmb.Tag is ViewportScaleOptions v) + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) { if (child == childCM) { - v.Active = true; + var index = customOptions.FindIndex(x => x == v); + _defaultScaleActiveIndex = -1; // Reset default index because custom was chosen. + _customScaleActiveIndex = index; childCM.Icon = Style.Current.CheckBoxTick; ChangeViewportRatio(v); } - else if (v.Active) + else if (cmb.Icon != SpriteHandle.Invalid) { cmb.Icon = SpriteHandle.Invalid; - v.Active = false; } } } @@ -855,20 +810,21 @@ namespace FlaxEditor.Windows if (childCM.Tag == null) return; - var v = (ViewportScaleOptions)childCM.Tag; - if (v.Active) + var v = (UIModule.ViewportScaleOption)childCM.Tag; + if (childCM.Icon != SpriteHandle.Invalid) { - v.Active = false; - _defaultViewportScaling[0].Active = true; - ChangeViewportRatio(_defaultViewportScaling[0]); + _customScaleActiveIndex = -1; + _defaultScaleActiveIndex = 0; + ChangeViewportRatio(defaultOptions[0]); } - _customViewportScaling.Remove(v); + customOptions.Remove(v); + Editor.UI.SaveCustomViewportScalingOptions(); vsMenu.DisposeAllItems(); CreateViewportSizingContextMenu(vsMenu); vsMenu.PerformLayout(); }; } - if (_customViewportScaling.Count != 0) + if (customOptions.Count != 0) vsMenu.AddSeparator(); // Add button @@ -966,19 +922,20 @@ namespace FlaxEditor.Windows submitButton.Clicked += () => { - Enum.TryParse(typeDropdown.SelectedItem, out ViewportScaleType type); + Enum.TryParse(typeDropdown.SelectedItem, out UIModule.ViewportScaleOption.ViewportScaleType type); - var combineString = type == ViewportScaleType.Aspect ? ":" : "x"; + var combineString = type == UIModule.ViewportScaleOption.ViewportScaleType.Aspect ? ":" : "x"; var name = nameTextBox.Text + " (" + wValue.Value + combineString + hValue.Value + ") " + typeDropdown.SelectedItem; - var newViewportOption = new ViewportScaleOptions + var newViewportOption = new UIModule.ViewportScaleOption { ScaleType = type, Label = name, Size = new Int2(wValue.Value, hValue.Value), }; - _customViewportScaling.Add(newViewportOption); + customOptions.Add(newViewportOption); + Editor.UI.SaveCustomViewportScalingOptions(); vsMenu.DisposeAllItems(); CreateViewportSizingContextMenu(vsMenu); vsMenu.PerformLayout(); @@ -1221,8 +1178,8 @@ namespace FlaxEditor.Windows writer.WriteAttributeString("ShowGUI", ShowGUI.ToString()); writer.WriteAttributeString("EditGUI", EditGUI.ToString()); writer.WriteAttributeString("ShowDebugDraw", ShowDebugDraw.ToString()); - writer.WriteAttributeString("DefaultViewportScaling", JsonSerializer.Serialize(_defaultViewportScaling)); - writer.WriteAttributeString("CustomViewportScaling", JsonSerializer.Serialize(_customViewportScaling)); + writer.WriteAttributeString("DefaultViewportScalingIndex", _defaultScaleActiveIndex.ToString()); + writer.WriteAttributeString("CustomViewportScalingIndex", _customScaleActiveIndex.ToString()); } /// @@ -1234,22 +1191,21 @@ namespace FlaxEditor.Windows EditGUI = value1; if (bool.TryParse(node.GetAttribute("ShowDebugDraw"), out value1)) ShowDebugDraw = value1; - if (node.HasAttribute("CustomViewportScaling")) - _customViewportScaling = JsonSerializer.Deserialize>(node.GetAttribute("CustomViewportScaling")); + if (int.TryParse(node.GetAttribute("DefaultViewportScalingIndex"), out int value2)) + _defaultScaleActiveIndex = value2; + if (int.TryParse(node.GetAttribute("CustomViewportScalingIndex"), out value2)) + _customScaleActiveIndex = value2; - for (int i = 0; i < _customViewportScaling.Count; i++) + if (_defaultScaleActiveIndex != -1) { - if (_customViewportScaling[i].Active) - ChangeViewportRatio(_customViewportScaling[i]); + var options = Editor.UI.DefaultViewportScaleOptions; + ChangeViewportRatio(options[_defaultScaleActiveIndex]); } - - if (node.HasAttribute("DefaultViewportScaling")) - _defaultViewportScaling = JsonSerializer.Deserialize>(node.GetAttribute("DefaultViewportScaling")); - - for (int i = 0; i < _defaultViewportScaling.Count; i++) + + if (_customScaleActiveIndex != -1) { - if (_defaultViewportScaling[i].Active) - ChangeViewportRatio(_defaultViewportScaling[i]); + var options = Editor.UI.CustomViewportScaleOptions; + ChangeViewportRatio(options[_customScaleActiveIndex]); } } From b9cfd054c180d3268805c7f23dc8f35461bd75b2 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 27 Jun 2025 21:38:10 -0500 Subject: [PATCH 031/137] Remove unused variable --- Source/Editor/Viewport/PrefabWindowViewport.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index f7c496703..2ca4feb27 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -77,7 +77,6 @@ namespace FlaxEditor.Viewport private int _defaultScaleActiveIndex = 0; private int _customScaleActiveIndex = -1; private ContextMenuButton _uiModeButton; - private ContextMenu _uiViewCM; /// /// Event fired when the UI Mode is toggled. From 52b64540ab26624f87b630606d4fc7bebd184a27 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sat, 28 Jun 2025 10:46:11 -0500 Subject: [PATCH 032/137] Add extra index guard logic --- .../Editor/Viewport/PrefabWindowViewport.cs | 27 ++++++++++++++----- Source/Editor/Windows/GameWindow.cs | 13 +++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index 2ca4feb27..10a6789a0 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -508,10 +508,17 @@ namespace FlaxEditor.Viewport { if (int.TryParse(defaultData, out var index)) { - _defaultScaleActiveIndex = index; - if (index != -1) + var options = Editor.Instance.UI.DefaultViewportScaleOptions; + if (options.Count > index) { - ChangeUIView(Editor.Instance.UI.DefaultViewportScaleOptions[index]); + _defaultScaleActiveIndex = index; + if (index != -1) + ChangeUIView(Editor.Instance.UI.DefaultViewportScaleOptions[index]); + } + // Assume option does not exist anymore so move to default. + else if (index != -1) + { + _defaultScaleActiveIndex = 0; } } } @@ -521,10 +528,18 @@ namespace FlaxEditor.Viewport { if (int.TryParse(data, out var index)) { - _customScaleActiveIndex = index; - if (index != -1) + var options = Editor.Instance.UI.CustomViewportScaleOptions; + if (options.Count > index) { - ChangeUIView(Editor.Instance.UI.CustomViewportScaleOptions[index]); + _customScaleActiveIndex = index; + if (index != -1) + ChangeUIView(options[index]); + } + // Assume option does not exist anymore so move to default. + else if (index != -1) + { + _defaultScaleActiveIndex = 0; + _customScaleActiveIndex = -1; } } } diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 1f5399926..db3ea9d7e 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -1199,13 +1199,22 @@ namespace FlaxEditor.Windows if (_defaultScaleActiveIndex != -1) { var options = Editor.UI.DefaultViewportScaleOptions; - ChangeViewportRatio(options[_defaultScaleActiveIndex]); + if (options.Count > _defaultScaleActiveIndex) + ChangeViewportRatio(options[_defaultScaleActiveIndex]); + else + _defaultScaleActiveIndex = 0; } if (_customScaleActiveIndex != -1) { var options = Editor.UI.CustomViewportScaleOptions; - ChangeViewportRatio(options[_customScaleActiveIndex]); + if (options.Count > _customScaleActiveIndex) + ChangeViewportRatio(options[_customScaleActiveIndex]); + else + { + _defaultScaleActiveIndex = 0; + _customScaleActiveIndex = -1; + } } } From 5c7712daadbb49dd13388d7a2f7521fe8bf9b0ee Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:07:25 -0500 Subject: [PATCH 033/137] Add audio clip started and finished events to audio source --- Source/Engine/Audio/AudioSource.cpp | 15 ++++++++++++++- Source/Engine/Audio/AudioSource.h | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index cff89e7e1..c15084dc3 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -168,7 +168,7 @@ void AudioSource::Play() else { // Source was nt properly added to the Audio Backend - LOG(Warning, "Cannot play unitialized audio source."); + LOG(Warning, "Cannot play uninitialized audio source."); } } @@ -395,6 +395,9 @@ void AudioSource::Update() AudioBackend::Source::VelocityChanged(SourceID, _velocity); } + if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) + ClipStarted(); + // Reset starting to play value once time is greater than zero if (_startingToPlay && GetTime() > 0.0f) { @@ -416,6 +419,7 @@ void AudioSource::Update() { Stop(); } + ClipFinished(); } } @@ -486,6 +490,7 @@ void AudioSource::Update() { Stop(); } + ClipFinished(); } ASSERT(_streamingFirstChunk < clip->Buffers.Count()); @@ -583,3 +588,11 @@ void AudioSource::BeginPlay(SceneBeginData* data) SetTime(GetStartTime()); } } + +void AudioSource::EndPlay() +{ + Actor::EndPlay(); + + ClipStarted.UnbindAll(); + ClipFinished.UnbindAll(); +} diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index b83a2b408..4e05d1594 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -76,6 +76,16 @@ public: API_FIELD(Attributes="EditorOrder(10), DefaultValue(null), EditorDisplay(\"Audio Source\")") AssetReference Clip; + /// + /// Event fired when the audio clip starts. + /// + API_EVENT() Delegate<> ClipStarted; + + /// + /// Event fired when the audio clip finishes. + /// + API_EVENT() Delegate<> ClipFinished; + /// /// Gets the velocity of the source. Determines pitch in relation to AudioListener's position. Only relevant for spatial (3D) sources. /// @@ -326,4 +336,5 @@ protected: void OnDisable() override; void OnTransformChanged() override; void BeginPlay(SceneBeginData* data) override; + void EndPlay() override; }; From 0dc1e04c897606bd3ecb03b917ebef70b551b89e Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:07:49 -0500 Subject: [PATCH 034/137] Add slider to audio debug editor for selecting time. --- .../Dedicated/AudioSourceEditor.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs b/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs index 1ddc1c144..0b15773b8 100644 --- a/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs @@ -13,6 +13,8 @@ namespace FlaxEditor.CustomEditors.Dedicated public class AudioSourceEditor : ActorEditor { private Label _infoLabel; + private Slider _slider; + private AudioSource.States _slideStartState; /// public override void Initialize(LayoutElementsContainer layout) @@ -28,6 +30,13 @@ namespace FlaxEditor.CustomEditors.Dedicated _infoLabel = playbackGroup.Label(string.Empty).Label; _infoLabel.AutoHeight = true; + // Play back slider + var sliderElement = playbackGroup.CustomContainer(); + _slider = sliderElement.CustomControl; + _slider.ThumbSize = new Float2(_slider.ThumbSize.X * 0.5f, _slider.ThumbSize.Y); + _slider.SlidingStart += OnSlidingStart; + _slider.SlidingEnd += OnSlidingEnd; + var grid = playbackGroup.UniformGrid(); var gridControl = grid.CustomControl; gridControl.ClipChildren = false; @@ -40,6 +49,38 @@ namespace FlaxEditor.CustomEditors.Dedicated } } + private void OnSlidingEnd() + { + foreach (var value in Values) + { + if (value is AudioSource audioSource && audioSource.Clip) + { + switch (_slideStartState) + { + case AudioSource.States.Playing: + audioSource.Play(); + break; + case AudioSource.States.Paused: + case AudioSource.States.Stopped: + audioSource.Pause(); + break; + default: break; + } + } + } + } + + private void OnSlidingStart() + { + foreach (var value in Values) + { + if (value is AudioSource audioSource && audioSource.Clip) + { + _slideStartState = audioSource.State; + } + } + } + /// public override void Refresh() { @@ -51,7 +92,29 @@ namespace FlaxEditor.CustomEditors.Dedicated foreach (var value in Values) { if (value is AudioSource audioSource && audioSource.Clip) + { text += $"Time: {audioSource.Time:##0.0}s / {audioSource.Clip.Length:##0.0}s\n"; + _slider.Maximum = audioSource.Clip.Length; + _slider.Minimum = 0; + if (_slider.IsSliding) + { + if (audioSource.State != AudioSource.States.Playing) + { + // Play to move slider correctly + audioSource.Play(); + audioSource.Time = _slider.Value; + } + else + { + audioSource.Time = _slider.Value; + } + } + else + { + _slider.Value = audioSource.Time; + } + + } } _infoLabel.Text = text; } From 0e3a22faa0a0207f8b1acbb86de801dcbd430a2c Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:11:06 -0500 Subject: [PATCH 035/137] Fix spelling in comment. --- Source/Engine/Audio/AudioSource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index c15084dc3..e17fbca0b 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -167,7 +167,7 @@ void AudioSource::Play() } else { - // Source was nt properly added to the Audio Backend + // Source was not properly added to the Audio Backend LOG(Warning, "Cannot play uninitialized audio source."); } } From 6f15ef769065ec3ac868a23ecd9aacdd55c84e72 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:15:54 -0500 Subject: [PATCH 036/137] Fix location of clip start call. --- Source/Engine/Audio/AudioSource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index e17fbca0b..069fa29a3 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -395,15 +395,15 @@ void AudioSource::Update() AudioBackend::Source::VelocityChanged(SourceID, _velocity); } - if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) - ClipStarted(); - // Reset starting to play value once time is greater than zero if (_startingToPlay && GetTime() > 0.0f) { _startingToPlay = false; } + if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) + ClipStarted(); + if (!UseStreaming() && Math::NearEqual(GetTime(), 0.0f) && _isActuallyPlayingSth && !_startingToPlay) { int32 queuedBuffers; From e27880c1e65a69fddf96433dd0e93e57372f4fcc Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sat, 2 Aug 2025 09:28:49 -0500 Subject: [PATCH 037/137] Make plugins into their own folders in VSCode. Order VSCode plugin folders with Engine at the bottom. --- .../VisualStudioCodeProjectGenerator.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index c92ae6986..12b9d1e4e 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -648,6 +648,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.AddField("**/Screenshots", true); json.AddField("**/Output", true); json.AddField("**/*.flax", true); + json.AddField("**/Plugins", true); json.EndObject(); // Extension settings @@ -683,9 +684,15 @@ namespace Flax.Build.Projects.VisualStudioCode json.EndObject(); // Referenced projects outside the current project (including engine too) - foreach (var project in Globals.Project.GetAllProjects()) + var projects = Globals.Project.GetAllProjects(); + // Move Engine to last for organizational purposes. + var engineProject = projects.First(x => x.Name == "Flax"); + var projectsWithoutEngine = projects.Where(x => x.Name != "Flax"); + projectsWithoutEngine = projectsWithoutEngine.OrderBy(x => x.Name); + var sortedProjects = projectsWithoutEngine.Concat([engineProject]); + foreach (var project in sortedProjects) { - if (!project.ProjectFolderPath.Contains(Globals.Project.ProjectFolderPath)) + if (!project.ProjectFolderPath.Equals(Globals.Project.ProjectFolderPath)) { json.BeginObject(); { From 14a69a11df38b8a5a86abbeba6d7bee09e4271e1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 7 Sep 2025 23:50:41 +0200 Subject: [PATCH 038/137] Add Android native crashes caching --- .../Platform/Android/AndroidPlatform.cpp | 54 +++++++++++++++++++ Source/Engine/Scripting/Runtime/DotNet.cpp | 6 +++ 2 files changed, 60 insertions(+) diff --git a/Source/Engine/Platform/Android/AndroidPlatform.cpp b/Source/Engine/Platform/Android/AndroidPlatform.cpp index 18fb85bb9..2f4577877 100644 --- a/Source/Engine/Platform/Android/AndroidPlatform.cpp +++ b/Source/Engine/Platform/Android/AndroidPlatform.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,57 @@ _Unwind_Reason_Code AndroidUnwindCallback(struct _Unwind_Context* context, void* #endif +static void CrashHandler(int32 signal, siginfo_t* info, void* context) +{ + // Skip if engine already crashed + if (Engine::FatalError != FatalErrorType::None) + return; + + // Get exception info + String errorMsg(TEXT("Unhandled exception: ")); + switch (signal) + { +#define CASE(x) case x: errorMsg += TEXT(#x); break + CASE(SIGABRT); + CASE(SIGILL); + CASE(SIGSEGV); + CASE(SIGQUIT); + CASE(SIGFPE); + CASE(SIGBUS); + CASE(SIGSYS); +#undef CASE + default: + errorMsg += StringUtils::ToString(signal); + } + + // Log exception and return to the crash location when using debugger + if (Platform::IsDebuggerPresent()) + { + LOG_STR(Error, errorMsg); + const String stackTrace = Platform::GetStackTrace(3, 60, nullptr); + LOG_STR(Error, stackTrace); + return; + } + + // Crash engine + Platform::Fatal(errorMsg.Get(), nullptr, FatalErrorType::Exception); +} + +void AndroidRegisterCrashHandling() +{ + struct sigaction action; + Platform::MemoryClear(&action, sizeof(action)); + action.sa_sigaction = CrashHandler; + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGILL, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + sigaction(SIGQUIT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGBUS, &action, nullptr); + sigaction(SIGSYS, &action, nullptr); +} + struct AndroidKeyEventType { uint32_t KeyCode; @@ -875,6 +927,8 @@ bool AndroidPlatform::Init() DeviceId.D = (uint32)AndroidCpu.ClockSpeed * AndroidCpu.LogicalProcessorCount * AndroidCpu.ProcessorCoreCount * AndroidCpu.CacheLineSize; } + AndroidRegisterCrashHandling(); + // Setup native platform input devices Input::Keyboard = KeyboardImpl = New(); Input::Gamepads.Add(GamepadImpl = New()); diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp index 7e717d185..97065487c 100644 --- a/Source/Engine/Scripting/Runtime/DotNet.cpp +++ b/Source/Engine/Scripting/Runtime/DotNet.cpp @@ -2276,6 +2276,12 @@ bool InitHostfxr() LOG(Info, "Mono runtime version: {0}", String(buildInfo)); mono_free(buildInfo); +#if PLATFORM_ANDROID + // Fix native crashes handling on Android + extern void AndroidRegisterCrashHandling(); + AndroidRegisterCrashHandling(); +#endif + return false; } From 24e088fc0876813225e93d25c3b42fc6d9d6727c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 10:23:07 +0200 Subject: [PATCH 039/137] Fix compilation warnings --- Source/Engine/Physics/Actors/IPhysicsDebug.h | 2 +- Source/Engine/Platform/Mac/MacPlatform.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Physics/Actors/IPhysicsDebug.h b/Source/Engine/Physics/Actors/IPhysicsDebug.h index cedd3d822..57e9a97e3 100644 --- a/Source/Engine/Physics/Actors/IPhysicsDebug.h +++ b/Source/Engine/Physics/Actors/IPhysicsDebug.h @@ -12,7 +12,7 @@ public: { } }; -#define ImplementPhysicsDebug void DrawPhysicsDebug(RenderView& view) +#define ImplementPhysicsDebug void DrawPhysicsDebug(RenderView& view) override #else #define ImplementPhysicsDebug #endif diff --git a/Source/Engine/Platform/Mac/MacPlatform.cpp b/Source/Engine/Platform/Mac/MacPlatform.cpp index 6c7fbf533..6ba001f20 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.cpp +++ b/Source/Engine/Platform/Mac/MacPlatform.cpp @@ -258,7 +258,10 @@ bool MacPlatform::Init() // Get device id { - io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/"); +#if MAC_OS_X_VERSION_MAX_ALLOWED < 120000 +#define kIOMainPortDefault kIOMasterPortDefault +#endif + io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMainPortDefault, "IOService:/"); CFStringRef deviceUuid = (CFStringRef)IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0); IOObjectRelease(ioRegistryRoot); String uuidStr = AppleUtils::ToString(deviceUuid); From 8921cf51569ef68a422c975f192952e01540c18e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 10:42:10 +0200 Subject: [PATCH 040/137] Add label/button text to string convertion for better debugging --- Source/Engine/UI/GUI/Common/Label.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs index 72d4cd188..df77acc14 100644 --- a/Source/Engine/UI/GUI/Common/Label.cs +++ b/Source/Engine/UI/GUI/Common/Label.cs @@ -344,5 +344,11 @@ namespace FlaxEngine.GUI base.PerformLayoutBeforeChildren(); } + + /// + public override string ToString() + { + return $"{GetType()}, '{ConvertedText()}'"; + } } } From 64e127a47acad54b9b43add552819c4389c40919 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 15:25:24 +0200 Subject: [PATCH 041/137] Fix crashes of scripting backend on Android --- .../Engine/Engine/NativeInterop.Unmanaged.cs | 2 +- Source/Engine/Engine/NativeInterop.cs | 65 ++++++++++--------- Source/Engine/Scripting/ManagedCLR/MUtils.cpp | 5 +- Source/Engine/Scripting/Runtime/DotNet.cpp | 2 +- Source/Engine/Scripting/ScriptingObject.cpp | 2 +- .../Video/Android/VideoBackendAndroid.cpp | 4 +- Source/ThirdParty/nethost/nethost.Build.cs | 2 + 7 files changed, 44 insertions(+), 38 deletions(-) diff --git a/Source/Engine/Engine/NativeInterop.Unmanaged.cs b/Source/Engine/Engine/NativeInterop.Unmanaged.cs index 7c1e2e64a..7af32fc9b 100644 --- a/Source/Engine/Engine/NativeInterop.Unmanaged.cs +++ b/Source/Engine/Engine/NativeInterop.Unmanaged.cs @@ -835,7 +835,7 @@ namespace FlaxEngine.Interop { object fieldOwner = fieldOwnerHandle.Target; IntPtr fieldRef; -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHolder field = Unsafe.As(fieldHandle.Target); fieldRef = IntPtr.Zero; Debug.LogError("Not supported FieldGetValueReference"); diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 7d16b4752..745a01c2f 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -107,17 +107,13 @@ namespace FlaxEngine.Interop { } -#if !USE_AOT +#if !USE_AOT && !DOTNET_HOST_MONO [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "__unmanagedPtr")] extern static ref IntPtr GetUnmanagedPtrFieldReference(Object obj); [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "__internalId")] extern static ref Guid GetInternalIdFieldReference(Object obj); - // Cache offsets to frequently accessed fields of FlaxEngine.Object - private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF); - private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read((typeof(FlaxEngine.Object).GetField("__internalId", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF); - [UnmanagedCallersOnly] internal static void ScriptingObjectSetInternalValues(ManagedHandle objectHandle, IntPtr unmanagedPtr, IntPtr idPtr) { @@ -418,14 +414,21 @@ namespace FlaxEngine.Interop if (field.IsLiteral) return 0; +#if DOTNET_HOST_CORECLR // Get the address of the field, source: https://stackoverflow.com/a/56512720 int fieldOffset = Unsafe.Read((field.FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF; if (!type.IsValueType) fieldOffset += IntPtr.Size; return fieldOffset; +#elif DOTNET_HOST_MONO + // Get the address from _MonoClassField::offset, source: https://meetemq.com/2023/09/10/nets-fields-and-their-offsets/ + IntPtr fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField + fieldOffsetPtr += 3; // Skip three pointers (type, name, parent_and_flags) + return *(int*)fieldOffsetPtr - IntPtr.Size * 2; // Load the value of a pointer (4 bytes, int32), then subtracting 16 bytes from it (2 pointers for vtable and threadsync) +#endif } -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO /// /// Helper utility to set field of the referenced value via reflection. /// @@ -756,12 +759,12 @@ namespace FlaxEngine.Interop } } } - throw new NativeInteropException($"Invalid field with offset {fieldOffset} to marshal for type {typeof(T).Name}"); + throw new NativeInteropException($"Invalid field with offset {fieldOffset} to marshal for type {typeof(T).FullName}"); } private static void ToManagedFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct { -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO IntPtr fieldValue = Unsafe.Read(nativeFieldPtr.ToPointer()); FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #else @@ -773,7 +776,7 @@ namespace FlaxEngine.Interop private static void ToManagedFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class { -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO IntPtr fieldValue = Unsafe.Read(nativeFieldPtr.ToPointer()); FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #else @@ -785,7 +788,7 @@ namespace FlaxEngine.Interop private static void ToNativeFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct { -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO object boxed = field.GetValue(fieldOwner); IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed)); #else @@ -797,7 +800,7 @@ namespace FlaxEngine.Interop private static void ToNativeFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class { -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO object boxed = field.GetValue(fieldOwner); IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed)); #else @@ -845,13 +848,13 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); } -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = default; #else ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, nativeFieldPtr, false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -866,13 +869,13 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); } -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = default; #else ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, nativeFieldPtr, false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -885,13 +888,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField[] fieldValue = (TField[])field.GetValue(fieldOwner); #else ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -904,13 +907,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField[] fieldValue = null; #else ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -925,7 +928,7 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - startPtr).ToInt32(); } -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = (TField)field.GetValue(fieldOwner); #else ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); @@ -978,13 +981,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = null; #else ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -996,13 +999,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = default; #else ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -1014,13 +1017,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField[] fieldValue = null; #else ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -1032,13 +1035,13 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField[] fieldValue = null; #else ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); #endif MarshalHelper.ToManaged(ref fieldValue, Unsafe.Read(nativeFieldPtr.ToPointer()), false); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue); #endif } @@ -1050,7 +1053,7 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = (TField)field.GetValue(fieldOwner); #else ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference(fieldOffset, ref fieldOwner); @@ -1065,7 +1068,7 @@ namespace FlaxEngine.Interop nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size); fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32(); -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = (TField)field.GetValue(fieldOwner); #else ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); @@ -1439,7 +1442,7 @@ namespace FlaxEngine.Interop return RuntimeHelpers.GetUninitializedObject(wrappedType); } -#if !USE_AOT +#if !USE_AOT && !DOTNET_HOST_MONO internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr) { object obj = RuntimeHelpers.GetUninitializedObject(wrappedType); diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp index fd0596ef5..69fb5aa08 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp @@ -414,8 +414,9 @@ Variant MUtils::UnboxVariant(MObject* value) // Array of Enums for (int32 i = 0; i < array.Count(); i++) { - array[i].SetType(VariantType(VariantType::Enum, elementTypename)); - Platform::MemoryCopy(&array[i].AsUint64, (byte*)ptr + elementSize * i, elementSize); + auto& a = array.Get()[i]; + a.SetType(VariantType(VariantType::Enum, elementTypename)); + Platform::MemoryCopy(&a.AsUint64, (byte*)ptr + elementSize * i, elementSize); } } else if (elementClass->IsValueType()) diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp index 97065487c..f69e0c060 100644 --- a/Source/Engine/Scripting/Runtime/DotNet.cpp +++ b/Source/Engine/Scripting/Runtime/DotNet.cpp @@ -710,7 +710,7 @@ void MCore::ScriptingObject::SetInternalValues(MClass* klass, MObject* object, v #if PLATFORM_DESKTOP && !USE_MONO_AOT static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectSetInternalValues")); CallStaticMethod(ScriptingObjectSetInternalValuesPtr, object, unmanagedPtr, id); -#elif !USE_EDITOR +#elif !USE_EDITOR && PLATFORM_SWITCH // TODO: test this on other AOT platforms (Android with Mono JIT doesn't work) static MField* monoUnmanagedPtrField = ::ScriptingObject::GetStaticClass()->GetField("__unmanagedPtr"); static MField* monoIdField = ::ScriptingObject::GetStaticClass()->GetField("__internalId"); if (monoUnmanagedPtrField) diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp index eb9afdeae..35bd16eb6 100644 --- a/Source/Engine/Scripting/ScriptingObject.cpp +++ b/Source/Engine/Scripting/ScriptingObject.cpp @@ -249,7 +249,7 @@ ScriptingObject* ScriptingObject::ToNative(MObject* obj) #if USE_CSHARP if (obj) { -#if USE_MONO || USE_MONO_AOT +#if USE_MONO || USE_MONO_AOT || DOTNET_HOST_MONO const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr); CHECK_RETURN(ptrField, nullptr); ptrField->GetValue(obj, &ptr); diff --git a/Source/Engine/Video/Android/VideoBackendAndroid.cpp b/Source/Engine/Video/Android/VideoBackendAndroid.cpp index 3358c46a2..145ce8aab 100644 --- a/Source/Engine/Video/Android/VideoBackendAndroid.cpp +++ b/Source/Engine/Video/Android/VideoBackendAndroid.cpp @@ -353,7 +353,7 @@ bool VideoBackendAndroid::Player_Create(const VideoBackendPlayerInfo& info, Vide { // File (AAsset* or Unix handle) #if VIDEO_API_ANDROID_DEBUG - LOG(Info, "[VideoBackendAndroid] Loading local file"); + LOG(Info, "[VideoBackendAndroid] Loading local file '{}'", info.Url); #endif auto* mediaSource = AMediaDataSource_new(); AMediaDataSource_setUserdata(mediaSource, fileStream); @@ -366,7 +366,7 @@ bool VideoBackendAndroid::Player_Create(const VideoBackendPlayerInfo& info, Vide { // Url #if VIDEO_API_ANDROID_DEBUG - LOG(Info, "[VideoBackendAndroid] Loading url"); + LOG(Info, "[VideoBackendAndroid] Loading url '{}'", info.Url); #endif const StringAsANSI<> url(info.Url.Get(), info.Url.Length()); status = AMediaExtractor_setDataSource(playerAndroid.Extractor, url.Get()); diff --git a/Source/ThirdParty/nethost/nethost.Build.cs b/Source/ThirdParty/nethost/nethost.Build.cs index 97f0d80bd..bac529778 100644 --- a/Source/ThirdParty/nethost/nethost.Build.cs +++ b/Source/ThirdParty/nethost/nethost.Build.cs @@ -112,6 +112,7 @@ public class nethost : ThirdPartyModule { // Use CoreCLR for runtime hosting options.PublicDefinitions.Add("DOTNET_HOST_CORECLR"); + options.ScriptingAPI.Defines.Add("DOTNET_HOST_CORECLR"); options.PublicIncludePaths.Add(hostRuntime.Path); break; } @@ -119,6 +120,7 @@ public class nethost : ThirdPartyModule { // Use Mono for runtime hosting options.PublicDefinitions.Add("DOTNET_HOST_MONO"); + options.ScriptingAPI.Defines.Add("DOTNET_HOST_MONO"); options.PublicIncludePaths.Add(Path.Combine(hostRuntime.Path, "include", "mono-2.0")); break; } From 1f56c75821d5471112919a7c90eaaf71fd3d4f3d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 15:26:03 +0200 Subject: [PATCH 042/137] Minor fixes --- Source/Engine/Engine/NativeInterop.cs | 2 +- Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp | 2 +- Source/Engine/GraphicsDevice/Vulkan/UploadBufferVulkan.cpp | 1 + Source/Engine/Renderer/RenderList.cpp | 5 +---- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 745a01c2f..082c6999a 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -422,7 +422,7 @@ namespace FlaxEngine.Interop return fieldOffset; #elif DOTNET_HOST_MONO // Get the address from _MonoClassField::offset, source: https://meetemq.com/2023/09/10/nets-fields-and-their-offsets/ - IntPtr fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField + var fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField fieldOffsetPtr += 3; // Skip three pointers (type, name, parent_and_flags) return *(int*)fieldOffsetPtr - IntPtr.Size * 2; // Load the value of a pointer (4 bytes, int32), then subtracting 16 bytes from it (2 pointers for vtable and threadsync) #endif diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index 2db4e202a..2afb18349 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -1388,7 +1388,7 @@ void GPUContextVulkan::UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 } else { - auto allocation = _device->UploadBuffer.Upload(data, size, 4); + auto allocation = _device->UploadBuffer.Upload(data, size, PLATFORM_MEMORY_ALIGNMENT); VkBufferCopy region; region.size = size; diff --git a/Source/Engine/GraphicsDevice/Vulkan/UploadBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/UploadBufferVulkan.cpp index 15b58a8b4..3a0258c8c 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/UploadBufferVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/UploadBufferVulkan.cpp @@ -111,6 +111,7 @@ UploadBufferVulkan::Allocation UploadBufferVulkan::Allocate(uint64 size, uint64 // Move within a page _currentOffset += size; + ASSERT_LOW_LAYER(_currentOffset <= _currentPage->Size); return result; } diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 50bf00f57..72b9a4e20 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -749,10 +749,7 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD else { for (int32 i = 0; i < listSize; i++) - { - const DrawCall& drawCall = drawCallsData[listData[i]]; - sortedKeys[i] = drawCall.SortKey; - } + sortedKeys[i] = drawCallsData[listData[i]].SortKey; } // Sort draw calls indices From 19d0d3b683d5b3fdf4232fc94c3394d6e7eff035 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 15:26:27 +0200 Subject: [PATCH 043/137] Remove system lockers during asset loads or saving (only unload needs it) --- Source/Engine/Content/Assets/Animation.cpp | 1 - Source/Engine/Content/Assets/AnimationGraph.cpp | 3 --- .../Content/Assets/AnimationGraphFunction.cpp | 2 -- Source/Engine/Particles/ParticleEmitter.cpp | 16 ---------------- .../Engine/Particles/ParticleEmitterFunction.cpp | 2 -- 5 files changed, 24 deletions(-) diff --git a/Source/Engine/Content/Assets/Animation.cpp b/Source/Engine/Content/Assets/Animation.cpp index 015f09e4e..917db28ac 100644 --- a/Source/Engine/Content/Assets/Animation.cpp +++ b/Source/Engine/Content/Assets/Animation.cpp @@ -600,7 +600,6 @@ void Animation::OnScriptingDispose() Asset::LoadResult Animation::load() { PROFILE_MEM(AnimationsData); - ScopeWriteLock systemScope(Animations::SystemLocker); // Get stream with animations data const auto dataChunk = GetChunk(0); diff --git a/Source/Engine/Content/Assets/AnimationGraph.cpp b/Source/Engine/Content/Assets/AnimationGraph.cpp index ad6353196..2823b012f 100644 --- a/Source/Engine/Content/Assets/AnimationGraph.cpp +++ b/Source/Engine/Content/Assets/AnimationGraph.cpp @@ -27,7 +27,6 @@ AnimationGraph::AnimationGraph(const SpawnParams& params, const AssetInfo* info) Asset::LoadResult AnimationGraph::load() { PROFILE_MEM(AnimationsData); - ScopeWriteLock systemScope(Animations::SystemLocker); // Get stream with graph data const auto surfaceChunk = GetChunk(0); @@ -86,7 +85,6 @@ bool AnimationGraph::InitAsAnimation(SkinnedModel* baseModel, Animation* anim, b return true; } PROFILE_MEM(AnimationsData); - ScopeWriteLock systemScope(Animations::SystemLocker); // Create Graph data MemoryWriteStream writeStream(512); @@ -172,7 +170,6 @@ bool AnimationGraph::SaveSurface(const BytesContainer& data) { if (OnCheckSave()) return true; - ScopeWriteLock systemScope(Animations::SystemLocker); ScopeLock lock(Locker); if (IsVirtual()) diff --git a/Source/Engine/Content/Assets/AnimationGraphFunction.cpp b/Source/Engine/Content/Assets/AnimationGraphFunction.cpp index 812a8f090..c70a9c8a0 100644 --- a/Source/Engine/Content/Assets/AnimationGraphFunction.cpp +++ b/Source/Engine/Content/Assets/AnimationGraphFunction.cpp @@ -22,7 +22,6 @@ AnimationGraphFunction::AnimationGraphFunction(const SpawnParams& params, const Asset::LoadResult AnimationGraphFunction::load() { PROFILE_MEM(AnimationsData); - ScopeWriteLock systemScope(Animations::SystemLocker); // Get graph data from chunk const auto surfaceChunk = GetChunk(0); @@ -98,7 +97,6 @@ bool AnimationGraphFunction::SaveSurface(const BytesContainer& data) const { if (OnCheckSave()) return true; - ScopeWriteLock systemScope(Animations::SystemLocker); ScopeLock lock(Locker); // Set Visject Surface data diff --git a/Source/Engine/Particles/ParticleEmitter.cpp b/Source/Engine/Particles/ParticleEmitter.cpp index 80738e65d..f4c883e20 100644 --- a/Source/Engine/Particles/ParticleEmitter.cpp +++ b/Source/Engine/Particles/ParticleEmitter.cpp @@ -106,7 +106,6 @@ namespace Asset::LoadResult ParticleEmitter::load() { PROFILE_MEM(Particles); - ScopeWriteLock systemScope(Particles::SystemLocker); // Load the graph const auto surfaceChunk = GetChunk(SHADER_FILE_CHUNK_VISJECT_SURFACE); @@ -330,8 +329,6 @@ Asset::LoadResult ParticleEmitter::load() // Wait for resources used by the emitter to be loaded // eg. texture used to place particles on spawn needs to be available - // Free Particles::SystemLocker when waiting on asset load to prevent lock-contention. - bool waitForAsset = false; for (const auto& node : Graph.Nodes) { if ((node.Type == GRAPH_NODE_MAKE_TYPE(5, 1) || node.Type == GRAPH_NODE_MAKE_TYPE(5, 2)) && node.Assets.Count() > 0) @@ -339,11 +336,6 @@ Asset::LoadResult ParticleEmitter::load() const auto texture = node.Assets[0].As(); if (texture) { - if (!waitForAsset) - { - waitForAsset = true; - Particles::SystemLocker.WriteUnlock(); - } WaitForAsset(texture); } } @@ -352,16 +344,9 @@ Asset::LoadResult ParticleEmitter::load() { if (parameter.Type.Type == VariantType::Asset) { - if (!waitForAsset) - { - waitForAsset = true; - Particles::SystemLocker.WriteUnlock(); - } WaitForAsset((Asset*)parameter.Value); } } - if (waitForAsset) - Particles::SystemLocker.WriteLock(); return LoadResult::Ok; } @@ -459,7 +444,6 @@ bool ParticleEmitter::SaveSurface(const BytesContainer& data) { if (OnCheckSave()) return true; - ScopeWriteLock systemScope(Particles::SystemLocker); ScopeLock lock(Locker); // Release all chunks diff --git a/Source/Engine/Particles/ParticleEmitterFunction.cpp b/Source/Engine/Particles/ParticleEmitterFunction.cpp index 37e879172..0079ec933 100644 --- a/Source/Engine/Particles/ParticleEmitterFunction.cpp +++ b/Source/Engine/Particles/ParticleEmitterFunction.cpp @@ -43,7 +43,6 @@ ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, cons Asset::LoadResult ParticleEmitterFunction::load() { PROFILE_MEM(Particles); - ScopeWriteLock systemScope(Particles::SystemLocker); // Load graph const auto surfaceChunk = GetChunk(0); @@ -189,7 +188,6 @@ bool ParticleEmitterFunction::SaveSurface(const BytesContainer& data) const { if (OnCheckSave()) return true; - ScopeWriteLock systemScope(Particles::SystemLocker); ScopeLock lock(Locker); // Set Visject Surface data From 64c62f269cc48a836d32c1a834c90408230461d1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 22:54:37 +0200 Subject: [PATCH 044/137] Optimize D3D12 with `D3D12_HEAP_FLAG_CREATE_NOT_ZEROED` in some cases --- Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp | 3 ++- Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp index bb1eaacdb..811076af6 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp @@ -136,8 +136,9 @@ bool GPUBufferDX12::OnInit() // Create resource ID3D12Resource* resource; + D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED; D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON; - VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource))); + VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, heapFlags, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource))); // Set state initResource(resource, initialState, 1); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp index c44d6f80d..5913468ee 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp @@ -159,7 +159,8 @@ bool GPUTextureDX12::OnInit() initialState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; // Create texture - auto result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, initialState, clearValuePtr, IID_PPV_ARGS(&resource)); + D3D12_HEAP_FLAGS heapFlags = useRTV || useDSV ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE; + auto result = device->CreateCommittedResource(&heapProperties, heapFlags, &resourceDesc, initialState, clearValuePtr, IID_PPV_ARGS(&resource)); LOG_DIRECTX_RESULT_WITH_RETURN(result, true); // Set state From 5e52bf64698eb8809a5a724a70bcbb604202dc09 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 23:21:10 +0200 Subject: [PATCH 045/137] Fix missing code from 80de56f469b4dcae7917dbf20b3bfb68d72364cf --- Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp index e4ed7d74f..010e14bf9 100644 --- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp +++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp @@ -884,7 +884,10 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex for (const auto& e : cascade.Chunks) { if (e.Key.Layer != 0) + { + maxLayer = Math::Max(maxLayer, e.Key.Layer); continue; + } auto& chunk = e.Value; data.ChunkCoord = e.Key.Coord * GLOBAL_SDF_RASTERIZE_CHUNK_SIZE; cascade.NonEmptyChunks.Add(e.Key); From b537a80031d7a86f23427f6fa8a41b85a640ba35 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 9 Sep 2025 23:53:28 +0200 Subject: [PATCH 046/137] Fix regression in lights/shadows setup from 1a88fefd76daae6cddd261e02b4a3d1b396c8b05 --- Source/Engine/Level/Actors/PointLight.cpp | 1 - Source/Engine/Level/Actors/SpotLight.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp index d28ee3f16..607bf1bc4 100644 --- a/Source/Engine/Level/Actors/PointLight.cpp +++ b/Source/Engine/Level/Actors/PointLight.cpp @@ -19,7 +19,6 @@ PointLight::PointLight(const SpawnParams& params) _direction = Float3::Forward; _sphere = BoundingSphere(Vector3::Zero, _radius); BoundingBox::FromSphere(_sphere, _box); - _drawCategory = SceneRendering::SceneDrawAsync; } float PointLight::ComputeBrightness() const diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp index af783ce84..85b77647a 100644 --- a/Source/Engine/Level/Actors/SpotLight.cpp +++ b/Source/Engine/Level/Actors/SpotLight.cpp @@ -27,7 +27,6 @@ SpotLight::SpotLight(const SpawnParams& params) const float boundsRadius = Math::Sqrt(1.25f * _radius * _radius - _radius * _radius * _cosOuterCone); _sphere = BoundingSphere(GetPosition() + 0.5f * GetDirection() * _radius, boundsRadius); BoundingBox::FromSphere(_sphere, _box); - _drawCategory = SceneRendering::SceneDrawAsync; } float SpotLight::ComputeBrightness() const From f0dea9d528a9f0f513d74a55fb16e1169dfaff79 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Wed, 10 Sep 2025 20:05:28 +0300 Subject: [PATCH 047/137] Add support for Visual Studio 2026 and v145 MSVC toolset --- .../InBuildSourceCodeEditor.cs | 4 ++++ Source/Editor/Scripting/CodeEditor.h | 5 +++++ .../VisualStudio/VisualStudioEditor.cpp | 6 ++++++ .../VisualStudio/VisualStudioEditor.h | 2 +- .../Flax.Build/Build/Builder.Projects.cs | 11 +++++++++-- Source/Tools/Flax.Build/Configuration.cs | 6 ++++++ .../Flax.Build/Platforms/GDK/GDKPlatform.cs | 5 ++++- .../Flax.Build/Platforms/UWP/UWPPlatform.cs | 10 ++++++++-- .../Flax.Build/Platforms/UWP/UWPToolchain.cs | 7 ++++++- .../Platforms/Windows/WindowsPlatform.cs | 3 ++- .../Platforms/Windows/WindowsPlatformBase.cs | 13 +++++++++++-- .../Platforms/Windows/WindowsToolchainBase.cs | 8 +++++++- .../Flax.Build/Projects/ProjectFormat.cs | 5 +++++ .../Flax.Build/Projects/ProjectGenerator.cs | 10 +++++++++- .../VisualStudio/CSProjectGenerator.cs | 4 +++- .../VisualStudio/CSSDKProjectGenerator.cs | 4 +++- .../VisualStudio/VCProjectGenerator.cs | 1 + .../VisualStudio/VisualStudioInstance.cs | 2 ++ .../VisualStudioProjectGenerator.cs | 19 +++++++++++++++++-- .../VisualStudio/VisualStudioVersion.cs | 5 +++++ 20 files changed, 114 insertions(+), 16 deletions(-) diff --git a/Source/Editor/Modules/SourceCodeEditing/InBuildSourceCodeEditor.cs b/Source/Editor/Modules/SourceCodeEditing/InBuildSourceCodeEditor.cs index 5aba20b65..a2a333805 100644 --- a/Source/Editor/Modules/SourceCodeEditing/InBuildSourceCodeEditor.cs +++ b/Source/Editor/Modules/SourceCodeEditing/InBuildSourceCodeEditor.cs @@ -54,6 +54,9 @@ namespace FlaxEditor.Modules.SourceCodeEditing case CodeEditorTypes.VS2022: Name = "Visual Studio 2022"; break; + case CodeEditorTypes.VS2026: + Name = "Visual Studio 2026"; + break; case CodeEditorTypes.VSCode: Name = "Visual Studio Code"; break; @@ -110,6 +113,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing case CodeEditorTypes.VS2017: case CodeEditorTypes.VS2019: case CodeEditorTypes.VS2022: + case CodeEditorTypes.VS2026: // TODO: finish dynamic files adding to the project //Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync(); break; diff --git a/Source/Editor/Scripting/CodeEditor.h b/Source/Editor/Scripting/CodeEditor.h index 13edd6af1..9cc71977b 100644 --- a/Source/Editor/Scripting/CodeEditor.h +++ b/Source/Editor/Scripting/CodeEditor.h @@ -62,6 +62,11 @@ API_ENUM(Namespace="FlaxEditor", Attributes="HideInEditor") enum class CodeEdito /// VS2022, + /// + /// Visual Studio 2026 + /// + VS2026, + /// /// Visual Studio Code /// diff --git a/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.cpp b/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.cpp index cebdc681d..5c06eec9c 100644 --- a/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.cpp +++ b/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.cpp @@ -43,6 +43,9 @@ VisualStudioEditor::VisualStudioEditor(VisualStudioVersion version, const String case VisualStudioVersion::VS2022: _type = CodeEditorTypes::VS2022; break; + case VisualStudioVersion::VS2026: + _type = CodeEditorTypes::VS2026; + break; default: CRASH; break; } @@ -70,6 +73,9 @@ void VisualStudioEditor::FindEditors(Array* output) VisualStudioVersion version; switch (info.VersionMajor) { + case 18: + version = VisualStudioVersion::VS2026; + break; case 17: version = VisualStudioVersion::VS2022; break; diff --git a/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.h b/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.h index 78f069897..1bf1f1433 100644 --- a/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.h +++ b/Source/Editor/Scripting/CodeEditors/VisualStudio/VisualStudioEditor.h @@ -10,7 +10,7 @@ /// /// Microsoft Visual Studio version types /// -DECLARE_ENUM_8(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022); +DECLARE_ENUM_9(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022, VS2026); /// /// Implementation of code editor utility that is using Microsoft Visual Studio. diff --git a/Source/Tools/Flax.Build/Build/Builder.Projects.cs b/Source/Tools/Flax.Build/Build/Builder.Projects.cs index 59538364c..46925355c 100644 --- a/Source/Tools/Flax.Build/Build/Builder.Projects.cs +++ b/Source/Tools/Flax.Build/Build/Builder.Projects.cs @@ -192,6 +192,8 @@ namespace Flax.Build { // Pick the project format var projectFormats = new HashSet(); + if (Configuration.ProjectFormatVS2026) + projectFormats.Add(ProjectFormat.VisualStudio2026); if (Configuration.ProjectFormatVS2022) projectFormats.Add(ProjectFormat.VisualStudio2022); if (Configuration.ProjectFormatVS2019) @@ -209,8 +211,13 @@ namespace Flax.Build if (projectFormats.Count == 0) projectFormats.Add(Platform.BuildPlatform.DefaultProjectFormat); - // Always generate VS solution files for project (needed for C# Intellisense support) - projectFormats.Add(ProjectFormat.VisualStudio2022); + // Always generate VS solution files for project (needed for C# Intellisense support in other IDEs) + if (!projectFormats.Contains(ProjectFormat.VisualStudio2026) && + !projectFormats.Contains(ProjectFormat.VisualStudio2022) && + !projectFormats.Contains(ProjectFormat.VisualStudio)) + { + projectFormats.Add(ProjectFormat.VisualStudio2022); + } foreach (ProjectFormat projectFormat in projectFormats) GenerateProject(projectFormat); diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index f6ad3b3a5..dd6983b3b 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -201,6 +201,12 @@ namespace Flax.Build [CommandLine("vs2022", "Generates Visual Studio 2022 project format files. Valid only with -genproject option.")] public static bool ProjectFormatVS2022 = false; + /// + /// Generates Visual Studio 2026 project format files. Valid only with -genproject option. + /// + [CommandLine("vs2026", "Generates Visual Studio 2026 project format files. Valid only with -genproject option.")] + public static bool ProjectFormatVS2026 = false; + /// /// Generates Visual Studio Code project format files. Valid only with -genproject option. /// diff --git a/Source/Tools/Flax.Build/Platforms/GDK/GDKPlatform.cs b/Source/Tools/Flax.Build/Platforms/GDK/GDKPlatform.cs index 9313c65b0..422299c79 100644 --- a/Source/Tools/Flax.Build/Platforms/GDK/GDKPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/GDK/GDKPlatform.cs @@ -32,8 +32,11 @@ namespace Flax.Build.Platforms if (!toolsets.ContainsKey(WindowsPlatformToolset.v141) && !toolsets.ContainsKey(WindowsPlatformToolset.v142) && !toolsets.ContainsKey(WindowsPlatformToolset.v143) && - !toolsets.ContainsKey(WindowsPlatformToolset.v144)) + !toolsets.ContainsKey(WindowsPlatformToolset.v144) && + !toolsets.ContainsKey(WindowsPlatformToolset.v145)) + { _hasRequiredSDKsInstalled = false; + } } } } diff --git a/Source/Tools/Flax.Build/Platforms/UWP/UWPPlatform.cs b/Source/Tools/Flax.Build/Platforms/UWP/UWPPlatform.cs index 6d8b9e5b1..529e75eda 100644 --- a/Source/Tools/Flax.Build/Platforms/UWP/UWPPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/UWP/UWPPlatform.cs @@ -31,7 +31,12 @@ namespace Flax.Build.Platforms } // Visual Studio 2017+ supported only - var visualStudio = VisualStudioInstance.GetInstances().FirstOrDefault(x => x.Version == VisualStudioVersion.VisualStudio2017 || x.Version == VisualStudioVersion.VisualStudio2019 || x.Version == VisualStudioVersion.VisualStudio2022); + var visualStudio = VisualStudioInstance.GetInstances().FirstOrDefault(x => + x.Version == VisualStudioVersion.VisualStudio2017 || + x.Version == VisualStudioVersion.VisualStudio2019 || + x.Version == VisualStudioVersion.VisualStudio2022 || + x.Version == VisualStudioVersion.VisualStudio2026 + ); if (visualStudio == null) _hasRequiredSDKsInstalled = false; @@ -46,7 +51,8 @@ namespace Flax.Build.Platforms if (!toolsets.ContainsKey(WindowsPlatformToolset.v141) && !toolsets.ContainsKey(WindowsPlatformToolset.v142) && !toolsets.ContainsKey(WindowsPlatformToolset.v143) && - !toolsets.ContainsKey(WindowsPlatformToolset.v144)) + !toolsets.ContainsKey(WindowsPlatformToolset.v144) && + !toolsets.ContainsKey(WindowsPlatformToolset.v145)) { _hasRequiredSDKsInstalled = false; } diff --git a/Source/Tools/Flax.Build/Platforms/UWP/UWPToolchain.cs b/Source/Tools/Flax.Build/Platforms/UWP/UWPToolchain.cs index 983ac37d2..5458c5d7d 100644 --- a/Source/Tools/Flax.Build/Platforms/UWP/UWPToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/UWP/UWPToolchain.cs @@ -29,7 +29,12 @@ namespace Flax.Build.Platforms public UWPToolchain(UWPPlatform platform, TargetArchitecture architecture, WindowsPlatformToolset toolsetVer = WindowsPlatformToolset.Latest, WindowsPlatformSDK sdkVer = WindowsPlatformSDK.Latest) : base(platform, architecture, toolsetVer, sdkVer) { - var visualStudio = VisualStudioInstance.GetInstances().FirstOrDefault(x => x.Version == VisualStudioVersion.VisualStudio2017 || x.Version == VisualStudioVersion.VisualStudio2019 || x.Version == VisualStudioVersion.VisualStudio2022); + var visualStudio = VisualStudioInstance.GetInstances().FirstOrDefault(x => + x.Version == VisualStudioVersion.VisualStudio2017 || + x.Version == VisualStudioVersion.VisualStudio2019 || + x.Version == VisualStudioVersion.VisualStudio2022 || + x.Version == VisualStudioVersion.VisualStudio2026 + ); if (visualStudio == null) throw new Exception("Missing Visual Studio 2017 or newer. It's required to build for UWP."); _usingDirs.Add(Path.Combine(visualStudio.Path, "VC", "vcpackages")); diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs index 02c5ce8f0..a78f8c24f 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs @@ -40,7 +40,8 @@ namespace Flax.Build.Platforms !toolsets.ContainsKey(WindowsPlatformToolset.v141) && !toolsets.ContainsKey(WindowsPlatformToolset.v142) && !toolsets.ContainsKey(WindowsPlatformToolset.v143) && - !toolsets.ContainsKey(WindowsPlatformToolset.v144)) + !toolsets.ContainsKey(WindowsPlatformToolset.v144) && + !toolsets.ContainsKey(WindowsPlatformToolset.v145)) { Log.Warning("Missing MSVC toolset v140 or later (VS 2015 or later C++ build tools). Cannot build for Windows platform."); _hasRequiredSDKsInstalled = false; diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs index 3cdc2f44b..26afcd894 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs @@ -54,6 +54,11 @@ namespace Flax.Build.Platforms /// Visual Studio 2022 (v17.10 and later) /// v144 = 144, + + /// + /// Visual Studio 2026 + /// + v145 = 145, } /// @@ -252,6 +257,8 @@ namespace Flax.Build.Platforms _toolsets[WindowsPlatformToolset.v143] = toolset; else if (version.Major == 14 && version.Minor / 10 == 4) _toolsets[WindowsPlatformToolset.v144] = toolset; + else if (version.Major == 14 && version.Minor / 10 == 5) + _toolsets[WindowsPlatformToolset.v145] = toolset; else Log.Warning("Found Unsupported MSVC toolset version: " + version); } @@ -287,11 +294,12 @@ namespace Flax.Build.Platforms } } - // Visual Studio 2017-2022 - multiple instances + // Visual Studio 2017 or later - multiple instances foreach (var vs in vsInstances.Where(x => x.Version == VisualStudioVersion.VisualStudio2017 || x.Version == VisualStudioVersion.VisualStudio2019 || - x.Version == VisualStudioVersion.VisualStudio2022 + x.Version == VisualStudioVersion.VisualStudio2022 || + x.Version == VisualStudioVersion.VisualStudio2026 )) { FindMsvcToolsets(Path.Combine(vs.Path, "VC", "Tools", "MSVC")); @@ -469,6 +477,7 @@ namespace Flax.Build.Platforms case WindowsPlatformToolset.v142: case WindowsPlatformToolset.v143: case WindowsPlatformToolset.v144: + case WindowsPlatformToolset.v145: { string hostFolder = hostArchitecture == TargetArchitecture.x86 ? "HostX86" : $"Host{hostArchitecture.ToString().ToLower()}"; string nativeCompilerPath = Path.Combine(vcToolChainDir, "bin", hostFolder, architecture.ToString().ToLower(), "cl.exe"); diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs index 1979c4748..fe5abe4a3 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs @@ -89,7 +89,11 @@ namespace Flax.Build.Platforms // Pick the newest installed Visual Studio version if using the default toolset if (toolsetVer == WindowsPlatformToolset.Default) { - if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2022)) + if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2026)) + { + toolsetVer = WindowsPlatformToolset.v145; + } + else if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2022)) { if (toolsets.Keys.Contains(WindowsPlatformToolset.v144)) { @@ -206,6 +210,7 @@ namespace Flax.Build.Platforms case WindowsPlatformToolset.v142: case WindowsPlatformToolset.v143: case WindowsPlatformToolset.v144: + case WindowsPlatformToolset.v145: { switch (Architecture) { @@ -392,6 +397,7 @@ namespace Flax.Build.Platforms var vcToolChainDir = toolsets[Toolset]; switch (Toolset) { + case WindowsPlatformToolset.v145: case WindowsPlatformToolset.v144: case WindowsPlatformToolset.v143: case WindowsPlatformToolset.v142: diff --git a/Source/Tools/Flax.Build/Projects/ProjectFormat.cs b/Source/Tools/Flax.Build/Projects/ProjectFormat.cs index 5f5017ced..3e5fd3a70 100644 --- a/Source/Tools/Flax.Build/Projects/ProjectFormat.cs +++ b/Source/Tools/Flax.Build/Projects/ProjectFormat.cs @@ -37,6 +37,11 @@ namespace Flax.Build.Projects /// VisualStudio2022, + /// + /// Visual Studio 2026. + /// + VisualStudio2026, + /// /// Visual Studio Code. /// diff --git a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs index fbbeca14d..a6e5b79ad 100644 --- a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs @@ -84,7 +84,11 @@ namespace Flax.Build.Projects // Pick the newest installed Visual Studio version if (format == ProjectFormat.VisualStudio) { - if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2022)) + if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2026)) + { + format = ProjectFormat.VisualStudio2026; + } + else if (VisualStudioInstance.HasIDE(VisualStudioVersion.VisualStudio2022)) { format = ProjectFormat.VisualStudio2022; } @@ -113,6 +117,7 @@ namespace Flax.Build.Projects case ProjectFormat.VisualStudio2017: case ProjectFormat.VisualStudio2019: case ProjectFormat.VisualStudio2022: + case ProjectFormat.VisualStudio2026: { VisualStudioVersion vsVersion; switch (format) @@ -129,6 +134,9 @@ namespace Flax.Build.Projects case ProjectFormat.VisualStudio2022: vsVersion = VisualStudioVersion.VisualStudio2022; break; + case ProjectFormat.VisualStudio2026: + vsVersion = VisualStudioVersion.VisualStudio2026; + break; default: throw new ArgumentOutOfRangeException(nameof(format), format, null); } switch (type) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs index 35bc7b0ac..99e3b083b 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs @@ -50,7 +50,9 @@ namespace Flax.Build.Projects.VisualStudio projectTypes = ProjectTypeGuids.ToOption(ProjectTypeGuids.FlaxVS) + ';' + projectTypes; // Try to reuse the existing project guid from solution file - vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); + vsProject.ProjectGuid = GetProjectGuid(vsProject.Path, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); if (vsProject.ProjectGuid == Guid.Empty) vsProject.ProjectGuid = Guid.NewGuid(); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs index f126bd3ef..671cfb5e8 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs @@ -55,7 +55,9 @@ namespace Flax.Build.Projects.VisualStudio } // Try to reuse the existing project guid from solution file - vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); + vsProject.ProjectGuid = GetProjectGuid(vsProject.Path, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); if (vsProject.ProjectGuid == Guid.Empty) vsProject.ProjectGuid = Guid.NewGuid(); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs index 4fc77e760..1a52274a7 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs @@ -28,6 +28,7 @@ namespace Flax.Build.Projects.VisualStudio case VisualStudioVersion.VisualStudio2017: return "v141"; case VisualStudioVersion.VisualStudio2019: return "v142"; case VisualStudioVersion.VisualStudio2022: return "v143"; + case VisualStudioVersion.VisualStudio2026: return "v145"; } return string.Empty; } diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioInstance.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioInstance.cs index b3b67482f..16e5fee80 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioInstance.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioInstance.cs @@ -128,6 +128,8 @@ namespace Flax.Build.Projects.VisualStudio version = VisualStudioVersion.VisualStudio2019; else if (displayName.Contains("2022")) version = VisualStudioVersion.VisualStudio2022; + else if (displayName.Contains("2026")) + version = VisualStudioVersion.VisualStudio2026; else { Log.Warning(string.Format("Unknown Visual Studio installation. Display name: {0}", displayName)); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs index 337f4497d..d657f6247 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs @@ -128,6 +128,7 @@ namespace Flax.Build.Projects.VisualStudio case VisualStudioVersion.VisualStudio2017: return "15.0"; case VisualStudioVersion.VisualStudio2019: return "16.0"; case VisualStudioVersion.VisualStudio2022: return "17.0"; + case VisualStudioVersion.VisualStudio2026: return "18.0"; } return string.Empty; @@ -193,7 +194,7 @@ namespace Flax.Build.Projects.VisualStudio } /// - public override string SolutionFileExtension => "sln"; + public override string SolutionFileExtension => /*Version >= VisualStudioVersion.VisualStudio2026 ? "slnx" :*/ "sln"; /// public override Project CreateProject() @@ -277,6 +278,20 @@ namespace Flax.Build.Projects.VisualStudio } } + if (Version >= VisualStudioVersion.VisualStudio2026) + GenerateXmlSolution(solution); + else + GenerateAsciiSolution(solution); + } + + private void GenerateXmlSolution(Solution solution) + { + // TODO: Generate the solution file in new format + GenerateAsciiSolution(solution); + } + + private void GenerateAsciiSolution(Solution solution) + { // Try to extract solution folder info from the existing solution file to make random IDs stable var solutionId = Guid.NewGuid(); var folderIds = new Dictionary(); @@ -313,7 +328,7 @@ namespace Flax.Build.Projects.VisualStudio var projects = solution.Projects.Cast().ToArray(); // Header - if (Version == VisualStudioVersion.VisualStudio2022) + if (Version >= VisualStudioVersion.VisualStudio2022) { vcSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00"); vcSolutionFileContent.AppendLine("# Visual Studio Version 17"); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioVersion.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioVersion.cs index 236aa5d7e..e7fc03c71 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioVersion.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioVersion.cs @@ -26,5 +26,10 @@ namespace Flax.Build.Projects.VisualStudio /// The Visual Studio 2022. /// VisualStudio2022, + + /// + /// The Visual Studio 2026. + /// + VisualStudio2026, } } From f323fdb592a2f667281a0ad30faedde477b5a0e3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 12 Sep 2025 17:53:14 +0200 Subject: [PATCH 048/137] Add and use `Max Mesh Position Error` to Build Settings for automatic mesh vertex positions storage --- Source/Engine/Content/Assets/ModelBase.cpp | 35 ++++++++++++++++++++-- Source/Engine/Core/Config/BuildSettings.h | 6 ++++ Source/Engine/Graphics/Models/ModelData.h | 3 +- Source/Engine/Tools/ModelTool/ModelTool.h | 14 +++++---- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/Source/Engine/Content/Assets/ModelBase.cpp b/Source/Engine/Content/Assets/ModelBase.cpp index 0946e6160..599caa810 100644 --- a/Source/Engine/Content/Assets/ModelBase.cpp +++ b/Source/Engine/Content/Assets/ModelBase.cpp @@ -3,6 +3,7 @@ #include "ModelBase.h" #include "Engine/Core/Log.h" #include "Engine/Core/Math/Transform.h" +#include "Engine/Core/Config/BuildSettings.h" #include "Engine/Content/WeakAssetReference.h" #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Profiler/ProfilerMemory.h" @@ -666,11 +667,42 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l return true; } + // Process mesh data if need to decide vertex buffer on format dynamically + auto positionFormat = modelData.PositionFormat; + if (positionFormat == ModelData::PositionFormats::Automatic) + { + const float maxPositionError = BuildSettings::Get()->MaxMeshPositionError; // In world-units + const float maxPositionErrorSq = maxPositionError * maxPositionError; + if (maxPositionErrorSq > 0.0f) + { + positionFormat = ModelData::PositionFormats::Float16; + const Float3* positions = mesh.Positions.Get(); + for (int32 i = 0; i < mesh.Positions.Count(); i++) + { + // Encode to Half3 and decode back to see the position error + Float3 position = positions[i]; + Half3 encoded(position); + Float3 decoded = encoded.ToFloat3(); + if (Float3::DistanceSquared(position, decoded) > maxPositionErrorSq) + { + // Cannot use lower quality so go back to full precision + positionFormat = ModelData::PositionFormats::Float32; + break; + } + } + } + else + { + // Full precision as default + positionFormat = ModelData::PositionFormats::Float32; + } + } + // Define vertex buffers layout and packing Array> vbElements; const bool useSeparatePositions = !isSkinned; const bool useSeparateColors = !isSkinned; - PixelFormat positionsFormat = modelData.PositionFormat == ModelData::PositionFormats::Float32 ? PixelFormat::R32G32B32_Float : PixelFormat::R16G16B16A16_Float; + PixelFormat positionsFormat = positionFormat == ModelData::PositionFormats::Float32 ? PixelFormat::R32G32B32_Float : PixelFormat::R16G16B16A16_Float; PixelFormat texCoordsFormat = modelData.TexCoordFormat == ModelData::TexCoordFormats::Float16 ? PixelFormat::R16G16_Float : PixelFormat::R8G8_UNorm; PixelFormat blendIndicesFormat = PixelFormat::R8G8B8A8_UInt; PixelFormat blendWeightsFormat = PixelFormat::R8G8B8A8_UNorm; @@ -684,7 +716,6 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l } { byte vbIndex = 0; - // TODO: add option to quantize vertex attributes (eg. 8-bit blend weights, 8-bit texcoords) // Position if (useSeparatePositions) diff --git a/Source/Engine/Core/Config/BuildSettings.h b/Source/Engine/Core/Config/BuildSettings.h index 4251798c1..54700278e 100644 --- a/Source/Engine/Core/Config/BuildSettings.h +++ b/Source/Engine/Core/Config/BuildSettings.h @@ -89,6 +89,12 @@ public: API_FIELD(Attributes="EditorOrder(2100), EditorDisplay(\"Content\")") bool SkipDefaultFonts = false; + /// + /// The maximum acceptable mesh vertex position error (in world units) for data quantization. Use 0 to disable this feature. Affects meshes during import (or reimpport). + /// + API_FIELD(Attributes="EditorOrder(2200), EditorDisplay(\"Content\"), ValueCategory(Utils.ValueCategory.Distance)") + float MaxMeshPositionError = 0.5f; + /// /// If checked, .NET Runtime won't be packaged with a game and will be required by user to be installed on system upon running game build. Available only on supported platforms such as Windows, Linux and macOS. /// diff --git a/Source/Engine/Graphics/Models/ModelData.h b/Source/Engine/Graphics/Models/ModelData.h index 8e401b973..27943942b 100644 --- a/Source/Engine/Graphics/Models/ModelData.h +++ b/Source/Engine/Graphics/Models/ModelData.h @@ -434,7 +434,8 @@ public: { Float32, Float16, - } PositionFormat = PositionFormats::Float32; + Automatic, + } PositionFormat = PositionFormats::Automatic; // See ModelTool::TexCoordFormats enum class TexCoordFormats diff --git a/Source/Engine/Tools/ModelTool/ModelTool.h b/Source/Engine/Tools/ModelTool/ModelTool.h index b09583471..d7545b92e 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.h +++ b/Source/Engine/Tools/ModelTool/ModelTool.h @@ -148,9 +148,11 @@ public: API_ENUM(Attributes="HideInEditor") enum class PositionFormat { // XYZ channels with 32-bit precision (12 bytes per vertex). - Float32, - // XYZ(W) channels with 12-bit precision (8 bytes per vertex). - Float16, + Float32 = 0, + // XYZ(W) channels with 16-bit precision (8 bytes per vertex). + Float16 = 1, + // Selects the most memory-efficient format that can represent positions within a max error defined in project Build Settings. + Automatic = 2, }; /// @@ -159,9 +161,9 @@ public: API_ENUM(Attributes="HideInEditor") enum class TexCoordFormats { // XY channels with 16-bit precision (4 bytes per vertex). - Float16, + Float16 = 0, // XY channels with 8-bit precision (2 bytes per vertex). Valid only for normalized UVs within range [0; 1], scaled or negative UVs won't work. - UNorm8, + UNorm8 = 1, }; /// @@ -226,7 +228,7 @@ public: public: // The imported vertex positions data format to use by meshes. Changing this affects memory usage of the mesh data, performance and overall quality. API_FIELD(Attributes = "EditorOrder(200), EditorDisplay(\"Data Format\"), VisibleIf(nameof(ShowGeometry))") - PositionFormat PositionFormat = PositionFormat::Float32; + PositionFormat PositionFormat = PositionFormat::Automatic; // The imported vertex texture coordinates data format to use by meshes. Changing this affects memory usage of the mesh data, performance and overall quality. API_FIELD(Attributes = "EditorOrder(205), EditorDisplay(\"Data Format\"), VisibleIf(nameof(ShowGeometry))") TexCoordFormats TexCoordFormat = TexCoordFormats::Float16; From 3d182c89f31281d657a30302ced7206cb109ee04 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 12 Sep 2025 18:04:01 +0200 Subject: [PATCH 049/137] Add `MaterialShader::BindParameters` to usable in game scripts #3668 --- Source/Engine/Graphics/Materials/IMaterial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Graphics/Materials/IMaterial.h b/Source/Engine/Graphics/Materials/IMaterial.h index 23d06589b..cd2b7a1e8 100644 --- a/Source/Engine/Graphics/Materials/IMaterial.h +++ b/Source/Engine/Graphics/Materials/IMaterial.h @@ -156,8 +156,8 @@ public: /// GPUTextureView* Input = nullptr; - BindParameters(::GPUContext* context, const ::RenderContext& renderContext); - BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const ::DrawCall& drawCall, bool instanced = false); + FLAXENGINE_API BindParameters(::GPUContext* context, const ::RenderContext& renderContext); + FLAXENGINE_API BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const ::DrawCall& drawCall, bool instanced = false); // Per-view shared constant buffer (see ViewData in MaterialCommon.hlsl). static GPUConstantBuffer* PerViewConstants; From a471861e9257c426404984b14e53ef61f769c243 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 12 Sep 2025 23:15:13 +0200 Subject: [PATCH 050/137] Fix editing UI Brush in prefabs #3501 --- .../Editors/ObjectSwitcherEditor.cs | 16 +++++- .../Engine/UI/GUI/Brushes/GPUTextureBrush.cs | 28 +++++++++- Source/Engine/UI/GUI/Brushes/IBrush.cs | 4 +- .../UI/GUI/Brushes/LinearGradientBrush.cs | 28 +++++++++- Source/Engine/UI/GUI/Brushes/MaterialBrush.cs | 28 +++++++++- .../Engine/UI/GUI/Brushes/SolidColorBrush.cs | 28 +++++++++- Source/Engine/UI/GUI/Brushes/SpriteBrush.cs | 52 +++++++++++++++++- Source/Engine/UI/GUI/Brushes/TextureBrush.cs | 54 ++++++++++++++++++- Source/Engine/UI/GUI/Brushes/UIBrush.cs | 28 +++++++++- Source/Engine/UI/GUI/Brushes/VideoBrush.cs | 28 +++++++++- 10 files changed, 283 insertions(+), 11 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs index 85efbadc3..d32f08c92 100644 --- a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs @@ -3,6 +3,7 @@ using System; using FlaxEditor.GUI; using FlaxEditor.Scripting; +using FlaxEngine; using FlaxEngine.Utilities; namespace FlaxEditor.CustomEditors.Editors @@ -81,9 +82,13 @@ namespace FlaxEditor.CustomEditors.Editors private OptionType[] _options; private ScriptType _type; + private Elements.PropertiesListElement _typeItem; private ScriptType Type => Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]); + /// + public override bool RevertValueWithChildren => false; // Always revert value for a whole object + /// public override void Initialize(LayoutElementsContainer layout) { @@ -98,7 +103,8 @@ namespace FlaxEditor.CustomEditors.Editors _type = type; // Type - var typeEditor = layout.ComboBox(TypeComboBoxName, "Type of the object value. Use it to change the object."); + _typeItem = layout.AddPropertyItem(TypeComboBoxName, "Type of the object value. Use it to change the object."); + var typeEditor = _typeItem.ComboBox(); for (int i = 0; i < _options.Length; i++) { typeEditor.ComboBox.AddItem(_options[i].Name); @@ -126,6 +132,8 @@ namespace FlaxEditor.CustomEditors.Editors // Value var values = new CustomValueContainer(type, (instance, index) => instance); + if (Values.HasReferenceValue) + values.SetReferenceValue(Values.ReferenceValue); values.AddRange(Values); var editor = CustomEditorsUtil.CreateEditor(type); var style = editor.Style; @@ -170,6 +178,12 @@ namespace FlaxEditor.CustomEditors.Editors { base.Refresh(); + // Show prefab diff when reference value type is different + var color = Color.Transparent; + if (Values.HasReferenceValue && CanRevertReferenceValue && Values[0].GetType() != Values.ReferenceValue.GetType()) + color = FlaxEngine.GUI.Style.Current.BackgroundSelected; + _typeItem.Labels[0].HighlightStripColor = color; + // Check if type has been modified outside the editor (eg. from code) if (Type != _type) { diff --git a/Source/Engine/UI/GUI/Brushes/GPUTextureBrush.cs b/Source/Engine/UI/GUI/Brushes/GPUTextureBrush.cs index fa4b5435d..781435740 100644 --- a/Source/Engine/UI/GUI/Brushes/GPUTextureBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/GPUTextureBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for . /// /// - public sealed class GPUTextureBrush : IBrush + public sealed class GPUTextureBrush : IBrush, IEquatable { /// /// The GPU texture. @@ -47,5 +49,29 @@ namespace FlaxEngine.GUI else Render2D.DrawTexture(Texture, rect, color); } + + /// + public bool Equals(GPUTextureBrush other) + { + return other != null && Texture == other.Texture && Filter == other.Filter; + } + + /// + public override bool Equals(object obj) + { + return obj is GPUTextureBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Texture, (int)Filter); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/IBrush.cs b/Source/Engine/UI/GUI/Brushes/IBrush.cs index f11ff6857..861c0b7df 100644 --- a/Source/Engine/UI/GUI/Brushes/IBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/IBrush.cs @@ -1,5 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// @@ -23,7 +25,7 @@ namespace FlaxEngine.GUI /// /// Interface that unifies input source textures, sprites, render targets, and any other brushes to be used in a more generic way. /// - public interface IBrush + public interface IBrush : IComparable { /// /// Gets the size of the image brush in pixels (if relevant). diff --git a/Source/Engine/UI/GUI/Brushes/LinearGradientBrush.cs b/Source/Engine/UI/GUI/Brushes/LinearGradientBrush.cs index 1ece73d1c..d2155a31c 100644 --- a/Source/Engine/UI/GUI/Brushes/LinearGradientBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/LinearGradientBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for linear color gradient (made of 2 color). /// /// - public sealed class LinearGradientBrush : IBrush + public sealed class LinearGradientBrush : IBrush, IEquatable { /// /// The brush start color. @@ -50,5 +52,29 @@ namespace FlaxEngine.GUI var endColor = EndColor * color; Render2D.FillRectangle(rect, startColor, startColor, endColor, endColor); } + + /// + public bool Equals(LinearGradientBrush other) + { + return other != null && StartColor == other.StartColor && EndColor == other.EndColor; + } + + /// + public override bool Equals(object obj) + { + return obj is LinearGradientBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(StartColor, EndColor); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/MaterialBrush.cs b/Source/Engine/UI/GUI/Brushes/MaterialBrush.cs index 13e9dab24..c610e9910 100644 --- a/Source/Engine/UI/GUI/Brushes/MaterialBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/MaterialBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for rendering. /// /// - public sealed class MaterialBrush : IBrush + public sealed class MaterialBrush : IBrush, IEquatable { /// /// The material. @@ -38,5 +40,29 @@ namespace FlaxEngine.GUI { Render2D.DrawMaterial(Material, rect, color); } + + /// + public bool Equals(MaterialBrush other) + { + return other != null && Material == other.Material; + } + + /// + public override bool Equals(object obj) + { + return obj is MaterialBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Material); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/SolidColorBrush.cs b/Source/Engine/UI/GUI/Brushes/SolidColorBrush.cs index 1e4a20670..d848d9368 100644 --- a/Source/Engine/UI/GUI/Brushes/SolidColorBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/SolidColorBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for single color fill. /// /// - public sealed class SolidColorBrush : IBrush + public sealed class SolidColorBrush : IBrush, IEquatable { /// /// The brush color. @@ -39,5 +41,29 @@ namespace FlaxEngine.GUI { Render2D.FillRectangle(rect, Color * color); } + + /// + public bool Equals(SolidColorBrush other) + { + return other != null && Color == other.Color; + } + + /// + public override bool Equals(object obj) + { + return obj is SolidColorBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Color); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/SpriteBrush.cs b/Source/Engine/UI/GUI/Brushes/SpriteBrush.cs index 205a9645c..24ca10015 100644 --- a/Source/Engine/UI/GUI/Brushes/SpriteBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/SpriteBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for . /// /// - public sealed class SpriteBrush : IBrush + public sealed class SpriteBrush : IBrush, IEquatable { /// /// The sprite. @@ -47,6 +49,30 @@ namespace FlaxEngine.GUI else Render2D.DrawSprite(Sprite, rect, color); } + + /// + public bool Equals(SpriteBrush other) + { + return other != null && Sprite == other.Sprite && Filter == other.Filter; + } + + /// + public override bool Equals(object obj) + { + return obj is SpriteBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Sprite, (int)Filter); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } /// @@ -121,5 +147,29 @@ namespace FlaxEngine.GUI } #endif } + + /// + public bool Equals(Sprite9SlicingBrush other) + { + return other != null && Sprite == other.Sprite && Filter == other.Filter; + } + + /// + public override bool Equals(object obj) + { + return obj is Sprite9SlicingBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Sprite, (int)Filter); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/TextureBrush.cs b/Source/Engine/UI/GUI/Brushes/TextureBrush.cs index 189e222b9..e3922eebb 100644 --- a/Source/Engine/UI/GUI/Brushes/TextureBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/TextureBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for . /// /// - public sealed class TextureBrush : IBrush + public sealed class TextureBrush : IBrush, IEquatable { /// /// The texture. @@ -47,13 +49,37 @@ namespace FlaxEngine.GUI else Render2D.DrawTexture(Texture, rect, color); } + + /// + public bool Equals(TextureBrush other) + { + return other != null && Texture == other.Texture && Filter == other.Filter; + } + + /// + public override bool Equals(object obj) + { + return obj is TextureBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Texture, (int)Filter); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } /// /// Implementation of for using 9-slicing. /// /// - public sealed class Texture9SlicingBrush : IBrush + public sealed class Texture9SlicingBrush : IBrush, IEquatable { /// /// The texture. @@ -130,5 +156,29 @@ namespace FlaxEngine.GUI } #endif } + + /// + public bool Equals(Texture9SlicingBrush other) + { + return other != null && Texture == other.Texture && Filter == other.Filter && BorderSize == other.BorderSize && Border == other.Border; + } + + /// + public override bool Equals(object obj) + { + return obj is Texture9SlicingBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Texture, (int)Filter, BorderSize, Border.GetHashCode()); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/UIBrush.cs b/Source/Engine/UI/GUI/Brushes/UIBrush.cs index 4441899c0..044c95285 100644 --- a/Source/Engine/UI/GUI/Brushes/UIBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/UIBrush.cs @@ -1,5 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// @@ -20,7 +22,7 @@ namespace FlaxEngine.GUI /// /// /// - public sealed class UIBrush : IBrush + public sealed class UIBrush : IBrush, IEquatable { /// /// The UI Brush asset to use. @@ -71,5 +73,29 @@ namespace FlaxEngine.GUI if (asset != null && asset.Brush != null) asset.Brush.Draw(rect, color); } + + /// + public bool Equals(UIBrush other) + { + return other != null && Asset == other.Asset; + } + + /// + public override bool Equals(object obj) + { + return obj is UIBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Asset); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } diff --git a/Source/Engine/UI/GUI/Brushes/VideoBrush.cs b/Source/Engine/UI/GUI/Brushes/VideoBrush.cs index b8a54662c..25d942ca6 100644 --- a/Source/Engine/UI/GUI/Brushes/VideoBrush.cs +++ b/Source/Engine/UI/GUI/Brushes/VideoBrush.cs @@ -1,12 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// /// Implementation of for frame displaying. /// /// - public sealed class VideoBrush : IBrush + public sealed class VideoBrush : IBrush, IEquatable { /// /// The video player to display frame from it. @@ -57,5 +59,29 @@ namespace FlaxEngine.GUI else Render2D.DrawTexture(texture, rect, color); } + + /// + public bool Equals(VideoBrush other) + { + return other != null && Player == other.Player && Filter == other.Filter; + } + + /// + public override bool Equals(object obj) + { + return obj is VideoBrush other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(Player, (int)Filter); + } + + /// + public int CompareTo(object obj) + { + return Equals(obj) ? 1 : 0; + } } } From 9e1f488f22ebcb1912124461feb965c72fdef55b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 13 Sep 2025 14:41:11 +0200 Subject: [PATCH 051/137] Fix prefab window to use UI Mode for empty UI Control prefab #3574 --- Source/Editor/Viewport/Previews/PrefabPreview.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Viewport/Previews/PrefabPreview.cs b/Source/Editor/Viewport/Previews/PrefabPreview.cs index 4ee763540..70316e4d9 100644 --- a/Source/Editor/Viewport/Previews/PrefabPreview.cs +++ b/Source/Editor/Viewport/Previews/PrefabPreview.cs @@ -112,8 +112,9 @@ namespace FlaxEditor.Viewport.Previews LinkCanvas(_instance); // Link UI control to the preview + var uiControl = _instance as UIControl; if (_uiControlLinked == null && - _instance is UIControl uiControl && + uiControl != null && uiControl.Control != null && uiControl.Control.Parent == null) { @@ -128,6 +129,12 @@ namespace FlaxEditor.Viewport.Previews _uiControlLinked.Control.Parent = _uiParentLink; _hasUILinked = true; } + + // Use UI mode when root is empty UI Control + if (_uiControlLinked == null && uiControl != null && uiControl.Control == null) + { + _hasUILinked = true; + } } private void LinkCanvas(Actor actor) From 88773e71e557b1d43afe4b31fd75754688049bc4 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 14 Sep 2025 14:25:19 +0200 Subject: [PATCH 052/137] Fix warning when cloning actor from prefab that is not a root #3578 --- Source/Engine/Level/Actor.cpp | 21 +++++++++++++++------ Source/Engine/Scripting/Scripting.cpp | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index 0c0a98e14..b119797e7 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -1124,9 +1124,10 @@ void Actor::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) } else if (!parent && parentId.IsValid()) { + Guid tmpId; if (_prefabObjectID.IsValid()) LOG(Warning, "Missing parent actor {0} for \'{1}\', prefab object {2}", parentId, ToString(), _prefabObjectID); - else + else if (!modifier->IdsMapping.TryGet(parentId, tmpId) || tmpId.IsValid()) // Skip warning if object was mapped to empty id (intentionally ignored) LOG(Warning, "Missing parent actor {0} for \'{1}\'", parentId, ToString()); } } @@ -1694,7 +1695,7 @@ bool Actor::ToBytes(const Array& actors, MemoryWriteStream& output) } // Collect object ids that exist in the serialized data to allow references mapping later - Array ids(Math::RoundUpToPowerOf2(actors.Count() * 2)); + Array ids(actors.Count()); for (int32 i = 0; i < actors.Count(); i++) { // By default we collect actors and scripts (they are ManagedObjects recognized by the id) @@ -1997,19 +1998,27 @@ Actor* Actor::Clone() // Remap object ids into a new ones auto modifier = Cache::ISerializeModifier.Get(); - for (int32 i = 0; i < actors->Count(); i++) + for (const Actor* actor : *actors.Value) { - auto actor = actors->At(i); if (!actor) continue; modifier->IdsMapping.Add(actor->GetID(), Guid::New()); - for (int32 j = 0; j < actor->Scripts.Count(); j++) + for (const Script* script : actor->Scripts) { - const auto script = actor->Scripts[j]; if (script) modifier->IdsMapping.Add(script->GetID(), Guid::New()); } } + if (HasPrefabLink() && HasParent() && !IsPrefabRoot()) + { + // When cloning actor that is part of prefab (but not as whole), ignore the prefab hierarchy + Actor* parent = GetParent(); + do + { + modifier->IdsMapping.Add(parent->GetPrefabObjectID(), Guid::Empty); + parent = parent->GetParent(); + } while (parent && !parent->IsPrefabRoot()); + } // Deserialize objects Array output; diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index db6867d34..e042b4633 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -904,6 +904,8 @@ ScriptingObject* Scripting::FindObject(Guid id, const MClass* type) if (idsMapping) { idsMapping->TryGet(id, id); + if (!id.IsValid()) + return nullptr; // Skip warning if object was mapped to empty id (intentionally ignored) } // Try to find it From ada6b9140fc345ad0db7ea9447c29c0bebe26813 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 14 Sep 2025 22:00:57 +0200 Subject: [PATCH 053/137] Minor adjustments for #3411 --- Content/Editor/Gizmo/MaterialAxisLocked.flax | 3 --- Source/Editor/Gizmo/TransformGizmoBase.Draw.cs | 17 ++++++++--------- Source/Editor/Options/VisualOptions.cs | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 Content/Editor/Gizmo/MaterialAxisLocked.flax diff --git a/Content/Editor/Gizmo/MaterialAxisLocked.flax b/Content/Editor/Gizmo/MaterialAxisLocked.flax deleted file mode 100644 index be44ece86..000000000 --- a/Content/Editor/Gizmo/MaterialAxisLocked.flax +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7518765847301a4b13625fb05d542fab4fc924190a7414d39227db817a0e29cb -size 661 diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index 8523b9378..03c18268d 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -1,9 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. using FlaxEditor.Options; -using FlaxEditor.SceneGraph; using FlaxEngine; -using System; namespace FlaxEditor.Gizmo { @@ -24,8 +22,8 @@ namespace FlaxEditor.Gizmo private MaterialBase _materialSphere; // Material Parameter Names - const String _brightnessParamName = "Brightness"; - const String _opacityParamName = "Opacity"; + private const string _brightnessParamName = "Brightness"; + private const string _opacityParamName = "Opacity"; /// /// Used for example when the selection can't be moved because one actor is static. @@ -82,7 +80,9 @@ namespace FlaxEditor.Gizmo { _isDisabled = ShouldGizmoBeLocked(); - float brightness = _isDisabled ? options.Visual.TransformGizmoBrighnessDisabled : options.Visual.TransformGizmoBrightness; + float brightness = _isDisabled ? options.Visual.TransformGizmoBrightnessDisabled : options.Visual.TransformGizmoBrightness; + if (Mathf.NearEqual(brightness, (float)_materialAxisX.GetParameterValue(_brightnessParamName))) + return; _materialAxisX.SetParameterValue(_brightnessParamName, brightness); _materialAxisY.SetParameterValue(_brightnessParamName, brightness); _materialAxisZ.SetParameterValue(_brightnessParamName, brightness); @@ -91,10 +91,10 @@ namespace FlaxEditor.Gizmo private bool ShouldGizmoBeLocked() { bool gizmoLocked = false; - - if (Editor.Instance.StateMachine.IsPlayMode) + if (Editor.Instance.StateMachine.IsPlayMode && Owner is Viewport.EditorGizmoViewport) { - foreach (SceneGraphNode obj in Editor.Instance.SceneEditing.Selection) + // Block editing static scene objects in main view during play mode + foreach (var obj in Editor.Instance.SceneEditing.Selection) { if (obj.CanTransform == false) { @@ -103,7 +103,6 @@ namespace FlaxEditor.Gizmo } } } - return gizmoLocked; } diff --git a/Source/Editor/Options/VisualOptions.cs b/Source/Editor/Options/VisualOptions.cs index 45a1f1b13..e0f0982f4 100644 --- a/Source/Editor/Options/VisualOptions.cs +++ b/Source/Editor/Options/VisualOptions.cs @@ -86,7 +86,7 @@ namespace FlaxEditor.Options /// [DefaultValue(0.25f), Range(0f, 5f)] [EditorDisplay("Transform Gizmo", "Disabled Gizmo Brightness"), EditorOrder(212)] - public float TransformGizmoBrighnessDisabled { get; set; } = 0.25f; + public float TransformGizmoBrightnessDisabled { get; set; } = 0.25f; /// /// Gets or sets a value indicating whether enable MSAA for DebugDraw primitives rendering. Helps with pixel aliasing but reduces performance. From 9749487e2449aff9e5320ae7140266dedd35c033 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 14 Sep 2025 23:59:40 +0200 Subject: [PATCH 054/137] Move prefab and game UI size context menu to shared UI Module #3571 --- Source/Editor/Modules/UIModule.cs | 262 +++++++++++++++++ .../Editor/Viewport/PrefabWindowViewport.cs | 269 ++---------------- Source/Editor/Windows/GameWindow.cs | 269 +----------------- 3 files changed, 283 insertions(+), 517 deletions(-) diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index e62dd6b6e..64f8c81e9 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -1185,5 +1185,267 @@ namespace FlaxEditor.Modules MenuTools = null; MenuHelp = null; } + + internal void CreateViewportSizingContextMenu(ContextMenu vsMenu, int defaultScaleActiveIndex, int customScaleActiveIndex, bool prefabViewport, Action changeView, Action changeActiveIndices) + { + // Add default viewport sizing options + var defaultOptions = DefaultViewportScaleOptions; + for (int i = 0; i < defaultOptions.Count; i++) + { + var viewportScale = defaultOptions[i]; + if (prefabViewport && viewportScale.ScaleType == ViewportScaleOption.ViewportScaleType.Aspect) + continue; // Skip aspect ratio types in prefab + var button = vsMenu.AddButton(viewportScale.Label); + button.CloseMenuOnClick = false; + button.Tag = viewportScale; + + // No default index is active + if (defaultScaleActiveIndex == -1) + { + button.Icon = SpriteHandle.Invalid; + } + // This is the active index + else if (defaultScaleActiveIndex == i) + { + button.Icon = Style.Current.CheckBoxTick; + changeView(viewportScale); + } + + button.Clicked += () => + { + if (button.Tag == null) + return; + + // Reset selected icon on all buttons + foreach (var child in vsMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) + { + if (cmb == button) + { + button.Icon = Style.Current.CheckBoxTick; + var index = defaultOptions.FindIndex(x => x == v); + changeActiveIndices(index, -1); // Reset custom index because default was chosen + changeView(v); + } + else if (cmb.Icon != SpriteHandle.Invalid) + { + cmb.Icon = SpriteHandle.Invalid; + } + } + } + }; + } + if (defaultOptions.Count != 0) + vsMenu.AddSeparator(); + + // Add custom viewport options + var customOptions = CustomViewportScaleOptions; + for (int i = 0; i < customOptions.Count; i++) + { + var viewportScale = customOptions[i]; + if (prefabViewport && viewportScale.ScaleType == ViewportScaleOption.ViewportScaleType.Aspect) + continue; // Skip aspect ratio types in prefab + var childCM = vsMenu.AddChildMenu(viewportScale.Label); + childCM.CloseMenuOnClick = false; + childCM.Tag = viewportScale; + + // No custom index is active + if (customScaleActiveIndex == -1) + { + childCM.Icon = SpriteHandle.Invalid; + } + // This is the active index + else if (customScaleActiveIndex == i) + { + childCM.Icon = Style.Current.CheckBoxTick; + changeView(viewportScale); + } + + var applyButton = childCM.ContextMenu.AddButton("Apply"); + applyButton.Tag = childCM.Tag = viewportScale; + applyButton.CloseMenuOnClick = false; + applyButton.Clicked += () => + { + if (childCM.Tag == null) + return; + + // Reset selected icon on all buttons + foreach (var child in vsMenu.Items) + { + if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) + { + if (child == childCM) + { + childCM.Icon = Style.Current.CheckBoxTick; + var index = customOptions.FindIndex(x => x == v); + changeActiveIndices(-1, index); // Reset default index because custom was chosen + changeView(v); + } + else if (cmb.Icon != SpriteHandle.Invalid) + { + cmb.Icon = SpriteHandle.Invalid; + } + } + } + }; + + var deleteButton = childCM.ContextMenu.AddButton("Delete"); + deleteButton.CloseMenuOnClick = false; + deleteButton.Clicked += () => + { + if (childCM.Tag == null) + return; + + var v = (ViewportScaleOption)childCM.Tag; + if (childCM.Icon != SpriteHandle.Invalid) + { + changeActiveIndices(-1, 0); + changeView(defaultOptions[0]); + } + customOptions.Remove(v); + SaveCustomViewportScalingOptions(); + vsMenu.DisposeAllItems(); + CreateViewportSizingContextMenu(vsMenu, defaultScaleActiveIndex, customScaleActiveIndex, prefabViewport, changeView, changeActiveIndices); + vsMenu.PerformLayout(); + }; + } + if (customOptions.Count != 0) + vsMenu.AddSeparator(); + + // Add button + var add = vsMenu.AddButton("Add..."); + add.CloseMenuOnClick = false; + add.Clicked += () => + { + var popup = new ContextMenuBase + { + Size = new Float2(230, 125), + ClipChildren = false, + CullChildren = false, + }; + popup.Show(add, new Float2(add.Width, 0)); + + var nameLabel = new Label + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Text = "Name", + HorizontalAlignment = TextAlignment.Near, + }; + nameLabel.LocalX += 10; + nameLabel.LocalY += 10; + + var nameTextBox = new TextBox + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + IsMultiline = false, + }; + nameTextBox.LocalX += 100; + nameTextBox.LocalY += 10; + + var typeLabel = new Label + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Text = "Type", + HorizontalAlignment = TextAlignment.Near, + }; + typeLabel.LocalX += 10; + typeLabel.LocalY += 35; + + var typeDropdown = new Dropdown + { + Parent = popup, + AnchorPreset = AnchorPresets.TopLeft, + Items = { "Aspect", "Resolution" }, + SelectedItem = "Aspect", + Visible = !prefabViewport, + 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 ViewportScaleOption.ViewportScaleType type); + if (prefabViewport) + type = ViewportScaleOption.ViewportScaleType.Resolution; + + var combineString = type == ViewportScaleOption.ViewportScaleType.Aspect ? ":" : "x"; + var name = nameTextBox.Text + " (" + wValue.Value + combineString + hValue.Value + ") " + typeDropdown.SelectedItem; + var newViewportOption = new ViewportScaleOption + { + ScaleType = type, + Label = name, + Size = new Int2(wValue.Value, hValue.Value), + }; + + customOptions.Add(newViewportOption); + SaveCustomViewportScalingOptions(); + vsMenu.DisposeAllItems(); + CreateViewportSizingContextMenu(vsMenu, defaultScaleActiveIndex, customScaleActiveIndex, prefabViewport, changeView, changeActiveIndices); + 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(); + }; + }; + } } } diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index 1a018004e..c38b36f1e 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -73,10 +73,11 @@ namespace FlaxEditor.Viewport private PrefabUIEditorRoot _uiRoot; private bool _showUI = false; - + private int _defaultScaleActiveIndex = 0; private int _customScaleActiveIndex = -1; private ContextMenuButton _uiModeButton; + private ContextMenuChildMenu _uiViewOptions; /// /// Event fired when the UI Mode is toggled. @@ -142,6 +143,8 @@ namespace FlaxEditor.Viewport UseAutomaticTaskManagement = defaultFeatures; ShowDefaultSceneActors = defaultFeatures; TintColor = defaultFeatures ? Color.White : Color.Transparent; + if (_uiViewOptions != null) + _uiViewOptions.Visible = _showUI; UIModeToggled?.Invoke(_showUI); } } @@ -215,10 +218,10 @@ namespace FlaxEditor.Viewport _uiParentLink = _uiRoot.UIRoot; // UI mode buton - _uiModeButton = ViewWidgetShowMenu.AddButton("UI Mode", (button) => ShowUI = button.Checked); + _uiModeButton = ViewWidgetShowMenu.AddButton("UI Mode", button => ShowUI = button.Checked); _uiModeButton.AutoCheck = true; _uiModeButton.VisibleChanged += control => (control as ContextMenuButton).Checked = ShowUI; - + EditorGizmoViewport.AddGizmoViewportWidgets(this, TransformGizmo); // Setup input actions @@ -232,10 +235,16 @@ namespace FlaxEditor.Viewport /// public void CreateViewScalingOptions() { - // View Scaling - var uiViewCM = ViewWidgetButtonMenu.AddChildMenu("UI View Scaling"); + if (_uiViewOptions != null) + return; + _uiViewOptions = ViewWidgetButtonMenu.AddChildMenu("UI View Scaling"); + _uiViewOptions.Visible = _showUI; LoadCustomUIScalingOption(); - CreateUIViewScalingContextMenu(uiViewCM.ContextMenu); + Editor.Instance.UI.CreateViewportSizingContextMenu(_uiViewOptions.ContextMenu, _defaultScaleActiveIndex, _customScaleActiveIndex, true, ChangeUIView, (a, b) => + { + _defaultScaleActiveIndex = a; + _customScaleActiveIndex = b; + }); } private void ChangeUIView(UIModule.ViewportScaleOption uiViewScaleOption) @@ -243,252 +252,6 @@ namespace FlaxEditor.Viewport _uiRoot.SetViewSize((Float2)uiViewScaleOption.Size); } - private void CreateUIViewScalingContextMenu(ContextMenu vsMenu) - { - // Add default viewport sizing options - var defaultOptions = Editor.Instance.UI.DefaultViewportScaleOptions; - for (int i = 0; i < defaultOptions.Count; i++) - { - var viewportScale = defaultOptions[i]; - - // Skip aspect ratio types in prefab - if (viewportScale.ScaleType == UIModule.ViewportScaleOption.ViewportScaleType.Aspect) - continue; - - var button = vsMenu.AddButton(viewportScale.Label); - button.CloseMenuOnClick = false; - button.Tag = viewportScale; - - // No default index is active. - if (_defaultScaleActiveIndex == -1) - { - button.Icon = SpriteHandle.Invalid; - } - // This is the active index. - else if (_defaultScaleActiveIndex == i) - { - button.Icon = Style.Current.CheckBoxTick; - ChangeUIView(viewportScale); - } - - button.Clicked += () => - { - if (button.Tag == null) - return; - - // Reset selected icon on all buttons - foreach (var child in vsMenu.Items) - { - if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) - { - if (cmb == button) - { - var index = defaultOptions.FindIndex(x => x == v); - _defaultScaleActiveIndex = index; - _customScaleActiveIndex = -1; // Reset custom index because default was chosen. - button.Icon = Style.Current.CheckBoxTick; - ChangeUIView(v); - } - else if (cmb.Icon != SpriteHandle.Invalid) - { - cmb.Icon = SpriteHandle.Invalid; - } - } - } - }; - } - if (defaultOptions.Count != 0) - vsMenu.AddSeparator(); - - // Add custom viewport options - var customOptions = Editor.Instance.UI.CustomViewportScaleOptions; - for (int i = 0; i < customOptions.Count; i++) - { - var viewportScale = customOptions[i]; - - // Skip aspect ratio types for prefabs - if (viewportScale.ScaleType == UIModule.ViewportScaleOption.ViewportScaleType.Aspect) - continue; - - var childCM = vsMenu.AddChildMenu(viewportScale.Label); - childCM.CloseMenuOnClick = false; - childCM.Tag = viewportScale; - - // No custom index is active. - if (_customScaleActiveIndex == -1) - { - childCM.Icon = SpriteHandle.Invalid; - } - // This is the active index. - else if (_customScaleActiveIndex == i) - { - childCM.Icon = Style.Current.CheckBoxTick; - ChangeUIView(viewportScale); - } - - var applyButton = childCM.ContextMenu.AddButton("Apply"); - applyButton.Tag = childCM.Tag = viewportScale; - applyButton.CloseMenuOnClick = false; - applyButton.Clicked += () => - { - if (childCM.Tag == null) - return; - - // Reset selected icon on all buttons - foreach (var child in vsMenu.Items) - { - if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) - { - if (child == childCM) - { - var index = customOptions.FindIndex(x => x == v); - _defaultScaleActiveIndex = -1; // Reset default index because custom was chosen. - _customScaleActiveIndex = index; - childCM.Icon = Style.Current.CheckBoxTick; - ChangeUIView(v); - } - else if (cmb.Icon != SpriteHandle.Invalid) - { - cmb.Icon = SpriteHandle.Invalid; - } - } - } - }; - - var deleteButton = childCM.ContextMenu.AddButton("Delete"); - deleteButton.CloseMenuOnClick = false; - deleteButton.Clicked += () => - { - if (childCM.Tag == null) - return; - - var v = (UIModule.ViewportScaleOption)childCM.Tag; - if (childCM.Icon != SpriteHandle.Invalid) - { - _customScaleActiveIndex = -1; - _defaultScaleActiveIndex = 0; - ChangeUIView(defaultOptions[0]); - } - customOptions.Remove(v); - Editor.Instance.UI.SaveCustomViewportScalingOptions(); - vsMenu.DisposeAllItems(); - CreateUIViewScalingContextMenu(vsMenu); - vsMenu.PerformLayout(); - }; - } - if (customOptions.Count != 0) - vsMenu.AddSeparator(); - - // Add button - var add = vsMenu.AddButton("Add..."); - add.CloseMenuOnClick = false; - add.Clicked += () => - { - var popup = new ContextMenuBase - { - Size = new Float2(230, 95), - 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 whLabel = new Label - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Width & Height", - HorizontalAlignment = TextAlignment.Near, - }; - whLabel.LocalX += 10; - whLabel.LocalY += 30; - - var wValue = new IntValueBox(1920) - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - MinValue = 1, - Width = 55, - }; - wValue.LocalY += 30; - wValue.LocalX += 100; - - var hValue = new IntValueBox(1080) - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - MinValue = 1, - Width = 55, - }; - hValue.LocalY += 30; - hValue.LocalX += 165; - - var submitButton = new Button - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Submit", - Width = 70, - }; - submitButton.LocalX += 40; - submitButton.LocalY += 60; - - submitButton.Clicked += () => - { - var name = nameTextBox.Text + " (" + wValue.Value + "x" + hValue.Value + ")"; - - var newViewportOption = new UIModule.ViewportScaleOption - { - Label = name, - ScaleType = UIModule.ViewportScaleOption.ViewportScaleType.Resolution, - Size = new Int2(wValue.Value, hValue.Value), - }; - - customOptions.Add(newViewportOption); - Editor.Instance.UI.SaveCustomViewportScalingOptions(); - vsMenu.DisposeAllItems(); - CreateUIViewScalingContextMenu(vsMenu); - vsMenu.PerformLayout(); - }; - - var cancelButton = new Button - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Cancel", - Width = 70, - }; - cancelButton.LocalX += 120; - cancelButton.LocalY += 60; - - cancelButton.Clicked += () => - { - nameTextBox.Clear(); - hValue.Value = 9; - wValue.Value = 16; - popup.Hide(); - }; - }; - } - /// /// Saves the active ui scaling option. /// @@ -522,7 +285,7 @@ namespace FlaxEditor.Viewport } } } - + var customKey = $"{Prefab.ID}:CustomViewportScalingIndex"; if (Editor.Instance.ProjectCache.TryGetCustomData(customKey, out string data)) { diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index a2b2d472d..63c2a1a48 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -606,10 +606,12 @@ namespace FlaxEditor.Windows // Viewport aspect ratio { - // Create default scaling options if they dont exist from deserialization. var vsMenu = menu.AddChildMenu("Viewport Size").ContextMenu; - - CreateViewportSizingContextMenu(vsMenu); + Editor.UI.CreateViewportSizingContextMenu(vsMenu, _defaultScaleActiveIndex, _customScaleActiveIndex, false, ChangeViewportRatio, (a, b) => + { + _defaultScaleActiveIndex = a; + _customScaleActiveIndex = b; + }); } // Take Screenshot @@ -707,267 +709,6 @@ namespace FlaxEditor.Windows } } - private void CreateViewportSizingContextMenu(ContextMenu vsMenu) - { - // Add default viewport sizing options - var defaultOptions = Editor.UI.DefaultViewportScaleOptions; - for (int i = 0; i < defaultOptions.Count; i++) - { - var viewportScale = defaultOptions[i]; - var button = vsMenu.AddButton(viewportScale.Label); - button.CloseMenuOnClick = false; - button.Tag = viewportScale; - - // No default index is active. - if (_defaultScaleActiveIndex == -1) - { - button.Icon = SpriteHandle.Invalid; - } - // This is the active index. - else if (_defaultScaleActiveIndex == i) - { - button.Icon = Style.Current.CheckBoxTick; - ChangeViewportRatio(viewportScale); - } - - button.Clicked += () => - { - if (button.Tag == null) - return; - - // Reset selected icon on all buttons - foreach (var child in vsMenu.Items) - { - if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) - { - if (cmb == button) - { - var index = defaultOptions.FindIndex(x => x == v); - _defaultScaleActiveIndex = index; - _customScaleActiveIndex = -1; // Reset custom index because default was chosen. - button.Icon = Style.Current.CheckBoxTick; - ChangeViewportRatio(v); - } - else if (cmb.Icon != SpriteHandle.Invalid) - { - cmb.Icon = SpriteHandle.Invalid; - } - } - } - }; - } - if (defaultOptions.Count != 0) - vsMenu.AddSeparator(); - - // Add custom viewport options - var customOptions = Editor.UI.CustomViewportScaleOptions; - for (int i = 0; i < customOptions.Count; i++) - { - var viewportScale = customOptions[i]; - var childCM = vsMenu.AddChildMenu(viewportScale.Label); - childCM.CloseMenuOnClick = false; - childCM.Tag = viewportScale; - - // No custom index is active. - if (_customScaleActiveIndex == -1) - { - childCM.Icon = SpriteHandle.Invalid; - } - // This is the active index. - else if (_customScaleActiveIndex == i) - { - childCM.Icon = Style.Current.CheckBoxTick; - ChangeViewportRatio(viewportScale); - } - - var applyButton = childCM.ContextMenu.AddButton("Apply"); - applyButton.Tag = childCM.Tag = viewportScale; - applyButton.CloseMenuOnClick = false; - applyButton.Clicked += () => - { - if (childCM.Tag == null) - return; - - // Reset selected icon on all buttons - foreach (var child in vsMenu.Items) - { - if (child is ContextMenuButton cmb && cmb.Tag is UIModule.ViewportScaleOption v) - { - if (child == childCM) - { - var index = customOptions.FindIndex(x => x == v); - _defaultScaleActiveIndex = -1; // Reset default index because custom was chosen. - _customScaleActiveIndex = index; - childCM.Icon = Style.Current.CheckBoxTick; - ChangeViewportRatio(v); - } - else if (cmb.Icon != SpriteHandle.Invalid) - { - cmb.Icon = SpriteHandle.Invalid; - } - } - } - }; - - var deleteButton = childCM.ContextMenu.AddButton("Delete"); - deleteButton.CloseMenuOnClick = false; - deleteButton.Clicked += () => - { - if (childCM.Tag == null) - return; - - var v = (UIModule.ViewportScaleOption)childCM.Tag; - if (childCM.Icon != SpriteHandle.Invalid) - { - _customScaleActiveIndex = -1; - _defaultScaleActiveIndex = 0; - ChangeViewportRatio(defaultOptions[0]); - } - customOptions.Remove(v); - Editor.UI.SaveCustomViewportScalingOptions(); - vsMenu.DisposeAllItems(); - CreateViewportSizingContextMenu(vsMenu); - vsMenu.PerformLayout(); - }; - } - if (customOptions.Count != 0) - vsMenu.AddSeparator(); - - // Add button - var add = vsMenu.AddButton("Add..."); - add.CloseMenuOnClick = false; - add.Clicked += () => - { - var popup = new ContextMenuBase - { - Size = new Float2(230, 125), - ClipChildren = false, - CullChildren = false, - }; - popup.Show(add, new Float2(add.Width, 0)); - - var nameLabel = new Label - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Name", - HorizontalAlignment = TextAlignment.Near, - }; - nameLabel.LocalX += 10; - nameLabel.LocalY += 10; - - var nameTextBox = new TextBox - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - IsMultiline = false, - }; - nameTextBox.LocalX += 100; - nameTextBox.LocalY += 10; - - var typeLabel = new Label - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Type", - HorizontalAlignment = TextAlignment.Near, - }; - typeLabel.LocalX += 10; - typeLabel.LocalY += 35; - - var typeDropdown = new Dropdown - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Items = { "Aspect", "Resolution" }, - SelectedItem = "Aspect", - Width = nameTextBox.Width - }; - typeDropdown.LocalY += 35; - typeDropdown.LocalX += 100; - - var whLabel = new Label - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Width & Height", - HorizontalAlignment = TextAlignment.Near, - }; - whLabel.LocalX += 10; - whLabel.LocalY += 60; - - var wValue = new IntValueBox(16) - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - MinValue = 1, - Width = 55, - }; - wValue.LocalY += 60; - wValue.LocalX += 100; - - var hValue = new IntValueBox(9) - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - MinValue = 1, - Width = 55, - }; - hValue.LocalY += 60; - hValue.LocalX += 165; - - var submitButton = new Button - { - Parent = popup, - AnchorPreset = AnchorPresets.TopLeft, - Text = "Submit", - Width = 70, - }; - submitButton.LocalX += 40; - submitButton.LocalY += 90; - - submitButton.Clicked += () => - { - Enum.TryParse(typeDropdown.SelectedItem, out UIModule.ViewportScaleOption.ViewportScaleType type); - - var combineString = type == UIModule.ViewportScaleOption.ViewportScaleType.Aspect ? ":" : "x"; - var name = nameTextBox.Text + " (" + wValue.Value + combineString + hValue.Value + ") " + typeDropdown.SelectedItem; - - var newViewportOption = new UIModule.ViewportScaleOption - { - ScaleType = type, - Label = name, - Size = new Int2(wValue.Value, hValue.Value), - }; - - customOptions.Add(newViewportOption); - Editor.UI.SaveCustomViewportScalingOptions(); - 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 7a4072296479e5b0cb38855734dd1829b1b242ea Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 14 Sep 2025 17:51:27 -0500 Subject: [PATCH 055/137] Fix view distance light property from affecting brightness all of the time. --- Source/Engine/Level/Actors/Light.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Level/Actors/Light.h b/Source/Engine/Level/Actors/Light.h index 08d311b6d..0e2a441db 100644 --- a/Source/Engine/Level/Actors/Light.h +++ b/Source/Engine/Level/Actors/Light.h @@ -63,7 +63,8 @@ protected: { const float dst2 = (float)Vector3::DistanceSquared(viewPosition, position); const float dst = Math::Sqrt(dst2); - brightness *= Math::Remap(dst, 0.9f * ViewDistance, ViewDistance, 1.0f, 0.0f); + if (dst < ViewDistance && dst > ViewDistance * 0.9f) + brightness *= Math::Remap(dst, 0.9f * ViewDistance, ViewDistance, 1.0f, 0.0f); return dst < ViewDistance; } return true; From ae4ae7a638e26a33985836b33362942c6e65a692 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 15 Sep 2025 15:17:18 +0200 Subject: [PATCH 056/137] Fix rich textbox vertical alignment #3502 --- .../UI/GUI/Common/RichTextBox.Parsing.cs | 29 ++++++++++++++++--- Source/Engine/UI/GUI/TextBlockStyle.cs | 3 ++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs index 9a10a327c..20ef1c401 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs @@ -240,11 +240,13 @@ namespace FlaxEngine.GUI // Organize text blocks within line var horizontalAlignments = TextBlockStyle.Alignments.Baseline; + var verticalAlignments = TextBlockStyle.Alignments.Baseline; for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) { ref TextBlock textBlock = ref textBlocks[i]; var vOffset = lineSize.Y - textBlock.Bounds.Height; horizontalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.HorizontalMask; + verticalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask; switch (textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask) { case TextBlockStyle.Alignments.Baseline: @@ -272,14 +274,16 @@ namespace FlaxEngine.GUI } } } - var hOffset = Width - lineSize.X; + + // Organize blocks within whole container + var sizeOffset = Size - lineSize; if ((horizontalAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center) { - hOffset *= 0.5f; + sizeOffset.X *= 0.5f; for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) { ref TextBlock textBlock = ref textBlocks[i]; - textBlock.Bounds.Location.X += hOffset; + textBlock.Bounds.Location.X += sizeOffset.X; } } else if ((horizontalAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right) @@ -287,7 +291,24 @@ namespace FlaxEngine.GUI for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) { ref TextBlock textBlock = ref textBlocks[i]; - textBlock.Bounds.Location.X += hOffset; + textBlock.Bounds.Location.X += sizeOffset.X; + } + } + if ((verticalAlignments & TextBlockStyle.Alignments.Middle) == TextBlockStyle.Alignments.Middle) + { + sizeOffset.Y *= 0.5f; + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + { + ref TextBlock textBlock = ref textBlocks[i]; + textBlock.Bounds.Location.Y += sizeOffset.Y; + } + } + else if ((verticalAlignments & TextBlockStyle.Alignments.Bottom) == TextBlockStyle.Alignments.Bottom) + { + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + { + ref TextBlock textBlock = ref textBlocks[i]; + textBlock.Bounds.Location.Y += sizeOffset.Y; } } diff --git a/Source/Engine/UI/GUI/TextBlockStyle.cs b/Source/Engine/UI/GUI/TextBlockStyle.cs index 399de41a3..fee385dfa 100644 --- a/Source/Engine/UI/GUI/TextBlockStyle.cs +++ b/Source/Engine/UI/GUI/TextBlockStyle.cs @@ -1,5 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. +using System; + namespace FlaxEngine.GUI { /// @@ -10,6 +12,7 @@ namespace FlaxEngine.GUI /// /// Text block alignments modes. /// + [Flags] public enum Alignments { /// From 56077a268abaac7b80afeb17cc1bf34e4066f652 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 Sep 2025 00:15:48 +0200 Subject: [PATCH 057/137] SImplify and cleanup GPUTexture editor #3452 #3194 --- .../Dedicated/GPUTextureEditor.cs | 63 ++++++++++ Source/Editor/GUI/GPUTextureEditor.cs | 112 ------------------ 2 files changed, 63 insertions(+), 112 deletions(-) create mode 100644 Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs delete mode 100644 Source/Editor/GUI/GPUTextureEditor.cs diff --git a/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs new file mode 100644 index 000000000..9df7ca377 --- /dev/null +++ b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs @@ -0,0 +1,63 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +using FlaxEditor.GUI.ContextMenu; +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.CustomEditors.Dedicated +{ + /// + /// Basic editor/viewer for . + /// + [CustomEditor(typeof(GPUTexture)), DefaultEditor] + public class GPUTextureEditor : CustomEditor + { + private Image _image; + + /// + public override DisplayStyle Style => DisplayStyle.Inline; + + /// + public override void Initialize(LayoutElementsContainer layout) + { + _image = new Image + { + Brush = new GPUTextureBrush(), + Size = new Float2(200, 100), + Parent = layout.ContainerControl, + }; + _image.Clicked += OnImageClicked; + } + + private void OnImageClicked(Image image, MouseButton button) + { + var texture = Values[0] as GPUTexture; + if (!texture) + return; + var menu = new ContextMenu(); + menu.AddButton("Save...", () => Screenshot.Capture(Values[0] as GPUTexture)); + menu.AddButton("Enlarge", () => _image.Size *= 2); + menu.AddButton("Shrink", () => _image.Size /= 2).Enabled = _image.Height > 32; + var location = image.PointFromScreen(Input.MouseScreenPosition); + menu.Show(image, location); + } + + /// + public override void Refresh() + { + base.Refresh(); + + var texture = Values[0] as GPUTexture; + ((GPUTextureBrush)_image.Brush).Texture = texture; + if (texture) + { + var desc = texture.Description; + _image.TooltipText = $"{texture.Name}\nType: {texture.ResourceType}\nSize: {desc.Width}x{desc.Height}\nFormat: {desc.Format}\nMemory: {Utilities.Utils.FormatBytesCount(texture.MemoryUsage)}"; + } + else + { + _image.TooltipText = "None"; + } + } + } +} diff --git a/Source/Editor/GUI/GPUTextureEditor.cs b/Source/Editor/GUI/GPUTextureEditor.cs deleted file mode 100644 index 5dd672941..000000000 --- a/Source/Editor/GUI/GPUTextureEditor.cs +++ /dev/null @@ -1,112 +0,0 @@ -#if FLAX_EDITOR -using FlaxEditor.CustomEditors; -using FlaxEditor.CustomEditors.Editors; -using FlaxEditor.CustomEditors.Elements; -using FlaxEditor.GUI.ContextMenu; -using FlaxEditor.Scripting; -using FlaxEditor.Tools.Foliage; -using FlaxEngine; -using FlaxEngine.GUI; -using FlaxEngine.Utilities; - -namespace FlaxEditor.GUI -{ - /// - /// basic custom property editor for GPUTexture - /// - [CustomEditor(typeof(GPUTexture))] - public class GPUTexturePropertyEditor : GenericEditor - { - public override DisplayStyle Style => DisplayStyle.Inline; - - ImageElement imageElement; - GroupElement group; - /// - /// - /// - public override void Initialize(LayoutElementsContainer layout) - { - imageElement = (group = layout.Group("")).Image(SpriteHandle.Default); - - //todo fix the AddSettingsButton func - //shit is buged - //the code below (until the Paint) is untested the Clear might not work - group.AddSettingsButton(); - group.SetupContextMenu += (ContextMenu.ContextMenu cxm, DropPanel dp) => - { - cxm.AddButton("Clear", (ContextMenuButton bt) => - { - SetValue(null); - }); - - cxm.AddSeparator(); - - //todo - //editor is needed - //cxm.AddButton("Display Full Texture", (ContextMenuButton bt) => - //{ - //}); - - //todo - // - //cxm.AddButton("Save To Asset", (ContextMenuButton bt) => - //{ - //}); - }; - Paint(); - group.Panel.Close(); - } - /// - /// - public override void Refresh() - { - Paint(); - base.Refresh(); - } - private void Paint() - { - string name = null; - string tt = null; - if (Values[0] is GPUTexture gputex) - { - name = gputex.Name; - tt += "Type: " + gputex.ResourceType.ToString() + "\n"; - tt += "Memory Usage: " + gputex.MemoryUsage + "B" + "\n"; - tt += "Format: " + gputex.Format.ToString() + "\n"; - //shorten the name it is a full path - if (name.EndsWith(".flax")) - { - if (name != ".flax")//sanity guard - { - var nameStartIndexWithEx = Globals.ProjectFolder.Length + 9 /* +9 to remove the "/Content/" */; - name = name.Substring - ( - nameStartIndexWithEx, - nameStartIndexWithEx - 5 /* -5 to remove the .flax */ + 2 - ); - - tt += "Path: " + gputex.Name.Remove(0, Globals.ProjectFolder.Length + 1); - } - } - - if (imageElement.Image.Brush is GPUTextureBrush brush) - { - brush.Texture = gputex; - imageElement.Control.Size = new Float2(group.Control.Width); - } - else - { - imageElement.Image.Brush = new GPUTextureBrush(); - Paint(); - } - } - name ??= "..."; - - DropPanel p = group.Control as DropPanel; - - p.HeaderText = name; - p.TooltipText = tt; - } - } -} -#endif From 521518bde4bb00803ea47b343f3f21e27ec639a7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 Sep 2025 00:15:58 +0200 Subject: [PATCH 058/137] Add hack to use GPUTextureEditor on ref pickers --- Source/Editor/CustomEditors/CustomEditorsUtil.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Editor/CustomEditors/CustomEditorsUtil.cs b/Source/Editor/CustomEditors/CustomEditorsUtil.cs index 7d7ef123d..476219960 100644 --- a/Source/Editor/CustomEditors/CustomEditorsUtil.cs +++ b/Source/Editor/CustomEditors/CustomEditorsUtil.cs @@ -87,8 +87,11 @@ namespace FlaxEditor.CustomEditors var targetTypeType = TypeUtils.GetType(targetType); if (canUseRefPicker) { + // TODO: add generic way of CustomEditor for ref pickers (use it on AssetRefEditor/GPUTextureEditor/...) if (typeof(Asset).IsAssignableFrom(targetTypeType)) return new AssetRefEditor(); + if (typeof(GPUTexture).IsAssignableFrom(targetTypeType)) + return new GPUTextureEditor(); if (typeof(FlaxEngine.Object).IsAssignableFrom(targetTypeType)) return new FlaxObjectRefEditor(); } From afdd264e639640227b17ab42008c324ad10689de Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 16 Sep 2025 16:34:58 +0200 Subject: [PATCH 059/137] Fix compilation of Editor in Release mode --- Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs index 9df7ca377..954059a28 100644 --- a/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs @@ -52,7 +52,12 @@ namespace FlaxEditor.CustomEditors.Dedicated if (texture) { var desc = texture.Description; - _image.TooltipText = $"{texture.Name}\nType: {texture.ResourceType}\nSize: {desc.Width}x{desc.Height}\nFormat: {desc.Format}\nMemory: {Utilities.Utils.FormatBytesCount(texture.MemoryUsage)}"; +#if BUILD_RELEASE + var name = string.Empty; +#else + var name = texture.Name; +#endif + _image.TooltipText = $"{name}\nType: {texture.ResourceType}\nSize: {desc.Width}x{desc.Height}\nFormat: {desc.Format}\nMemory: {Utilities.Utils.FormatBytesCount(texture.MemoryUsage)}"; } else { From 364a52337522b7eaf1d2d05aa7dd73aff997df2f Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:04:24 +0200 Subject: [PATCH 060/137] hide TrackLabel control in editor --- Source/Editor/Windows/Profiler/Timeline.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs index c7a3dc7e6..ea653a5aa 100644 --- a/Source/Editor/Windows/Profiler/Timeline.cs +++ b/Source/Editor/Windows/Profiler/Timeline.cs @@ -100,6 +100,7 @@ namespace FlaxEditor.Windows.Profiler /// Timeline track label /// /// + [HideInEditor] public class TrackLabel : ContainerControl { /// From c124713e996ae63c56bd2c418fb473c3ca35be82 Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:05:28 +0200 Subject: [PATCH 061/137] remove create new script items when searchbox is cleared --- .../Editor/CustomEditors/Dedicated/ScriptsEditor.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index 123c7252a..bb3cdd9d4 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -70,7 +70,7 @@ namespace FlaxEditor.CustomEditors.Dedicated var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4; _addScriptsButton = new Button { - TooltipText = "Add new scripts to the actor", + TooltipText = "Add new scripts to the actor.", AnchorPreset = AnchorPresets.MiddleCenter, Text = buttonText, Parent = this, @@ -114,7 +114,16 @@ namespace FlaxEditor.CustomEditors.Dedicated cm.TextChanged += text => { if (!IsValidScriptName(text)) + { + // Remove NewScriptItems + List die = cm.ItemsPanel.Children.FindAll(c => c is NewScriptItem); + foreach (var c in die) + { + cm.ItemsPanel.RemoveChild(c); + } + return; + } if (!cm.ItemsPanel.Children.Any(x => x.Visible && x is not NewScriptItem)) { // If there are no visible items, that means the search failed so we can find the create script button or create one if it's the first time @@ -876,7 +885,7 @@ namespace FlaxEditor.CustomEditors.Dedicated // Add drag button to the group var scriptDrag = new DragImage { - TooltipText = "Script reference", + TooltipText = "Script reference.", AutoFocus = true, IsScrollable = false, Color = FlaxEngine.GUI.Style.Current.ForegroundGrey, From eea44ac89753bca4a1985f7cc50270e0f03d01af Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:06:49 +0200 Subject: [PATCH 062/137] remove search query highlights showing on create new script item --- Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs | 1 + Source/Editor/GUI/ItemsListContextMenu.cs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index bb3cdd9d4..01e221755 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -36,6 +36,7 @@ namespace FlaxEditor.CustomEditors.Dedicated { ScriptName = scriptName; TooltipText = "Create a new script"; + DrawHighlights = false; } } diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs index 8fdf21e4c..033af782f 100644 --- a/Source/Editor/GUI/ItemsListContextMenu.cs +++ b/Source/Editor/GUI/ItemsListContextMenu.cs @@ -51,6 +51,11 @@ namespace FlaxEditor.GUI /// public float SortScore; + /// + /// Wether the query highlights should be draw. + /// + public bool DrawHighlights = true; + /// /// Occurs when items gets clicked by the user. /// @@ -165,7 +170,7 @@ namespace FlaxEditor.GUI Render2D.FillRectangle(new Rectangle(Float2.Zero, Size), style.BackgroundHighlighted); // Draw all highlights - if (_highlights != null) + if (DrawHighlights && _highlights != null) { var color = style.ProgressNormal * 0.6f; for (int i = 0; i < _highlights.Count; i++) From de2ee36529b748e0bea700862be63a20d2412553 Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:07:42 +0200 Subject: [PATCH 063/137] fix naming lol --- Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index 01e221755..356ae5ee4 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -117,10 +117,10 @@ namespace FlaxEditor.CustomEditors.Dedicated if (!IsValidScriptName(text)) { // Remove NewScriptItems - List die = cm.ItemsPanel.Children.FindAll(c => c is NewScriptItem); - foreach (var c in die) + List newScriptItems = cm.ItemsPanel.Children.FindAll(c => c is NewScriptItem); + foreach (var item in newScriptItems) { - cm.ItemsPanel.RemoveChild(c); + cm.ItemsPanel.RemoveChild(item); } return; From 553a00750842bc57ecc3ddcee16b04d46502210c Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:14:22 +0200 Subject: [PATCH 064/137] Revert "hide TrackLabel control in editor" This reverts commit 364a52337522b7eaf1d2d05aa7dd73aff997df2f. --- Source/Editor/Windows/Profiler/Timeline.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs index ea653a5aa..c7a3dc7e6 100644 --- a/Source/Editor/Windows/Profiler/Timeline.cs +++ b/Source/Editor/Windows/Profiler/Timeline.cs @@ -100,7 +100,6 @@ namespace FlaxEditor.Windows.Profiler /// Timeline track label /// /// - [HideInEditor] public class TrackLabel : ContainerControl { /// From 1196db6d178d3d2b3f0898216aed88ac4c8da3c9 Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 16 Sep 2025 22:54:57 +0200 Subject: [PATCH 065/137] check if control is control meant for gui editor use --- Source/Editor/Content/Create/PrefabCreateEntry.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Content/Create/PrefabCreateEntry.cs b/Source/Editor/Content/Create/PrefabCreateEntry.cs index 90cca263d..34439a989 100644 --- a/Source/Editor/Content/Create/PrefabCreateEntry.cs +++ b/Source/Editor/Content/Create/PrefabCreateEntry.cs @@ -1,6 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. using System; +using System.Linq; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; @@ -117,7 +118,8 @@ namespace FlaxEditor.Content.Create private static bool IsValid(Type type) { - return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType; + var controlTypes = Editor.Instance.CodeEditing.Controls.Get(); + return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType && controlTypes.Any(c => c.Type == type); } } From c7e403661d96c916d8392f6782884f4cffe44001 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Tue, 16 Sep 2025 17:42:24 -0500 Subject: [PATCH 066/137] Dont allow remove and duplicate options for non-resizing collections. --- Source/Editor/CustomEditors/Editors/CollectionEditor.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index a0ee8d3dc..423daf0d4 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -407,7 +407,7 @@ namespace FlaxEditor.CustomEditors.Editors menu.AddButton("Copy", linkedEditor.Copy); var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index)); - b.Enabled = linkedEditor.CanPaste && !Editor._readOnly; + b.Enabled = linkedEditor.CanPaste && !Editor._readOnly && Editor._canResize; var paste = menu.AddButton("Paste", linkedEditor.Paste); paste.Enabled = linkedEditor.CanPaste && !Editor._readOnly; @@ -422,7 +422,8 @@ namespace FlaxEditor.CustomEditors.Editors moveDownButton.Enabled = Index + 1 < Editor.Count; } - menu.AddButton("Remove", OnRemoveClicked); + b = menu.AddButton("Remove", OnRemoveClicked); + b.Enabled = !Editor._readOnly && Editor._canResize; menu.Show(panel, location); } From 01d1d634c2b08147ccd8ba3060cedf933bd4a2b7 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Tue, 16 Sep 2025 17:43:55 -0500 Subject: [PATCH 067/137] Fix other missing duplicate. --- Source/Editor/CustomEditors/Editors/CollectionEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index 423daf0d4..b977dab63 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -71,7 +71,7 @@ namespace FlaxEditor.CustomEditors.Editors menu.AddButton("Copy", linkedEditor.Copy); var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index)); - b.Enabled = linkedEditor.CanPaste && !Editor._readOnly; + b.Enabled = linkedEditor.CanPaste && !Editor._readOnly && Editor._canResize; b = menu.AddButton("Paste", linkedEditor.Paste); b.Enabled = linkedEditor.CanPaste && !Editor._readOnly; From 2604d5868754adfe73db5e60b245dc4138c622fe Mon Sep 17 00:00:00 2001 From: Saas Date: Thu, 18 Sep 2025 17:37:04 +0200 Subject: [PATCH 068/137] no more Linq --- Source/Editor/Content/Create/PrefabCreateEntry.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Editor/Content/Create/PrefabCreateEntry.cs b/Source/Editor/Content/Create/PrefabCreateEntry.cs index 34439a989..e9ceaaa68 100644 --- a/Source/Editor/Content/Create/PrefabCreateEntry.cs +++ b/Source/Editor/Content/Create/PrefabCreateEntry.cs @@ -1,7 +1,6 @@ // Copyright (c) Wojciech Figat. All rights reserved. using System; -using System.Linq; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; @@ -119,7 +118,7 @@ namespace FlaxEditor.Content.Create private static bool IsValid(Type type) { var controlTypes = Editor.Instance.CodeEditing.Controls.Get(); - return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType && controlTypes.Any(c => c.Type == type); + return (type.IsPublic || type.IsNestedPublic) && !type.IsAbstract && !type.IsGenericType && controlTypes.Contains(new ScriptType(type)); } } From fd191f7ffb10583af123c890d1910adb433dc268 Mon Sep 17 00:00:00 2001 From: Saas Date: Thu, 18 Sep 2025 23:24:10 +0200 Subject: [PATCH 069/137] don't clear content panel folder- and scene tree search box on script reload and enter/ exit play --- Source/Editor/Windows/ContentWindow.Search.cs | 1 + Source/Editor/Windows/ContentWindow.cs | 2 ++ Source/Editor/Windows/SceneTreeWindow.cs | 7 ++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs index f28dc4834..5a0ed63aa 100644 --- a/Source/Editor/Windows/ContentWindow.Search.cs +++ b/Source/Editor/Windows/ContentWindow.Search.cs @@ -115,6 +115,7 @@ namespace FlaxEditor.Windows var root = _root; root.LockChildrenRecursive(); + PerformLayout(); // Update tree var query = _foldersSearchBox.Text; diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 3d2ec4a66..d0cf84251 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -1085,6 +1085,8 @@ namespace FlaxEditor.Windows if (Editor.ContentDatabase.Find(_lastViewedFolderBeforeReload) is ContentFolder folder) _tree.Select(folder.Node); } + + OnFoldersSearchBoxTextChanged(); } private void Refresh() diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index 75a3723cf..6b401c2cd 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -68,6 +68,7 @@ namespace FlaxEditor.Windows TooltipText = "Search the scene tree.\n\nYou can prefix your search with different search operators:\ns: -> Actor with script of type\na: -> Actor type\nc: -> Control type", }; _searchBox.TextChanged += OnSearchBoxTextChanged; + ScriptsBuilder.ScriptsReloadEnd += OnSearchBoxTextChanged; // Scene tree panel _sceneTreePanel = new Panel @@ -112,7 +113,7 @@ namespace FlaxEditor.Windows InputActions.Add(options => options.LockFocusSelection, () => Editor.Windows.EditWin.Viewport.LockFocusSelection()); InputActions.Add(options => options.Rename, RenameSelection); } - + /// public override void OnPlayBeginning() { @@ -125,6 +126,7 @@ namespace FlaxEditor.Windows { base.OnPlayBegin(); _blockSceneTreeScroll = false; + OnSearchBoxTextChanged(); } /// @@ -139,6 +141,7 @@ namespace FlaxEditor.Windows { base.OnPlayEnd(); _blockSceneTreeScroll = true; + OnSearchBoxTextChanged(); } /// @@ -174,6 +177,7 @@ namespace FlaxEditor.Windows return; _tree.LockChildrenRecursive(); + PerformLayout(); // Update tree var query = _searchBox.Text; @@ -599,6 +603,7 @@ namespace FlaxEditor.Windows _dragHandlers = null; _tree = null; _searchBox = null; + ScriptsBuilder.ScriptsReloadEnd += OnSearchBoxTextChanged; base.OnDestroy(); } From 7183a3306eb9d4d7992e7b22fb803075fbbbe714 Mon Sep 17 00:00:00 2001 From: Saas Date: Fri, 19 Sep 2025 16:57:50 +0200 Subject: [PATCH 070/137] fix typo --- Source/Editor/Windows/SceneTreeWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index 6b401c2cd..ab6d2e262 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -603,7 +603,7 @@ namespace FlaxEditor.Windows _dragHandlers = null; _tree = null; _searchBox = null; - ScriptsBuilder.ScriptsReloadEnd += OnSearchBoxTextChanged; + ScriptsBuilder.ScriptsReloadEnd -= OnSearchBoxTextChanged; base.OnDestroy(); } From d1fbc66cb9860bb6827255bedc3017c95cef15cc Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 19 Sep 2025 15:58:22 -0500 Subject: [PATCH 071/137] Fix not attaching updated collision data to rigid body. --- Source/Engine/Physics/Colliders/Collider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp index 8249577c2..d60048ba9 100644 --- a/Source/Engine/Physics/Colliders/Collider.cpp +++ b/Source/Engine/Physics/Colliders/Collider.cpp @@ -248,7 +248,7 @@ void Collider::UpdateGeometry() const auto rigidBody = dynamic_cast(GetParent()); if (_staticActor != nullptr || (rigidBody && CanAttach(rigidBody))) { - PhysicsBackend::AttachShape(_shape, actor); + Attach(rigidBody); } else { From 47711ec5bebfabf1bd71baca76f9727d020deba1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 19 Sep 2025 23:10:03 +0200 Subject: [PATCH 072/137] Fix Volumetric Fog flicker on camera cuts #3443 --- Source/Engine/Renderer/VolumetricFogPass.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 817f25eef..2fa957ab1 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -179,6 +179,8 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, (float)_cache.GridSizeZ); auto& fogData = renderContext.Buffers->VolumetricFogData; fogData.MaxDistance = options.Distance; + if (renderContext.Task->IsCameraCut) + _cache.HistoryWeight = 0.0f; // Init data (partial, without directional light or sky light data); GBufferPass::SetInputs(renderContext.View, _cache.Data.GBuffer); @@ -528,7 +530,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) { PROFILE_GPU("Light Scattering"); - const bool temporalHistoryIsValid = renderContext.Buffers->VolumetricFogHistory && !renderContext.Task->IsCameraCut && Float3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize); + const bool temporalHistoryIsValid = renderContext.Buffers->VolumetricFogHistory && Float3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize); const auto lightScatteringHistory = temporalHistoryIsValid ? renderContext.Buffers->VolumetricFogHistory : nullptr; context->BindUA(0, lightScattering->ViewVolume()); From 92f4327fc2ea0a1a4d3512164af98ebe1dcd8187 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 20 Sep 2025 00:13:52 +0200 Subject: [PATCH 073/137] Fix missing volumetric fog affecting transparent materials #3436 --- Source/Engine/Graphics/Materials/MaterialShader.h | 2 +- .../Graphics/Materials/MaterialShaderFeatures.cpp | 10 ++++++++++ .../Engine/Graphics/Materials/MaterialShaderFeatures.h | 2 +- Source/Shaders/ExponentialHeightFog.hlsl | 5 +++++ Source/Shaders/Fog.shader | 2 +- 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index aedf2e870..117246671 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 174 +#define MATERIAL_GRAPH_VERSION 175 class Material; class GPUShader; diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index 0dae6c93e..a140fb577 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -2,6 +2,7 @@ #include "MaterialShaderFeatures.h" #include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/ShadowsPass.h" @@ -24,18 +25,27 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanFog) { cache->Fog->GetExponentialHeightFogData(view, data.ExponentialHeightFog); + VolumetricFogOptions volumetricFog; + cache->Fog->GetVolumetricFogOptions(volumetricFog); + if (volumetricFog.UseVolumetricFog() && params.RenderContext.Buffers->VolumetricFog) + volumetricFogTexture = params.RenderContext.Buffers->VolumetricFog->ViewVolume(); + else + data.ExponentialHeightFog.VolumetricFogMaxDistance = -1.0f; } else { data.ExponentialHeightFog.FogMinOpacity = 1.0f; data.ExponentialHeightFog.ApplyDirectionalInscattering = 0.0f; } + params.GPUContext->BindSR(volumetricFogTextureRegisterIndex, volumetricFogTexture); // Set directional light input if (cache->DirectionalLights.HasItems()) diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h index 25689e765..54b91af23 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h @@ -25,7 +25,7 @@ struct ForwardShadingFeature : MaterialShaderFeature { enum { MaxLocalLights = 4 }; - enum { SRVs = 4 }; + enum { SRVs = 5 }; PACK_STRUCT(struct Data { diff --git a/Source/Shaders/ExponentialHeightFog.hlsl b/Source/Shaders/ExponentialHeightFog.hlsl index f6fb918f5..b5af721d8 100644 --- a/Source/Shaders/ExponentialHeightFog.hlsl +++ b/Source/Shaders/ExponentialHeightFog.hlsl @@ -92,4 +92,9 @@ float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, fl return GetExponentialHeightFog(exponentialHeightFog, posWS, camWS, skipDistance, distance(posWS, camWS)); } +float4 CombineVolumetricFog(float4 fog, float4 volumetricFog) +{ + return float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a); +} + #endif diff --git a/Source/Shaders/Fog.shader b/Source/Shaders/Fog.shader index dfea921cc..5c4344688 100644 --- a/Source/Shaders/Fog.shader +++ b/Source/Shaders/Fog.shader @@ -63,7 +63,7 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0 #if VOLUMETRIC_FOG // Sample volumetric fog and mix it in float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0); - fog = float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a); + fog = CombineVolumetricFog(fog, volumetricFog); #endif return fog; From 9cc44825c6f69416e6ed20dba9456419dfa6608f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 20 Sep 2025 00:14:51 +0200 Subject: [PATCH 074/137] Update engine materials 92f4327fc2ea0a1a4d3512164af98ebe1dcd8187 --- Content/Editor/Camera/M_Camera.flax | 2 +- Content/Editor/CubeTexturePreviewMaterial.flax | 2 +- Content/Editor/DebugMaterials/DDGIDebugProbes.flax | 2 +- .../Editor/DebugMaterials/SingleColor/Decal.flax | 2 +- .../Editor/DebugMaterials/SingleColor/Particle.flax | 4 ++-- .../Editor/DebugMaterials/SingleColor/Surface.flax | 2 +- .../DebugMaterials/SingleColor/SurfaceAdditive.flax | 4 ++-- .../Editor/DebugMaterials/SingleColor/Terrain.flax | 2 +- Content/Editor/DefaultFontMaterial.flax | 2 +- Content/Editor/Gizmo/FoliageBrushMaterial.flax | 4 ++-- Content/Editor/Gizmo/Material.flax | 4 ++-- Content/Editor/Gizmo/MaterialWire.flax | 4 ++-- Content/Editor/Gizmo/SelectionOutlineMaterial.flax | 2 +- .../Editor/Gizmo/VertexColorsPreviewMaterial.flax | 2 +- Content/Editor/Highlight Material.flax | 4 ++-- Content/Editor/Icons/IconsMaterial.flax | 4 ++-- Content/Editor/IesProfilePreviewMaterial.flax | 2 +- .../MaterialTemplates/Features/ForwardShading.hlsl | 13 +++++++++++++ .../Editor/Particles/Particle Material Color.flax | 4 ++-- Content/Editor/Particles/Smoke Material.flax | 4 ++-- Content/Editor/SpriteMaterial.flax | 2 +- Content/Editor/Terrain/Circle Brush Material.flax | 2 +- .../Editor/Terrain/Highlight Terrain Material.flax | 2 +- Content/Editor/TexturePreviewMaterial.flax | 2 +- Content/Editor/Wires Debug Material.flax | 4 ++-- Content/Engine/DefaultDeformableMaterial.flax | 2 +- Content/Engine/DefaultMaterial.flax | 2 +- Content/Engine/DefaultRadialMenu.flax | 2 +- Content/Engine/DefaultTerrainMaterial.flax | 2 +- Content/Engine/SingleColorMaterial.flax | 2 +- Content/Engine/SkyboxMaterial.flax | 2 +- Content/Shaders/Fog.flax | 4 ++-- 32 files changed, 55 insertions(+), 42 deletions(-) diff --git a/Content/Editor/Camera/M_Camera.flax b/Content/Editor/Camera/M_Camera.flax index 5012b16e9..25b184d86 100644 --- a/Content/Editor/Camera/M_Camera.flax +++ b/Content/Editor/Camera/M_Camera.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a2936be1789e6a7c663f84ddfea8c897fe8273cd2d29910ac37720907d7b930 +oid sha256:5ef316cb161204b2c7a9dd4746c6c7281507a1e26c4c48c1a917b7645ac611f6 size 29533 diff --git a/Content/Editor/CubeTexturePreviewMaterial.flax b/Content/Editor/CubeTexturePreviewMaterial.flax index 973a01177..3d7014519 100644 --- a/Content/Editor/CubeTexturePreviewMaterial.flax +++ b/Content/Editor/CubeTexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ecf44ea82025d0f491c68b0470e1704ca5f385bd54ad196d6912aeb2f3aee0f +oid sha256:99287e35e0c8ed22fd336cce66d8a675ad43fb318d431e63baf23670bc1212a7 size 31125 diff --git a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax index d598ac9bb..a5c8ccda0 100644 --- a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax +++ b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6e897a2fcbbb21efdd589604b4e3fc657f457ea124384842b380295af66cf13 +oid sha256:83aee3f2d5088930b7395099150a1bc062584996082cc1e13465c546d6f90fa3 size 40358 diff --git a/Content/Editor/DebugMaterials/SingleColor/Decal.flax b/Content/Editor/DebugMaterials/SingleColor/Decal.flax index 6024d3961..a85229155 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Decal.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Decal.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8301da35f0b45f58f5c59221bd22bf0a8500555d31ab84ec1c8cd5eca9fc101 +oid sha256:aa1b7b7f37b73cbcdef2faa6a6a1a1ce11c08033233606dd34e558195f4718cd size 9973 diff --git a/Content/Editor/DebugMaterials/SingleColor/Particle.flax b/Content/Editor/DebugMaterials/SingleColor/Particle.flax index 9c2c0755a..423396308 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Particle.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Particle.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e432328bb19eaa58caf35f60cd6495a46cca694314828010f3be401d7de9434 -size 32108 +oid sha256:5096f5c6aff954618c4fc863e59a76ce880879695bac1abc990fbabd0b8d330b +size 32699 diff --git a/Content/Editor/DebugMaterials/SingleColor/Surface.flax b/Content/Editor/DebugMaterials/SingleColor/Surface.flax index 0fb0d1c6f..f405ecd8b 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Surface.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Surface.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1688861997cc2e8a433cdea81ee62662f45b261bc863cdb9431beed612f0aad7 +oid sha256:0c1c2e4e2324de02092f73a0477cd909e400e99a400ce255c59751b21af3ed8e size 29306 diff --git a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax index e5bda89f6..98a9221f6 100644 --- a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax +++ b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42363fad30e29b0e0c4cf7ad9e02dc91040eb6821c3c28bd49996771e65893c4 -size 31559 +oid sha256:7b8794eaf03955f5afb9cf8a56a6327d7fe3b7c287e2eeb50c95d1a78dd2c7c4 +size 32150 diff --git a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax index 09a253a8d..2ab956aad 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb957ea2ee358b0e611d6612703261c9837099b6d03d48484cdab1151a461d8f +oid sha256:dfd8cdbfe96f53c2795b7c408a5f6c09fbf67b0d3ded6c34aacf2e34313e1925 size 21004 diff --git a/Content/Editor/DefaultFontMaterial.flax b/Content/Editor/DefaultFontMaterial.flax index b4f659e34..71b91f9a6 100644 --- a/Content/Editor/DefaultFontMaterial.flax +++ b/Content/Editor/DefaultFontMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a46410b49a7e38c4c2569e4d8d8c8f4744cf26f79c632a53899ce753ab7c88a +oid sha256:9a5f051b559c86cd397dda551afd4f3b751a99bc9cb14de989a80c2a04651d82 size 29627 diff --git a/Content/Editor/Gizmo/FoliageBrushMaterial.flax b/Content/Editor/Gizmo/FoliageBrushMaterial.flax index 1d8e89a65..7af84241d 100644 --- a/Content/Editor/Gizmo/FoliageBrushMaterial.flax +++ b/Content/Editor/Gizmo/FoliageBrushMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f377cc4e05d89e4edbec6382a052abe571f3261bc273cd4475541b7b7051cffb -size 37586 +oid sha256:3d2bb53a8b94d596738a6a1527d2516e032a287a7a6de6fab472be7a28978de2 +size 38177 diff --git a/Content/Editor/Gizmo/Material.flax b/Content/Editor/Gizmo/Material.flax index cce270410..2d52c87a9 100644 --- a/Content/Editor/Gizmo/Material.flax +++ b/Content/Editor/Gizmo/Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:271c80d9d9971d96d6ea430dfaf8f8f57d9b5f9fe1770b387f426d3c8721c3d8 -size 32713 +oid sha256:261de215acfeee3d2e37bfea0c4f807c7f685f20719032f1706f82b07ae52992 +size 33304 diff --git a/Content/Editor/Gizmo/MaterialWire.flax b/Content/Editor/Gizmo/MaterialWire.flax index 4b30df5f5..4b90f0311 100644 --- a/Content/Editor/Gizmo/MaterialWire.flax +++ b/Content/Editor/Gizmo/MaterialWire.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff3e7b3e77afa7191f1db9cf12f21908b80bb8f71e832c37e55547dc9dcab31c -size 31410 +oid sha256:072c5ae6e0248b8f48bb933a8bd51935218afe425ab9f6df5fb853003e545b52 +size 32001 diff --git a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax index 962179da0..7dc84ec92 100644 --- a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax +++ b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc2facc8fa980e5baa399fa7510a87d33d21bbd4c97eaab24856f6db49b13172 +oid sha256:87f9eee9186d2862aa04c837d05e4cffeb1eff8be706ea856bd74a179ad591bb size 16212 diff --git a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax index 305c6a4c2..b6e40d5b4 100644 --- a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax +++ b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4458a9483e81fb0526cc395f93eeae238f4f91fa5d4889e3196b6530a8f17ec2 +oid sha256:c8b6d69f23dc6dd94e03180127e1b5eafb9bb610a392d41b6aee94d3e03bebef size 30419 diff --git a/Content/Editor/Highlight Material.flax b/Content/Editor/Highlight Material.flax index e944ae62d..4371e5753 100644 --- a/Content/Editor/Highlight Material.flax +++ b/Content/Editor/Highlight Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:391606b1f7563d9a8e414baf6c19f3d99694a28f3f574b7aca64a325294d8e39 -size 30104 +oid sha256:bde47005982dbcb96abb900d5773d5f6d707ea0eee94b7b385945e3b3b350372 +size 30695 diff --git a/Content/Editor/Icons/IconsMaterial.flax b/Content/Editor/Icons/IconsMaterial.flax index 320547f9a..dfcfed0b6 100644 --- a/Content/Editor/Icons/IconsMaterial.flax +++ b/Content/Editor/Icons/IconsMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7951a44b138e60aa9dee4fdaf000eba8a7faef7b31c2e387f78b4a393d0cd0bc -size 30021 +oid sha256:c6524caaaf72bc30bc32bffcfdf26b4d1d2adc466dd5143c4b1980e62b14b97f +size 30612 diff --git a/Content/Editor/IesProfilePreviewMaterial.flax b/Content/Editor/IesProfilePreviewMaterial.flax index c7a025108..9f23ac666 100644 --- a/Content/Editor/IesProfilePreviewMaterial.flax +++ b/Content/Editor/IesProfilePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41210c6c490513503f01e8a628d80dd98e58fc0482f9966f9342700118ccd04c +oid sha256:f796e403ee85d33eb2be0a371e18085a31ca7bf970e26c19c26f9ea2b0224a33 size 20445 diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl index 22d9ca9b4..bb18b3011 100644 --- a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -27,6 +27,7 @@ TextureCube EnvProbe : register(t__SRV__); TextureCube SkyLightTexture : register(t__SRV__); Buffer ShadowsBuffer : register(t__SRV__); Texture2D ShadowMap : register(t__SRV__); +Texture3D VolumetricFogTexture : register(t__SRV__); @4// Forward Shading: Utilities @5// Forward Shading: Shaders @@ -147,6 +148,18 @@ void PS_Forward( // Calculate exponential height fog float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z); + if (ExponentialHeightFog.VolumetricFogMaxDistance > 0) + { + // Sample volumetric fog and mix it in + float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw; + float3 viewVector = materialInput.WorldPosition - ViewPos; + float sceneDepth = length(viewVector); + float depthSlice = sceneDepth / ExponentialHeightFog.VolumetricFogMaxDistance; + float3 volumeUV = float3(screenUV, depthSlice); + float4 volumetricFog = VolumetricFogTexture.SampleLevel(SamplerLinearClamp, volumeUV, 0); + fog = CombineVolumetricFog(fog, volumetricFog); + } + // Apply fog to the output color #if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE output = float4(output.rgb * fog.a + fog.rgb, output.a); diff --git a/Content/Editor/Particles/Particle Material Color.flax b/Content/Editor/Particles/Particle Material Color.flax index bde834456..50cf3b09f 100644 --- a/Content/Editor/Particles/Particle Material Color.flax +++ b/Content/Editor/Particles/Particle Material Color.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b600cd725f5550de72d5a2544571ca2c1ea8de1a3d45038bac273d2b6f3b04c2 -size 30429 +oid sha256:d4fcde3b4d440561997706160c0f10e4b82e30b7c2f8aa732fd1439d9bae160e +size 31020 diff --git a/Content/Editor/Particles/Smoke Material.flax b/Content/Editor/Particles/Smoke Material.flax index 7a8fdeb1a..38b79ec48 100644 --- a/Content/Editor/Particles/Smoke Material.flax +++ b/Content/Editor/Particles/Smoke Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96d3865771cfa47ad59e0493c8f1b6e9fd9950593b2b929c91ea2692eca71efd -size 38495 +oid sha256:1a1fdeeb738daa07787556cac664214c33633a1f9a3021aff4dc0727e105ea4c +size 39087 diff --git a/Content/Editor/SpriteMaterial.flax b/Content/Editor/SpriteMaterial.flax index 876a38a56..2c98b951e 100644 --- a/Content/Editor/SpriteMaterial.flax +++ b/Content/Editor/SpriteMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d02a6d11ea83ea6c519a1644950750e58433e6a2aea9a2daa646db1d2b0c293 +oid sha256:3059c52ee632be69bab545192e170b61ddabcf67d4848bbdb46f4c1da5414072 size 30502 diff --git a/Content/Editor/Terrain/Circle Brush Material.flax b/Content/Editor/Terrain/Circle Brush Material.flax index af191fdaa..71a54e7f6 100644 --- a/Content/Editor/Terrain/Circle Brush Material.flax +++ b/Content/Editor/Terrain/Circle Brush Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e9ef5186642a38af8ebb5856a891215686576b23841aabe16b7dde7f2bcb57f +oid sha256:bd3172fc12d5ad7c6cc862f4b62a77b781974242e14518dbf81805605941cd55 size 27676 diff --git a/Content/Editor/Terrain/Highlight Terrain Material.flax b/Content/Editor/Terrain/Highlight Terrain Material.flax index 14bd86c35..863c238b7 100644 --- a/Content/Editor/Terrain/Highlight Terrain Material.flax +++ b/Content/Editor/Terrain/Highlight Terrain Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f1a9524d9bc7ee41df761b9fb34613fc04357377a81836fb28b3ee5a6f2dcf4 +oid sha256:fbdc0533affafaaf7f8813cfdbe5a9d5596038e0e5e46ad3e970ec7ffd924fab size 21179 diff --git a/Content/Editor/TexturePreviewMaterial.flax b/Content/Editor/TexturePreviewMaterial.flax index fac30b4f1..2ab0e2c23 100644 --- a/Content/Editor/TexturePreviewMaterial.flax +++ b/Content/Editor/TexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c178081b59417439b2d523486f3c7e4f7f391ff57e5ab5a565aadf3fd31f5488 +oid sha256:b5d4eda6497493dabf6697a9df34ec59b11183648e481399a7b1beae3c8596e1 size 10744 diff --git a/Content/Editor/Wires Debug Material.flax b/Content/Editor/Wires Debug Material.flax index 8fff1a174..8c5a07c5d 100644 --- a/Content/Editor/Wires Debug Material.flax +++ b/Content/Editor/Wires Debug Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c31daed51b38e6aa9eeceaad85498d6ae7079f7b125c6f71f036799278c34e22 -size 30104 +oid sha256:037ea2b610ee9c7ceb2cdb680d2a5d898a0600a896df93036565e11aef02a17c +size 30695 diff --git a/Content/Engine/DefaultDeformableMaterial.flax b/Content/Engine/DefaultDeformableMaterial.flax index 8af3db999..b3be3fe58 100644 --- a/Content/Engine/DefaultDeformableMaterial.flax +++ b/Content/Engine/DefaultDeformableMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df767eeb060d058d502271f1cd89581c57ad339cd690cc9c588f9a34cc9344b1 +oid sha256:4591783ed6e6cca6b8639dd3ebb624101b623c3813b80f75e22ce606d914b8db size 18985 diff --git a/Content/Engine/DefaultMaterial.flax b/Content/Engine/DefaultMaterial.flax index a253452df..51e67d79f 100644 --- a/Content/Engine/DefaultMaterial.flax +++ b/Content/Engine/DefaultMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b00388390410aabb11f1d9b032361902d2f284daa765d536c8f2a821f659effe +oid sha256:f1906849094ff4ad6022e14762961e2a235160d29427f82724d91ca8b8cfb320 size 31331 diff --git a/Content/Engine/DefaultRadialMenu.flax b/Content/Engine/DefaultRadialMenu.flax index 2b3d7f0de..8175a130a 100644 --- a/Content/Engine/DefaultRadialMenu.flax +++ b/Content/Engine/DefaultRadialMenu.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b0272c8f2df095e6609f49845a3d329daaf634e0776ca764e4c51596cac60ff +oid sha256:5ab4c3c9d3f425b136eb0cdee3342b5c99f9372e691d5bf0b1f85c7654362805 size 20514 diff --git a/Content/Engine/DefaultTerrainMaterial.flax b/Content/Engine/DefaultTerrainMaterial.flax index 8d195ab98..cd1a11e93 100644 --- a/Content/Engine/DefaultTerrainMaterial.flax +++ b/Content/Engine/DefaultTerrainMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a86caeef4de5a84783ba34208701c0f272f3b4b3ff82c64c2553d6aec631e07b +oid sha256:04a300665f72ea9543edb0419f660c09bd6d41eb46021a52be4b5bb14fa257a1 size 23301 diff --git a/Content/Engine/SingleColorMaterial.flax b/Content/Engine/SingleColorMaterial.flax index b6906b930..a9534c2db 100644 --- a/Content/Engine/SingleColorMaterial.flax +++ b/Content/Engine/SingleColorMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74d77dbfdf72c9281b0760a266adac7f1eb849f9656ea8da5cd8951f2fab5343 +oid sha256:5da0e59ceaa1921fce54a8602837fe4782436ba67af4c945b2827cbc672cb362 size 29507 diff --git a/Content/Engine/SkyboxMaterial.flax b/Content/Engine/SkyboxMaterial.flax index 8faccf8c0..8882f13ec 100644 --- a/Content/Engine/SkyboxMaterial.flax +++ b/Content/Engine/SkyboxMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8149367ccbef36932866e6af53fedf79931f26677db5dfcce71ba33caeff5980 +oid sha256:e47dc45042b8b802c6b7dec8ffeab7feb761c7b31a116031fa6db5d6d41f7855 size 31070 diff --git a/Content/Shaders/Fog.flax b/Content/Shaders/Fog.flax index 3f934412c..9bce56170 100644 --- a/Content/Shaders/Fog.flax +++ b/Content/Shaders/Fog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e83f9dbbcf84550de09e7c63bbdd3acc6591cf6ba1bcce2a2699772122ae07f4 -size 2633 +oid sha256:72daf0834367b96cc0732e6b3a5d8944c1048f516a52146bfd47f8ad83c95b4a +size 2590 From 1c581bceafc7af25f317e21e2cea63ab8290db25 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 20 Sep 2025 23:52:04 +0200 Subject: [PATCH 075/137] Fix sun shadows when direction is perfectly vertical #3614 --- Source/Engine/Renderer/ShadowsPass.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 0bf2f70d1..34ff5d3a9 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -946,7 +946,10 @@ void ShadowsPass::SetupLight(ShadowsCustomBuffer& shadows, RenderContext& render Matrix shadowView, shadowProjection, shadowVP, cullingVP; // Create view matrix - Matrix::LookAt(frustumCenter + light.Direction * minExtents.Z, frustumCenter, Float3::Up, shadowView); + Float3 up = Float3::Up; + if (Math::Abs(Float3::Dot(light.Direction, up)) > 0.9f) + up = Float3::Right; + Matrix::LookAt(frustumCenter + light.Direction * minExtents.Z, frustumCenter, up, shadowView); // Create viewport for culling with extended near/far planes due to culling issues (aka pancaking) const float cullRangeExtent = 100000.0f; From 902744a0cef9631a101d57ed57022a9c08719c32 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 21 Sep 2025 15:08:35 +0200 Subject: [PATCH 076/137] Fix model import scale on nodes that could be applied multiple times on the same mesh #3562 --- Source/Engine/Tools/ModelTool/ModelTool.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index fe268c350..e0ee85cac 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1611,9 +1611,16 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option // Transform the nodes using the import transformation if (data.LODs.HasItems() && data.LODs[0].Meshes.HasItems()) { + BitArray<> visitedNodes; + visitedNodes.Resize(data.Nodes.Count()); + visitedNodes.SetAll(false); for (int i = 0; i < data.LODs[0].Meshes.Count(); ++i) { auto* meshData = data.LODs[0].Meshes[i]; + int32 nodeIndex = meshData->NodeIndex; + if (visitedNodes[nodeIndex]) + continue; + visitedNodes.Set(nodeIndex, true); Transform transform = importTransform; if (options.UseLocalOrigin) { @@ -1627,8 +1634,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option transform.Translation -= center; } - int32 nodeIndex = meshData->NodeIndex; - auto& node = data.Nodes[nodeIndex]; node.LocalTransform = transform.LocalToWorld(node.LocalTransform); } From 26e94f6f8ef284818f6da120cdcddec989b109e6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 21 Sep 2025 20:59:25 +0200 Subject: [PATCH 077/137] Refactor material instance to not override all public parameters by default (need explicit set) #3444 --- Source/Engine/Content/Assets/MaterialInstance.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Engine/Content/Assets/MaterialInstance.cpp b/Source/Engine/Content/Assets/MaterialInstance.cpp index 7d6c9d7fc..b3710ebbd 100644 --- a/Source/Engine/Content/Assets/MaterialInstance.cpp +++ b/Source/Engine/Content/Assets/MaterialInstance.cpp @@ -90,9 +90,11 @@ void MaterialInstance::OnBaseParamsChanged() // Get the newest parameters baseParams->Clone(Params); +#if 0 // Override all public parameters by default for (auto& param : Params) param.SetIsOverride(param.IsPublic()); +#endif // Copy previous parameters values for (int32 i = 0; i < oldParams.Count(); i++) From a0f764a774580b916c7e3c9d94adbe712f152ceb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 21 Sep 2025 21:58:03 +0200 Subject: [PATCH 078/137] Add skybox rotation feature #3592 --- Content/Engine/SkyboxMaterial.flax | 4 ++-- Source/Engine/Level/Actors/Skybox.cpp | 2 ++ Source/Engine/Level/Actors/Skybox.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Content/Engine/SkyboxMaterial.flax b/Content/Engine/SkyboxMaterial.flax index 8882f13ec..7f9545007 100644 --- a/Content/Engine/SkyboxMaterial.flax +++ b/Content/Engine/SkyboxMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e47dc45042b8b802c6b7dec8ffeab7feb761c7b31a116031fa6db5d6d41f7855 -size 31070 +oid sha256:98a0d6b06a90d753e68638ac64836cb96e6edc90e5b13770b722f33512034c09 +size 31650 diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp index 6bfc98723..e08d8a61a 100644 --- a/Source/Engine/Level/Actors/Skybox.cpp +++ b/Source/Engine/Level/Actors/Skybox.cpp @@ -129,6 +129,7 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M material->SetParameterValue(TEXT("PanoramicTexture"), PanoramicTexture.Get(), false); material->SetParameterValue(TEXT("Color"), Color * Math::Exp2(Exposure), false); material->SetParameterValue(TEXT("IsPanoramic"), PanoramicTexture != nullptr, false); + material->SetParameterValue(TEXT("RotationEuler"), _rotationEuler, false); material->Bind(bindParams); } } @@ -163,4 +164,5 @@ void Skybox::OnTransformChanged() _box = BoundingBox(_transform.Translation); _sphere = BoundingSphere(_transform.Translation, 0.0f); + _rotationEuler = GetOrientation().GetEuler() * DegreesToRadians; } diff --git a/Source/Engine/Level/Actors/Skybox.h b/Source/Engine/Level/Actors/Skybox.h index f571a211f..fb831df44 100644 --- a/Source/Engine/Level/Actors/Skybox.h +++ b/Source/Engine/Level/Actors/Skybox.h @@ -18,6 +18,7 @@ class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer private: AssetReference _proxyMaterial; int32 _sceneRenderingKey = -1; + Float3 _rotationEuler; public: /// From 5f1e905e8fadab9c485e38f49a9de26eb70691d1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 21 Sep 2025 22:52:57 +0200 Subject: [PATCH 079/137] Fix crash when importing model as prefab and handle duplicated object names #3558 --- Source/Engine/ContentImporters/ImportModel.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index be71236ab..91547dc8d 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -26,6 +26,7 @@ #include "Engine/Utilities/RectPack.h" #include "Engine/Scripting/Scripting.h" #include "Engine/Profiler/ProfilerCPU.h" +#include "Editor/Utilities/EditorUtilities.h" #include "AssetsImportingManager.h" bool ImportModel::TryGetImportOptions(const StringView& path, Options& options) @@ -281,13 +282,19 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) // Import all of the objects recursive but use current model data to skip loading file again options.Cached = &cached; - Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData) + HashSet objectNames; + Function splitImport = [&context, &autoImportOutput, &objectNames](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData) { // Recursive importing of the split object String postFix = objectName; const int32 splitPos = postFix.FindLast(TEXT('|')); - if (splitPos != -1) + if (splitPos != -1 && splitPos + 1 < postFix.Length()) postFix = postFix.Substring(splitPos + 1); + EditorUtilities::ValidatePathChars(postFix); // Ensure name is valid path + int32 duplicate = 0; + String postFixPre = postFix; + while (!objectNames.Add(postFix)) // Ensure name is unique + postFix = String::Format(TEXT("{} {}"), postFixPre, duplicate++); // TODO: check for name collisions with material/texture assets outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax"); splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above) From a151c78412626bb0b366620d6f490795771f37bb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 22 Sep 2025 08:42:16 +0200 Subject: [PATCH 080/137] Fix loading projects that have similar path to engine folder #3565 --- .../Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index 18459ddb5..4c9d521b4 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -192,11 +192,18 @@ namespace Flax.Build { if (string.IsNullOrEmpty(path)) return string.Empty; - if (path.StartsWith(Globals.EngineRoot)) + path = Utilities.NormalizePath(path); + if (IsMacroPath(path, Globals.EngineRoot)) path = "$(EnginePath)" + path.Substring(Globals.EngineRoot.Length); - else if (path.StartsWith(projectPath)) + else if (IsMacroPath(path, projectPath)) path = "$(ProjectPath)" + path.Substring(projectPath.Length); - return Utilities.NormalizePath(path); + return path; + } + + private static bool IsMacroPath(string path, string root) + { + root = Utilities.NormalizePath(root); + return path == root || path.StartsWith(root + '/'); } } From e9a7b1c8eb7e754d6e39aa9cd1b06b14a62cbc48 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 22 Sep 2025 10:22:32 +0200 Subject: [PATCH 081/137] Fix using enums as Scene Animation Event parameters #3554 --- .../Editor/GUI/Timeline/Tracks/EventTrack.cs | 32 ++++++++++++++++--- .../Timeline/Tracks/KeyframesPropertyTrack.cs | 5 ++- Source/Editor/Utilities/Utils.cs | 24 ++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs index c18c64ac5..f7aba94b3 100644 --- a/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/EventTrack.cs @@ -10,6 +10,7 @@ using System.Text; using FlaxEditor.GUI.Timeline.Undo; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEngine.Json; using FlaxEngine.Utilities; namespace FlaxEditor.GUI.Timeline.Tracks @@ -54,7 +55,10 @@ namespace FlaxEditor.GUI.Timeline.Tracks var paramTypeName = LoadName(stream); e.EventParamsTypes[i] = TypeUtils.GetManagedType(paramTypeName); if (e.EventParamsTypes[i] == null) + { + Editor.LogError($"Unknown type {paramTypeName}."); isInvalid = true; + } } if (isInvalid) @@ -82,7 +86,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks for (int j = 0; j < paramsCount; j++) { stream.Read(dataBuffer, 0, e.EventParamsSizes[j]); - key.Parameters[j] = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), e.EventParamsTypes[j]); + key.Parameters[j] = Utilities.Utils.ByteArrayToStructure(handle.AddrOfPinnedObject(), e.EventParamsTypes[j], e.EventParamsSizes[j]); } events[i] = new KeyframesEditor.Keyframe @@ -125,8 +129,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks for (int j = 0; j < paramsCount; j++) { - Marshal.StructureToPtr(key.Parameters[j], ptr, true); - Marshal.Copy(ptr, dataBuffer, 0, e.EventParamsSizes[j]); + Utilities.Utils.StructureToByteArray(key.Parameters[j], e.EventParamsSizes[j], ptr, dataBuffer); stream.Write(dataBuffer, 0, e.EventParamsSizes[j]); } } @@ -153,7 +156,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks /// /// The event key data. /// - public struct EventKey + public struct EventKey : ICloneable { /// /// The parameters values. @@ -178,6 +181,26 @@ namespace FlaxEditor.GUI.Timeline.Tracks sb.Append(')'); return sb.ToString(); } + + /// + public object Clone() + { + if (Parameters == null) + return new EventKey(); + + // Deep clone parameter values (especially boxed value types need to be duplicated to avoid referencing the same ones) + var parameters = new object[Parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + var p = Parameters[i]; + if (p == null || p is FlaxEngine.Object) + parameters[i] = Parameters[i]; + else + parameters[i] = JsonSerializer.Deserialize(JsonSerializer.Serialize(p), p.GetType()); + } + + return new EventKey { Parameters = parameters }; + } } /// @@ -234,6 +257,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks var time = Timeline.CurrentTime; if (!TryGetValue(out var value)) value = Events.Evaluate(time); + value = ((ICloneable)value).Clone(); // Find event at the current location for (int i = Events.Keyframes.Count - 1; i >= 0; i--) diff --git a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs index 389041381..32f1575ec 100644 --- a/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/KeyframesPropertyTrack.cs @@ -77,7 +77,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks { var time = stream.ReadSingle(); stream.Read(dataBuffer, 0, e.ValueSize); - var value = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), propertyType); + var value = Utilities.Utils.ByteArrayToStructure(handle.AddrOfPinnedObject(), propertyType, e.ValueSize); keyframes[i] = new KeyframesEditor.Keyframe { @@ -142,8 +142,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks for (int i = 0; i < keyframes.Count; i++) { var keyframe = keyframes[i]; - Marshal.StructureToPtr(keyframe.Value, ptr, true); - Marshal.Copy(ptr, dataBuffer, 0, e.ValueSize); + Utilities.Utils.StructureToByteArray(keyframe.Value, e.ValueSize, ptr, dataBuffer); stream.Write(keyframe.Time); stream.Write(dataBuffer); } diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 949479783..688cec470 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -212,6 +212,10 @@ namespace FlaxEditor.Utilities if (value is FlaxEngine.Object) return value; + // For custom types use interface + if (value is ICloneable clonable) + return clonable.Clone(); + // For objects (eg. arrays) we need to clone them to prevent editing default/reference value within editor if (value != null && (!value.GetType().IsValueType || !value.GetType().IsClass)) { @@ -548,6 +552,26 @@ namespace FlaxEditor.Utilities return arr; } + internal static void StructureToByteArray(object value, int valueSize, IntPtr tempBuffer, byte[] dataBuffer) + { + var valueType = value.GetType(); + if (valueType.IsEnum) + { + var ptr = FlaxEngine.Interop.NativeInterop.ValueTypeUnboxer.GetPointer(value, valueType); + FlaxEngine.Utils.MemoryCopy(tempBuffer, ptr, (ulong)valueSize); + } + else + Marshal.StructureToPtr(value, tempBuffer, true); + Marshal.Copy(tempBuffer, dataBuffer, 0, valueSize); + } + + internal static object ByteArrayToStructure(IntPtr valuePtr, Type valueType, int valueSize) + { + if (valueType.IsEnum) + return FlaxEngine.Interop.NativeInterop.MarshalToManaged(valuePtr, valueType); + return Marshal.PtrToStructure(valuePtr, valueType); + } + internal static unsafe string ReadStr(this BinaryReader stream, int check) { int length = stream.ReadInt32(); From 5eea5a72c99ae10f69cd6f6bf6deb1bbd2ef567d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 22 Sep 2025 11:44:11 +0200 Subject: [PATCH 082/137] Fix particle material compilation error when using position offset #3661 --- Content/Editor/MaterialTemplates/Particle.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader index 6f0be21e0..661a8f69b 100644 --- a/Content/Editor/MaterialTemplates/Particle.shader +++ b/Content/Editor/MaterialTemplates/Particle.shader @@ -645,7 +645,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID) materialInput.TBN = output.TBN; materialInput.TwoSidedSign = 1; materialInput.SvPosition = output.Position; - materialInput.PreSkinnedPosition = Position; + materialInput.PreSkinnedPosition = position; materialInput.PreSkinnedNormal = tangentToLocal[2].xyz; materialInput.InstanceOrigin = output.InstanceOrigin; materialInput.InstanceParams = output.InstanceParams; From 4ae3d57adc531e99cbe9174a07733b8d6035c0c2 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 22 Sep 2025 11:32:24 -0500 Subject: [PATCH 083/137] Resolve code suggestions --- Source/Engine/Audio/AudioSource.cpp | 8 -------- Source/Engine/Audio/AudioSource.h | 5 ++--- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index 069fa29a3..f16f95423 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -588,11 +588,3 @@ void AudioSource::BeginPlay(SceneBeginData* data) SetTime(GetStartTime()); } } - -void AudioSource::EndPlay() -{ - Actor::EndPlay(); - - ClipStarted.UnbindAll(); - ClipFinished.UnbindAll(); -} diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index 4e05d1594..9858d283a 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -79,12 +79,12 @@ public: /// /// Event fired when the audio clip starts. /// - API_EVENT() Delegate<> ClipStarted; + API_EVENT() Action ClipStarted; /// /// Event fired when the audio clip finishes. /// - API_EVENT() Delegate<> ClipFinished; + API_EVENT() Action ClipFinished; /// /// Gets the velocity of the source. Determines pitch in relation to AudioListener's position. Only relevant for spatial (3D) sources. @@ -336,5 +336,4 @@ protected: void OnDisable() override; void OnTransformChanged() override; void BeginPlay(SceneBeginData* data) override; - void EndPlay() override; }; From 70ba750a5e32ee3d2f11ee97d79a95185c4eb529 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 22 Sep 2025 22:31:23 +0200 Subject: [PATCH 084/137] Fix code #3511 --- Source/Engine/Debug/DebugCommands.cpp | 5 +---- Source/Engine/Debug/DebugCommands.h | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Debug/DebugCommands.cpp b/Source/Engine/Debug/DebugCommands.cpp index 9c66341ab..fc568a181 100644 --- a/Source/Engine/Debug/DebugCommands.cpp +++ b/Source/Engine/Debug/DebugCommands.cpp @@ -439,11 +439,8 @@ void DebugCommands::GetAllCommands(Array& commands) { EnsureInited(); ScopeLock lock(Locker); - - for (auto& command : Commands) - { + for (const auto& command : Commands) commands.Add(command.Name); - } } DebugCommands::CommandFlags DebugCommands::GetCommandFlags(StringView command) diff --git a/Source/Engine/Debug/DebugCommands.h b/Source/Engine/Debug/DebugCommands.h index cfe70db73..f25fe0581 100644 --- a/Source/Engine/Debug/DebugCommands.h +++ b/Source/Engine/Debug/DebugCommands.h @@ -49,7 +49,7 @@ public: /// /// Gets all available commands. /// - /// The output list of all commands (unsorted). + /// The output list of all commands (unsorted). API_FUNCTION() static void GetAllCommands(API_PARAM(Out) Array& commands); /// From d8f7199c110af6a7fe7b8f3673e3ec4d0021748b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 23 Sep 2025 15:42:49 +0200 Subject: [PATCH 085/137] Fix importing emissive, roughness, metalness and wireframe properties of materials with Assimp #3418 --- .../ContentImporters/CreateMaterial.cpp | 12 ++++++---- .../Engine/ContentImporters/CreateMaterial.h | 8 +++++++ Source/Engine/Graphics/Models/ModelData.cpp | 2 ++ Source/Engine/Graphics/Models/ModelData.h | 9 ++++++++ .../Tools/ModelTool/ModelTool.Assimp.cpp | 23 ++++++++++++++++++- Source/Engine/Tools/ModelTool/ModelTool.cpp | 14 +++++++++++ 6 files changed, 62 insertions(+), 6 deletions(-) diff --git a/Source/Engine/ContentImporters/CreateMaterial.cpp b/Source/Engine/ContentImporters/CreateMaterial.cpp index 3991585a3..a41d09454 100644 --- a/Source/Engine/ContentImporters/CreateMaterial.cpp +++ b/Source/Engine/ContentImporters/CreateMaterial.cpp @@ -93,14 +93,15 @@ namespace }; template - void AddInput(MaterialLayer* layer, Meta11 meta, MaterialGraphBoxes box, const Guid& texture, const T& value, const T& defaultValue, const Float2& pos, ShaderGraphNode<>** outTextureNode = nullptr) + void AddInput(MaterialLayer* layer, Meta11 meta, MaterialGraphBoxes box, const Guid& texture, const T& value, const T& defaultValue, const Float2& pos, ShaderGraphNode<>** outTextureNode = nullptr, uint8 channel = MAX_uint8) { auto textureNode = AddTextureNode(layer, texture); auto valueNode = AddValueNode(layer, value, defaultValue); + auto textureNodeBox = channel == MAX_uint8 ? 1 : channel + 2; // Color or specific channel (RGBA) if (textureNode && valueNode) { auto diffuseMultiply = AddMultiplyNode(layer); - CONNECT(diffuseMultiply->Boxes[0], textureNode->Boxes[1]); + CONNECT(diffuseMultiply->Boxes[0], textureNode->Boxes[textureNodeBox]); CONNECT(diffuseMultiply->Boxes[1], valueNode->Boxes[0]); CONNECT(layer->Root->Boxes[static_cast(box)], diffuseMultiply->Boxes[2]); SET_POS(valueNode, pos + Float2(-467.7404, 91.41332)); @@ -109,7 +110,7 @@ namespace } else if (textureNode) { - CONNECT(layer->Root->Boxes[static_cast(box)], textureNode->Boxes[1]); + CONNECT(layer->Root->Boxes[static_cast(box)], textureNode->Boxes[textureNodeBox]); SET_POS(textureNode, pos + Float2(-293.5272f, -2.926111f)); } else if (valueNode) @@ -178,8 +179,9 @@ CreateAssetResult CreateMaterial::Create(CreateAssetContext& context) // Opacity AddInput(layer, meta, MaterialGraphBoxes::Opacity, options.Opacity.Texture, options.Opacity.Value, 1.0f, Float2(0, 400)); - // Opacity - AddInput(layer, meta, MaterialGraphBoxes::Roughness, options.Roughness.Texture, options.Roughness.Value, 0.5f, Float2(200, 400)); + // Roughness + Metalness + AddInput(layer, meta, MaterialGraphBoxes::Roughness, options.Roughness.Texture, options.Roughness.Value, 0.5f, Float2(200, 400), nullptr, options.Roughness.Channel); + AddInput(layer, meta, MaterialGraphBoxes::Metalness, options.Metalness.Texture, options.Metalness.Value, 0.0f, Float2(200, 600), nullptr, options.Metalness.Channel); // Normal auto normalMap = AddTextureNode(layer, options.Normals.Texture, true); diff --git a/Source/Engine/ContentImporters/CreateMaterial.h b/Source/Engine/ContentImporters/CreateMaterial.h index 6b37067e8..df0680e18 100644 --- a/Source/Engine/ContentImporters/CreateMaterial.h +++ b/Source/Engine/ContentImporters/CreateMaterial.h @@ -40,9 +40,17 @@ public: struct { float Value = 0.5f; + uint8 Channel = 0; Guid Texture = Guid::Empty; } Roughness; + struct + { + float Value = 0.0f; + uint8 Channel = 0; + Guid Texture = Guid::Empty; + } Metalness; + struct { Guid Texture = Guid::Empty; diff --git a/Source/Engine/Graphics/Models/ModelData.cpp b/Source/Engine/Graphics/Models/ModelData.cpp index 877d8c826..69ae5d9a1 100644 --- a/Source/Engine/Graphics/Models/ModelData.cpp +++ b/Source/Engine/Graphics/Models/ModelData.cpp @@ -372,6 +372,8 @@ bool MaterialSlotEntry::UsesProperties() const Opacity.TextureIndex != -1 || Math::NotNearEqual(Roughness.Value, 0.5f) || Roughness.TextureIndex != -1 || + Math::NotNearEqual(Metalness.Value, 0.5f) || + Metalness.TextureIndex != -1 || Normals.TextureIndex != -1; } diff --git a/Source/Engine/Graphics/Models/ModelData.h b/Source/Engine/Graphics/Models/ModelData.h index 8e401b973..d9167c858 100644 --- a/Source/Engine/Graphics/Models/ModelData.h +++ b/Source/Engine/Graphics/Models/ModelData.h @@ -327,14 +327,23 @@ struct FLAXENGINE_API MaterialSlotEntry { float Value = 0.5f; int32 TextureIndex = -1; + uint8 Channel = 0; } Roughness; + struct + { + float Value = 0.0f; + int32 TextureIndex = -1; + uint8 Channel = 0; + } Metalness; + struct { int32 TextureIndex = -1; } Normals; bool TwoSided = false; + bool Wireframe = false; bool UsesProperties() const; static float ShininessToRoughness(float shininess); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index f5b043994..b1340bfa7 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -528,12 +528,24 @@ bool ImportMaterials(ModelData& result, AssimpImporterData& data, String& errorM aiColor3D aColor; if (aMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aColor) == AI_SUCCESS) materialSlot.Diffuse.Color = ToColor(aColor); + if (aMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, aColor) == AI_SUCCESS) + materialSlot.Emissive.Color = ToColor(aColor); + if (aMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, aColor) == AI_SUCCESS) + materialSlot.Emissive.Color = ToColor(aColor); bool aBoolean; if (aMaterial->Get(AI_MATKEY_TWOSIDED, aBoolean) == AI_SUCCESS) materialSlot.TwoSided = aBoolean; - bool aFloat; + if (aMaterial->Get(AI_MATKEY_ENABLE_WIREFRAME, aBoolean) == AI_SUCCESS) + materialSlot.Wireframe = aBoolean; + float aFloat; if (aMaterial->Get(AI_MATKEY_OPACITY, aFloat) == AI_SUCCESS) materialSlot.Opacity.Value = aFloat; + if (aMaterial->Get(AI_MATKEY_GLOSSINESS_FACTOR, aFloat) == AI_SUCCESS) + materialSlot.Roughness.Value = 1.0f - aFloat; + else if (aMaterial->Get(AI_MATKEY_SHININESS, aFloat) == AI_SUCCESS) + materialSlot.Roughness.Value = MaterialSlotEntry::ShininessToRoughness(aFloat); + if (aMaterial->Get(AI_MATKEY_EMISSIVE_INTENSITY, aFloat) == AI_SUCCESS) + materialSlot.Emissive.Color *= aFloat; if (EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Textures)) { @@ -541,6 +553,15 @@ bool ImportMaterials(ModelData& result, AssimpImporterData& data, String& errorM ImportMaterialTexture(result, data, aMaterial, aiTextureType_EMISSIVE, materialSlot.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, data, aMaterial, aiTextureType_NORMALS, materialSlot.Normals.TextureIndex, TextureEntry::TypeHint::Normals); ImportMaterialTexture(result, data, aMaterial, aiTextureType_OPACITY, materialSlot.Opacity.TextureIndex, TextureEntry::TypeHint::ColorRGBA); + ImportMaterialTexture(result, data, aMaterial, aiTextureType_METALNESS, materialSlot.Metalness.TextureIndex, TextureEntry::TypeHint::ColorRGB); + ImportMaterialTexture(result, data, aMaterial, aiTextureType_DIFFUSE_ROUGHNESS, materialSlot.Roughness.TextureIndex, TextureEntry::TypeHint::ColorRGB); + + if (materialSlot.Roughness.TextureIndex != -1 && (data.Path.EndsWith(TEXT(".gltf")) || data.Path.EndsWith(TEXT(".glb")))) + { + // glTF specification with a single metallicRoughnessTexture (G = roughness, B = metalness) + materialSlot.Roughness.Channel = 1; + materialSlot.Metalness.Channel = 2; + } if (materialSlot.Diffuse.TextureIndex != -1) { diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index e0ee85cac..bddd56296 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1520,6 +1520,9 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option const Char* roughnessNames[] = { TEXT("roughness"), TEXT("rough") }; TrySetupMaterialParameter(materialInstance, ToSpan(roughnessNames, ARRAY_COUNT(roughnessNames)), material.Roughness.Value, MaterialParameterType::Float); TRY_SETUP_TEXTURE_PARAM(Roughness, roughnessNames, Texture); + const Char* metalnessNames[] = { TEXT("metalness"), TEXT("metallic") }; + TrySetupMaterialParameter(materialInstance, ToSpan(metalnessNames, ARRAY_COUNT(metalnessNames)), material.Metalness.Value, MaterialParameterType::Float); + TRY_SETUP_TEXTURE_PARAM(Metalness, metalnessNames, Texture); #undef TRY_SETUP_TEXTURE_PARAM materialInstance->Save(); @@ -1545,11 +1548,22 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option materialOptions.Opacity.Texture = data.Textures[material.Opacity.TextureIndex].AssetID; materialOptions.Roughness.Value = material.Roughness.Value; if (material.Roughness.TextureIndex != -1) + { materialOptions.Roughness.Texture = data.Textures[material.Roughness.TextureIndex].AssetID; + materialOptions.Roughness.Channel = material.Roughness.Channel; + } + materialOptions.Metalness.Value = material.Metalness.Value; + if (material.Metalness.TextureIndex != -1) + { + materialOptions.Metalness.Texture = data.Textures[material.Metalness.TextureIndex].AssetID; + materialOptions.Metalness.Channel = material.Metalness.Channel; + } if (material.Normals.TextureIndex != -1) materialOptions.Normals.Texture = data.Textures[material.Normals.TextureIndex].AssetID; if (material.TwoSided || material.Diffuse.HasAlphaMask) materialOptions.Info.CullMode = CullMode::TwoSided; + if (material.Wireframe) + materialOptions.Info.FeaturesFlags |= MaterialFeaturesFlags::Wireframe; if (!Math::IsOne(material.Opacity.Value) || material.Opacity.TextureIndex != -1) materialOptions.Info.BlendMode = MaterialBlendMode::Transparent; AssetsImportingManager::Create(AssetsImportingManager::CreateMaterialTag, assetPath, material.AssetID, &materialOptions); From 7060cb5696976eb8029e2795b9445160de3df1cc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 23 Sep 2025 17:20:18 +0200 Subject: [PATCH 086/137] Fix UI Brush editing in prefab regression from a471861e9257c426404984b14e53ef61f769c243 #3694 --- Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs index d32f08c92..09670f1b2 100644 --- a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs +++ b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs @@ -180,7 +180,7 @@ namespace FlaxEditor.CustomEditors.Editors // Show prefab diff when reference value type is different var color = Color.Transparent; - if (Values.HasReferenceValue && CanRevertReferenceValue && Values[0].GetType() != Values.ReferenceValue.GetType()) + if (Values.HasReferenceValue && CanRevertReferenceValue && Values[0]?.GetType() != Values.ReferenceValue?.GetType()) color = FlaxEngine.GUI.Style.Current.BackgroundSelected; _typeItem.Labels[0].HighlightStripColor = color; From 797cb3c3f2afefe543f0e22de64e60041e12ead4 Mon Sep 17 00:00:00 2001 From: Saas Date: Tue, 23 Sep 2025 20:56:43 +0200 Subject: [PATCH 087/137] fix 1.10 becoming 1.1 and some spelling issue in issue template --- .github/ISSUE_TEMPLATE/1-bug.yaml | 12 ++++++------ .github/ISSUE_TEMPLATE/2-feature-request.yaml | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1-bug.yaml b/.github/ISSUE_TEMPLATE/1-bug.yaml index acae26c00..4a58ed11d 100644 --- a/.github/ISSUE_TEMPLATE/1-bug.yaml +++ b/.github/ISSUE_TEMPLATE/1-bug.yaml @@ -5,7 +5,7 @@ body: - type: markdown attributes: value: | - Thanks for taking the time to fill out this bug report! Please attach any minimal repoduction projects! + Thanks for taking the time to fill out this bug report! Please attach any minimal reproduction projects! - type: textarea id: description-area attributes: @@ -17,7 +17,7 @@ body: id: steps-area attributes: label: Steps to reproduce - description: Please provide an repoduction steps. + description: Please provide an reproduction steps. validations: required: true - type: dropdown @@ -26,10 +26,10 @@ body: label: Version description: What version of Flax are you running? options: - - 1.8 - - 1.9 - - 1.10 - - 1.11 + - '1.8' + - '1.9' + - '1.10' + - '1.11' - master branch default: 2 validations: diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.yaml b/.github/ISSUE_TEMPLATE/2-feature-request.yaml index 235c863e3..338c9aea0 100644 --- a/.github/ISSUE_TEMPLATE/2-feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/2-feature-request.yaml @@ -14,9 +14,9 @@ body: validations: required: true - type: textarea - id: benifits-area + id: benefits-area attributes: - label: Benifits - description: Please provide what benifits this feature would provide to the engine! + label: Benefits + description: Please provide what benefits this feature would provide to the engine! validations: required: true \ No newline at end of file From d57eec3403e32da4bbf35cdd77cf17321314d01e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 24 Sep 2025 18:26:33 +0200 Subject: [PATCH 088/137] Bump up materials after merge --- Source/Engine/Graphics/Materials/MaterialShader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index 117246671..2d21f5b29 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 175 +#define MATERIAL_GRAPH_VERSION 176 class Material; class GPUShader; From 4a3fb410350194a8bfd0ac574acbcacfeb9d8e8b Mon Sep 17 00:00:00 2001 From: Saas Date: Thu, 25 Sep 2025 13:32:21 +0200 Subject: [PATCH 089/137] further fixes and make some stuff a bit nicer --- .github/ISSUE_TEMPLATE/1-bug.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1-bug.yaml b/.github/ISSUE_TEMPLATE/1-bug.yaml index 4a58ed11d..2e2c65485 100644 --- a/.github/ISSUE_TEMPLATE/1-bug.yaml +++ b/.github/ISSUE_TEMPLATE/1-bug.yaml @@ -10,14 +10,14 @@ body: id: description-area attributes: label: Description - description: Please provide a description and what you expected to happen. + description: Please provide a description of the bug and what you expected to happen. validations: required: true - type: textarea id: steps-area attributes: label: Steps to reproduce - description: Please provide an reproduction steps. + description: Please provide reproduction steps if possible. validations: required: true - type: dropdown From 41e851298dcd4d419d6ffa348b768cd84b6d890d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 25 Sep 2025 17:35:10 +0200 Subject: [PATCH 090/137] Add new PreIntegratedGF with 80% smaller but more accurate data Update old generation code, use R16G16_UNorm format instead of R11G11B10, skip mips and reduce Y axis to 32 pixels. #1492 --- Content/Engine/Textures/PreIntegratedGF.flax | 4 +- Source/Engine/Renderer/ReflectionsPass.cpp | 296 ++++++------------ .../TextureTool/TextureTool.DirectXTex.cpp | 2 + Source/Engine/Tools/TextureTool/TextureTool.h | 4 + .../Tools/TextureTool/TextureTool.stb.cpp | 2 + 5 files changed, 110 insertions(+), 198 deletions(-) diff --git a/Content/Engine/Textures/PreIntegratedGF.flax b/Content/Engine/Textures/PreIntegratedGF.flax index 97783def3..108c92efb 100644 --- a/Content/Engine/Textures/PreIntegratedGF.flax +++ b/Content/Engine/Textures/PreIntegratedGF.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcaf6ab41c5745842a005284259b9ed8eaec73587d73a9e3d7f39086b78ec0e2 -size 87789 +oid sha256:37d0bdbf79b2499b3251a95ffe60702dab1a26a87849fe35e6e47c73f9b46a5e +size 17359 diff --git a/Source/Engine/Renderer/ReflectionsPass.cpp b/Source/Engine/Renderer/ReflectionsPass.cpp index d9e8df3fe..5d5f7f432 100644 --- a/Source/Engine/Renderer/ReflectionsPass.cpp +++ b/Source/Engine/Renderer/ReflectionsPass.cpp @@ -25,219 +25,123 @@ GPU_CB_STRUCT(Data { // https://blog.selfshadow.com/publications/s2015-shading-course/ // https://blog.selfshadow.com/publications/s2012-shading-course/ -#include -#include -#include -#define _USE_MATH_DEFINES -#include +#define COMPILE_WITH_ASSETS_IMPORTER 1 +#define COMPILE_WITH_TEXTURE_TOOL 1 +#include "Engine/Engine/Globals.h" +#include "Engine/Core/Math/Math.h" +#include "Engine/Graphics/Textures/TextureData.h" +#include "Engine/ContentImporters/ImportTexture.h" +#include "Engine/ContentImporters/AssetsImportingManager.h" namespace PreIntegratedGF { - static const int Resolution = 128; - static const int NumSamples = 512; + static const int ResolutionX = 128; + static const int ResolutionY = 32; + static const int NumSamples = 256; - struct vec2 { - double x, y; - vec2(double _x, double _y) :x(_x), y(_y) { }; + Float2 Hammersley(int32 i, int32 sampleCount) + { + float E1 = (float)i / (float)sampleCount; + float E2 = (float)((double)ReverseBits((uint32)i) * 2.3283064365386963e-10); + return Float2(E1, E2); + } - vec2& operator /=(const double& b) + Float3 ImportanceSampleGGX(Float2 E, float roughness) + { + float m = roughness * roughness; + float m2 = m * m; + + float phi = 2 * PI * E.X; + float cosTheta = sqrtf((1 - E.Y) / (1 + (m2 - 1) * E.Y)); + float sinTheta = sqrtf(1 - cosTheta * cosTheta); + + return Float3(sinTheta * cosf(phi), sinTheta * sinf(phi), cosTheta); + } + + float Vis_SmithJointApprox(float roughness, float NoV, float NoL) + { + float a = roughness * roughness; + float Vis_SmithV = NoL * (NoV * (1 - a) + a); + float Vis_SmithL = NoV * (NoL * (1 - a) + a); + return 0.5f / (Vis_SmithV + Vis_SmithL); + } + + Float2 IntegrateBRDF(float roughness, float NoV) + { + if (roughness < 0.04f) roughness = 0.04f; + + Float3 V(sqrtf(1 - NoV * NoV), 0, NoV); + float a = 0, b = 0; + for (int32 i = 0; i < NumSamples; i++) { - x /= b; - y /= b; - return *this; - } - }; + Float2 E = Hammersley(i, NumSamples); + Float3 H = ImportanceSampleGGX(E, roughness); + Float3 L = 2 * Float3::Dot(V, H) * H - V; - struct ivec2 { - int x, y; - }; - - struct vec3 { - double x, y, z; - vec3(double _x, double _y, double _z) :x(_x), y(_y), z(_z) { }; - - double dot(const vec3& b) - { - return x*b.x + y*b.y + z*b.z; - } - }; - - vec3 operator*(const double& a, const vec3& b) - { - return vec3(b.x * a, b.y * a, b.z * a); - } - vec3 operator-(const vec3& a, const vec3& b) - { - return vec3(a.x - b.x, a.y - b.y, a.z - b.z); - } - - inline double saturate(double x) - { - if (x < 0) x = 0; - if (x > 1) x = 1; - return x; - } - - unsigned int ReverseBits32(unsigned int bits) - { - bits = (bits << 16) | (bits >> 16); - bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8); - bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1); - return bits; - } - - inline double rand_0_1() - { - return 1.0 * rand() / RAND_MAX; - } - - inline unsigned int rand_32bit() - { - unsigned int x = rand() & 0xff; - x |= (rand() & 0xff) << 8; - x |= (rand() & 0xff) << 16; - x |= (rand() & 0xff) << 24; - return x; - } - - // using uniform randomness :( - double t1 = rand_0_1(); - unsigned int t2 = rand_32bit(); - vec2 Hammersley(int Index, int NumSamples) - { - double E1 = 1.0 * Index / NumSamples + t1; - E1 = E1 - int(E1); - double E2 = double(ReverseBits32(Index) ^ t2) * 2.3283064365386963e-10; - return vec2(E1, E2); - } - - vec3 ImportanceSampleGGX(vec2 E, double Roughness) - { - double m = Roughness * Roughness; - double m2 = m * m; - - double phi = 2 * PI * E.x; - double cosTheta = sqrt((1 - E.y) / (1 + (m2 - 1) * E.y)); - double sinTheta = sqrt(1 - cosTheta * cosTheta); - - vec3 H(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - double d = (cosTheta * m2 - cosTheta) * cosTheta + 1; - double D = m2 / (M_PI*d*d); - double PDF = D * cosTheta; - - return H; - } - - double Vis_SmithJointApprox(double Roughness, double NoV, double NoL) - { - double a = Roughness * Roughness; - double Vis_SmithV = NoL * (NoV * (1 - a) + a); - double Vis_SmithL = NoV * (NoL * (1 - a) + a); - return 0.5 / (Vis_SmithV + Vis_SmithL); - } - - vec2 IntegrateBRDF(double Roughness, double NoV) - { - if (Roughness < 0.04) Roughness = 0.04; - - vec3 V(sqrt(1 - NoV*NoV), 0, NoV); - double A = 0, B = 0; - for (int i = 0; i < NumSamples; i++) - { - vec2 E = Hammersley(i, NumSamples); - vec3 H = ImportanceSampleGGX(E, Roughness); - vec3 L = 2 * V.dot(H) * H - V; - - double NoL = saturate(L.z); - double NoH = saturate(H.z); - double VoH = saturate(V.dot(H)); + float NoL = Math::Saturate(L.Z); + float NoH = Math::Saturate(H.Z); + float VoH = Math::Saturate(Float3::Dot(V, H)); if (NoL > 0) { - double Vis = Vis_SmithJointApprox(Roughness, NoV, NoL); + float Vis = Vis_SmithJointApprox(roughness, NoV, NoL); + float NoL_Vis_PDF = NoL * Vis * (4 * VoH / NoH); - double a = Roughness * Roughness; - double a2 = a*a; - double Vis_SmithV = NoL * sqrt(NoV * (NoV - NoV * a2) + a2); - double Vis_SmithL = NoV * sqrt(NoL * (NoL - NoL * a2) + a2); - - double NoL_Vis_PDF = NoL * Vis * (4 * VoH / NoH); - - double Fc = pow(1 - VoH, 5); - A += (1 - Fc) * NoL_Vis_PDF; - B += Fc * NoL_Vis_PDF; + float Fc = powf(1 - VoH, 5); + a += NoL_Vis_PDF * (1 - Fc); + b += NoL_Vis_PDF * Fc; } } - vec2 res(A, B); - res /= NumSamples; - return res; + return Float2(a, b) / (float)NumSamples; + } + + bool OnGenerate(TextureData& image) + { + // Setup image + image.Width = ResolutionX; + image.Height = ResolutionY; + image.Depth = 1; + image.Format = PixelFormat::R16G16_UNorm; + image.Items.Resize(1); + image.Items[0].Mips.Resize(1); + auto& mip = image.Items[0].Mips[0]; + mip.RowPitch = 4 * image.Width; + mip.DepthPitch = mip.RowPitch * image.Height; + mip.Lines = image.Height; + mip.Data.Allocate(mip.DepthPitch); + + // Generate GF pairs to be sampled in [NoV, roughness] space + auto pos = (uint16*)mip.Data.Get(); + for (int32 y = 0; y < image.Height; y++) + { + float roughness = ((float)y + 0.5f) / (float)image.Height; + for (int32 x = 0; x < image.Width; x++) + { + float NoV = ((float)x + 0.5f) / (float)image.Width; + Float2 brdf = IntegrateBRDF(roughness, NoV); + *pos++ = (uint16)(Math::Saturate(brdf.X) * MAX_uint16 + 0.5f); + *pos++ = (uint16)(Math::Saturate(brdf.Y) * MAX_uint16 + 0.5f); + } + } + + return false; } void Generate() { - String path = Globals::TemporaryFolder / TEXT("PreIntegratedGF.bmp"); - - FILE* pFile = fopen(path.ToSTD().c_str(), "wb"); - - byte data[Resolution * 3 * Resolution]; - int c = 0; - for (int x = 0; x < Resolution; x++) - { - for (int y = 0; y < Resolution; y++) - { - vec2 brdf = IntegrateBRDF(1 - 1.0 * x / (Resolution - 1), 1.0 * y / (Resolution - 1)); - data[c + 2] = byte(brdf.x * 255); - data[c + 1] = byte(brdf.y * 255); - data[c + 0] = 0; - c += 3; - } - } - - BITMAPINFOHEADER BMIH; - BMIH.biSize = sizeof(BITMAPINFOHEADER); - BMIH.biSizeImage = Resolution * Resolution * 3; - BMIH.biSize = sizeof(BITMAPINFOHEADER); - BMIH.biWidth = Resolution; - BMIH.biHeight = Resolution; - BMIH.biPlanes = 1; - BMIH.biBitCount = 24; - BMIH.biCompression = BI_RGB; - BMIH.biSizeImage = Resolution * Resolution * 3; - - BITMAPFILEHEADER bmfh; - int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize; - LONG lImageSize = BMIH.biSizeImage; - LONG lFileSize = nBitsOffset + lImageSize; - - bmfh.bfType = 'B' + ('M' << 8); - bmfh.bfOffBits = nBitsOffset; - bmfh.bfSize = lFileSize; - bmfh.bfReserved1 = bmfh.bfReserved2 = 0; - - //Write the bitmap file header - UINT nWrittenFileHeaderSize = fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER), pFile); - - //And then the bitmap info header - UINT nWrittenInfoHeaderSize = fwrite(&BMIH, 1, sizeof(BITMAPINFOHEADER), pFile); - - //Finally, write the image data itself - - //-- the data represents our drawing - UINT nWrittenDIBDataSize = fwrite(data, 1, lImageSize, pFile); - - fclose(pFile); - - Guid id; - Importers::TextureImportArgument arg; - arg.Options.Type = FormatType::HdrRGB; - arg.Options.IndependentChannels = true; - arg.Options.IsAtlas = false; - arg.Options.IsSRGB = false; - arg.Options.NeverStream = true; - Content::Import(path, Globals:... + PRE_INTEGRATED_GF_ASSET_NAME, &id, &arg); + Guid id = Guid::Empty; + ImportTexture::Options options; + options.Type = TextureFormatType::HdrRGB; + options.InternalFormat = PixelFormat::R16G16_UNorm; + options.IndependentChannels = true; + options.IsAtlas = false; + options.sRGB = false; + options.NeverStream = true; + options.GenerateMipMaps = false; + options.Compress = false; + options.InternalLoad.Bind(&OnGenerate); + const String path = Globals::EngineContentFolder / PRE_INTEGRATED_GF_ASSET_NAME + ASSET_FILES_EXTENSION_WITH_DOT; + AssetsImportingManager::Create(AssetsImportingManager::CreateTextureTag, path, id, &options); } }; diff --git a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp index bf74213d4..d7199a470 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp @@ -707,6 +707,8 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path PixelFormat targetFormat = TextureTool::ToPixelFormat(options.Type, width, height, options.Compress); if (options.sRGB) targetFormat = PixelFormatExtensions::TosRGB(targetFormat); + if (options.InternalFormat != PixelFormat::Unknown) + targetFormat = options.InternalFormat; DXGI_FORMAT targetDxgiFormat = ToDxgiFormat(targetFormat); // Check mip levels diff --git a/Source/Engine/Tools/TextureTool/TextureTool.h b/Source/Engine/Tools/TextureTool/TextureTool.h index aa26283ff..97199680c 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.h +++ b/Source/Engine/Tools/TextureTool/TextureTool.h @@ -121,6 +121,10 @@ API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API TextureTool API_FIELD(Attributes="HideInEditor") Array Sprites; + // The custom format to use. Can be used to override default format from texture Type. + API_FIELD(Attributes="HideInEditor") + PixelFormat InternalFormat = PixelFormat::Unknown; + // Function used for fast importing textures used by internal parts of the engine Function InternalLoad; diff --git a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp index f8f012c15..b88bc4ef3 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp @@ -527,6 +527,8 @@ bool TextureTool::ImportTextureStb(ImageType type, const StringView& path, Textu PixelFormat targetFormat = ToPixelFormat(options.Type, width, height, options.Compress); if (options.sRGB) targetFormat = PixelFormatExtensions::TosRGB(targetFormat); + if (options.InternalFormat != PixelFormat::Unknown) + targetFormat = options.InternalFormat; // Check mip levels int32 sourceMipLevels = textureDataSrc->GetMipLevels(); From 02c5ad3fa428e625e69d7ef8892833fbd07fb1e4 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 25 Sep 2025 18:38:46 +0200 Subject: [PATCH 091/137] Fix particles to support any amount of contexts drawings --- .../Engine/Networking/NetworkReplicationHierarchy.h | 2 +- Source/Engine/Particles/Particles.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Networking/NetworkReplicationHierarchy.h b/Source/Engine/Networking/NetworkReplicationHierarchy.h index 7e9978635..9db851996 100644 --- a/Source/Engine/Networking/NetworkReplicationHierarchy.h +++ b/Source/Engine/Networking/NetworkReplicationHierarchy.h @@ -69,7 +69,7 @@ API_STRUCT(NoDefault, Namespace="FlaxEngine.Networking") struct FLAXENGINE_API N API_FIELD() uint64 Word1 = 0; // All bits set for all clients. - API_FIELD() static NetworkClientsMask All; + API_FIELD(ReadOnly) static NetworkClientsMask All; FORCE_INLINE bool HasBit(int32 bitIndex) const { diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index bfbf35f29..487bc4b03 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -1146,8 +1146,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf bounds.Center -= viewOrigin; // Cull particles against all views - uint64 viewsMask = 0; - ASSERT_LOW_LAYER(renderContextBatch.Contexts.Count() <= 64); + bool drawAnyView = false, drawMainView = false; DrawPass viewsDrawModes = DrawPass::None; for (int32 i = 0; i < renderContextBatch.Contexts.Count(); i++) { @@ -1155,11 +1154,12 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf const bool visible = (view.Pass & effect->DrawModes) != DrawPass::None && (view.IsCullingDisabled || view.CullingFrustum.Intersects(bounds)); if (visible) { - viewsMask |= 1ull << (uint64)i; + drawAnyView = true; + drawMainView |= i == 0; viewsDrawModes |= view.Pass; } } - if (viewsMask == 0) + if (drawAnyView == false) return; viewsDrawModes &= effect->DrawModes; @@ -1175,7 +1175,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf const int8 sortOrder = effect->SortOrder; // Draw lights (only to into the main view) - if ((viewsMask & 1) == 1 && renderContextBatch.GetMainContext().View.Pass != DrawPass::Depth) + if (drawMainView && renderContextBatch.GetMainContext().View.Pass != DrawPass::Depth) { for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++) { @@ -1275,7 +1275,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf !material->IsReady() || material->GetInfo().Domain != MaterialDomain::VolumeParticle || (renderContextBatch.GetMainContext().View.Flags & ViewFlags::Fog) == ViewFlags::None || - (viewsMask & 1) == 0 + drawMainView ) break; renderModulesIndices |= 1u << moduleIndex; From 537d8b57ca2457496322754fdc3e630d16fe28a3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 26 Sep 2025 22:25:49 +0200 Subject: [PATCH 092/137] Revert "Merge branch 'NoClearSearchboxesWhenStuffHappens' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-NoClearSearchboxesWhenStuffHappens" This reverts commit 1186833b2d98cd2b25c91a60436abb3635a0f02b, reversing changes made to bb180b0f59d4e075c7c8ed3fb041c1e2fd1599a3. #3687 #3701 --- Source/Editor/Windows/ContentWindow.Search.cs | 1 - Source/Editor/Windows/ContentWindow.cs | 2 -- Source/Editor/Windows/SceneTreeWindow.cs | 7 +------ 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs index 5a0ed63aa..f28dc4834 100644 --- a/Source/Editor/Windows/ContentWindow.Search.cs +++ b/Source/Editor/Windows/ContentWindow.Search.cs @@ -115,7 +115,6 @@ namespace FlaxEditor.Windows var root = _root; root.LockChildrenRecursive(); - PerformLayout(); // Update tree var query = _foldersSearchBox.Text; diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index d0cf84251..3d2ec4a66 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -1085,8 +1085,6 @@ namespace FlaxEditor.Windows if (Editor.ContentDatabase.Find(_lastViewedFolderBeforeReload) is ContentFolder folder) _tree.Select(folder.Node); } - - OnFoldersSearchBoxTextChanged(); } private void Refresh() diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs index ab6d2e262..75a3723cf 100644 --- a/Source/Editor/Windows/SceneTreeWindow.cs +++ b/Source/Editor/Windows/SceneTreeWindow.cs @@ -68,7 +68,6 @@ namespace FlaxEditor.Windows TooltipText = "Search the scene tree.\n\nYou can prefix your search with different search operators:\ns: -> Actor with script of type\na: -> Actor type\nc: -> Control type", }; _searchBox.TextChanged += OnSearchBoxTextChanged; - ScriptsBuilder.ScriptsReloadEnd += OnSearchBoxTextChanged; // Scene tree panel _sceneTreePanel = new Panel @@ -113,7 +112,7 @@ namespace FlaxEditor.Windows InputActions.Add(options => options.LockFocusSelection, () => Editor.Windows.EditWin.Viewport.LockFocusSelection()); InputActions.Add(options => options.Rename, RenameSelection); } - + /// public override void OnPlayBeginning() { @@ -126,7 +125,6 @@ namespace FlaxEditor.Windows { base.OnPlayBegin(); _blockSceneTreeScroll = false; - OnSearchBoxTextChanged(); } /// @@ -141,7 +139,6 @@ namespace FlaxEditor.Windows { base.OnPlayEnd(); _blockSceneTreeScroll = true; - OnSearchBoxTextChanged(); } /// @@ -177,7 +174,6 @@ namespace FlaxEditor.Windows return; _tree.LockChildrenRecursive(); - PerformLayout(); // Update tree var query = _searchBox.Text; @@ -603,7 +599,6 @@ namespace FlaxEditor.Windows _dragHandlers = null; _tree = null; _searchBox = null; - ScriptsBuilder.ScriptsReloadEnd -= OnSearchBoxTextChanged; base.OnDestroy(); } From 0848f1fa83d73efdb751c838508caafc2a518c02 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 15:43:55 +0200 Subject: [PATCH 093/137] Refactor specular lighting to properly map specular as reflectance in BRDF Reference: https://google.github.io/filament/Filament.md.html #1492 --- Source/Engine/Content/Assets/Material.cpp | 47 +++++++++++++++++-- .../Graphics/Materials/MaterialShader.h | 2 +- .../MaterialGenerator.Material.cpp | 8 ++-- Source/Shaders/BRDF.hlsl | 6 +++ Source/Shaders/GBufferCommon.hlsl | 18 +++---- Source/Shaders/Lighting.hlsl | 1 + Source/Shaders/Reflections.shader | 2 - Source/Shaders/SSR.shader | 2 - 8 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Source/Engine/Content/Assets/Material.cpp b/Source/Engine/Content/Assets/Material.cpp index 1e36b36ae..019fd9dd8 100644 --- a/Source/Engine/Content/Assets/Material.cpp +++ b/Source/Engine/Content/Assets/Material.cpp @@ -190,16 +190,55 @@ Asset::LoadResult Material::load() // Load layer layer = MaterialLayer::Load(GetID(), &stream, _shaderHeader.Material.Info, name); - if (ContentDeprecated::Clear()) + const bool upgradeOldSpecular = _shaderHeader.Material.GraphVersion < 177; + if (ContentDeprecated::Clear() || upgradeOldSpecular) { // If encountered any deprecated data when loading graph then serialize it MaterialGraph graph; MemoryWriteStream writeStream(1024); stream.SetPosition(0); - if (!graph.Load(&stream, true) && !graph.Save(&writeStream, true)) + if (!graph.Load(&stream, true)) { - surfaceChunk->Data.Copy(ToSpan(writeStream)); - ContentDeprecated::Clear(); + if (upgradeOldSpecular) + { + // [Deprecated in 1.11] + // Specular calculations were changed to support up to 16% of reflectance via ^2 curve instead of linear up to 8% + // Insert Custom Code node that converts old materials into a new system to ensure they look the same + MaterialGraph::Node* rootNode = nullptr; + for (auto& e : graph.Nodes) + { + if (e.Type == ROOT_NODE_TYPE) + { + rootNode = &e; + break; + } + } + const auto& specularBoxInfo = MaterialGenerator::GetMaterialRootNodeBox(MaterialGraphBoxes::Specular); + auto specularBox = rootNode ? rootNode->GetBox(specularBoxInfo.ID) : nullptr; + if (specularBox && specularBox->HasConnection()) + { + auto& customCodeNode = graph.Nodes.AddOne(); + customCodeNode.ID = graph.Nodes.Count() + 1000; + customCodeNode.Type = GRAPH_NODE_MAKE_TYPE(1, 8); + customCodeNode.Boxes.Resize(2); + customCodeNode.Boxes[0] = MaterialGraphBox(&customCodeNode, 0, VariantType::Float4); // Input0 + customCodeNode.Boxes[1] = MaterialGraphBox(&customCodeNode, 8, VariantType::Float4); // Output0 + customCodeNode.Values.Resize(1); + customCodeNode.Values[0] = TEXT("// Convert old Specular value to a new range\nOutput0.x = min(Input0.x * 0.5f, 0.6f);"); + auto specularSourceBox = specularBox->Connections[0]; + specularBox->Connections.Clear(); + specularSourceBox->Connections.Clear(); +#define CONNECT(boxA, boxB) boxA->Connections.Add(boxB); boxB->Connections.Add(boxA) + CONNECT(specularSourceBox, (&customCodeNode.Boxes[0])); // Specular -> Input0 + CONNECT((&customCodeNode.Boxes[1]), specularBox); // Output0 -> Specular +#undef CONNECT + } + } + if (!graph.Save(&writeStream, true)) + { + surfaceChunk->Data.Copy(ToSpan(writeStream)); + ContentDeprecated::Clear(); + } } } } diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index 2d21f5b29..c45fd3748 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 176 +#define MATERIAL_GRAPH_VERSION 177 class Material; class GPUShader; diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp index cdf5d4b35..4594446ec 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp @@ -106,7 +106,7 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) Value values[OutputsMax]; for (int32 i = 0; i < OutputsMax; i++) { - const auto outputBox = node->GetBox(Output0BoxID + i); + const auto outputBox = node->TryGetBox(Output0BoxID + i); if (outputBox && outputBox->HasConnection()) { values[i] = writeLocal(VariantType::Float4, node); @@ -119,7 +119,7 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) for (int32 i = 0; i < InputsMax; i++) { auto inputName = TEXT("Input") + StringUtils::ToString(i); - const auto inputBox = node->GetBox(Input0BoxID + i); + const auto inputBox = node->TryGetBox(Input0BoxID + i); if (inputBox && inputBox->HasConnection()) { auto inputValue = tryGetValue(inputBox, Value::Zero); @@ -131,7 +131,7 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) for (int32 i = 0; i < OutputsMax; i++) { auto outputName = TEXT("Output") + StringUtils::ToString(i); - const auto outputBox = node->GetBox(Output0BoxID + i); + const auto outputBox = node->TryGetBox(Output0BoxID + i); if (outputBox && outputBox->HasConnection()) { code.Replace(*outputName, *values[i].Value, StringSearchCase::CaseSensitive); @@ -146,7 +146,7 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) // Link output values to boxes for (int32 i = 0; i < OutputsMax; i++) { - const auto outputBox = node->GetBox(Output0BoxID + i); + const auto outputBox = node->TryGetBox(Output0BoxID + i); if (outputBox && outputBox->HasConnection()) { outputBox->Cache = values[i]; diff --git a/Source/Shaders/BRDF.hlsl b/Source/Shaders/BRDF.hlsl index 9eed9a670..37aa36e42 100644 --- a/Source/Shaders/BRDF.hlsl +++ b/Source/Shaders/BRDF.hlsl @@ -58,6 +58,12 @@ float3 F_Schlick(float3 specularColor, float VoH) return saturate(50.0 * specularColor.g) * fc + (1 - fc) * specularColor; } +float3 F_Schlick(float3 f0, float3 f90, float VoH) +{ + float fc = Pow5(1 - VoH); + return f90 * fc + (1 - fc) * f0; +} + #define REFLECTION_CAPTURE_NUM_MIPS 7 #define REFLECTION_CAPTURE_ROUGHEST_MIP 1 #define REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE 1.2 diff --git a/Source/Shaders/GBufferCommon.hlsl b/Source/Shaders/GBufferCommon.hlsl index 346c9c24a..678168220 100644 --- a/Source/Shaders/GBufferCommon.hlsl +++ b/Source/Shaders/GBufferCommon.hlsl @@ -27,26 +27,28 @@ bool IsSubsurfaceMode(int shadingModel) return shadingModel == SHADING_MODEL_SUBSURFACE || shadingModel == SHADING_MODEL_FOLIAGE; } -float3 GetDiffuseColor(in float3 color, in float metalness) +float3 GetDiffuseColor(float3 color, float metalness) { - return color - color * metalness; + return color * (1.0 - metalness); } -float3 GetSpecularColor(in float3 color, in float specular, in float metalness) +// [https://google.github.io/filament/Filament.md.html] +float3 GetSpecularColor(float3 color, float specular, float metalness) { - return lerp(0.08 * specular.xxx, color.rgb, metalness.xxx); + float dielectricF0 = 0.16 * specular * specular; + return lerp(dielectricF0.xxx, color, metalness.xxx); } // Calculate material diffuse color -float3 GetDiffuseColor(in GBufferSample gBuffer) +float3 GetDiffuseColor(GBufferSample gBuffer) { - return gBuffer.Color - gBuffer.Color * gBuffer.Metalness; + return GetDiffuseColor(gBuffer.Color, gBuffer.Metalness); } // Calculate material specular color -float3 GetSpecularColor(in GBufferSample gBuffer) +float3 GetSpecularColor(GBufferSample gBuffer) { - return lerp(0.08 * gBuffer.Specular.xxx, gBuffer.Color.rgb, gBuffer.Metalness.xxx); + return GetSpecularColor(gBuffer.Color, gBuffer.Specular, gBuffer.Metalness); } // Compact Normal Storage for Small G-Buffers diff --git a/Source/Shaders/Lighting.hlsl b/Source/Shaders/Lighting.hlsl index 4d6e474fa..2e3f9dc76 100644 --- a/Source/Shaders/Lighting.hlsl +++ b/Source/Shaders/Lighting.hlsl @@ -31,6 +31,7 @@ LightSample StandardShading(GBufferSample gBuffer, float energy, float3 L, float float3 F = F_Schlick(specularColor, VoH); float D = D_GGX(gBuffer.Roughness, NoH) * energy; float Vis = Vis_SmithJointApprox(gBuffer.Roughness, NoV, NoL); + // TODO: apply energy compensation to specular (1.0 + specularColor * (1.0 / PreIntegratedGF.y - 1.0)) lighting.Specular = (D * Vis) * F; #endif lighting.Transmission = 0; diff --git a/Source/Shaders/Reflections.shader b/Source/Shaders/Reflections.shader index 1ae38f0eb..dd0b695e5 100644 --- a/Source/Shaders/Reflections.shader +++ b/Source/Shaders/Reflections.shader @@ -78,8 +78,6 @@ float4 PS_CombinePass(Quad_VS2PS input) : SV_Target0 // Calculate specular color float3 specularColor = GetSpecularColor(gBuffer); - if (gBuffer.Metalness < 0.001) - specularColor = 0.04f * gBuffer.Specular; // Calculate reflecion color float3 V = normalize(gBufferData.ViewPos - gBuffer.WorldPos); diff --git a/Source/Shaders/SSR.shader b/Source/Shaders/SSR.shader index e13ae9611..3a7f52f7c 100644 --- a/Source/Shaders/SSR.shader +++ b/Source/Shaders/SSR.shader @@ -83,8 +83,6 @@ float4 PS_CombinePass(Quad_VS2PS input) : SV_Target0 // Calculate specular color float3 specularColor = GetSpecularColor(gBuffer); - if (gBuffer.Metalness < 0.001) - specularColor = 0.04f * gBuffer.Specular; // Calculate reflection color float3 V = normalize(gBufferData.ViewPos - gBuffer.WorldPos); From f09d6aa0ebaf174b8cad9f6fa530c034b773ff21 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 15:44:34 +0200 Subject: [PATCH 094/137] Fix fog rendering bug on d3d11/d3d10 --- .../Editor/MaterialTemplates/Features/ForwardShading.hlsl | 8 +++++++- .../Engine/Graphics/Materials/MaterialShaderFeatures.cpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl index 92f3bfd30..123201d1e 100644 --- a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -152,7 +152,13 @@ void PS_Forward( #if USE_FOG && MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT // Calculate exponential height fog - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z); +#if DIRECTX && FEATURE_LEVEL < FEATURE_LEVEL_SM6 + // TODO: fix D3D11/D3D10 bug with incorrect distance + float fogSceneDistance = distance(materialInput.WorldPosition, ViewPos); +#else + float fogSceneDistance = gBuffer.ViewPos.z; +#endif + float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, fogSceneDistance); if (ExponentialHeightFog.VolumetricFogMaxDistance > 0) { diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index a140fb577..64dfe8303 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -43,6 +43,9 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanBindSR(volumetricFogTextureRegisterIndex, volumetricFogTexture); From 2a5898c1de858b3499f2afadc08f15d4fb999417 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 15:45:24 +0200 Subject: [PATCH 095/137] Fix regression from #3342 to use existing time as unscaled to match previous content --- Content/Editor/MaterialTemplates/GUI.shader | 2 +- Content/Editor/MaterialTemplates/PostProcess.shader | 2 +- Source/Editor/Surface/Archetypes/Tools.cs | 2 +- .../Engine/Graphics/Materials/GUIMaterialShader.cpp | 4 ++-- Source/Engine/Graphics/Materials/IMaterial.h | 2 +- Source/Engine/Graphics/Materials/MaterialShader.cpp | 12 ++++++------ .../Graphics/Materials/PostFxMaterialShader.cpp | 4 ++-- .../MaterialGenerator/MaterialGenerator.Tools.cpp | 2 +- .../Tools/MaterialGenerator/MaterialGenerator.cpp | 2 +- .../Tools/MaterialGenerator/MaterialGenerator.h | 2 +- Source/Shaders/MaterialCommon.hlsl | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Content/Editor/MaterialTemplates/GUI.shader b/Content/Editor/MaterialTemplates/GUI.shader index 69b6d3539..22da15796 100644 --- a/Content/Editor/MaterialTemplates/GUI.shader +++ b/Content/Editor/MaterialTemplates/GUI.shader @@ -21,7 +21,7 @@ float4 ViewInfo; float4 ScreenSize; float4 ViewSize; float3 ViewPadding0; -float UnscaledTimeParam; +float ScaledTimeParam; @1META_CB_END // Shader resources diff --git a/Content/Editor/MaterialTemplates/PostProcess.shader b/Content/Editor/MaterialTemplates/PostProcess.shader index 753ccb253..1ef747ecb 100644 --- a/Content/Editor/MaterialTemplates/PostProcess.shader +++ b/Content/Editor/MaterialTemplates/PostProcess.shader @@ -20,7 +20,7 @@ float4 ScreenSize; float4 TemporalAAJitter; float4x4 InverseViewProjectionMatrix; float3 ViewPadding0; -float UnscaledTimeParam; +float ScaledTimeParam; @1META_CB_END // Shader resources diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs index 091fbe48f..aacebd189 100644 --- a/Source/Editor/Surface/Archetypes/Tools.cs +++ b/Source/Editor/Surface/Archetypes/Tools.cs @@ -1390,7 +1390,7 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Output(0, "Time", typeof(float), 0), - NodeElementArchetype.Factory.Output(1, "Unscaled Time", typeof(float), 1), + NodeElementArchetype.Factory.Output(1, "Scaled Time", typeof(float), 1), } }, new NodeArchetype diff --git a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp index 874694702..834fc35fd 100644 --- a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp @@ -24,7 +24,7 @@ PACK_STRUCT(struct GUIMaterialShaderData { Float4 ScreenSize; Float4 ViewSize; Float3 ViewPadding0; - float UnscaledTimeParam; + float ScaledTimeParam; }); void GUIMaterialShader::Bind(BindParameters& params) @@ -58,7 +58,7 @@ void GUIMaterialShader::Bind(BindParameters& params) materialData->ViewFar = 0.0f; materialData->ViewDir = Float3::Forward; materialData->TimeParam = params.Time; - materialData->UnscaledTimeParam = params.UnscaledTime; + materialData->ScaledTimeParam = params.ScaledTime; materialData->ViewInfo = Float4::Zero; auto& viewport = Render2D::GetViewport(); materialData->ScreenSize = Float4(viewport.Width, viewport.Height, 1.0f / viewport.Width, 1.0f / viewport.Height); diff --git a/Source/Engine/Graphics/Materials/IMaterial.h b/Source/Engine/Graphics/Materials/IMaterial.h index cd2b7a1e8..40d197ddb 100644 --- a/Source/Engine/Graphics/Materials/IMaterial.h +++ b/Source/Engine/Graphics/Materials/IMaterial.h @@ -148,7 +148,7 @@ public: const ::DrawCall* DrawCall = nullptr; MaterialParamsLink* ParamsLink = nullptr; void* CustomData = nullptr; - float Time, UnscaledTime; + float Time, ScaledTime; bool Instanced = false; /// diff --git a/Source/Engine/Graphics/Materials/MaterialShader.cpp b/Source/Engine/Graphics/Materials/MaterialShader.cpp index f1e9fd542..5d929320d 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShader.cpp @@ -38,14 +38,14 @@ GPU_CB_STRUCT(MaterialShaderDataPerView { Float3 LargeWorldsChunkIndex; float LargeWorldsChunkSize; Float3 ViewPadding0; - float UnscaledTimeParam; + float ScaledTimeParam; }); IMaterial::BindParameters::BindParameters(::GPUContext* context, const ::RenderContext& renderContext) : GPUContext(context) , RenderContext(renderContext) - , Time(Time::Draw.Time.GetTotalSeconds()) - , UnscaledTime(Time::Draw.UnscaledTime.GetTotalSeconds()) + , Time(Time::Draw.UnscaledTime.GetTotalSeconds()) + , ScaledTime(Time::Draw.Time.GetTotalSeconds()) { } @@ -53,8 +53,8 @@ IMaterial::BindParameters::BindParameters(::GPUContext* context, const ::RenderC : GPUContext(context) , RenderContext(renderContext) , DrawCall(&drawCall) - , Time(Time::Draw.Time.GetTotalSeconds()) - , UnscaledTime(Time::Draw.UnscaledTime.GetTotalSeconds()) + , Time(Time::Draw.UnscaledTime.GetTotalSeconds()) + , ScaledTime(Time::Draw.Time.GetTotalSeconds()) , Instanced(instanced) { } @@ -83,7 +83,7 @@ void IMaterial::BindParameters::BindViewData() cb.ViewFar = view.Far; cb.ViewDir = view.Direction; cb.TimeParam = Time; - cb.UnscaledTimeParam = UnscaledTime; + cb.ScaledTimeParam = ScaledTime; cb.ViewInfo = view.ViewInfo; cb.ScreenSize = view.ScreenSize; cb.TemporalAAJitter = view.TemporalAAJitter; diff --git a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp index c82dd7447..ee7a41853 100644 --- a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp @@ -22,7 +22,7 @@ PACK_STRUCT(struct PostFxMaterialShaderData { Float4 TemporalAAJitter; Matrix InverseViewProjectionMatrix; Float3 ViewPadding0; - float UnscaledTimeParam; + float ScaledTimeParam; }); void PostFxMaterialShader::Bind(BindParameters& params) @@ -54,7 +54,7 @@ void PostFxMaterialShader::Bind(BindParameters& params) materialData->ViewFar = view.Far; materialData->ViewDir = view.Direction; materialData->TimeParam = params.Time; - materialData->UnscaledTimeParam = params.UnscaledTime; + materialData->ScaledTimeParam = params.ScaledTime; materialData->ViewInfo = view.ViewInfo; materialData->ScreenSize = view.ScreenSize; materialData->TemporalAAJitter = view.TemporalAAJitter; diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Tools.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Tools.cpp index 056ddd7ce..3388c965f 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Tools.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Tools.cpp @@ -48,7 +48,7 @@ void MaterialGenerator::ProcessGroupTools(Box* box, Node* node, Value& value) } // Time case 3: - value = box->ID == 1 ? getUnscaledTime : getTime; + value = box->ID == 1 ? getScaledTime : getTime; break; // Panner case 6: diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index 9c42d1865..b2c998410 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -107,7 +107,7 @@ bool FeatureData::Init() MaterialValue MaterialGenerator::getUVs(VariantType::Float2, TEXT("input.TexCoord")); MaterialValue MaterialGenerator::getTime(VariantType::Float, TEXT("TimeParam")); -MaterialValue MaterialGenerator::getUnscaledTime(VariantType::Float, TEXT("UnscaledTimeParam")); +MaterialValue MaterialGenerator::getScaledTime(VariantType::Float, TEXT("ScaledTimeParam")); MaterialValue MaterialGenerator::getNormal(VariantType::Float3, TEXT("input.TBN[2]")); MaterialValue MaterialGenerator::getNormalZero(VariantType::Float3, TEXT("float3(0, 0, 1)")); MaterialValue MaterialGenerator::getVertexColor(VariantType::Float4, TEXT("GetVertexColor(input)")); diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h index 706929d75..d80e1e359 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.h @@ -210,7 +210,7 @@ public: static MaterialValue getUVs; static MaterialValue getTime; - static MaterialValue getUnscaledTime; + static MaterialValue getScaledTime; static MaterialValue getNormal; static MaterialValue getNormalZero; static MaterialValue getVertexColor; diff --git a/Source/Shaders/MaterialCommon.hlsl b/Source/Shaders/MaterialCommon.hlsl index 897b01d7e..02f754c94 100644 --- a/Source/Shaders/MaterialCommon.hlsl +++ b/Source/Shaders/MaterialCommon.hlsl @@ -177,7 +177,7 @@ cbuffer ViewData : register(b1) float3 LargeWorldsChunkIndex; float LargeWorldsChunkSize; float3 ViewPadding0; - float UnscaledTimeParam; + float ScaledTimeParam; }; #endif From c46e1164d60ab37b991a56cc32624da106d478f1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 15:45:45 +0200 Subject: [PATCH 096/137] Add hot-reload support for material feature template sources on material generation --- .../MaterialGenerator/MaterialGenerator.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index b2c998410..46368cf73 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -5,6 +5,7 @@ #include "MaterialGenerator.h" #include "Engine/Visject/ShaderGraphUtilities.h" #include "Engine/Platform/File.h" +#include "Engine/Platform/FileSystem.h" #include "Engine/Graphics/Materials/MaterialShader.h" #include "Engine/Graphics/Materials/MaterialShaderFeatures.h" #include "Engine/Engine/Globals.h" @@ -47,9 +48,11 @@ enum class FeatureTemplateInputsMapping struct FeatureData { MaterialShaderFeature::GeneratorData Data; + DateTime FileTime; String Inputs[(int32)FeatureTemplateInputsMapping::MAX]; bool Init(); + void CheckReload(); }; namespace @@ -69,6 +72,7 @@ bool FeatureData::Init() LOG(Error, "Cannot open file {0}", path); return true; } + FileTime = FileSystem::GetFileLastEditTime(path); int32 i = 0; const int32 length = contents.Length(); @@ -105,6 +109,20 @@ bool FeatureData::Init() return false; } +void FeatureData::CheckReload() +{ +#if COMPILE_WITH_DEV_ENV + // Reload if template has been modified + const String path = Globals::EngineContentFolder / TEXT("Editor/MaterialTemplates/") + Data.Template; + if (FileTime < FileSystem::GetFileLastEditTime(path)) + { + for (auto& e : Inputs) + e.Clear(); + Init(); + } +#endif +} + MaterialValue MaterialGenerator::getUVs(VariantType::Float2, TEXT("input.TexCoord")); MaterialValue MaterialGenerator::getTime(VariantType::Float, TEXT("TimeParam")); MaterialValue MaterialGenerator::getScaledTime(VariantType::Float, TEXT("ScaledTimeParam")); @@ -183,7 +201,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo type::Generate(feature.Data); \ if (feature.Init()) \ return true; \ - } \ + } else if (COMPILE_WITH_DEV_ENV) Features[typeName].CheckReload(); \ } const bool isOpaque = materialInfo.BlendMode == MaterialBlendMode::Opaque; switch (baseLayer->Domain) From 086a49f45d231f41457369257b8215cc562a7c1e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 15:46:06 +0200 Subject: [PATCH 097/137] Fix deadlock when updating Text Render layout during scene rendering --- Source/Engine/Level/Scene/SceneRendering.cpp | 27 ++++++++++++-------- Source/Engine/Level/Scene/SceneRendering.h | 3 +++ Source/Engine/UI/TextRender.cpp | 2 +- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp index fac756af8..dc3a57ea8 100644 --- a/Source/Engine/Level/Scene/SceneRendering.cpp +++ b/Source/Engine/Level/Scene/SceneRendering.cpp @@ -191,20 +191,25 @@ void SceneRendering::AddActor(Actor* a, int32& key) void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::UpdateFlags flags) { const int32 category = a->_drawCategory; - ScopeReadLock lock(Locker); // Read-access only as list doesn't get resized (like Add/Remove do) so allow updating actors from different threads at once + bool lock = !_isRendering || ((int32)flags & (int32)ISceneRenderingListener::AutoDelayDuringRendering) == 0; // Allow updating actors during rendering + if (lock) + Locker.ReadLock(); // Read-access only as list doesn't get resized (like Add/Remove do) so allow updating actors from different threads at once auto& list = Actors[category]; - if (list.Count() <= key || key < 0) // Ignore invalid key softly - return; - auto& e = list[key]; - if (e.Actor == a) + if (list.Count() > key && key >= 0) // Ignore invalid key softly { - for (auto* listener : _listeners) - listener->OnSceneRenderingUpdateActor(a, e.Bounds, flags); - if (flags & ISceneRenderingListener::Layer) - e.LayerMask = a->GetLayerMask(); - if (flags & ISceneRenderingListener::Bounds) - e.Bounds = a->GetSphere(); + auto& e = list[key]; + if (e.Actor == a) + { + for (auto* listener : _listeners) + listener->OnSceneRenderingUpdateActor(a, e.Bounds, flags); + if (flags & ISceneRenderingListener::Layer) + e.LayerMask = a->GetLayerMask(); + if (flags & ISceneRenderingListener::Bounds) + e.Bounds = a->GetSphere(); + } } + if (lock) + Locker.ReadUnlock(); } void SceneRendering::RemoveActor(Actor* a, int32& key) diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h index c11c94de8..25dfc63fa 100644 --- a/Source/Engine/Level/Scene/SceneRendering.h +++ b/Source/Engine/Level/Scene/SceneRendering.h @@ -55,6 +55,7 @@ public: Bounds = 2, Layer = 4, StaticFlags = 8, + AutoDelayDuringRendering = 16, // Conditionally allow updating data during rendering when writes are locked Auto = Visual | Bounds | Layer, }; @@ -68,6 +69,8 @@ public: virtual void OnSceneRenderingClear(SceneRendering* scene) = 0; }; +DECLARE_ENUM_OPERATORS(ISceneRenderingListener::UpdateFlags); + /// /// Scene rendering helper subsystem that boosts the level rendering by providing efficient objects cache and culling implementation. /// diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index 3a0d03c68..52132b972 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -352,7 +352,7 @@ void TextRender::UpdateLayout() BoundingBox::Transform(_localBox, _transform, _box); BoundingSphere::FromBox(_box, _sphere); if (_sceneRenderingKey != -1) - GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); + GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Auto | ISceneRenderingListener::AutoDelayDuringRendering); } bool TextRender::HasContentLoaded() const From 32f2ef3f0687e95fd89e545235a005407b4fa7d8 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 18:26:10 +0200 Subject: [PATCH 098/137] Fix Android compilation --- Source/Engine/Engine/NativeInterop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index 082c6999a..2d8f8db84 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -946,7 +946,7 @@ namespace FlaxEngine.Interop fieldSize += (nativeFieldPtr - startPtr).ToInt32(); } -#if USE_AOT +#if USE_AOT || DOTNET_HOST_MONO TField fieldValue = (TField)field.GetValue(fieldOwner); #else ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference(fieldOffset, ref fieldOwner); From 9cc2c1da4050fc22d967711611b05e1b933360bc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 22:58:08 +0200 Subject: [PATCH 099/137] Fix terrain exporting to properly calculate size and sample positions #3534 --- Source/Editor/Tools/Terrain/TerrainTools.cpp | 110 +++++++------------ 1 file changed, 38 insertions(+), 72 deletions(-) diff --git a/Source/Editor/Tools/Terrain/TerrainTools.cpp b/Source/Editor/Tools/Terrain/TerrainTools.cpp index 2a17f7960..065f7ffeb 100644 --- a/Source/Editor/Tools/Terrain/TerrainTools.cpp +++ b/Source/Editor/Tools/Terrain/TerrainTools.cpp @@ -149,13 +149,13 @@ bool GetTextureDataForSampling(Texture* texture, TextureDataResult& data, bool h bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches, Texture* heightmap, float heightmapScale, Texture* splatmap1, Texture* splatmap2) { + PROFILE_CPU_NAMED("Terrain.GenerateTerrain"); CHECK_RETURN(terrain && terrain->GetChunkSize() != 0, true); if (numberOfPatches.X < 1 || numberOfPatches.Y < 1) { - LOG(Warning, "Cannot setup terain with no patches."); + LOG(Warning, "Cannot setup terrain with no patches."); return false; } - PROFILE_CPU_NAMED("Terrain.GenerateTerrain"); // Wait for assets to be loaded if (heightmap && heightmap->WaitForLoaded()) @@ -178,7 +178,9 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches terrain->AddPatches(numberOfPatches); // Prepare data - const auto heightmapSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1; + const int32 heightmapSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1; + const float heightmapSizeInv = 1.0f / (float)(heightmapSize - 1); + const Float2 uvPerPatch = Float2::One / Float2(numberOfPatches); Array heightmapData; heightmapData.Resize(heightmapSize * heightmapSize); @@ -192,19 +194,17 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches const auto sampler = PixelFormatSampler::Get(dataHeightmap.Format); // Initialize with sub-range of the input heightmap - const Vector2 uvPerPatch = Vector2::One / Vector2(numberOfPatches); - const float heightmapSizeInv = 1.0f / (heightmapSize - 1); for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++) { auto patch = terrain->GetPatch(patchIndex); - const Vector2 uvStart = Vector2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch; + const Float2 uvStart = Float2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch; // Sample heightmap pixels with interpolation to get actual heightmap vertices locations for (int32 z = 0; z < heightmapSize; z++) { for (int32 x = 0; x < heightmapSize; x++) { - const Vector2 uv = uvStart + Vector2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch; + const Float2 uv = uvStart + Float2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch; const Color color = sampler->SampleLinear(dataHeightmap.Mip0DataPtr->Get(), uv, dataHeightmap.Mip0Size, dataHeightmap.RowPitch); heightmapData[z * heightmapSize + x] = color.R * heightmapScale; } @@ -230,37 +230,30 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches Texture* splatmaps[2] = { splatmap1, splatmap2 }; Array splatmapData; TextureDataResult data1; - const Vector2 uvPerPatch = Vector2::One / Vector2(numberOfPatches); - const float heightmapSizeInv = 1.0f / (heightmapSize - 1); for (int32 index = 0; index < ARRAY_COUNT(splatmaps); index++) { const auto splatmap = splatmaps[index]; if (!splatmap) continue; - // Prepare data - if (splatmapData.IsEmpty()) - splatmapData.Resize(heightmapSize * heightmapSize); - // Get splatmap data if (GetTextureDataForSampling(splatmap, data1)) return true; const auto sampler = PixelFormatSampler::Get(data1.Format); // Modify heightmap splatmaps with sub-range of the input splatmaps + splatmapData.Resize(heightmapSize * heightmapSize); for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++) { auto patch = terrain->GetPatch(patchIndex); - - const Vector2 uvStart = Vector2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch; + const Float2 uvStart = Float2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch; // Sample splatmap pixels with interpolation to get actual splatmap values for (int32 z = 0; z < heightmapSize; z++) { for (int32 x = 0; x < heightmapSize; x++) { - const Vector2 uv = uvStart + Vector2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch; - + const Float2 uv = uvStart + Float2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch; const Color color = sampler->SampleLinear(data1.Mip0DataPtr->Get(), uv, data1.Mip0Size, data1.RowPitch); Color32 layers; @@ -374,63 +367,38 @@ Color32* TerrainTools::GetSplatMapData(Terrain* terrain, const Int2& patchCoord, bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder) { + PROFILE_CPU_NAMED("Terrain.ExportTerrain"); CHECK_RETURN(terrain && terrain->GetPatchesCount() != 0, true); - const auto firstPatch = terrain->GetPatch(0); - - // Calculate texture size - const int32 patchEdgeVertexCount = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1; - const int32 patchVertexCount = patchEdgeVertexCount * patchEdgeVertexCount; // Find size of heightmap in patches + const auto firstPatch = terrain->GetPatch(0); Int2 start(firstPatch->GetX(), firstPatch->GetZ()); Int2 end(start); - for (int32 i = 0; i < terrain->GetPatchesCount(); i++) + for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++) { - const int32 x = terrain->GetPatch(i)->GetX(); - const int32 y = terrain->GetPatch(i)->GetZ(); - - if (x < start.X) - start.X = x; - if (y < start.Y) - start.Y = y; - if (x > end.X) - end.X = x; - if (y > end.Y) - end.Y = y; + const auto patch = terrain->GetPatch(patchIndex); + const Int2 pos(patch->GetX(), patch->GetZ()); + start = Int2::Min(start, pos); + end = Int2::Max(end, pos); } const Int2 size = (end + 1) - start; - // Allocate - with space for non-existent patches + // Allocate heightmap for a whole terrain (NumberOfPatches * 4x4 * ChunkSize + 1) + const Int2 heightmapSize = size * Terrain::ChunksCountEdge * terrain->GetChunkSize() + 1; Array heightmap; - heightmap.Resize(patchVertexCount * size.X * size.Y); - - // Set to any element, where: min < elem < max + heightmap.Resize(heightmapSize.X * heightmapSize.Y); heightmap.SetAll(firstPatch->GetHeightmapData()[0]); - const int32 heightmapWidth = patchEdgeVertexCount * size.X; - - // Fill heightmap with data + // Fill heightmap with data from all patches + const int32 rowSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1; for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++) { - // Pick a patch const auto patch = terrain->GetPatch(patchIndex); - const float* data = patch->GetHeightmapData(); - - // Beginning of patch - int32 dstIndex = (patch->GetX() - start.X) * patchEdgeVertexCount + - (patch->GetZ() - start.Y) * size.Y * patchVertexCount; - - // Iterate over lines in patch - for (int32 z = 0; z < patchEdgeVertexCount; z++) - { - // Iterate over vertices in line - for (int32 x = 0; x < patchEdgeVertexCount; x++) - { - heightmap[dstIndex + x] = data[z * patchEdgeVertexCount + x]; - } - - dstIndex += heightmapWidth; - } + const Int2 pos(patch->GetX() - start.X, patch->GetZ() - start.Y); + const float* src = patch->GetHeightmapData(); + float* dst = heightmap.Get() + pos.X * (rowSize - 1) + pos.Y * heightmapSize.X * (rowSize - 1); + for (int32 row = 0; row < rowSize; row++) + Platform::MemoryCopy(dst + row * heightmapSize.X, src + row * rowSize, rowSize * sizeof(float)); } // Interpolate to 16-bit int @@ -438,44 +406,42 @@ bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder) maxHeight = minHeight = heightmap[0]; for (int32 i = 1; i < heightmap.Count(); i++) { - float h = heightmap[i]; + float h = heightmap.Get()[i]; if (maxHeight < h) maxHeight = h; else if (minHeight > h) minHeight = h; } - - const float maxValue = 65535.0f; - const float alpha = maxValue / (maxHeight - minHeight); + const float alpha = MAX_uint16 / (maxHeight - minHeight); // Storage for pixel data - Array byteHeightmap(heightmap.Capacity()); - - for (auto& elem : heightmap) + Array byteHeightmap; + byteHeightmap.Resize(heightmap.Count()); + for (int32 i = 0; i < heightmap.Count(); i++) { - byteHeightmap.Add(static_cast(alpha * (elem - minHeight))); + float height = heightmap.Get()[i]; + byteHeightmap.Get()[i] = static_cast(alpha * (height - minHeight)); } // Create texture TextureData textureData; - textureData.Height = textureData.Width = heightmapWidth; + textureData.Width = heightmapSize.X; + textureData.Height = heightmapSize.Y; textureData.Depth = 1; textureData.Format = PixelFormat::R16_UNorm; textureData.Items.Resize(1); textureData.Items[0].Mips.Resize(1); - - // Fill mip data TextureMipData* srcMip = textureData.GetData(0, 0); srcMip->Data.Link(byteHeightmap.Get()); srcMip->Lines = textureData.Height; - srcMip->RowPitch = textureData.Width * 2; // 2 bytes per pixel for format R16 + srcMip->RowPitch = textureData.Width * sizeof(uint16); srcMip->DepthPitch = srcMip->Lines * srcMip->RowPitch; // Find next non-existing file heightmap file FileSystem::NormalizePath(outputFolder); const String baseFileName(TEXT("heightmap")); String outputPath; - for (int32 i = 0; i < MAX_int32; i++) + for (int32 i = 0; i < 100; i++) { outputPath = outputFolder / baseFileName + StringUtils::ToString(i) + TEXT(".png"); if (!FileSystem::FileExists(outputPath)) From 028b5fedecdde43d9beb44c921143f83ee6777ce Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 30 Sep 2025 23:37:15 +0200 Subject: [PATCH 100/137] Use right-click only on GPUTextureEditor context menu --- Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs index 954059a28..2daa3c0a5 100644 --- a/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/GPUTextureEditor.cs @@ -32,7 +32,7 @@ namespace FlaxEditor.CustomEditors.Dedicated private void OnImageClicked(Image image, MouseButton button) { var texture = Values[0] as GPUTexture; - if (!texture) + if (!texture || button != MouseButton.Right) return; var menu = new ContextMenu(); menu.AddButton("Save...", () => Screenshot.Capture(Values[0] as GPUTexture)); From 7e1ac5e167cea42b0a77cfc220845ae90a7263b3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 2 Oct 2025 18:48:14 +0200 Subject: [PATCH 101/137] Fix sky rendering in ortho and oblique projection #3448 --- Content/Shaders/Sky.flax | 4 +- Source/Engine/Level/Actors/Sky.cpp | 74 +++----------------------- Source/Engine/Level/Actors/Sky.h | 4 +- Source/Engine/Renderer/GBufferPass.cpp | 14 ++++- Source/Shaders/Sky.shader | 57 ++++---------------- 5 files changed, 34 insertions(+), 119 deletions(-) diff --git a/Content/Shaders/Sky.flax b/Content/Shaders/Sky.flax index 87a5b6b3a..a568db451 100644 --- a/Content/Shaders/Sky.flax +++ b/Content/Shaders/Sky.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28d44ef295d989d49ad4d59d6581eee921bc5fa5237e046d271a433454496388 -size 3463 +oid sha256:8541d1f0590167498f44da231f6de4f2938e15b26a5eb58e27b5067e1c882be8 +size 2252 diff --git a/Source/Engine/Level/Actors/Sky.cpp b/Source/Engine/Level/Actors/Sky.cpp index 4e635489f..6d7d5efe2 100644 --- a/Source/Engine/Level/Actors/Sky.cpp +++ b/Source/Engine/Level/Actors/Sky.cpp @@ -21,7 +21,8 @@ #endif GPU_CB_STRUCT(Data { - Matrix WVP; + Matrix WorldViewProjection; + Matrix InvViewProjection; Float3 ViewOffset; float Padding; ShaderGBufferData GBuffer; @@ -30,9 +31,6 @@ GPU_CB_STRUCT(Data { Sky::Sky(const SpawnParams& params) : Actor(params) - , _shader(nullptr) - , _psSky(nullptr) - , _psFog(nullptr) { _drawNoCulling = 1; _drawCategory = SceneRendering::PreRender; @@ -52,7 +50,6 @@ Sky::Sky(const SpawnParams& params) Sky::~Sky() { SAFE_DELETE_GPU_RESOURCE(_psSky); - SAFE_DELETE_GPU_RESOURCE(_psFog); } void Sky::InitConfig(ShaderAtmosphericFogData& config) const @@ -91,7 +88,7 @@ void Sky::Draw(RenderContext& renderContext) if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky)) { // Ensure to have pipeline state cache created - if (_psSky == nullptr || _psFog == nullptr) + if (_psSky == nullptr) { const auto shader = _shader->GetShader(); @@ -113,21 +110,6 @@ void Sky::Draw(RenderContext& renderContext) LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString()); } } - if (_psFog == nullptr) - { - _psFog = GPUDevice::Instance->CreatePipelineState(); - - GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle; - psDesc.PS = shader->GetPS("PS_Fog"); - psDesc.DepthWriteEnable = false; - psDesc.DepthClipEnable = false; - psDesc.BlendMode = BlendingMode::Additive; - - if (_psFog->Init(psDesc)) - { - LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString()); - } - } } // Register for the sky and fog pass @@ -139,7 +121,6 @@ void Sky::Draw(RenderContext& renderContext) void Sky::Serialize(SerializeStream& stream, const void* otherObj) { - // Base Actor::Serialize(stream, otherObj); SERIALIZE_GET_OTHER_OBJ(Sky); @@ -152,7 +133,6 @@ void Sky::Serialize(SerializeStream& stream, const void* otherObj) void Sky::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) { - // Base Actor::Deserialize(stream, modifier); DESERIALIZE_MEMBER(Sun, SunLight); @@ -173,39 +153,7 @@ bool Sky::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output) { - // Get precomputed cache and bind it to the pipeline - AtmosphereCache cache; - if (!AtmospherePreCompute::GetCache(&cache)) - return; - context->BindSR(4, cache.Transmittance); - context->BindSR(5, cache.Irradiance); - context->BindSR(6, cache.Inscatter->ViewVolume()); - - // Bind GBuffer inputs - context->BindSR(0, renderContext.Buffers->GBuffer0); - context->BindSR(1, renderContext.Buffers->GBuffer1); - context->BindSR(2, renderContext.Buffers->GBuffer2); - context->BindSR(3, renderContext.Buffers->DepthBuffer); - - // Setup constants data - Data data; - GBufferPass::SetInputs(renderContext.View, data.GBuffer); - data.ViewOffset = renderContext.View.Origin + GetPosition(); - InitConfig(data.Fog); - data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f; - bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight); - if (!useSpecularLight) - { - data.Fog.AtmosphericFogSunDiscScale = 0; - } - - // Bind pipeline - auto cb = _shader->GetShader()->GetCB(0); - context->UpdateCB(cb, &data); - context->BindCB(0, cb); - context->SetState(_psFog); - context->SetRenderTarget(output); - context->DrawFullscreenTriangle(); + MISSING_CODE("sky fog"); } bool Sky::IsDynamicSky() const @@ -231,14 +179,14 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr // Setup constants data Matrix m; Data data; - Matrix::Multiply(world, renderContext.View.Frustum.GetMatrix(), m); - Matrix::Transpose(m, data.WVP); + Matrix::Multiply(world, renderContext.View.ViewProjection(), m); + Matrix::Transpose(m, data.WorldViewProjection); + Matrix::Transpose(renderContext.View.IVP, data.InvViewProjection); GBufferPass::SetInputs(renderContext.View, data.GBuffer); data.ViewOffset = renderContext.View.Origin + GetPosition(); InitConfig(data.Fog); //data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f; - bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight); - if (!useSpecularLight) + if (EnumHasNoneFlags(renderContext.View.Flags, ViewFlags::SpecularLight)) { // Hide sun disc if specular light is disabled data.Fog.AtmosphericFogSunDiscScale = 0; @@ -253,11 +201,8 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr void Sky::EndPlay() { - // Cleanup SAFE_DELETE_GPU_RESOURCE(_psSky); - SAFE_DELETE_GPU_RESOURCE(_psFog); - // Base Actor::EndPlay(); } @@ -268,7 +213,6 @@ void Sky::OnEnable() GetSceneRendering()->AddViewportIcon(this); #endif - // Base Actor::OnEnable(); } @@ -279,13 +223,11 @@ void Sky::OnDisable() #endif GetSceneRendering()->RemoveActor(this, _sceneRenderingKey); - // Base Actor::OnDisable(); } void Sky::OnTransformChanged() { - // Base Actor::OnTransformChanged(); _box = BoundingBox(_transform.Translation); diff --git a/Source/Engine/Level/Actors/Sky.h b/Source/Engine/Level/Actors/Sky.h index 65bcc631a..61bb048ef 100644 --- a/Source/Engine/Level/Actors/Sky.h +++ b/Source/Engine/Level/Actors/Sky.h @@ -20,8 +20,7 @@ class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public DECLARE_SCENE_OBJECT(Sky); private: AssetReference _shader; - GPUPipelineState* _psSky; - GPUPipelineState* _psFog; + GPUPipelineState* _psSky = nullptr; int32 _sceneRenderingKey = -1; public: @@ -57,7 +56,6 @@ private: void OnShaderReloading(Asset* obj) { _psSky = nullptr; - _psFog = nullptr; } #endif void InitConfig(ShaderAtmosphericFogData& config) const; diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 9d3684010..7c9abb413 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -19,6 +19,7 @@ #include "Engine/Content/Content.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Level/Actors/Decal.h" +#include "Engine/Level/Actors/Sky.h" #include "Engine/Engine/Engine.h" GPU_CB_STRUCT(GBufferPassData { @@ -416,8 +417,17 @@ void GBufferPass::DrawSky(RenderContext& renderContext, GPUContext* context) // Calculate sphere model transform to cover far plane Matrix m1, m2; - Matrix::Scaling(renderContext.View.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum - Matrix::CreateWorld(renderContext.View.Position, Float3::Up, Float3::Backward, m2); // Rotate sphere model + float size = renderContext.View.Far; + Float3 origin = renderContext.View.Position; + if (dynamic_cast(renderContext.List->Sky)) // TODO: refactor sky rendering (eg. let sky draw with custom projection) + { + BoundingSphere frustumBounds; + renderContext.View.CullingFrustum.GetSphere(frustumBounds); + origin = frustumBounds.Center; + size = frustumBounds.Radius; + } + Matrix::Scaling(size / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum + Matrix::CreateWorld(origin, Float3::Up, Float3::Backward, m2); // Rotate sphere model m1 *= m2; // Draw sky diff --git a/Source/Shaders/Sky.shader b/Source/Shaders/Sky.shader index af5d0053c..de29e5d3f 100644 --- a/Source/Shaders/Sky.shader +++ b/Source/Shaders/Sky.shader @@ -7,7 +7,8 @@ #include "./Flax/AtmosphereFog.hlsl" META_CB_BEGIN(0, Data) -float4x4 WVP; +float4x4 WorldViewProjection; +float4x4 InvViewProjection; float3 ViewOffset; float Padding; GBufferData GBuffer; @@ -18,7 +19,7 @@ DECLARE_GBUFFERDATA_ACCESS(GBuffer) struct MaterialInput { - float4 Position : SV_Position; + float4 Position : SV_Position; float4 ScreenPos : TEXCOORD0; }; @@ -30,12 +31,9 @@ MaterialInput VS(ModelInput_PosOnly input) MaterialInput output; // Compute vertex position - output.Position = mul(float4(input.Position.xyz, 1), WVP); + output.Position = mul(float4(input.Position.xyz, 1), WorldViewProjection); output.ScreenPos = output.Position; - // Place pixels on the far plane - output.Position = output.Position.xyzz; - return output; } @@ -45,15 +43,15 @@ GBufferOutput PS_Sky(MaterialInput input) { GBufferOutput output; - // Obtain UVs corresponding to the current pixel - float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5); + // Calculate view vector (unproject at the far plane) + GBufferData gBufferData = GetGBufferData(); + float4 clipPos = float4(input.ScreenPos.xy / input.ScreenPos.w, 1.0, 1.0); + clipPos = mul(clipPos, InvViewProjection); + float3 worldPos = clipPos.xyz / clipPos.w; + float3 viewVector = normalize(worldPos - gBufferData.ViewPos); // Sample atmosphere color - GBufferData gBufferData = GetGBufferData(); - float3 vsPos = GetViewPos(gBufferData, uv, LinearZ2DeviceDepth(gBufferData, 1)); - float3 wsPos = mul(float4(vsPos, 1), gBufferData.InvViewMatrix).xyz; - float3 viewVector = wsPos - gBufferData.ViewPos; - float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, wsPos + ViewOffset, gBufferData.ViewPos + ViewOffset); + float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, gBufferData.ViewPos + ViewOffset, viewVector, gBufferData.ViewFar, float3(0, 0, 0)); // Pack GBuffer output.Light = color; @@ -64,36 +62,3 @@ GBufferOutput PS_Sky(MaterialInput input) return output; } - -META_PS(true, FEATURE_LEVEL_ES2) -float4 PS_Fog(Quad_VS2PS input) : SV_Target0 -{ - float4 result; - /* - // Sample GBuffer - GBufferSample gBuffer = SampleGBuffer(GBuffer, input.TexCoord); - - // TODO: set valid scene color for better inscatter reflectance - //float3 sceneColor = gBuffer.Color * AtmosphericFogDensityOffset; - float3 sceneColor = float3(0, 0, 0); - - // Sample atmosphere color - float3 viewVector = gBuffer.WorldPos - GBuffer.ViewPos; - float SceneDepth = length(ViewVector); - result = GetAtmosphericFog(AtmosphericFog, GBuffer.ViewFar, GBuffer.ViewPos, viewVector, SceneDepth, sceneColor); - - //result.rgb = normalize(ViewVector); - //result.rgb = ViewVector; - //result.rgb = SceneDepth.xxx / GBuffer.ViewFar * 0.5f; - - //result = float4(input.TexCoord, 0, 1); - //result = AtmosphereTransmittanceTexture.Sample(SamplerLinearClamp, input.TexCoord); - //result = float4(AtmosphereIrradianceTexture.Sample(SamplerLinearClamp, input.TexCoord).rgb*5.0, 1.0); - //result = AtmosphereInscatterTexture.Sample(SamplerLinearClamp, float3(input.TexCoord.xy, (AtmosphericFogSunDirection.x+1.0)/2.0)); - */ - - // TODO: finish fog - result = float4(1, 0, 0, 1); - - return result; -} From 9b812ec34a0022b2b3f604424fae75ceecb3af69 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 2 Oct 2025 18:48:32 +0200 Subject: [PATCH 102/137] Fix `BoundingFrustum::GetPlane` in C++ to match C# version (and doc comment) --- Source/Engine/Core/Math/BoundingFrustum.cpp | 13 ++++++++++--- Source/Engine/Core/Math/BoundingFrustum.cs | 2 +- Source/Engine/Core/Math/BoundingFrustum.h | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Core/Math/BoundingFrustum.cpp b/Source/Engine/Core/Math/BoundingFrustum.cpp index e296fa1a8..e0697ce5e 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.cpp +++ b/Source/Engine/Core/Math/BoundingFrustum.cpp @@ -63,9 +63,16 @@ void BoundingFrustum::SetMatrix(const Matrix& matrix) Plane BoundingFrustum::GetPlane(int32 index) const { - if (index > 5) - return Plane(); - return _planes[index]; + switch (index) + { + case 0: return _pLeft; + case 1: return _pRight; + case 2: return _pTop; + case 3: return _pBottom; + case 4: return _pNear; + case 5: return _pFar; + default: return Plane(); + } } static Vector3 Get3PlanesInterPoint(const Plane& p1, const Plane& p2, const Plane& p3) diff --git a/Source/Engine/Core/Math/BoundingFrustum.cs b/Source/Engine/Core/Math/BoundingFrustum.cs index 6f6e034ce..4f1e27e1e 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.cs +++ b/Source/Engine/Core/Math/BoundingFrustum.cs @@ -182,7 +182,7 @@ namespace FlaxEngine /// /// Returns one of the 6 planes related to this frustum. /// - /// Plane index where 0 fro Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far + /// Plane index where 0 for Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far /// The frustum plane. public Plane GetPlane(int index) { diff --git a/Source/Engine/Core/Math/BoundingFrustum.h b/Source/Engine/Core/Math/BoundingFrustum.h index 30eb70f43..a3a5442e9 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.h +++ b/Source/Engine/Core/Math/BoundingFrustum.h @@ -148,13 +148,13 @@ public: Plane GetPlane(int32 index) const; /// - /// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner). + /// Gets the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner). /// /// The corners. void GetCorners(Float3 corners[8]) const; /// - /// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner). + /// Gets the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner). /// /// The corners. void GetCorners(Double3 corners[8]) const; From adcfc5021801b8a3fc730dff1a294f199c8d5b10 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 2 Oct 2025 20:49:50 +0200 Subject: [PATCH 103/137] Fix stack overflow exception in shader graph recursion to be detected #3706 --- Source/Engine/Visject/ShaderGraph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Visject/ShaderGraph.h b/Source/Engine/Visject/ShaderGraph.h index 84c4b64d0..ab0e7d405 100644 --- a/Source/Engine/Visject/ShaderGraph.h +++ b/Source/Engine/Visject/ShaderGraph.h @@ -14,7 +14,7 @@ #include "Engine/Content/AssetsContainer.h" #include "Engine/Animations/Curve.h" -#define SHADER_GRAPH_MAX_CALL_STACK 100 +#define SHADER_GRAPH_MAX_CALL_STACK 50 enum class MaterialSceneTextures; template From 60c19303f65b4fc08c2c46d6881c18dda94c77bc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 2 Oct 2025 23:31:03 +0200 Subject: [PATCH 104/137] Fix duplicating splines with parents #3531 --- Source/Editor/Modules/SceneEditingModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Editor/Modules/SceneEditingModule.cs b/Source/Editor/Modules/SceneEditingModule.cs index 3c7130615..c96e79ed9 100644 --- a/Source/Editor/Modules/SceneEditingModule.cs +++ b/Source/Editor/Modules/SceneEditingModule.cs @@ -673,6 +673,7 @@ namespace FlaxEditor.Modules pasteAction.Do(out _, out var nodeParents); // Select spawned objects (parents only) + newSelection.Clear(); newSelection.AddRange(nodeParents); var selectAction = new SelectionChangeAction(Selection.ToArray(), newSelection.ToArray(), OnSelectionUndo); selectAction.Do(); From 1f3f1ea67eb71567154ea1ac94c9c2f5a556579d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 10:52:01 +0200 Subject: [PATCH 105/137] Fix Blend Poses nodes to smoothly blend back when transition goes back #3595 --- .../Animations/Graph/AnimGraph.Base.cpp | 1 + Source/Engine/Animations/Graph/AnimGraph.h | 3 +- .../Animations/Graph/AnimGroup.Animation.cpp | 40 ++++++++----------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/Source/Engine/Animations/Graph/AnimGraph.Base.cpp b/Source/Engine/Animations/Graph/AnimGraph.Base.cpp index c49f0e26e..e4d7eda70 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.Base.cpp +++ b/Source/Engine/Animations/Graph/AnimGraph.Base.cpp @@ -93,6 +93,7 @@ void MultiBlendBucketInit(AnimGraphInstanceData::Bucket& bucket) void BlendPoseBucketInit(AnimGraphInstanceData::Bucket& bucket) { bucket.BlendPose.TransitionPosition = 0.0f; + bucket.BlendPose.BlendPoseIndex = -1; bucket.BlendPose.PreviousBlendPoseIndex = -1; } diff --git a/Source/Engine/Animations/Graph/AnimGraph.h b/Source/Engine/Animations/Graph/AnimGraph.h index e03d84fd9..6c36e37a5 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.h +++ b/Source/Engine/Animations/Graph/AnimGraph.h @@ -239,7 +239,8 @@ public: struct BlendPoseBucket { float TransitionPosition; - int32 PreviousBlendPoseIndex; + int16 BlendPoseIndex; + int16 PreviousBlendPoseIndex; }; struct StateMachineBucket diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp index f75a8abd1..c76bddf3f 100644 --- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp +++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp @@ -676,9 +676,12 @@ Variant AnimGraphExecutor::Blend(AnimGraphNode* node, const Value& poseA, const if (!ANIM_GRAPH_IS_VALID_PTR(poseB)) nodesB = GetEmptyNodes(); + const Transform* srcA = nodesA->Nodes.Get(); + const Transform* srcB = nodesB->Nodes.Get(); + Transform* dst = nodes->Nodes.Get(); for (int32 i = 0; i < nodes->Nodes.Count(); i++) { - Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]); + Transform::Lerp(srcA[i], srcB[i], alpha, dst[i]); } Transform::Lerp(nodesA->RootMotion, nodesB->RootMotion, alpha, nodes->RootMotion); nodes->Position = Math::Lerp(nodesA->Position, nodesB->Position, alpha); @@ -1263,21 +1266,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu { const auto valueA = tryGetValue(node->GetBox(1), Value::Null); const auto valueB = tryGetValue(node->GetBox(2), Value::Null); - const auto nodes = node->GetNodes(this); - - auto nodesA = static_cast(valueA.AsPointer); - auto nodesB = static_cast(valueB.AsPointer); - if (!ANIM_GRAPH_IS_VALID_PTR(valueA)) - nodesA = GetEmptyNodes(); - if (!ANIM_GRAPH_IS_VALID_PTR(valueB)) - nodesB = GetEmptyNodes(); - - for (int32 i = 0; i < nodes->Nodes.Count(); i++) - { - Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]); - } - Transform::Lerp(nodesA->RootMotion, nodesB->RootMotion, alpha, nodes->RootMotion); - value = nodes; + value = Blend(node, valueA, valueB, alpha, AlphaBlendMode::Linear); } break; @@ -1758,35 +1747,38 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu // [2]: int Pose Count // [3]: AlphaBlendMode Mode - // Prepare auto& bucket = context.Data->State[node->BucketIndex].BlendPose; - const int32 poseIndex = (int32)tryGetValue(node->GetBox(1), node->Values[0]); + const int16 poseIndex = (int32)tryGetValue(node->GetBox(1), node->Values[0]); const float blendDuration = (float)tryGetValue(node->GetBox(2), node->Values[1]); const int32 poseCount = Math::Clamp(node->Values[2].AsInt, 0, MaxBlendPoses); const AlphaBlendMode mode = (AlphaBlendMode)node->Values[3].AsInt; - - // Skip if nothing to blend if (poseCount == 0 || poseIndex < 0 || poseIndex >= poseCount) - { break; + + // Check if swap transition end points + if (bucket.PreviousBlendPoseIndex == poseIndex && bucket.BlendPoseIndex != poseIndex && bucket.TransitionPosition >= ANIM_GRAPH_BLEND_THRESHOLD) + { + bucket.TransitionPosition = blendDuration - bucket.TransitionPosition; + Swap(bucket.BlendPoseIndex, bucket.PreviousBlendPoseIndex); } // Check if transition is not active (first update, pose not changing or transition ended) bucket.TransitionPosition += context.DeltaTime; + bucket.BlendPoseIndex = poseIndex; if (bucket.PreviousBlendPoseIndex == -1 || bucket.PreviousBlendPoseIndex == poseIndex || bucket.TransitionPosition >= blendDuration || blendDuration <= ANIM_GRAPH_BLEND_THRESHOLD) { bucket.TransitionPosition = 0.0f; + bucket.BlendPoseIndex = poseIndex; bucket.PreviousBlendPoseIndex = poseIndex; - value = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + poseIndex), Value::Null); + value = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.BlendPoseIndex), Value::Null); break; } - ASSERT(bucket.PreviousBlendPoseIndex >= 0 && bucket.PreviousBlendPoseIndex < poseCount); // Blend two animations { const float alpha = bucket.TransitionPosition / blendDuration; const auto valueA = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.PreviousBlendPoseIndex), Value::Null); - const auto valueB = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + poseIndex), Value::Null); + const auto valueB = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.BlendPoseIndex), Value::Null); value = Blend(node, valueA, valueB, alpha, mode); } From 4c640b915fe573b4e40960308fbd6201e1599e7b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 11:25:25 +0200 Subject: [PATCH 106/137] Fix `CheckBox` to display check state when created in game without editor icon atlas #3705 --- Source/Engine/UI/GUI/Common/CheckBox.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/CheckBox.cs b/Source/Engine/UI/GUI/Common/CheckBox.cs index c779d6e83..47073cb27 100644 --- a/Source/Engine/UI/GUI/Common/CheckBox.cs +++ b/Source/Engine/UI/GUI/Common/CheckBox.cs @@ -181,8 +181,8 @@ namespace FlaxEngine.GUI ImageColor = style.BorderSelected * 1.2f; BorderColor = style.BorderNormal; BorderColorHighlighted = style.BorderSelected; - CheckedImage = new SpriteBrush(style.CheckBoxTick); - IntermediateImage = new SpriteBrush(style.CheckBoxIntermediate); + CheckedImage = style.CheckBoxTick.IsValid ? new SpriteBrush(style.CheckBoxTick) : new SolidColorBrush(style.Foreground); + IntermediateImage = style.CheckBoxIntermediate.IsValid ? new SpriteBrush(style.CheckBoxIntermediate) : new SolidColorBrush(style.ForegroundGrey); CacheBox(); } From 4f45b3c1d0377da75226fe55030fbb8751fc3d70 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 11:33:01 +0200 Subject: [PATCH 107/137] Fix missing root motion copy when using input skeleton pose (eg. IK node) #3445 --- Source/Engine/Animations/Graph/AnimGraph.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Engine/Animations/Graph/AnimGraph.h b/Source/Engine/Animations/Graph/AnimGraph.h index 6c36e37a5..051f6613d 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.h +++ b/Source/Engine/Animations/Graph/AnimGraph.h @@ -811,6 +811,7 @@ public: { // Copy the node transformations Platform::MemoryCopy(dstNodes->Nodes.Get(), srcNodes->Nodes.Get(), sizeof(Transform) * _skeletonNodesCount); + dstNodes->RootMotion = srcNodes->RootMotion; // Copy the animation playback state dstNodes->Position = srcNodes->Position; From c4c7ee941f2964860a2f93ad159a556dcb713e1a Mon Sep 17 00:00:00 2001 From: Saas Date: Fri, 3 Oct 2025 14:46:43 +0200 Subject: [PATCH 108/137] add industry standard shortcut for editor settings --- Source/Editor/Modules/UIModule.cs | 2 +- Source/Editor/Options/InputOptions.cs | 4 ++++ Source/Editor/Windows/EditorWindow.cs | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index fe89026c5..0e482441e 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -669,7 +669,7 @@ namespace FlaxEditor.Modules if (item != null) Editor.ContentEditing.Open(item); }); - cm.AddButton("Editor Options", () => Editor.Windows.EditorOptionsWin.Show()); + cm.AddButton("Editor Options", inputOptions.EditorOptionsWindow, () => Editor.Windows.EditorOptionsWin.Show()); // Scene MenuScene = MainMenu.AddButton("Scene"); diff --git a/Source/Editor/Options/InputOptions.cs b/Source/Editor/Options/InputOptions.cs index af919c1f3..ab473ebed 100644 --- a/Source/Editor/Options/InputOptions.cs +++ b/Source/Editor/Options/InputOptions.cs @@ -650,6 +650,10 @@ namespace FlaxEditor.Options [EditorDisplay("Windows"), EditorOrder(4020)] public InputBinding VisualScriptDebuggerWindow = new InputBinding(KeyboardKeys.None); + [DefaultValue(typeof(InputBinding), "Control+Comma")] + [EditorDisplay("Windows"), EditorOrder(4030)] + public InputBinding EditorOptionsWindow = new InputBinding(KeyboardKeys.Comma, KeyboardKeys.Control); + #endregion #region Node Editors diff --git a/Source/Editor/Windows/EditorWindow.cs b/Source/Editor/Windows/EditorWindow.cs index 6d01432ba..03d435efe 100644 --- a/Source/Editor/Windows/EditorWindow.cs +++ b/Source/Editor/Windows/EditorWindow.cs @@ -116,6 +116,11 @@ namespace FlaxEditor.Windows if (InputOptions.WindowShortcutsAvaliable) Editor.Windows.VisualScriptDebuggerWin.FocusOrShow(); }); + InputActions.Add(options => options.EditorOptionsWindow, () => + { + if (InputOptions.WindowShortcutsAvaliable) + Editor.Windows.EditorOptionsWin.FocusOrShow(); + }); // Register Editor.Windows.OnWindowAdd(this); From da5c8555e594eb8d7c6c715ca235437baa2e57e7 Mon Sep 17 00:00:00 2001 From: Saas Date: Fri, 3 Oct 2025 21:16:28 +0200 Subject: [PATCH 109/137] add myself to list of Flax authors lol Mafi said I should do this :) --- Source/Editor/Windows/AboutDialog.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs index b970c9e09..1d9afbdfe 100644 --- a/Source/Editor/Windows/AboutDialog.cs +++ b/Source/Editor/Windows/AboutDialog.cs @@ -97,6 +97,7 @@ namespace FlaxEditor.Windows "Jean-Baptiste Perrier", "Chandler Cox", "Ari Vuollet", + "Vincent Saarmann", }); authors.Sort(); var authorsLabel = new Label(4, topParentControl.Bottom + 20, Width - 8, 70) From 6ae370f8fc6e7377016d3e79813b4b3634244933 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 22:20:58 +0200 Subject: [PATCH 110/137] Fix camera cut flag in rendering to not trigger on origin change for smother visuals --- Source/Engine/Graphics/RenderView.h | 8 ++++++++ Source/Engine/Renderer/Renderer.cpp | 2 -- Source/Engine/Renderer/VolumetricFogPass.cpp | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Graphics/RenderView.h b/Source/Engine/Graphics/RenderView.h index e7b60491c..a85480e3e 100644 --- a/Source/Engine/Graphics/RenderView.h +++ b/Source/Engine/Graphics/RenderView.h @@ -265,6 +265,14 @@ public: return Projection.M44 >= 1.0f; } + /// + /// Determines whether view Origin has been moved in this frame. Old history buffers/data might be invalid. + /// + FORCE_INLINE bool IsOriginTeleport() const + { + return Origin != PrevOrigin; + } + public: // Ignore deprecation warnings in defaults PRAGMA_DISABLE_DEPRECATION_WARNINGS diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 7fd12ba73..cd2c9ca2b 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -353,8 +353,6 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode); { PROFILE_CPU_NAMED("Setup"); - if (renderContext.View.Origin != renderContext.View.PrevOrigin) - renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change const int32 screenWidth = renderContext.Buffers->GetWidth(); const int32 screenHeight = renderContext.Buffers->GetHeight(); setup.UpscaleLocation = renderContext.Task->UpscaleLocation; diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 2fa957ab1..4cb672fc2 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -179,7 +179,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context, (float)_cache.GridSizeZ); auto& fogData = renderContext.Buffers->VolumetricFogData; fogData.MaxDistance = options.Distance; - if (renderContext.Task->IsCameraCut) + if (renderContext.Task->IsCameraCut || renderContext.View.IsOriginTeleport()) _cache.HistoryWeight = 0.0f; // Init data (partial, without directional light or sky light data); @@ -313,7 +313,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) PROFILE_GPU_CPU("Volumetric Fog"); // TODO: test exponential depth distribution (should give better quality near the camera) - // TODO: use tiled light culling and render unshadowed lights in single pass + // TODO: use tiled light culling and render shadowed/unshadowed lights in single pass // Try to get shadows atlas GPUTexture* shadowMap; From 4f1f77fb321db286f035b5062258c19a8e50b5af Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 22:21:11 +0200 Subject: [PATCH 111/137] Simplify code of EditorViewport to access editor instance --- Source/Editor/Viewport/EditorViewport.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index 0f9fce7c0..c16d3d9f5 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -535,7 +535,7 @@ namespace FlaxEditor.Viewport // Setup options { - Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged; + _editor.Options.OptionsChanged += OnEditorOptionsChanged; SetupViewportOptions(); } @@ -581,7 +581,7 @@ namespace FlaxEditor.Viewport // Camera Settings Menu var cameraCM = new ContextMenu(); - _cameraButton = new ViewportWidgetButton(string.Format(MovementSpeedTextFormat, _movementSpeed), Editor.Instance.Icons.Camera64, cameraCM, false, cameraSpeedTextWidth) + _cameraButton = new ViewportWidgetButton(string.Format(MovementSpeedTextFormat, _movementSpeed), _editor.Icons.Camera64, cameraCM, false, cameraSpeedTextWidth) { Tag = this, TooltipText = "Camera Settings", @@ -590,7 +590,7 @@ namespace FlaxEditor.Viewport _cameraWidget.Parent = this; // Orthographic/Perspective Mode Widget - _orthographicModeButton = new ViewportWidgetButton(string.Empty, Editor.Instance.Icons.CamSpeed32, null, true) + _orthographicModeButton = new ViewportWidgetButton(string.Empty, _editor.Icons.CamSpeed32, null, true) { Checked = !_isOrtho, TooltipText = "Toggle Orthographic/Perspective Mode", @@ -863,8 +863,8 @@ namespace FlaxEditor.Viewport { } }); - viewLayers.AddButton("Reset layers", () => Task.ViewLayersMask = LayersMask.Default).Icon = Editor.Instance.Icons.Rotate32; - viewLayers.AddButton("Disable layers", () => Task.ViewLayersMask = new LayersMask(0)).Icon = Editor.Instance.Icons.Rotate32; + viewLayers.AddButton("Reset layers", () => Task.ViewLayersMask = LayersMask.Default).Icon = _editor.Icons.Rotate32; + viewLayers.AddButton("Disable layers", () => Task.ViewLayersMask = new LayersMask(0)); viewLayers.AddSeparator(); var layers = LayersAndTagsSettings.GetCurrentLayers(); if (layers != null && layers.Length > 0) @@ -904,8 +904,8 @@ namespace FlaxEditor.Viewport { } }); - viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = Editor.Instance.Icons.Rotate32; - viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None).Icon = Editor.Instance.Icons.Rotate32; + viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = _editor.Icons.Rotate32; + viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None); viewFlags.AddSeparator(); for (int i = 0; i < ViewFlagsValues.Length; i++) { @@ -1085,7 +1085,7 @@ namespace FlaxEditor.Viewport /// private void SetupViewportOptions() { - var options = Editor.Instance.Options.Options; + var options = _editor.Options.Options; _minMovementSpeed = options.Viewport.MinMovementSpeed; MovementSpeed = options.Viewport.MovementSpeed; _maxMovementSpeed = options.Viewport.MaxMovementSpeed; @@ -1701,7 +1701,7 @@ namespace FlaxEditor.Viewport // Check if update mouse var size = Size; - var options = Editor.Instance.Options.Options; + var options = _editor.Options.Options; if (_isControllingMouse) { var rmbWheel = false; @@ -1926,7 +1926,7 @@ namespace FlaxEditor.Viewport return true; // Custom input events - return InputActions.Process(Editor.Instance, this, key); + return InputActions.Process(_editor, this, key); } /// @@ -1943,7 +1943,7 @@ namespace FlaxEditor.Viewport base.Draw(); // Add overlay during debugger breakpoint hang - if (Editor.Instance.Simulation.IsDuringBreakpointHang) + if (_editor.Simulation.IsDuringBreakpointHang) { var bounds = new Rectangle(Float2.Zero, Size); Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f)); @@ -1967,7 +1967,7 @@ namespace FlaxEditor.Viewport /// public override void OnDestroy() { - Editor.Instance.Options.OptionsChanged -= OnEditorOptionsChanged; + _editor.Options.OptionsChanged -= OnEditorOptionsChanged; base.OnDestroy(); } From 8f3b80492ed2d9c44f3366ab0af784b8f1a206a1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 3 Oct 2025 22:30:44 +0200 Subject: [PATCH 112/137] Fix terrain physics error on end play when it's disabled #3590 #3603 --- Source/Engine/Terrain/Terrain.cpp | 4 ---- Source/Engine/Terrain/TerrainPatch.cpp | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp index f13d3bcc4..ace6246b2 100644 --- a/Source/Engine/Terrain/Terrain.cpp +++ b/Source/Engine/Terrain/Terrain.cpp @@ -852,9 +852,7 @@ void Terrain::OnEnable() { auto patch = _patches[i]; if (patch->_physicsActor) - { PhysicsBackend::AddSceneActor(scene, patch->_physicsActor); - } } // Base @@ -873,9 +871,7 @@ void Terrain::OnDisable() { auto patch = _patches[i]; if (patch->_physicsActor) - { PhysicsBackend::RemoveSceneActor(scene, patch->_physicsActor); - } } // Base diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp index a9388224d..f73a7552c 100644 --- a/Source/Engine/Terrain/TerrainPatch.cpp +++ b/Source/Engine/Terrain/TerrainPatch.cpp @@ -2218,7 +2218,8 @@ void TerrainPatch::DestroyCollision() void* scene = _terrain->GetPhysicsScene()->GetPhysicsScene(); PhysicsBackend::RemoveCollider(_terrain); - PhysicsBackend::RemoveSceneActor(scene, _physicsActor); + if (_terrain->IsDuringPlay() && _terrain->IsActiveInHierarchy()) + PhysicsBackend::RemoveSceneActor(scene, _physicsActor); PhysicsBackend::DestroyActor(_physicsActor); PhysicsBackend::DestroyShape(_physicsShape); PhysicsBackend::DestroyObject(_physicsHeightField); From e9f83f77bb5680df2529fbd188c626b5cde048f4 Mon Sep 17 00:00:00 2001 From: Saas Date: Sat, 4 Oct 2025 14:03:02 +0200 Subject: [PATCH 113/137] fix "Straighten Connections" to actually straighten all connections --- Source/Editor/Surface/VisjectSurface.Formatting.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Surface/VisjectSurface.Formatting.cs b/Source/Editor/Surface/VisjectSurface.Formatting.cs index 39ac58242..e1b9a6777 100644 --- a/Source/Editor/Surface/VisjectSurface.Formatting.cs +++ b/Source/Editor/Surface/VisjectSurface.Formatting.cs @@ -176,10 +176,10 @@ namespace FlaxEditor.Surface if (connectedNodes.Count == 0) return; - for (int i = 0; i < connectedNodes.Count - 1; i++) + for (int i = 0; i < connectedNodes.Count; i++) { SurfaceNode nodeA = connectedNodes[i]; - List connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.IsOutput && b.HasAnyConnection).ToList(); + List connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.HasAnyConnection).ToList(); for (int j = 0; j < connectedOutputBoxes.Count; j++) { From 3682159da66932b0c992622a23f93d25d004af84 Mon Sep 17 00:00:00 2001 From: ZaPx64 Date: Sun, 5 Oct 2025 09:20:54 +0200 Subject: [PATCH 114/137] Fix Save() failing on virtual texture asset --- Source/Engine/Content/Assets/Texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Content/Assets/Texture.cpp b/Source/Engine/Content/Assets/Texture.cpp index e31b40a25..4e3aec94d 100644 --- a/Source/Engine/Content/Assets/Texture.cpp +++ b/Source/Engine/Content/Assets/Texture.cpp @@ -36,7 +36,7 @@ bool Texture::Save(const StringView& path) bool Texture::Save(const StringView& path, const InitData* customData) { - if (OnCheckSave()) + if (OnCheckSave(path)) return true; ScopeLock lock(Locker); From 361fc3ecfb628b5441b07e5ce2ed3f95edca0775 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:07:23 +0200 Subject: [PATCH 115/137] Add stencil buffer usage with object layer information #3080 #967 --- .../Utilities/ViewportIconsRenderer.cpp | 1 + Source/Engine/Foliage/Foliage.cpp | 2 + Source/Engine/Graphics/Config.h | 2 +- .../Materials/DeferredMaterialShader.cpp | 15 ++++-- .../Materials/DeformableMaterialShader.cpp | 17 ++++--- .../Materials/ForwardMaterialShader.cpp | 7 +-- .../Materials/TerrainMaterialShader.cpp | 14 +++--- Source/Engine/Graphics/Models/Mesh.cpp | 8 ++-- Source/Engine/Graphics/Models/Mesh.h | 3 +- Source/Engine/Graphics/Models/MeshBase.h | 11 +++++ Source/Engine/Graphics/Models/SkinnedMesh.cpp | 4 +- Source/Engine/Graphics/RenderBuffers.h | 11 +++++ Source/Engine/Graphics/Textures/GPUTexture.h | 6 +++ .../DirectX/DX11/GPUContextDX11.cpp | 6 ++- .../DirectX/DX11/GPUTextureDX11.cpp | 36 ++++++++++++++ .../DirectX/DX11/GPUTextureDX11.h | 6 +++ .../DirectX/DX12/GPUContextDX12.cpp | 6 ++- .../DirectX/DX12/GPUTextureDX12.cpp | 41 ++++++++++++++++ .../DirectX/DX12/GPUTextureDX12.h | 8 +++- .../GraphicsDevice/Null/GPUTextureNull.h | 4 ++ .../Vulkan/GPUTextureVulkan.cpp | 47 +++++++++++++++++-- .../GraphicsDevice/Vulkan/GPUTextureVulkan.h | 8 +++- Source/Engine/Level/Actors/AnimatedModel.cpp | 2 + Source/Engine/Level/Actors/Camera.cpp | 1 + Source/Engine/Level/Actors/Skybox.cpp | 1 - Source/Engine/Level/Actors/SplineModel.cpp | 3 +- Source/Engine/Level/Actors/StaticModel.cpp | 2 + Source/Engine/Particles/Particles.cpp | 5 +- Source/Engine/Renderer/DrawCall.h | 23 +++++++-- .../Renderer/Editor/MaterialComplexity.cpp | 2 - .../Renderer/Editor/QuadOverdrawPass.cpp | 3 -- Source/Engine/Renderer/RenderList.cpp | 16 +++++-- Source/Engine/Renderer/RenderList.h | 6 ++- Source/Engine/Terrain/TerrainChunk.cpp | 4 +- Source/Engine/UI/TextRender.cpp | 2 +- Source/Shaders/Stencil.hlsl | 23 +++++++++ 36 files changed, 291 insertions(+), 65 deletions(-) create mode 100644 Source/Shaders/Stencil.hlsl diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 44b3b4ea0..26a705970 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -89,6 +89,7 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor draw.Flags = StaticFlags::Transform; draw.DrawModes = DrawPass::Forward; draw.PerInstanceRandom = 0; + draw.StencilValue = 0; draw.LODBias = 0; draw.ForcedLOD = -1; draw.SortOrder = 0; diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index 8a0e75a6e..ddc3468f7 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -323,6 +323,7 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, draw.Bounds = sphere; draw.PerInstanceRandom = instance.Random; draw.DrawModes = type._drawModes; + draw.SetStencilValue(_layer); type.Model->Draw(renderContext, draw); //DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen); @@ -1182,6 +1183,7 @@ void Foliage::Draw(RenderContext& renderContext) draw.Bounds = instance.Bounds; draw.PerInstanceRandom = instance.Random; draw.DrawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); + draw.SetStencilValue(_layer); type.Model->Draw(renderContext, draw); return; } diff --git a/Source/Engine/Graphics/Config.h b/Source/Engine/Graphics/Config.h index 542669f03..43fb319bf 100644 --- a/Source/Engine/Graphics/Config.h +++ b/Source/Engine/Graphics/Config.h @@ -70,7 +70,7 @@ // Default depth buffer pixel format #ifndef GPU_DEPTH_BUFFER_PIXEL_FORMAT -#define GPU_DEPTH_BUFFER_PIXEL_FORMAT PixelFormat::D32_Float +#define GPU_DEPTH_BUFFER_PIXEL_FORMAT PixelFormat::D24_UNorm_S8_UInt #endif // Enable/disable gpu resources naming diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index 5f0abad33..bbcdc8207 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -85,13 +85,10 @@ void DeferredMaterialShader::Bind(BindParameters& params) if (IsRunningRadiancePass) cullMode = CullMode::TwoSided; #endif - if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0) + if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant) { // Invert culling when scale is negative - if (cullMode == CullMode::Normal) - cullMode = CullMode::Inverted; - else - cullMode = CullMode::Normal; + cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal; } ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes const auto cache = params.Instanced ? &_cacheInstanced : &_cache; @@ -101,6 +98,7 @@ void DeferredMaterialShader::Bind(BindParameters& params) // Bind pipeline context->SetState(state); + context->SetStencilRef(drawCall.StencilValue); } void DeferredMaterialShader::Unload() @@ -137,6 +135,10 @@ bool DeferredMaterialShader::Load() } #endif + psDesc.StencilEnable = true; + psDesc.StencilReadMask = 0; + psDesc.StencilPassOp = StencilOperation::Replace; + // GBuffer Pass psDesc.VS = _shader->GetVS("VS"); failed |= psDesc.VS == nullptr; @@ -160,6 +162,9 @@ bool DeferredMaterialShader::Load() psDesc.PS = _shader->GetPS("PS_GBuffer"); _cache.DefaultSkinned.Init(psDesc); + psDesc.StencilEnable = false; + psDesc.StencilPassOp = StencilOperation::Keep; + #if USE_EDITOR if (_shader->HasShader("PS_QuadOverdraw")) { diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp index 3efd9a2bc..6260163f4 100644 --- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp @@ -62,7 +62,7 @@ void DeformableMaterialShader::Bind(BindParameters& params) { Matrix::Transpose(drawCall.World, materialData->WorldMatrix); Matrix::Transpose(drawCall.Deformable.LocalMatrix, materialData->LocalMatrix); - materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; + materialData->WorldDeterminantSign = drawCall.WorldDeterminant ? -1.0f : 1.0f; materialData->Segment = drawCall.Deformable.Segment; materialData->ChunksPerSegment = drawCall.Deformable.ChunksPerSegment; materialData->MeshMinZ = drawCall.Deformable.MeshMinZ; @@ -84,13 +84,10 @@ void DeformableMaterialShader::Bind(BindParameters& params) // Select pipeline state based on current pass and render mode 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) + if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant) { // Invert culling when scale is negative - if (cullMode == CullMode::Normal) - cullMode = CullMode::Inverted; - else - cullMode = CullMode::Normal; + cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal; } PipelineStateCache* psCache = _cache.GetPS(view.Pass); ASSERT(psCache); @@ -98,6 +95,7 @@ void DeformableMaterialShader::Bind(BindParameters& params) // Bind pipeline context->SetState(state); + context->SetStencilRef(drawCall.StencilValue); } void DeformableMaterialShader::Unload() @@ -139,10 +137,17 @@ bool DeformableMaterialShader::Load() { _drawModes |= DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas; + psDesc.StencilEnable = true; + psDesc.StencilReadMask = 0; + psDesc.StencilPassOp = StencilOperation::Replace; + // GBuffer Pass psDesc.VS = _shader->GetVS("VS_SplineModel"); psDesc.PS = _shader->GetPS("PS_GBuffer"); _cache.Default.Init(psDesc); + + psDesc.StencilEnable = false; + psDesc.StencilPassOp = StencilOperation::Keep; } else { diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index a966507d8..72ec3c7bd 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -80,13 +80,10 @@ void ForwardMaterialShader::Bind(BindParameters& params) if (IsRunningRadiancePass) cullMode = CullMode::TwoSided; #endif - if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0) + if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant) { // Invert culling when scale is negative - if (cullMode == CullMode::Normal) - cullMode = CullMode::Inverted; - else - cullMode = CullMode::Normal; + cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal; } ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes const auto cacheObj = params.Instanced ? &_cacheInstanced : &_cache; diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp index d99e0f5d0..b6b455f20 100644 --- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp @@ -76,7 +76,7 @@ void TerrainMaterialShader::Bind(BindParameters& params) scaleX > 0.00001f ? 1.0f / scaleX : 0.0f, scaleY > 0.00001f ? 1.0f / scaleY : 0.0f, scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f); - materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; + materialData->WorldDeterminantSign = drawCall.WorldDeterminant ? -1.0f : 1.0f; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->CurrentLOD = drawCall.Terrain.CurrentLOD; materialData->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD; @@ -109,13 +109,10 @@ void TerrainMaterialShader::Bind(BindParameters& params) if (IsRunningRadiancePass) cullMode = CullMode::TwoSided; #endif - if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminantSign < 0) + if (cullMode != CullMode::TwoSided && drawCall.WorldDeterminant) { // Invert culling when scale is negative - if (cullMode == CullMode::Normal) - cullMode = CullMode::Inverted; - else - cullMode = CullMode::Normal; + cullMode = cullMode == CullMode::Normal ? CullMode::Inverted : CullMode::Normal; } const PipelineStateCache* psCache = _cache.GetPS(view.Pass, useLightmap); ASSERT(psCache); @@ -123,6 +120,7 @@ void TerrainMaterialShader::Bind(BindParameters& params) // Bind pipeline context->SetState(state); + context->SetStencilRef(drawCall.StencilValue); } void TerrainMaterialShader::Unload() @@ -139,6 +137,10 @@ bool TerrainMaterialShader::Load() psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None; psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None; + psDesc.StencilEnable = true; + psDesc.StencilReadMask = 0; + psDesc.StencilPassOp = StencilOperation::Replace; + #if GPU_ALLOW_TESSELLATION_SHADERS // 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 32df730e8..c2f340645 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -218,7 +218,7 @@ bool Mesh::Load(uint32 vertices, uint32 triangles, const void* vb0, const void* return Init(vertices, triangles, vbData, ib, use16BitIndexBuffer, vbLayout); } -void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder) const +void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder, uint8 stencilValue) const { if (!material || !material->IsSurface() || !IsInitialized()) return; @@ -240,8 +240,8 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons drawCall.ObjectRadius = (float)_sphere.Radius * drawCall.World.GetScaleVector().GetAbsolute().MaxValue(); drawCall.Surface.GeometrySize = _box.GetSize(); drawCall.Surface.PrevWorld = world; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = perInstanceRandom; + drawCall.StencilValue = stencilValue; #if USE_EDITOR const ViewMode viewMode = renderContext.View.Mode; if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) @@ -307,8 +307,8 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty; drawCall.Surface.LODDitherFactor = lodDitherFactor; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = info.PerInstanceRandom; + drawCall.StencilValue = info.StencilValue; #if USE_EDITOR const ViewMode viewMode = renderContext.View.Mode; if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) @@ -370,8 +370,8 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty; drawCall.Surface.LODDitherFactor = lodDitherFactor; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = info.PerInstanceRandom; + drawCall.StencilValue = info.StencilValue; #if USE_EDITOR const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode; if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) diff --git a/Source/Engine/Graphics/Models/Mesh.h b/Source/Engine/Graphics/Models/Mesh.h index 63b069f9a..8e273a3d5 100644 --- a/Source/Engine/Graphics/Models/Mesh.h +++ b/Source/Engine/Graphics/Models/Mesh.h @@ -142,7 +142,8 @@ public: /// The draw passes to use for rendering this object. /// The random per-instance value (normalized to range 0-1). /// Object sorting key. - API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const; + /// Object stencil value. + API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0, uint8 stencilValue = 0) const; /// /// Draws the mesh. diff --git a/Source/Engine/Graphics/Models/MeshBase.h b/Source/Engine/Graphics/Models/MeshBase.h index 6a61ec3a5..1c76df166 100644 --- a/Source/Engine/Graphics/Models/MeshBase.h +++ b/Source/Engine/Graphics/Models/MeshBase.h @@ -404,6 +404,11 @@ public: /// float PerInstanceRandom; + /// + /// The 8-bit stencil value to write into Depth-Stencil Buffer. + /// + uint8 StencilValue; + /// /// The LOD bias value. /// @@ -422,6 +427,12 @@ public: #if USE_EDITOR float LightmapScale = -1.0f; #endif + + // Packs object layer into the stencil bits. + FORCE_INLINE void SetStencilValue(int32 layer) + { + StencilValue = uint8(layer & 0x1f); + } }; /// diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index 8c1b98ebf..66b3e5701 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -314,8 +314,8 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info, drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.Skinning = info.Skinning; drawCall.Surface.LODDitherFactor = lodDitherFactor; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = info.PerInstanceRandom; + drawCall.StencilValue = info.StencilValue; // Push draw call to the render list renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals, info.SortOrder); @@ -355,8 +355,8 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.Skinning = info.Skinning; drawCall.Surface.LODDitherFactor = lodDitherFactor; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = info.PerInstanceRandom; + drawCall.StencilValue = info.StencilValue; // Push draw call to the render lists const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode; diff --git a/Source/Engine/Graphics/RenderBuffers.h b/Source/Engine/Graphics/RenderBuffers.h index 647d28c4c..dadd06175 100644 --- a/Source/Engine/Graphics/RenderBuffers.h +++ b/Source/Engine/Graphics/RenderBuffers.h @@ -13,6 +13,17 @@ #define GBUFFER2_FORMAT PixelFormat::R8G8B8A8_UNorm #define GBUFFER3_FORMAT PixelFormat::R8G8B8A8_UNorm +// Stencil bits usage (must match GBuffer.hlsl) +// [0] | Object Layer +// [1] | Object Layer +// [2] | Object Layer +// [3] | Object Layer +// [4] | Object Layer +// [5] | +// [6] | +// [7] | +#define STENCIL_BUFFER_OBJECT_LAYER(value) uint8(value & 0x1f) + /// /// The scene rendering buffers container. /// diff --git a/Source/Engine/Graphics/Textures/GPUTexture.h b/Source/Engine/Graphics/Textures/GPUTexture.h index 85ac4ae0b..184f50c89 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.h +++ b/Source/Engine/Graphics/Textures/GPUTexture.h @@ -437,6 +437,12 @@ public: /// The view to the depth-stencil resource descriptor as read-only depth. API_FUNCTION() virtual GPUTextureView* ViewReadOnlyDepth() const = 0; + /// + /// Gets the view to the texture as stencil buffer. + /// + /// The view to the stencil resource descriptor. + API_FUNCTION() virtual GPUTextureView* ViewStencil() const = 0; + /// /// Implicit conversion to the first surface (only for 2D textures). /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index 2a50fbfd8..a0ec80bb1 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -11,6 +11,7 @@ #include "GPUSamplerDX11.h" #include "GPUVertexLayoutDX11.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" +#include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Math/Rectangle.h" #include "Engine/Profiler/RenderStats.h" @@ -216,7 +217,10 @@ void GPUContextDX11::ClearDepth(GPUTextureView* depthBuffer, float depthValue, u if (depthBufferDX11) { ASSERT(depthBufferDX11->DSV()); - _context->ClearDepthStencilView(depthBufferDX11->DSV(), D3D11_CLEAR_DEPTH, depthValue, stencilValue); + UINT clearFlags = D3D11_CLEAR_DEPTH; + if (PixelFormatExtensions::HasStencil(depthBufferDX11->GetFormat())) + clearFlags |= D3D11_CLEAR_STENCIL; + _context->ClearDepthStencilView(depthBufferDX11->DSV(), clearFlags, depthValue, stencilValue); } } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp index e858f7e3e..a05585696 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp @@ -150,6 +150,7 @@ void GPUTextureDX11::OnReleaseGPU() _handleArray.Release(); _handleVolume.Release(); _handleReadOnlyDepth.Release(); + _handleStencil.Release(); DX_SAFE_RELEASE_CHECK(_resource, 0); // Base @@ -547,6 +548,41 @@ void GPUTextureDX11::initHandles() } _handleReadOnlyDepth.Init(this, rtView, srView, dsView, nullptr, format, msaa); } + + // Stencil view + if (useDSV && useSRV && PixelFormatExtensions::HasStencil(format)) + { + PixelFormat stencilFormat; + switch (_dxgiFormatDSV) + { + case PixelFormat::D24_UNorm_S8_UInt: + srDesc.Format = DXGI_FORMAT_X24_TYPELESS_G8_UINT; + stencilFormat = PixelFormat::X24_Typeless_G8_UInt; + break; + case PixelFormat::D32_Float_S8X24_UInt: + srDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt; + break; + } + if (isCubeMap) + { + srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srDesc.TextureCube.MostDetailedMip = 0; + srDesc.TextureCube.MipLevels = mipLevels; + } + else if (isMsaa) + { + srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + } + else + { + srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srDesc.Texture2D.MostDetailedMip = 0; + srDesc.Texture2D.MipLevels = mipLevels; + } + VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView)); + _handleStencil.Init(this, nullptr, srView, nullptr, nullptr, stencilFormat, msaa); + } } bool GPUTextureDX11::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h index d33c56158..35101e79b 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h @@ -158,6 +158,7 @@ private: GPUTextureViewDX11 _handleArray; GPUTextureViewDX11 _handleVolume; GPUTextureViewDX11 _handleReadOnlyDepth; + GPUTextureViewDX11 _handleStencil; Array _handlesPerSlice; // [slice] Array> _handlesPerMip; // [slice][mip] @@ -225,6 +226,11 @@ public: ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView); return (GPUTextureView*)&_handleReadOnlyDepth; } + GPUTextureView* ViewStencil() const override + { + ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil); + return (GPUTextureView*)&_handleStencil; + } void* GetNativePtr() const override { return static_cast(_resource); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index c68e7f262..64c384447 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -36,6 +36,7 @@ #include "CommandSignatureDX12.h" #include "Engine/Profiler/RenderStats.h" #include "Engine/Graphics/GPUResourceAccess.h" +#include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Threading/Threading.h" @@ -823,7 +824,10 @@ void GPUContextDX12::ClearDepth(GPUTextureView* depthBuffer, float depthValue, u SetResourceState(depthBufferDX12->GetResourceOwner(), D3D12_RESOURCE_STATE_DEPTH_WRITE, depthBufferDX12->SubresourceIndex); flushRBs(); - _commandList->ClearDepthStencilView(depthBufferDX12->DSV(), D3D12_CLEAR_FLAG_DEPTH, depthValue, stencilValue, 0, nullptr); + D3D12_CLEAR_FLAGS clearFlags = D3D12_CLEAR_FLAG_DEPTH; + if (PixelFormatExtensions::HasStencil(depthBufferDX12->GetFormat())) + clearFlags |= D3D12_CLEAR_FLAG_STENCIL; + _commandList->ClearDepthStencilView(depthBufferDX12->DSV(), clearFlags, depthValue, stencilValue, 0, nullptr); } } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp index 5913468ee..abecfd776 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp @@ -227,6 +227,8 @@ void GPUTextureDX12::OnReleaseGPU() _handlesPerSlice.Resize(0, false); _handleArray.Release(); _handleVolume.Release(); + _handleReadOnlyDepth.Release(); + _handleStencil.Release(); _srv.Release(); _uav.Release(); releaseResource(); @@ -721,6 +723,45 @@ void GPUTextureDX12::initHandles() _handleReadOnlyDepth.SetSRV(srDesc); } } + + // Stencil view + if (useDSV && useSRV && PixelFormatExtensions::HasStencil(format)) + { + PixelFormat stencilFormat; + switch (_dxgiFormatDSV) + { + case PixelFormat::D24_UNorm_S8_UInt: + srDesc.Format = DXGI_FORMAT_X24_TYPELESS_G8_UINT; + stencilFormat = PixelFormat::X24_Typeless_G8_UInt; + break; + case PixelFormat::D32_Float_S8X24_UInt: + srDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt; + break; + } + if (isCubeMap) + { + srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + srDesc.TextureCube.MostDetailedMip = 0; + srDesc.TextureCube.MipLevels = mipLevels; + srDesc.TextureCube.ResourceMinLODClamp = 0; + } + else if (isMsaa) + { + srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + } + else + { + srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srDesc.Texture2D.MostDetailedMip = 0; + srDesc.Texture2D.MipLevels = mipLevels; + srDesc.Texture2D.ResourceMinLODClamp = 0; + srDesc.Texture2D.PlaneSlice = 1; + } + _handleStencil.Init(this, _device, this, stencilFormat, msaa); + _handleStencil.ReadOnlyDepthView = true; + _handleStencil.SetSRV(srDesc); + } } #endif diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h index e6427ab6d..b513b5b4f 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h @@ -91,7 +91,7 @@ public: // [IShaderResourceDX12] bool IsDepthStencilResource() const override { - return _dsv.IsValid(); + return ReadOnlyDepthView || _dsv.IsValid(); } D3D12_CPU_DESCRIPTOR_HANDLE SRV() const override { @@ -117,6 +117,7 @@ private: GPUTextureViewDX12 _handleArray; GPUTextureViewDX12 _handleVolume; GPUTextureViewDX12 _handleReadOnlyDepth; + GPUTextureViewDX12 _handleStencil; Array _handlesPerSlice; // [slice] Array> _handlesPerMip; // [slice][mip] @@ -165,6 +166,11 @@ public: ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView); return (GPUTextureView*)&_handleReadOnlyDepth; } + GPUTextureView* ViewStencil() const override + { + ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil); + return (GPUTextureView*)&_handleStencil; + } void* GetNativePtr() const override { return (void*)_resource; diff --git a/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h b/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h index 25b204184..23e7d2b54 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h @@ -33,6 +33,10 @@ public: { return nullptr; } + GPUTextureView* ViewStencil() const override + { + return nullptr; + } void* GetNativePtr() const override { return nullptr; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp index 326c87e8d..52f347959 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp @@ -11,7 +11,7 @@ #include "Engine/Graphics/Textures/TextureData.h" #include "Engine/Scripting/Enums.h" -void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels, int32 firstMipIndex, int32 arraySize, int32 firstArraySlice, bool readOnlyDepth) +void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels, int32 firstMipIndex, int32 arraySize, int32 firstArraySlice, bool readOnlyDepth, bool stencilView) { ASSERT(View == VK_NULL_HANDLE); @@ -57,7 +57,13 @@ void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* ow SubresourceIndex = RenderTools::CalcSubresourceIndex(firstMipIndex, firstArraySlice, totalMipLevels); } - if (PixelFormatExtensions::IsDepthStencil(format)) + if (stencilView) + { + range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + LayoutRTV = readOnlyDepth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + LayoutSRV = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + } + else if (PixelFormatExtensions::IsDepthStencil(format)) { range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; #if 0 @@ -157,13 +163,23 @@ void GPUTextureViewVulkan::DescriptorAsImage(GPUContextVulkan* context, VkImageV imageView = View; layout = LayoutSRV; const VkImageAspectFlags aspectMask = Info.subresourceRange.aspectMask; - if (aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + if (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - // Transition depth-only when binding depth buffer with stencil + // Transition depth-only when binding depth buffer with stencil (or stencil-only without depth) if (ViewSRV == VK_NULL_HANDLE) { VkImageViewCreateInfo createInfo = Info; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) + { + // Stencil + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + createInfo.components.g = VK_COMPONENT_SWIZZLE_R; // Map .g component in shader to .r of stencil plane + } + else + { + // Depth + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + } VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewSRV)); } imageView = ViewSRV; @@ -434,6 +450,26 @@ void GPUTextureVulkan::initHandles() { _handleReadOnlyDepth.Init(_device, this, _image, mipLevels, format, msaa, extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, 0, 1, 0, true); } + + // Stencil view + if (IsDepthStencil() && IsShaderResource() && PixelFormatExtensions::HasStencil(format)) + { + PixelFormat stencilFormat; + switch (format) + { + case PixelFormat::D24_UNorm_S8_UInt: + case PixelFormat::R24_UNorm_X8_Typeless: + case PixelFormat::R24G8_Typeless: + stencilFormat = PixelFormat::X24_Typeless_G8_UInt; + break; + case PixelFormat::D32_Float_S8X24_UInt: + case PixelFormat::R32_Float_X8X24_Typeless: + case PixelFormat::R32G8X24_Typeless: + stencilFormat = PixelFormat::X32_Typeless_G8X24_UInt; + break; + } + _handleStencil.Init(_device, this, _image, mipLevels, stencilFormat, msaa, extent, VK_IMAGE_VIEW_TYPE_2D, mipLevels, 0, 1, 0, true, true); + } } void GPUTextureVulkan::OnResidentMipsChanged() @@ -457,6 +493,7 @@ void GPUTextureVulkan::OnReleaseGPU() _handleVolume.Release(); _handleUAV.Release(); _handleReadOnlyDepth.Release(); + _handleStencil.Release(); for (int32 i = 0; i < _handlesPerMip.Count(); i++) { for (int32 j = 0; j < _handlesPerMip[i].Count(); j++) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h index 999e0f602..178938b82 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h @@ -45,7 +45,7 @@ public: #endif public: - void Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels = 1, int32 firstMipIndex = 0, int32 arraySize = 1, int32 firstArraySlice = 0, bool readOnlyDepth = false); + void Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* owner, VkImage image, int32 totalMipLevels, PixelFormat format, MSAALevel msaa, VkExtent3D extent, VkImageViewType viewType, int32 mipLevels = 1, int32 firstMipIndex = 0, int32 arraySize = 1, int32 firstArraySlice = 0, bool readOnlyDepth = false, bool stencilView = false); VkImageView GetFramebufferView(); @@ -79,6 +79,7 @@ private: GPUTextureViewVulkan _handleVolume; GPUTextureViewVulkan _handleUAV; GPUTextureViewVulkan _handleReadOnlyDepth; + GPUTextureViewVulkan _handleStencil; Array _handlesPerSlice; // [slice] Array> _handlesPerMip; // [slice][mip] @@ -140,6 +141,11 @@ public: ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView); return (GPUTextureView*)&_handleReadOnlyDepth; } + GPUTextureView* ViewStencil() const override + { + ASSERT(_desc.Flags & GPUTextureFlags::DepthStencil); + return (GPUTextureView*)&_handleStencil; + } void* GetNativePtr() const override { return (void*)_image; diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 18342dbbb..ee66c6c77 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -1027,6 +1027,7 @@ void AnimatedModel::Draw(RenderContext& renderContext) draw.LODBias = LODBias; draw.ForcedLOD = ForcedLOD; draw.SortOrder = SortOrder; + draw.SetStencilValue(_layer); SkinnedModel->Draw(renderContext, draw); } @@ -1068,6 +1069,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch) draw.LODBias = LODBias; draw.ForcedLOD = ForcedLOD; draw.SortOrder = SortOrder; + draw.SetStencilValue(_layer); PRAGMA_DISABLE_DEPRECATION_WARNINGS if (ShadowsMode != ShadowsCastingMode::All) diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp index 490f9d786..4a7d2aa75 100644 --- a/Source/Engine/Level/Actors/Camera.cpp +++ b/Source/Engine/Level/Actors/Camera.cpp @@ -374,6 +374,7 @@ void Camera::Draw(RenderContext& renderContext) BoundingSphere::FromBox(_previewModelBox, draw.Bounds); draw.Bounds.Center -= renderContext.View.Origin; draw.PerInstanceRandom = GetPerInstanceRandom(); + draw.StencilValue = 0; draw.LODBias = 0; draw.ForcedLOD = -1; draw.SortOrder = 0; diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp index e08d8a61a..dbda65d3f 100644 --- a/Source/Engine/Level/Actors/Skybox.cpp +++ b/Source/Engine/Level/Actors/Skybox.cpp @@ -107,7 +107,6 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M drawCall.ObjectPosition = drawCall.World.GetTranslation(); drawCall.ObjectRadius = (float)_sphere.Radius; drawCall.Surface.GeometrySize = _box.GetSize(); - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = GetPerInstanceRandom(); MaterialBase::BindParameters bindParams(context, renderContext, drawCall); bindParams.BindViewData(); diff --git a/Source/Engine/Level/Actors/SplineModel.cpp b/Source/Engine/Level/Actors/SplineModel.cpp index 8680fb8d5..42b2dc620 100644 --- a/Source/Engine/Level/Actors/SplineModel.cpp +++ b/Source/Engine/Level/Actors/SplineModel.cpp @@ -407,12 +407,12 @@ void SplineModel::Draw(RenderContext& renderContext) drawCall.Deformable.MeshMaxZ = _meshMaxZ; drawCall.Deformable.GeometrySize = _box.GetSize(); drawCall.PerInstanceRandom = GetPerInstanceRandom(); + drawCall.SetStencilValue(_layer); _preTransform.GetWorld(drawCall.Deformable.LocalMatrix); const Transform splineTransform = GetTransform(); renderContext.View.GetWorldMatrix(splineTransform, drawCall.World); drawCall.ObjectPosition = drawCall.World.GetTranslation() + drawCall.Deformable.LocalMatrix.GetTranslation(); drawCall.ObjectRadius = (float)_sphere.Radius; // TODO: use radius for the spline chunk rather than whole spline - const float worldDeterminantSign = drawCall.World.RotDeterminant() * drawCall.Deformable.LocalMatrix.RotDeterminant(); for (int32 segment = 0; segment < _instances.Count(); segment++) { auto& instance = _instances[segment]; @@ -468,7 +468,6 @@ void SplineModel::Draw(RenderContext& renderContext) // Submit draw call mesh->GetDrawCallGeometry(drawCall); drawCall.Material = material; - drawCall.WorldDeterminantSign = Math::FloatSelect(worldDeterminantSign * instance.RotDeterminant, 1, -1); renderContext.List->AddDrawCall(renderContext, drawModes, _staticFlags, drawCall, entry.ReceiveDecals); } } diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index 912009b3b..f41e4a805 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -361,6 +361,7 @@ void StaticModel::Draw(RenderContext& renderContext) draw.ForcedLOD = _forcedLod; draw.SortOrder = _sortOrder; draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr; + draw.SetStencilValue(_layer); #if USE_EDITOR if (HasStaticFlag(StaticFlags::Lightmap)) draw.LightmapScale = _scaleInLightmap; @@ -397,6 +398,7 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch) draw.ForcedLOD = _forcedLod; draw.SortOrder = _sortOrder; draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr; + draw.SetStencilValue(_layer); #if USE_EDITOR if (HasStaticFlag(StaticFlags::Lightmap)) draw.LightmapScale = _scaleInLightmap; diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index 487bc4b03..03da3e324 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -1168,9 +1168,6 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf Matrix worlds[2]; Matrix::Translation(-viewOrigin, worlds[0]); // World renderContextBatch.GetMainContext().View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local - float worldDeterminantSigns[2]; - worldDeterminantSigns[0] = Math::FloatSelect(worlds[0].RotDeterminant(), 1, -1); - worldDeterminantSigns[1] = Math::FloatSelect(worlds[1].RotDeterminant(), 1, -1); const StaticFlags staticFlags = effect->GetStaticFlags(); const int8 sortOrder = effect->SortOrder; @@ -1194,6 +1191,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf // Setup a draw call common data DrawCall drawCall; drawCall.PerInstanceRandom = effect->GetPerInstanceRandom(); + drawCall.SetStencilValue(effect->GetLayer()); drawCall.ObjectPosition = bounds.Center; drawCall.ObjectRadius = (float)bounds.Radius; @@ -1209,7 +1207,6 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf continue; drawCall.World = worlds[(int32)emitter->SimulationSpace]; - drawCall.WorldDeterminantSign = worldDeterminantSigns[(int32)emitter->SimulationSpace]; drawCall.Particle.Particles = buffer; // Check if need to render any module diff --git a/Source/Engine/Renderer/DrawCall.h b/Source/Engine/Renderer/DrawCall.h index 1a8d23285..b71b64874 100644 --- a/Source/Engine/Renderer/DrawCall.h +++ b/Source/Engine/Renderer/DrawCall.h @@ -265,16 +265,23 @@ struct DrawCall /// float ObjectRadius; - /// - /// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling). - /// - float WorldDeterminantSign; - /// /// The random per-instance value (normalized to range 0-1). /// float PerInstanceRandom; + /// + /// The 8-bit stencil value to write into Depth-Stencil Buffer. + /// + uint8 StencilValue; + + /// + /// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling). + /// 0 - sign is positive + /// 1 - sign is negative (flips object surfaces) + /// + uint8 WorldDeterminant : 1; + /// /// The sorting key for the draw call calculate by RenderList. /// @@ -287,6 +294,12 @@ struct DrawCall { Platform::MemoryClear(this, sizeof(DrawCall)); } + + // Packs object layer into the stencil bits. + FORCE_INLINE void SetStencilValue(int32 layer) + { + StencilValue = uint8(layer & 0x1f); + } }; template<> diff --git a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp index 41283f63e..eb4afc26c 100644 --- a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp +++ b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp @@ -129,8 +129,6 @@ void MaterialComplexityMaterialShader::Draw(RenderContext& renderContext, GPUCon DrawCall drawCall; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); bindParams.BindViewData(); - drawCall.WorldDeterminantSign = 1.0f; - drawCall.PerInstanceRandom = 0.0f; context->SetRenderTarget(lightBuffer); for (int32 i = 0; i < decals.Count(); i++) { diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index c6804f300..3c38d11a4 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -50,8 +50,6 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, context->BindUA(1, overdrawTexture->View()); context->BindUA(2, liveCountTexture->View()); DrawCall drawCall; - drawCall.WorldDeterminantSign = 1.0f; - drawCall.PerInstanceRandom = 0.0f; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); bindParams.BindViewData(); renderContext.View.Pass = DrawPass::QuadOverdraw; @@ -83,7 +81,6 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, m1 *= m2; drawCall.World = m1; drawCall.ObjectPosition = drawCall.World.GetTranslation(); - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); skyMaterial->Bind(bindParams); skyModel->Render(context); } diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 72b9a4e20..bb580aaf3 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -564,7 +564,8 @@ FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall& IMaterial::InstancingHandler handler; if (drawCall.Material->CanUseInstancing(handler)) handler.GetHash(drawCall, batchKey); - uint32 drawKey = (uint32)(471 * drawCall.WorldDeterminantSign); + batchKey = (batchKey * 397) ^ drawCall.StencilValue; + uint32 drawKey = (uint32)(471 * drawCall.WorldDeterminant); drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]); drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]); drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]); @@ -586,8 +587,11 @@ void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawMo ASSERT_LOW_LAYER(drawModes != DrawPass::None && ((uint32)drawModes & ~(uint32)materialDrawModes) == 0); #endif - // Append draw call data + // Finalize draw call initialization + drawCall.WorldDeterminant = drawCall.World.RotDeterminant() < 0 ? 1 : 0; CalculateSortKey(renderContext, drawCall, sortOrder); + + // Append draw call data const int32 index = DrawCalls.Add(drawCall); // Add draw call to proper draw lists @@ -625,8 +629,11 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP #endif const RenderContext& mainRenderContext = renderContextBatch.Contexts.Get()[0]; - // Append draw call data + // Finalize draw call initialization + drawCall.WorldDeterminant = drawCall.World.RotDeterminant() < 0 ? 1 : 0; CalculateSortKey(mainRenderContext, drawCall, sortOrder); + + // Append draw call data const int32 index = DrawCalls.Add(drawCall); // Add draw call to proper draw lists @@ -777,7 +784,8 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD other.InstanceCount != 0 && drawCallHandler.CanBatch == otherHandler.CanBatch && drawCallHandler.CanBatch(drawCall, other, pass) && - drawCall.WorldDeterminantSign * other.WorldDeterminantSign > 0; + drawCall.WorldDeterminant == other.WorldDeterminant && + drawCall.StencilValue == other.StencilValue; if (!canBatch) break; batchSize++; diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h index 24262162d..fc11b26cc 100644 --- a/Source/Engine/Renderer/RenderList.h +++ b/Source/Engine/Renderer/RenderList.h @@ -651,13 +651,15 @@ GPU_CB_STRUCT(ShaderObjectData FORCE_INLINE void Store(const DrawCall& drawCall) { - Store(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminantSign, drawCall.Surface.LODDitherFactor); + Store(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminant ? -1.0f : 1.0f, drawCall.Surface.LODDitherFactor); } FORCE_INLINE void Load(DrawCall& drawCall) const { - Load(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, drawCall.WorldDeterminantSign, drawCall.Surface.LODDitherFactor); + float worldDeterminantSign; + Load(drawCall.World, drawCall.Surface.PrevWorld, drawCall.Surface.LightmapUVsArea, drawCall.Surface.GeometrySize, drawCall.PerInstanceRandom, worldDeterminantSign, drawCall.Surface.LODDitherFactor); drawCall.ObjectPosition = drawCall.World.GetTranslation(); + drawCall.WorldDeterminant = worldDeterminantSign < 0 ? 1 : 0; } }); diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp index 513f6af97..d1bcb7842 100644 --- a/Source/Engine/Terrain/TerrainChunk.cpp +++ b/Source/Engine/Terrain/TerrainChunk.cpp @@ -122,8 +122,8 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const drawCall.Terrain.Lightmap = nullptr; drawCall.Terrain.LightmapUVsArea = Rectangle::Empty; } - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = _perInstanceRandom; + drawCall.SetStencilValue(_patch->_terrain->GetLayer()); #if USE_EDITOR if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader @@ -183,8 +183,8 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi drawCall.Terrain.Lightmap = nullptr; drawCall.Terrain.LightmapUVsArea = Rectangle::Empty; } - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = _perInstanceRandom; + drawCall.SetStencilValue(_patch->_terrain->GetLayer()); #if USE_EDITOR if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index 52132b972..c2f6789c7 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -390,8 +390,8 @@ void TextRender::Draw(RenderContext& renderContext) drawCall.ObjectRadius = (float)_sphere.Radius; drawCall.Surface.GeometrySize = _localBox.GetSize(); drawCall.Surface.PrevWorld = _drawState.PrevWorld; - drawCall.WorldDeterminantSign = RenderTools::GetWorldDeterminantSign(drawCall.World); drawCall.PerInstanceRandom = GetPerInstanceRandom(); + drawCall.SetStencilValue(_layer); drawCall.Geometry.IndexBuffer = _ib.GetBuffer(); drawCall.Geometry.VertexBuffers[0] = _vb.GetBuffer(); drawCall.InstanceCount = 1; diff --git a/Source/Shaders/Stencil.hlsl b/Source/Shaders/Stencil.hlsl new file mode 100644 index 000000000..7cb72f024 --- /dev/null +++ b/Source/Shaders/Stencil.hlsl @@ -0,0 +1,23 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +#ifndef __STENCIL__ +#define __STENCIL__ + +#include "./Flax/Common.hlsl" + +// Stencil bits usage (must match RenderBuffers.h) +// [0] | Object Layer +// [1] | Object Layer +// [2] | Object Layer +// [3] | Object Layer +// [4] | Object Layer +// [5] | +// [6] | +// [7] | +#define STENCIL_BUFFER_OBJECT_LAYER(stencil) uint(stencil & 0x1f) +#ifndef STENCIL_BUFFER_SWIZZLE +#define STENCIL_BUFFER_SWIZZLE .g +#endif +#define STENCIL_BUFFER_LOAD(rt, pos) rt.Load(int3(pos, 0)) STENCIL_BUFFER_SWIZZLE + +#endif From d3c54e590a802a80aed581ac310228fc43581ba6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:08:32 +0200 Subject: [PATCH 116/137] Fix quad overdraw debug drawing regression --- Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index 3c38d11a4..f5e264c86 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -60,11 +60,12 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, if (boxModel && boxModel->CanBeRendered() && defaultMaterial && defaultMaterial->IsReady()) { // Draw decals - for (int32 i = 0; i < renderContext.List->Decals.Count(); i++) + PROFILE_GPU_CPU_NAMED("Decals"); + for (const RenderDecalData& decal : renderContext.List->Decals) { - const RenderDecalData& decal = renderContext.List->Decals.Get()[i]; drawCall.World = decal.World; defaultMaterial->Bind(bindParams); + bindParams.BindDrawData(); boxModel->Render(context); } } @@ -74,6 +75,7 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, if (renderContext.List->Sky && skyModel && skyModel->CanBeRendered() && skyMaterial && skyMaterial->IsReady()) { // Draw sky + PROFILE_GPU_CPU_NAMED("Sky"); auto box = skyModel->GetBox(); Matrix m1, m2; Matrix::Scaling(renderContext.View.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); @@ -81,6 +83,7 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, m1 *= m2; drawCall.World = m1; drawCall.ObjectPosition = drawCall.World.GetTranslation(); + bindParams.BindDrawData(); skyMaterial->Bind(bindParams); skyModel->Render(context); } From fc1451254dad9c716dfaad13d17e20d807370971 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:08:51 +0200 Subject: [PATCH 117/137] Fix missing terrain debug shapes drawing when only in a view --- Source/Engine/Debug/DebugDraw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index 2f063e2c6..7c798f88f 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -853,7 +853,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe auto vb = DebugDrawVB->GetBuffer(); // Draw with depth test - if (depthTestLines.VertexCount + depthTestTriangles.VertexCount + depthTestWireTriangles.VertexCount > 0) + if (depthTestLines.VertexCount + depthTestTriangles.VertexCount + depthTestWireTriangles.VertexCount + Context->DebugDrawDepthTest.GeometryBuffers.Count() > 0) { if (data.EnableDepthTest) context->BindSR(0, renderContext.Buffers->DepthBuffer); @@ -909,7 +909,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe } // Draw without depth - if (defaultLines.VertexCount + defaultTriangles.VertexCount + defaultWireTriangles.VertexCount > 0) + if (defaultLines.VertexCount + defaultTriangles.VertexCount + defaultWireTriangles.VertexCount + Context->DebugDrawDefault.GeometryBuffers.Count() > 0) { context->SetRenderTarget(target); From f8dbf363b6112c033dd0225462227ca17c2ec75c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:09:18 +0200 Subject: [PATCH 118/137] Fix crash on Android when loading mesh with SDF data --- Source/Engine/Content/Assets/Model.cpp | 3 +++ Source/Engine/Content/Storage/FlaxStorageReference.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp index 1830f40de..829eaeb11 100644 --- a/Source/Engine/Content/Assets/Model.cpp +++ b/Source/Engine/Content/Assets/Model.cpp @@ -33,12 +33,14 @@ class StreamModelSDFTask : public GPUUploadTextureMipTask { private: WeakAssetReference _asset; + FlaxStorageReference _dataRef; FlaxStorage::LockData _dataLock; public: StreamModelSDFTask(Model* model, GPUTexture* texture, const Span& data, int32 mipIndex, int32 rowPitch, int32 slicePitch) : GPUUploadTextureMipTask(texture, mipIndex, data, rowPitch, slicePitch, false) , _asset(model) + , _dataRef(model->Storage) , _dataLock(model->Storage->Lock()) { } @@ -59,6 +61,7 @@ public: void OnEnd() override { _dataLock.Release(); + _dataRef = FlaxStorageReference(); // Base GPUUploadTextureMipTask::OnEnd(); diff --git a/Source/Engine/Content/Storage/FlaxStorageReference.h b/Source/Engine/Content/Storage/FlaxStorageReference.h index 94929baa4..402e312d8 100644 --- a/Source/Engine/Content/Storage/FlaxStorageReference.h +++ b/Source/Engine/Content/Storage/FlaxStorageReference.h @@ -13,6 +13,11 @@ private: FlaxStorage* _storage; public: + FlaxStorageReference() + : _storage(nullptr) + { + } + FlaxStorageReference(FlaxStorage* storage) : _storage(storage) { From 2f1f3800622f989039e62b690a09161beaff5074 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:10:14 +0200 Subject: [PATCH 119/137] Add new scene textures `SceneStencil` and `ObjectLayer` to sample Stencil buffer --- Source/Engine/Graphics/Materials/MaterialInfo.h | 10 ++++++++++ .../Graphics/Materials/MaterialParams.cpp | 4 ++++ .../GPU/ParticleEmitterGraph.GPU.Textures.cpp | 2 ++ .../MaterialGenerator.Textures.cpp | 17 +++++++++++++++++ Source/Engine/Visject/ShaderGraphUtilities.cpp | 5 ++++- 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Graphics/Materials/MaterialInfo.h b/Source/Engine/Graphics/Materials/MaterialInfo.h index 69a9bd0a6..84771fed8 100644 --- a/Source/Engine/Graphics/Materials/MaterialInfo.h +++ b/Source/Engine/Graphics/Materials/MaterialInfo.h @@ -444,6 +444,16 @@ API_ENUM() enum class MaterialSceneTextures /// The scene world-space position (relative to the render view origin). /// WorldPosition = 11, + + /// + /// The scene stencil. + /// + SceneStencil = 12, + + /// + /// The object layer index. + /// + ObjectLayer = 13, }; /// diff --git a/Source/Engine/Graphics/Materials/MaterialParams.cpp b/Source/Engine/Graphics/Materials/MaterialParams.cpp index 2fa5a8e5f..05bb29c4a 100644 --- a/Source/Engine/Graphics/Materials/MaterialParams.cpp +++ b/Source/Engine/Graphics/Materials/MaterialParams.cpp @@ -393,6 +393,10 @@ void MaterialParameter::Bind(BindMeta& meta) const case MaterialSceneTextures::Specular: view = meta.CanSampleGBuffer ? meta.Buffers->GBuffer2->View() : nullptr; break; + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: + view = meta.CanSampleDepth ? meta.Buffers->DepthBuffer->ViewStencil() : nullptr; + break; default: ; } } diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp index 820f8da3d..ed4f5f0e3 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Textures.cpp @@ -246,6 +246,8 @@ void ParticleEmitterGPUGenerator::ProcessGroupTextures(Box* box, Node* node, Val break; } case MaterialSceneTextures::WorldPosition: + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: value = Value::Zero; // Not implemented break; default: diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp index 6bd88f2ae..c48a4c569 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp @@ -474,6 +474,23 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) value = writeLocal(VariantType::Float3, String::Format(TEXT("GetWorldPos({1}, {0}.rgb)"), depthSample->Value, uv), node); break; } + case MaterialSceneTextures::SceneStencil: + case MaterialSceneTextures::ObjectLayer: + { + auto stencilParam = findOrAddSceneTexture(MaterialSceneTextures::SceneStencil); + const auto parent = box->GetParent>(); + MaterialGraphBox* uvBox = parent->GetBox(0); + bool useCustomUVs = uvBox->HasConnection(); + String uv; + if (useCustomUVs) + uv = MaterialValue::Cast(tryGetValue(uvBox, getUVs), VariantType::Float2).Value; + else + uv = TEXT("input.TexCoord.xy"); + const Char* func = type == MaterialSceneTextures::ObjectLayer ? TEXT("STENCIL_BUFFER_OBJECT_LAYER") : TEXT(""); + value = writeLocal(VariantType::Int, String::Format(TEXT("{2}(STENCIL_BUFFER_LOAD({0}, {1} * ScreenSize.xy))"), stencilParam.ShaderName, uv, func), node); + _includes.Add(TEXT("./Flax/Stencil.hlsl")); + break; + } default: { // Sample single texture diff --git a/Source/Engine/Visject/ShaderGraphUtilities.cpp b/Source/Engine/Visject/ShaderGraphUtilities.cpp index 83db4590a..bdcb55c05 100644 --- a/Source/Engine/Visject/ShaderGraphUtilities.cpp +++ b/Source/Engine/Visject/ShaderGraphUtilities.cpp @@ -157,7 +157,10 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri case MaterialParameterType::GPUTexture: case MaterialParameterType::SceneTexture: case MaterialParameterType::Texture: - format = TEXT("Texture2D {0} : register(t{1});"); + if (param.AsInteger == (int32)MaterialSceneTextures::SceneStencil) + format = TEXT("Texture2D {0} : register(t{1});"); + else + format = TEXT("Texture2D {0} : register(t{1});"); break; case MaterialParameterType::GPUTextureCube: case MaterialParameterType::CubeTexture: From 39803ce6b29a0aa59ea4ba22a38e7130bc3763ac Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:23:03 +0200 Subject: [PATCH 120/137] Add **render layer mask to decals** #967 #3080 --- Content/Editor/MaterialTemplates/Decal.shader | 12 ++++++++++++ .../Graphics/Materials/DecalMaterialShader.cpp | 4 ++++ Source/Engine/Graphics/Materials/MaterialShader.h | 2 +- Source/Engine/Level/Actors/Decal.cpp | 3 +++ Source/Engine/Level/Actors/Decal.h | 7 +++++++ Source/Engine/Renderer/GBufferPass.cpp | 1 + Source/Engine/Renderer/RenderList.h | 1 + .../Tools/MaterialGenerator/MaterialGenerator.cpp | 2 +- 8 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Decal.shader b/Content/Editor/MaterialTemplates/Decal.shader index b933fcbb3..c958d8a4a 100644 --- a/Content/Editor/MaterialTemplates/Decal.shader +++ b/Content/Editor/MaterialTemplates/Decal.shader @@ -6,6 +6,7 @@ @3 #include "./Flax/Common.hlsl" +#include "./Flax/Stencil.hlsl" #include "./Flax/MaterialCommon.hlsl" #include "./Flax/GBufferCommon.hlsl" @7 @@ -14,10 +15,13 @@ META_CB_BEGIN(0, Data) float4x4 WorldMatrix; float4x4 InvWorld; float4x4 SvPositionToWorld; +float3 Padding0; +uint RenderLayersMask; @1META_CB_END // Use depth buffer for per-pixel decal layering Texture2D DepthBuffer : register(t0); +Texture2D StencilBuffer : register(t1); // Material shader resources @2 @@ -200,6 +204,14 @@ void PS_Decal( #endif ) { + // Stencil masking + uint stencilObjectLayer = STENCIL_BUFFER_OBJECT_LAYER(STENCIL_BUFFER_LOAD(StencilBuffer, SvPosition.xy)); + if ((RenderLayersMask & (1 << stencilObjectLayer)) == 0) + { + clip(-1); + return; + } + float2 screenUV = SvPosition.xy * ScreenSize.zw; SvPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r; diff --git a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp index ffc8fa241..7cf9c96d1 100644 --- a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp @@ -17,6 +17,8 @@ PACK_STRUCT(struct DecalMaterialShaderData { Matrix WorldMatrix; Matrix InvWorld; Matrix SvPositionToWorld; + Float3 Padding0; + uint32 RenderLayersMask; }); DrawPass DecalMaterialShader::GetDrawModes() const @@ -50,6 +52,7 @@ void DecalMaterialShader::Bind(BindParameters& params) GPUTexture* depthBuffer = params.RenderContext.Buffers->DepthBuffer; GPUTextureView* depthBufferView = EnumHasAnyFlags(depthBuffer->Flags(), GPUTextureFlags::ReadOnlyDepthView) ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View(); context->BindSR(0, depthBufferView); + context->BindSR(1, depthBuffer->ViewStencil()); // Setup material constants { @@ -68,6 +71,7 @@ void DecalMaterialShader::Bind(BindParameters& params) -1.0f, 1.0f, 0, 1); const Matrix svPositionToWorld = offsetMatrix * view.IVP; Matrix::Transpose(svPositionToWorld, materialData->SvPositionToWorld); + materialData->RenderLayersMask = (uint32)drawCall.SortKey; // Provided by GBufferPass::DrawDecals } // Bind constants diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index c45fd3748..5da4ee04f 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 177 +#define MATERIAL_GRAPH_VERSION 178 class Material; class GPUShader; diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp index 82661b131..78066133c 100644 --- a/Source/Engine/Level/Actors/Decal.cpp +++ b/Source/Engine/Level/Actors/Decal.cpp @@ -87,6 +87,7 @@ void Decal::Draw(RenderContext& renderContext) transform.Scale *= _size; renderContext.View.GetWorldMatrix(transform, data.World); data.SortOrder = SortOrder; + data.RenderLayersMask = RenderLayersMask; data.Material = material; renderContext.List->Decals.Add(data); } @@ -102,6 +103,7 @@ void Decal::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE(Material); SERIALIZE_MEMBER(Size, _size); SERIALIZE(SortOrder); + SERIALIZE(RenderLayersMask); SERIALIZE(DrawMinScreenSize); } @@ -113,6 +115,7 @@ void Decal::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) DESERIALIZE(Material); DESERIALIZE_MEMBER(Size, _size); DESERIALIZE(SortOrder); + DESERIALIZE(RenderLayersMask); DESERIALIZE(DrawMinScreenSize); _bounds.Extents = _size * 0.5f; diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h index 3adfdcbac..068a4447e 100644 --- a/Source/Engine/Level/Actors/Decal.h +++ b/Source/Engine/Level/Actors/Decal.h @@ -3,6 +3,7 @@ #pragma once #include "../Actor.h" +#include "Engine/Core/Types/LayersMask.h" #include "Engine/Core/Math/Matrix.h" #include "Engine/Core/Math/OrientedBoundingBox.h" #include "Engine/Content/Assets/MaterialBase.h" @@ -33,6 +34,12 @@ public: API_FIELD(Attributes="EditorOrder(20), EditorDisplay(\"Decal\")") int32 SortOrder = 0; + /// + /// The layers mask used for render composition. Can be used to include or exclude specific actor layers from the drawing on top of them. + /// + API_FIELD(Attributes = "EditorOrder(25), EditorDisplay(\"Decal\")") + LayersMask RenderLayersMask; + /// /// The minimum screen size for the decal drawing. If the decal size on the screen is smaller than this value then decal will be culled. Set it to higher value to make culling more aggressive. /// diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 7c9abb413..1881aac3b 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -518,6 +518,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light // Draw decal drawCall.World = decal.World; + drawCall.SortKey = (uint64)decal.RenderLayersMask; decal.Material->Bind(bindParams); // TODO: use hardware instancing context->DrawIndexed(drawCall.Draw.IndicesCount); diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h index fc11b26cc..7a3ac867a 100644 --- a/Source/Engine/Renderer/RenderList.h +++ b/Source/Engine/Renderer/RenderList.h @@ -167,6 +167,7 @@ struct RenderDecalData Matrix World; MaterialBase* Material; int32 SortOrder; + uint32 RenderLayersMask; }; /// diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index 46368cf73..c473f940c 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -490,7 +490,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo srv = 3; // Objects + Skinning Bones + Prev Bones break; case MaterialDomain::Decal: - srv = 1; // Depth buffer + srv = 2; // Depth buffer + Stencil buffer break; case MaterialDomain::Terrain: srv = 3; // Heightmap + 2 splatmaps From 7b643e9685581638a2d840b03a864d11f464625d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:23:39 +0200 Subject: [PATCH 121/137] Fix volumetric fog particles drawing regression --- Source/Engine/Particles/Particles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index 03da3e324..951b657b2 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -1272,7 +1272,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf !material->IsReady() || material->GetInfo().Domain != MaterialDomain::VolumeParticle || (renderContextBatch.GetMainContext().View.Flags & ViewFlags::Fog) == ViewFlags::None || - drawMainView + !drawMainView ) break; renderModulesIndices |= 1u << moduleIndex; From 8cb67f017a0828eb9e6a42981bae0086be6a6db8 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 7 Oct 2025 18:23:53 +0200 Subject: [PATCH 122/137] Fix PlayStation build regression --- .../Engine/Platform/Unix/UnixFileSystem.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Source/Engine/Platform/Unix/UnixFileSystem.cpp b/Source/Engine/Platform/Unix/UnixFileSystem.cpp index 1fb47f0f5..528df5b88 100644 --- a/Source/Engine/Platform/Unix/UnixFileSystem.cpp +++ b/Source/Engine/Platform/Unix/UnixFileSystem.cpp @@ -2,6 +2,8 @@ #if PLATFORM_UNIX +#define HAS_DIRS !PLATFORM_PS4 && !PLATFORM_PS5 + #include "UnixFileSystem.h" #include "Engine/Platform/File.h" #include "Engine/Core/Types/TimeSpan.h" @@ -13,7 +15,9 @@ #include #include #include +#if HAS_DIRS #include +#endif #if PLATFORM_MAC || PLATFORM_IOS typedef StringAsANSI<> UnixString; @@ -48,6 +52,8 @@ bool UnixFileSystem::CreateDirectory(const StringView& path) return mkdir(pathAnsi.Get(), 0755) != 0 && errno != EEXIST; } +#if HAS_DIRS + bool DeleteUnixPathTree(const char* path) { size_t pathLength; @@ -114,8 +120,11 @@ bool DeleteUnixPathTree(const char* path) return false; } +#endif + bool UnixFileSystem::DeleteDirectory(const String& path, bool deleteContents) { +#if HAS_DIRS const UnixString pathANSI(*path, path.Length()); if (deleteContents) { @@ -125,6 +134,9 @@ bool UnixFileSystem::DeleteDirectory(const String& path, bool deleteContents) { return rmdir(pathANSI.Get()) != 0; } +#else + return true; +#endif } bool UnixFileSystem::DirectoryExists(const StringView& path) @@ -151,6 +163,7 @@ bool UnixFileSystem::DirectoryGetFiles(Array& results, const String& pat bool UnixFileSystem::GetChildDirectories(Array& results, const String& path) { +#if HAS_DIRS size_t pathLength; DIR* dir; struct stat statPath, statEntry; @@ -206,6 +219,9 @@ bool UnixFileSystem::GetChildDirectories(Array& results, const String& p closedir(dir); return false; +#else + return true; +#endif } bool UnixFileSystem::FileExists(const StringView& path) @@ -243,12 +259,16 @@ uint64 UnixFileSystem::GetFileSize(const StringView& path) bool UnixFileSystem::IsReadOnly(const StringView& path) { +#if HAS_DIRS const UnixString pathANSI(*path, path.Length()); if (access(pathANSI.Get(), W_OK) == -1) { return errno == EACCES; } return false; +#else + return true; +#endif } bool UnixFileSystem::SetReadOnly(const StringView& path, bool isReadOnly) @@ -299,6 +319,7 @@ bool UnixFileSystem::MoveFile(const StringView& dst, const StringView& src, bool bool UnixFileSystem::getFilesFromDirectoryTop(Array& results, const char* path, const char* searchPattern) { +#if HAS_DIRS size_t pathLength; struct stat statPath, statEntry; struct dirent* entry; @@ -389,10 +410,14 @@ bool UnixFileSystem::getFilesFromDirectoryTop(Array& results, const char closedir(dir); return false; +#else + return true; +#endif } bool UnixFileSystem::getFilesFromDirectoryAll(Array& results, const char* path, const char* searchPattern) { +#if HAS_DIRS // Find all files in this directory getFilesFromDirectoryTop(results, path, searchPattern); @@ -452,6 +477,9 @@ bool UnixFileSystem::getFilesFromDirectoryAll(Array& results, const char closedir(dir); return false; +#else + return true; +#endif } DateTime UnixFileSystem::GetFileLastEditTime(const StringView& path) From deb2ad7c8fdb95ee7a4c4170ad7fe2c54015fd95 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 16:36:34 +0200 Subject: [PATCH 123/137] Fix font hit test on multi-line text past the line end character #3503 --- Source/Engine/Render2D/Font.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp index cf478abda..63c59ff70 100644 --- a/Source/Engine/Render2D/Font.cpp +++ b/Source/Engine/Render2D/Font.cpp @@ -388,7 +388,10 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te if (dst < smallestDst) { // Pointer is behind the last character in the line - smallestIndex = line.LastCharIndex + 1; + if (text[line.LastCharIndex] == '\n' && lineIndex != lines.Count() - 1) + smallestIndex = line.LastCharIndex; + else + smallestIndex = line.LastCharIndex + 1; // Fix for last line //if (lineIndex == lines.Count() - 1) From 7ab6bafe399545a5e43f4a7b30602c1be0cbfcc3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 22:02:05 +0200 Subject: [PATCH 124/137] Fix crash when saving empty json string --- Source/ThirdParty/rapidjson/prettywriter.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/ThirdParty/rapidjson/prettywriter.h b/Source/ThirdParty/rapidjson/prettywriter.h index fe45df1d1..c66b6d734 100644 --- a/Source/ThirdParty/rapidjson/prettywriter.h +++ b/Source/ThirdParty/rapidjson/prettywriter.h @@ -108,7 +108,6 @@ public: } bool String(const Ch* str, SizeType length, bool copy = false) { - RAPIDJSON_ASSERT(str != 0); (void)copy; PrettyPrefix(kStringType); return Base::EndValue(Base::WriteString(str, length)); From 73976f3ed9f608778290b77473a13d4aca9dc4aa Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 22:08:34 +0200 Subject: [PATCH 125/137] Fix box collider to properly draw small bounds --- .../Engine/Physics/Colliders/BoxCollider.cpp | 35 +++++++++++-------- Source/Engine/Physics/Colliders/Collider.h | 1 - 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index 160120f87..37a38dfd4 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -86,7 +86,7 @@ void BoxCollider::OnDebugDraw() namespace { - OrientedBoundingBox GetWriteBox(const Vector3& min, const Vector3& max, const float margin) + OrientedBoundingBox GetWireBox(const Vector3& min, const Vector3& max, const float margin) { OrientedBoundingBox box; const Vector3 vec = max - min; @@ -125,20 +125,27 @@ void BoxCollider::OnDebugDrawSelected() Vector3 corners[8]; _bounds.GetCorners(corners); - const float margin = 1.0f; + const float margin = Math::Min(1.0f, _bounds.GetSize().MinValue() * 0.01f); const Color wiresColor = color.AlphaMultiplied(0.6f); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[1], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[3], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[4], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[1], corners[2], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[1], corners[5], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[2], corners[3], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[2], corners[6], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[3], corners[7], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[4], corners[5], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[4], corners[7], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[5], corners[6], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[6], corners[7], margin), wiresColor, 0, true); + if (margin > 0.05f) + { + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[1], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[3], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[4], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[1], corners[2], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[1], corners[5], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[2], corners[3], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[2], corners[6], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[3], corners[7], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[4], corners[5], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[4], corners[7], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[5], corners[6], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[6], corners[7], margin), wiresColor, 0, true); + } + else + { + DEBUG_DRAW_WIRE_BOX(_bounds, wiresColor, 0, true); + } // Base Collider::OnDebugDrawSelected(); diff --git a/Source/Engine/Physics/Colliders/Collider.h b/Source/Engine/Physics/Colliders/Collider.h index 5fd34f187..5c7db4c72 100644 --- a/Source/Engine/Physics/Colliders/Collider.h +++ b/Source/Engine/Physics/Colliders/Collider.h @@ -169,7 +169,6 @@ public: void ClosestPoint(const Vector3& point, Vector3& result) const final; bool ContainsPoint(const Vector3& point) const final; - protected: // [PhysicsColliderActor] void OnEnable() override; From e2fc8a62838da22cf66a9a9eb9d4d7fe09f87e24 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 22:16:16 +0200 Subject: [PATCH 126/137] Add drawing RigidBody center of mass and attached colliders #2325 #3247 --- Source/Engine/Physics/Actors/RigidBody.cpp | 28 +++++++++++++++++++ Source/Engine/Physics/Actors/RigidBody.h | 3 ++ .../Engine/Physics/Colliders/BoxCollider.cpp | 22 +++++++++------ Source/Engine/Physics/Colliders/BoxCollider.h | 1 + .../Physics/Colliders/CapsuleCollider.cpp | 11 ++++++++ .../Physics/Colliders/CapsuleCollider.h | 1 + Source/Engine/Physics/Colliders/Collider.h | 4 +++ .../Engine/Physics/Colliders/MeshCollider.cpp | 7 ++++- .../Engine/Physics/Colliders/MeshCollider.h | 1 + .../Physics/Colliders/SphereCollider.cpp | 7 ++++- .../Engine/Physics/Colliders/SphereCollider.h | 1 + 11 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp index a58911dfb..08b8eb0ed 100644 --- a/Source/Engine/Physics/Actors/RigidBody.cpp +++ b/Source/Engine/Physics/Actors/RigidBody.cpp @@ -338,6 +338,34 @@ void RigidBody::AddMovement(const Vector3& translation, const Quaternion& rotati SetTransform(t); } +#if USE_EDITOR + +#include "Engine/Debug/DebugDraw.h" + +void RigidBody::OnDebugDrawSelected() +{ + // Draw center of mass + if (!_centerOfMassOffset.IsZero()) + { + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(GetPosition() + (GetOrientation() * (GetCenterOfMass() - GetCenterOfMassOffset())), 5.0f), Color::Red, 0, false); + } + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(GetPosition() + (GetOrientation() * GetCenterOfMass()), 2.5f), Color::Aqua, 0, false); + + // Draw all attached colliders + for (Actor* child : Children) + { + const auto collider = Cast(child); + if (collider && collider->GetAttachedRigidBody() == this) + { + collider->OnDebugDrawSelf(); + } + } + + Actor::OnDebugDrawSelected(); +} + +#endif + void RigidBody::OnCollisionEnter(const Collision& c) { CollisionEnter(c); diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h index f9f36edf9..82599ebb8 100644 --- a/Source/Engine/Physics/Actors/RigidBody.h +++ b/Source/Engine/Physics/Actors/RigidBody.h @@ -487,6 +487,9 @@ public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void AddMovement(const Vector3& translation, const Quaternion& rotation) override; +#if USE_EDITOR + void OnDebugDrawSelected() override; +#endif // [IPhysicsActor] void* GetPhysicsActor() const override; diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index 37a38dfd4..59e5ebfd3 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -111,18 +111,11 @@ namespace } } -void BoxCollider::OnDebugDrawSelected() +void BoxCollider::OnDebugDrawSelf() { const Color color = Color::GreenYellow; DEBUG_DRAW_WIRE_BOX(_bounds, color * 0.3f, 0, false); - if (_contactOffset > 0) - { - OrientedBoundingBox contactBounds = _bounds; - contactBounds.Extents += Vector3(_contactOffset) / contactBounds.Transformation.Scale; - DEBUG_DRAW_WIRE_BOX(contactBounds, Color::Blue.AlphaMultiplied(0.2f), 0, false); - } - Vector3 corners[8]; _bounds.GetCorners(corners); const float margin = Math::Min(1.0f, _bounds.GetSize().MinValue() * 0.01f); @@ -146,8 +139,19 @@ void BoxCollider::OnDebugDrawSelected() { DEBUG_DRAW_WIRE_BOX(_bounds, wiresColor, 0, true); } +} + +void BoxCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); + + if (_contactOffset > 0) + { + OrientedBoundingBox contactBounds = _bounds; + contactBounds.Extents += Vector3(_contactOffset) / contactBounds.Transformation.Scale; + DEBUG_DRAW_WIRE_BOX(contactBounds, Color::Blue.AlphaMultiplied(0.2f), 0, false); + } - // Base Collider::OnDebugDrawSelected(); } diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h index c0eeaea5c..7dbbc830d 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.h +++ b/Source/Engine/Physics/Colliders/BoxCollider.h @@ -52,6 +52,7 @@ public: // [Collider] #if USE_EDITOR void OnDebugDraw() override; + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp index 8a9e1d1cf..83ce85115 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp @@ -52,6 +52,17 @@ void CapsuleCollider::DrawPhysicsDebug(RenderView& view) DEBUG_DRAW_WIRE_CAPSULE(_transform.LocalToWorld(_center), rotation, radius, height, Color::GreenYellow * 0.8f, 0, true); } +void CapsuleCollider::OnDebugDrawSelf() +{ + Quaternion rotation; + Quaternion::Multiply(_transform.Orientation, Quaternion::Euler(0, 90, 0), rotation); + const float minSize = 0.001f; + const float radius = Math::Max(Math::Abs(_radius) * _cachedScale, minSize); + const float height = Math::Max(Math::Abs(_height) * _cachedScale, minSize); + const Vector3 position = _transform.LocalToWorld(_center); + DEBUG_DRAW_WIRE_CAPSULE(position, rotation, radius, height, Color::GreenYellow, 0, false); +} + void CapsuleCollider::OnDebugDrawSelected() { Quaternion rotation; diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.h b/Source/Engine/Physics/Colliders/CapsuleCollider.h index 234916f87..784d346eb 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.h +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.h @@ -56,6 +56,7 @@ public: public: // [Collider] #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/Collider.h b/Source/Engine/Physics/Colliders/Collider.h index 5c7db4c72..1aa2ce385 100644 --- a/Source/Engine/Physics/Colliders/Collider.h +++ b/Source/Engine/Physics/Colliders/Collider.h @@ -160,6 +160,10 @@ protected: private: void OnMaterialChanged(); + friend RigidBody; +#if USE_EDITOR + virtual void OnDebugDrawSelf() {} +#endif public: // [PhysicsColliderActor] diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp index 0902f1106..2af533ca3 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.cpp +++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp @@ -85,13 +85,18 @@ void MeshCollider::DrawPhysicsDebug(RenderView& view) } } -void MeshCollider::OnDebugDrawSelected() +void MeshCollider::OnDebugDrawSelf() { if (CollisionData && CollisionData->IsLoaded()) { const auto& debugLines = CollisionData->GetDebugLines(); DEBUG_DRAW_LINES(Span(debugLines.Get(), debugLines.Count()), _transform.GetWorld(), Color::GreenYellow, 0, false); } +} + +void MeshCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); // Base Collider::OnDebugDrawSelected(); diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h index 99f2980f6..8d0e77179 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.h +++ b/Source/Engine/Physics/Colliders/MeshCollider.h @@ -31,6 +31,7 @@ public: bool CanAttach(RigidBody* rigidBody) const override; bool CanBeTrigger() const override; #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/SphereCollider.cpp b/Source/Engine/Physics/Colliders/SphereCollider.cpp index f40d9e4af..0576ae6cf 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.cpp +++ b/Source/Engine/Physics/Colliders/SphereCollider.cpp @@ -35,9 +35,14 @@ void SphereCollider::DrawPhysicsDebug(RenderView& view) DEBUG_DRAW_WIRE_SPHERE(_sphere, Color::GreenYellow * 0.8f, 0, true); } -void SphereCollider::OnDebugDrawSelected() +void SphereCollider::OnDebugDrawSelf() { DEBUG_DRAW_WIRE_SPHERE(_sphere, Color::GreenYellow, 0, false); +} + +void SphereCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); if (_contactOffset > 0) { diff --git a/Source/Engine/Physics/Colliders/SphereCollider.h b/Source/Engine/Physics/Colliders/SphereCollider.h index 67addf17b..47459cf34 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.h +++ b/Source/Engine/Physics/Colliders/SphereCollider.h @@ -36,6 +36,7 @@ public: public: // [Collider] #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; From 65cf59642c1186a34f9b6c1a33e84953235c6be3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 22:16:46 +0200 Subject: [PATCH 127/137] Fix changing Rigid Body center of mass offset #2325 #3247 --- Source/Engine/Physics/Actors/RigidBody.cpp | 7 +++---- Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp | 2 +- Source/Engine/Physics/PhysicsBackend.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp index 08b8eb0ed..062264b58 100644 --- a/Source/Engine/Physics/Actors/RigidBody.cpp +++ b/Source/Engine/Physics/Actors/RigidBody.cpp @@ -159,9 +159,10 @@ void RigidBody::SetCenterOfMassOffset(const Float3& value) { if (value == _centerOfMassOffset) return; + Float3 delta = value - _centerOfMassOffset; _centerOfMassOffset = value; if (_actor) - PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); + PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(_actor, delta); } void RigidBody::SetConstraints(const RigidbodyConstraints value) @@ -356,9 +357,7 @@ void RigidBody::OnDebugDrawSelected() { const auto collider = Cast(child); if (collider && collider->GetAttachedRigidBody() == this) - { collider->OnDebugDrawSelf(); - } } Actor::OnDebugDrawSelected(); @@ -534,7 +533,7 @@ void RigidBody::BeginPlay(SceneBeginData* data) // Apply the Center Of Mass offset if (!_centerOfMassOffset.IsZero()) - PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); + PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); // Register actor PhysicsBackend::AddSceneActor(scene, _actor); diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index b023b49f7..0c23a1881 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -2482,7 +2482,7 @@ Vector3 PhysicsBackend::GetRigidDynamicActorCenterOfMass(void* actor) return P2C(actorPhysX->getCMassLocalPose().p); } -void PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value) +void PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value) { auto actorPhysX = (PxRigidDynamic*)actor; auto pose = actorPhysX->getCMassLocalPose(); diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h index dacd6c7fd..4307d2c6d 100644 --- a/Source/Engine/Physics/PhysicsBackend.h +++ b/Source/Engine/Physics/PhysicsBackend.h @@ -164,7 +164,7 @@ public: static Vector3 GetRigidDynamicActorAngularVelocity(void* actor); static void SetRigidDynamicActorAngularVelocity(void* actor, const Vector3& value, bool wakeUp); static Vector3 GetRigidDynamicActorCenterOfMass(void* actor); - static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value); + static void AddRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value); static bool GetRigidDynamicActorIsSleeping(void* actor); static void RigidDynamicActorSleep(void* actor); static void RigidDynamicActorWakeUp(void* actor); From ef2c551cee6075862dcc122d5c2262df72e607e7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Oct 2025 23:24:15 +0200 Subject: [PATCH 128/137] Fix build --- Source/Engine/Physics/Actors/IPhysicsDebug.h | 2 +- Source/Engine/Physics/Colliders/BoxCollider.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Physics/Actors/IPhysicsDebug.h b/Source/Engine/Physics/Actors/IPhysicsDebug.h index cedd3d822..57e9a97e3 100644 --- a/Source/Engine/Physics/Actors/IPhysicsDebug.h +++ b/Source/Engine/Physics/Actors/IPhysicsDebug.h @@ -12,7 +12,7 @@ public: { } }; -#define ImplementPhysicsDebug void DrawPhysicsDebug(RenderView& view) +#define ImplementPhysicsDebug void DrawPhysicsDebug(RenderView& view) override #else #define ImplementPhysicsDebug #endif diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index 59e5ebfd3..1e90cb91f 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -118,7 +118,7 @@ void BoxCollider::OnDebugDrawSelf() Vector3 corners[8]; _bounds.GetCorners(corners); - const float margin = Math::Min(1.0f, _bounds.GetSize().MinValue() * 0.01f); + const float margin = Math::Min(1.0f, (float)_bounds.GetSize().MinValue() * 0.01f); const Color wiresColor = color.AlphaMultiplied(0.6f); if (margin > 0.05f) { From 2bf62cc54f9ed7798e0a8a666a1c72227717873a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 9 Oct 2025 15:13:04 +0200 Subject: [PATCH 129/137] Add `GPUDevice.VideoOutputs` with a list of attached monitors --- Source/Engine/Graphics/GPUDevice.cpp | 3 + Source/Engine/Graphics/GPUDevice.h | 47 ++++++++++- .../DirectX/DX12/GPUBufferDX12.cpp | 4 + .../DirectX/DX12/GPUDeviceDX12.cpp | 27 +++++++ .../DirectX/DX12/GPUTextureDX12.cpp | 4 + .../GraphicsDevice/DirectX/RenderToolsDX.cpp | 77 +++++++++++++++---- 6 files changed, 143 insertions(+), 19 deletions(-) diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index eda66d95e..be41ad228 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -392,6 +392,8 @@ bool GPUDevice::Init() LOG(Info, "Total graphics memory: {0}", Utilities::BytesToText(TotalGraphicsMemory)); if (!Limits.HasCompute) LOG(Warning, "Compute Shaders are not supported"); + for (const auto& videoOutput : VideoOutputs) + LOG(Info, "Video output '{0}' {1}x{2} {3} Hz", videoOutput.Name, videoOutput.Width, videoOutput.Height, videoOutput.RefreshRate); Engine::RequestingExit.Bind(this); return false; } @@ -725,6 +727,7 @@ void GPUDevice::Draw() void GPUDevice::Dispose() { RenderList::CleanupCache(); + VideoOutputs.Resize(0); VideoOutputModes.Resize(0); } diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index 8914085eb..8f9393a5b 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -54,7 +54,40 @@ public: }; /// - /// Describes a video output display mode. + /// Describes a video output display (monitor). + /// + API_STRUCT() struct VideoOutput + { + DECLARE_SCRIPTING_TYPE_NO_SPAWN(VideoOutputMode); + + /// + /// The display name. + /// + API_FIELD() String Name; + + /// + /// The native screen resolution width (in pixel). + /// + API_FIELD() uint32 Width = 0; + + /// + /// The native screen resolution height (in pixel). + /// + API_FIELD() uint32 Height = 0; + + /// + /// The maximum screen refresh rate (in hertz). + /// + API_FIELD() float RefreshRate = 0; + + /// + /// Flag that indicates that monitor supports displaying High Dynamic Range colors. + /// + API_FIELD() bool HDR = false; + }; + + /// + /// Describes a video output display mode (monitor screen mode). /// API_STRUCT() struct VideoOutputMode { @@ -73,7 +106,12 @@ public: /// /// The screen refresh rate (in hertz). /// - API_FIELD() uint32 RefreshRate; + API_FIELD() float RefreshRate; + + /// + /// The index of the VideoOutput from the device monitors list. + /// + API_FIELD() int32 VideoOutputIndex; }; /// @@ -134,6 +172,11 @@ public: /// API_FIELD(ReadOnly) GPULimits Limits; + /// + /// The available video outputs (monitors). + /// + API_FIELD(ReadOnly) Array VideoOutputs; + /// /// The available video output modes. /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp index 811076af6..0d9ff88d4 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUBufferDX12.cpp @@ -136,7 +136,11 @@ bool GPUBufferDX12::OnInit() // Create resource ID3D12Resource* resource; +#if PLATFORM_WINDOWS D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED; +#else + D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE; +#endif D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON; VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, heapFlags, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource))); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index e140da37e..88334be60 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -307,6 +307,32 @@ bool GPUDeviceDX12::Init() LOG(Info, "Hardware Version: {0}", hwVer); updateFrameEvents(); + // Setup display output + auto& videoOutput = VideoOutputs.AddOne(); + videoOutput.Name = hwVer; + ComPtr dxgiDevice; + VALIDATE_DIRECTX_CALL(_device->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxgiDevice))); + ComPtr dxgiAdapter; + VALIDATE_DIRECTX_CALL(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); + ComPtr dxgiOutput; + VALIDATE_DIRECTX_CALL(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf())); + DXGI_FORMAT backbufferFormat = RenderToolsDX::ToDxgiFormat(GPU_BACK_BUFFER_PIXEL_FORMAT); + UINT modesCount = 0; + VALIDATE_DIRECTX_CALL(dxgiOutput->GetDisplayModeList(backbufferFormat, 0, &modesCount, NULL)); + Array modes; + modes.Resize((int32)modesCount); + VALIDATE_DIRECTX_CALL(dxgiOutput->GetDisplayModeListX(backbufferFormat, 0, &modesCount, modes.Get())); + for (const DXGIXBOX_MODE_DESC& mode : modes) + { + if (mode.Width > videoOutput.Width) + { + videoOutput.Width = mode.Width; + videoOutput.Height = mode.Height; + } + videoOutput.RefreshRate = Math::Max(videoOutput.RefreshRate, mode.RefreshRate.Numerator / (float)mode.RefreshRate.Denominator); + } + modes.Resize(0); + #if PLATFORM_GDK GDKPlatform::Suspended.Bind(this); GDKPlatform::Resumed.Bind(this); @@ -943,6 +969,7 @@ void GPUDeviceDX12::updateFrameEvents() dxgiAdapter->GetDesc(&_adapter->Description); ComPtr dxgiOutput; VALIDATE_DIRECTX_CALL(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf())); + // TODO: support 120/40/30/24 fps VALIDATE_DIRECTX_CALL(_device->SetFrameIntervalX(dxgiOutput.Get(), D3D12XBOX_FRAME_INTERVAL_60_HZ, DX12_BACK_BUFFER_COUNT - 1u, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE)); VALIDATE_DIRECTX_CALL(_device->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0U, nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp index abecfd776..e7e4c5ca2 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp @@ -159,7 +159,11 @@ bool GPUTextureDX12::OnInit() initialState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; // Create texture +#if PLATFORM_WINDOWS D3D12_HEAP_FLAGS heapFlags = useRTV || useDSV ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE; +#else + D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE; +#endif auto result = device->CreateCommittedResource(&heapProperties, heapFlags, &resourceDesc, initialState, clearValuePtr, IID_PPV_ARGS(&resource)); LOG_DIRECTX_RESULT_WITH_RETURN(result, true); diff --git a/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp b/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp index f195b8b41..7e38ecadb 100644 --- a/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/RenderToolsDX.cpp @@ -7,6 +7,7 @@ #include "GPUDeviceDX.h" #include "Engine/Core/Types/DateTime.h" #include "Engine/Core/Types/StringBuilder.h" +#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Graphics/GPUDevice.h" #include "IncludeDirectXHeaders.h" #include @@ -21,6 +22,9 @@ typedef void* LPCDLGTEMPLATE; #pragma comment(lib, "SetupAPI.lib") #endif +#define DISPLAY_DEVICE_ACTIVE 0x00000001 +#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008 + namespace Windows { typedef struct _devicemodeW @@ -84,7 +88,18 @@ namespace Windows DWORD dmPanningHeight; } DEVMODEW, *PDEVMODEW, *NPDEVMODEW, *LPDEVMODEW; + typedef struct _DISPLAY_DEVICEW + { + DWORD cb; + WCHAR DeviceName[32]; + WCHAR DeviceString[128]; + DWORD StateFlags; + WCHAR DeviceID[128]; + WCHAR DeviceKey[128]; + } DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW; + WIN_API BOOL WIN_API_CALLCONV EnumDisplaySettingsW(LPCWSTR lpszDeviceName, DWORD iModeNum, DEVMODEW* lpDevMode); + WIN_API BOOL WIN_API_CALLCONV EnumDisplayDevicesW(LPCWSTR lpDevice, DWORD iDevNum, PDISPLAY_DEVICEW lpDisplayDevice, DWORD dwFlags); } // @formatter:off @@ -590,13 +605,14 @@ void GPUAdapterDX::SetDriverVersion(Version& ver) DriverVersion = ver; } +#if PLATFORM_WINDOWS + void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter) { -#if PLATFORM_WINDOWS - // Collect output devices + PROFILE_CPU(); uint32 outputIdx = 0; ComPtr output; - DXGI_FORMAT defaultBackbufferFormat = RenderToolsDX::ToDxgiFormat(GPU_BACK_BUFFER_PIXEL_FORMAT); + DXGI_FORMAT backbufferFormat = RenderToolsDX::ToDxgiFormat(GPU_BACK_BUFFER_PIXEL_FORMAT); Array modeDesc; while (adapter->EnumOutputs(outputIdx, &output) != DXGI_ERROR_NOT_FOUND) { @@ -606,7 +622,7 @@ void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter) output->GetDesc(&outputDX11.Desc); uint32 numModes = 0; - HRESULT hr = output->GetDisplayModeList(defaultBackbufferFormat, 0, &numModes, nullptr); + HRESULT hr = output->GetDisplayModeList(backbufferFormat, 0, &numModes, nullptr); if (FAILED(hr)) { LOG(Warning, "Error while enumerating adapter output video modes."); @@ -614,7 +630,7 @@ void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter) } modeDesc.Resize(numModes, false); - hr = output->GetDisplayModeList(defaultBackbufferFormat, 0, &numModes, modeDesc.Get()); + hr = output->GetDisplayModeList(backbufferFormat, 0, &numModes, modeDesc.Get()); if (FAILED(hr)) { LOG(Warning, "Error while enumerating adapter output video modes."); @@ -635,16 +651,10 @@ void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter) break; } } - if (!foundVideoMode) { outputDX11.VideoModes.Add(mode); - - // Collect only from the main monitor - if (Outputs.Count() == 1) - { - VideoOutputModes.Add({ mode.Width, mode.Height, (uint32)(mode.RefreshRate.Numerator / (float)mode.RefreshRate.Denominator) }); - } + VideoOutputModes.Add({ mode.Width, mode.Height, mode.RefreshRate.Numerator / (float)mode.RefreshRate.Denominator, VideoOutputs.Count() }); } } @@ -659,24 +669,57 @@ void GPUDeviceDX::UpdateOutputs(IDXGIAdapter* adapter) devMode.dmDriverExtra = 0; Windows::EnumDisplaySettingsW(monitorInfo.szDevice, ((DWORD)-1), &devMode); + // Initialize display mode for Desktop DXGI_MODE_DESC currentMode; currentMode.Width = devMode.dmPelsWidth; currentMode.Height = devMode.dmPelsHeight; bool useDefaultRefreshRate = 1 == devMode.dmDisplayFrequency || 0 == devMode.dmDisplayFrequency; currentMode.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : devMode.dmDisplayFrequency; currentMode.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1; - currentMode.Format = defaultBackbufferFormat; + currentMode.Format = backbufferFormat; currentMode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; currentMode.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - if (output->FindClosestMatchingMode(¤tMode, &outputDX11.DesktopViewMode, nullptr) != S_OK) outputDX11.DesktopViewMode = currentMode; - float refreshRate = outputDX11.DesktopViewMode.RefreshRate.Numerator / (float)outputDX11.DesktopViewMode.RefreshRate.Denominator; - LOG(Info, "Video output '{0}' {1}x{2} {3} Hz", outputDX11.Desc.DeviceName, devMode.dmPelsWidth, devMode.dmPelsHeight, refreshRate); + // Add video output + auto& videoOutput = VideoOutputs.AddOne(); + videoOutput.Width = devMode.dmPelsWidth; + videoOutput.Height = devMode.dmPelsHeight; + videoOutput.RefreshRate = outputDX11.DesktopViewMode.RefreshRate.Numerator / (float)outputDX11.DesktopViewMode.RefreshRate.Denominator; + + // Query display device name + Windows::DISPLAY_DEVICEW displayDevice; + displayDevice.cb = sizeof(displayDevice); + DWORD monitorIndex = 0; + while (Windows::EnumDisplayDevicesW(outputDX11.Desc.DeviceName, monitorIndex, &displayDevice, 0)) + { + if (displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE && !(displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) + { + StringView id(displayDevice.DeviceID); + videoOutput.Name = id.Substring(8, id.Substring(9).Find(TEXT('\\')) + 1); + break; + } + monitorIndex++; + } + if (videoOutput.Name.IsEmpty()) + videoOutput.Name = outputDX11.Desc.DeviceName; + +#ifdef __IDXGIOutput6_INTERFACE_DEFINED__ + // Query HDR support + ComPtr output6; + if (SUCCEEDED(output->QueryInterface(IID_PPV_ARGS(&output6)))) + { + DXGI_OUTPUT_DESC1 outputDesc; + output6->GetDesc1(&outputDesc); + videoOutput.HDR = outputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + } +#endif + outputIdx++; } -#endif } #endif + +#endif From d3389604b07f3cf29aeb02cdc206ae7cd2e844f1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 11 Oct 2025 00:17:02 +0200 Subject: [PATCH 130/137] Update engine materials --- Content/Editor/Camera/M_Camera.flax | 2 +- Content/Editor/CubeTexturePreviewMaterial.flax | 4 ++-- Content/Editor/DebugMaterials/DDGIDebugProbes.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Decal.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Particle.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Surface.flax | 4 ++-- .../Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Terrain.flax | 4 ++-- Content/Editor/DefaultFontMaterial.flax | 2 +- Content/Editor/Gizmo/FoliageBrushMaterial.flax | 4 ++-- Content/Editor/Gizmo/Material.flax | 4 ++-- Content/Editor/Gizmo/MaterialWire.flax | 4 ++-- Content/Editor/Gizmo/SelectionOutlineMaterial.flax | 4 ++-- Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax | 4 ++-- Content/Editor/Highlight Material.flax | 4 ++-- Content/Editor/Icons/IconsMaterial.flax | 4 ++-- Content/Editor/IesProfilePreviewMaterial.flax | 4 ++-- Content/Editor/Particles/Particle Material Color.flax | 4 ++-- Content/Editor/Particles/Smoke Material.flax | 4 ++-- Content/Editor/SpriteMaterial.flax | 4 ++-- Content/Editor/Terrain/Circle Brush Material.flax | 4 ++-- Content/Editor/Terrain/Highlight Terrain Material.flax | 2 +- Content/Editor/TexturePreviewMaterial.flax | 4 ++-- Content/Editor/Wires Debug Material.flax | 4 ++-- Content/Engine/DefaultDeformableMaterial.flax | 4 ++-- Content/Engine/DefaultMaterial.flax | 4 ++-- Content/Engine/DefaultRadialMenu.flax | 4 ++-- Content/Engine/DefaultTerrainMaterial.flax | 4 ++-- Content/Engine/SingleColorMaterial.flax | 4 ++-- Content/Engine/SkyboxMaterial.flax | 4 ++-- 30 files changed, 57 insertions(+), 57 deletions(-) diff --git a/Content/Editor/Camera/M_Camera.flax b/Content/Editor/Camera/M_Camera.flax index 25b184d86..7d7213a8d 100644 --- a/Content/Editor/Camera/M_Camera.flax +++ b/Content/Editor/Camera/M_Camera.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ef316cb161204b2c7a9dd4746c6c7281507a1e26c4c48c1a917b7645ac611f6 +oid sha256:7edc1b9d2c7fbd32fcf778814deb719c71781f657da050ac0c7c78984aeb360d size 29533 diff --git a/Content/Editor/CubeTexturePreviewMaterial.flax b/Content/Editor/CubeTexturePreviewMaterial.flax index 3d7014519..5969c90fa 100644 --- a/Content/Editor/CubeTexturePreviewMaterial.flax +++ b/Content/Editor/CubeTexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:99287e35e0c8ed22fd336cce66d8a675ad43fb318d431e63baf23670bc1212a7 -size 31125 +oid sha256:ac6023e5d6525c3b7c385a380ed9d6fc71ec9d683c587391d14c9daf6653e31a +size 31445 diff --git a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax index 39677f815..fc45d33cc 100644 --- a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax +++ b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d317dc7b2fc2700b28e4a2581c567b888ea1ebb62c5da84f826d9b29c510ff17 -size 40805 +oid sha256:ecd573c40f534f293d4827b1a8150d439d4f5e7729552474926208c5814f3d3e +size 41149 diff --git a/Content/Editor/DebugMaterials/SingleColor/Decal.flax b/Content/Editor/DebugMaterials/SingleColor/Decal.flax index a85229155..05e99be76 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Decal.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Decal.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa1b7b7f37b73cbcdef2faa6a6a1a1ce11c08033233606dd34e558195f4718cd -size 9973 +oid sha256:c0b2ad25738c2bc55bb3e76fc94fc81992b1d65b8b3091b132c75b2ed064c517 +size 10398 diff --git a/Content/Editor/DebugMaterials/SingleColor/Particle.flax b/Content/Editor/DebugMaterials/SingleColor/Particle.flax index 423396308..7a328e7a0 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Particle.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Particle.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5096f5c6aff954618c4fc863e59a76ce880879695bac1abc990fbabd0b8d330b -size 32699 +oid sha256:02ddea5bcb3fccb697081e47cc26a0b546b23b89ceca299e702a1d431775dfd6 +size 33503 diff --git a/Content/Editor/DebugMaterials/SingleColor/Surface.flax b/Content/Editor/DebugMaterials/SingleColor/Surface.flax index f405ecd8b..84e05ee36 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Surface.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Surface.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c1c2e4e2324de02092f73a0477cd909e400e99a400ce255c59751b21af3ed8e -size 29306 +oid sha256:741a7619b5aebc6c7c6a573a0407e8b7aa42d1b50d0ed5cf6a21026932807d0e +size 29398 diff --git a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax index 98a9221f6..ab4591176 100644 --- a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax +++ b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b8794eaf03955f5afb9cf8a56a6327d7fe3b7c287e2eeb50c95d1a78dd2c7c4 -size 32150 +oid sha256:358370943d21a97f8b45ff2181b7c6c2d7a6297e3f166ae7a77363aadf89b152 +size 32954 diff --git a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax index 2ab956aad..54151179a 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfd8cdbfe96f53c2795b7c408a5f6c09fbf67b0d3ded6c34aacf2e34313e1925 -size 21004 +oid sha256:486b4db3e1d825d026753d944a04defe4d72eb73eb03a438944c366f19de824e +size 21096 diff --git a/Content/Editor/DefaultFontMaterial.flax b/Content/Editor/DefaultFontMaterial.flax index 71b91f9a6..8d48c5827 100644 --- a/Content/Editor/DefaultFontMaterial.flax +++ b/Content/Editor/DefaultFontMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a5f051b559c86cd397dda551afd4f3b751a99bc9cb14de989a80c2a04651d82 +oid sha256:ebdfc478caabc84a3a75384a64d262d2d509bbac3540eea462e45911719c288f size 29627 diff --git a/Content/Editor/Gizmo/FoliageBrushMaterial.flax b/Content/Editor/Gizmo/FoliageBrushMaterial.flax index 7af84241d..79385ada6 100644 --- a/Content/Editor/Gizmo/FoliageBrushMaterial.flax +++ b/Content/Editor/Gizmo/FoliageBrushMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d2bb53a8b94d596738a6a1527d2516e032a287a7a6de6fab472be7a28978de2 -size 38177 +oid sha256:aa4f1a733150c62064cac60c07980df7c84bb6163dc9507782aa98df07f48874 +size 39637 diff --git a/Content/Editor/Gizmo/Material.flax b/Content/Editor/Gizmo/Material.flax index 2d52c87a9..ace3bde90 100644 --- a/Content/Editor/Gizmo/Material.flax +++ b/Content/Editor/Gizmo/Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:261de215acfeee3d2e37bfea0c4f807c7f685f20719032f1706f82b07ae52992 -size 33304 +oid sha256:26e1832496c01cb31bd4dc9000d3cd326ea4fd54de02910d3801d2641bff685c +size 34240 diff --git a/Content/Editor/Gizmo/MaterialWire.flax b/Content/Editor/Gizmo/MaterialWire.flax index 4b90f0311..7ea0a596f 100644 --- a/Content/Editor/Gizmo/MaterialWire.flax +++ b/Content/Editor/Gizmo/MaterialWire.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:072c5ae6e0248b8f48bb933a8bd51935218afe425ab9f6df5fb853003e545b52 -size 32001 +oid sha256:ca8bc1ac9d45534d3efd3b4308d7492fa016726b4ec744be26619069ce911b73 +size 32689 diff --git a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax index 7dc84ec92..0c1461b72 100644 --- a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax +++ b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87f9eee9186d2862aa04c837d05e4cffeb1eff8be706ea856bd74a179ad591bb -size 16212 +oid sha256:09f7dff17af9cd055352e0da534f3466c8efa235c40faf5e56da92c788342f6a +size 17394 diff --git a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax index b6e40d5b4..bd4935d96 100644 --- a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax +++ b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8b6d69f23dc6dd94e03180127e1b5eafb9bb610a392d41b6aee94d3e03bebef -size 30419 +oid sha256:1bc0005c64c561a430a17e4707abc000e06498af968890e2c4e223dc07f07c12 +size 30655 diff --git a/Content/Editor/Highlight Material.flax b/Content/Editor/Highlight Material.flax index 4371e5753..ccecb98aa 100644 --- a/Content/Editor/Highlight Material.flax +++ b/Content/Editor/Highlight Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bde47005982dbcb96abb900d5773d5f6d707ea0eee94b7b385945e3b3b350372 -size 30695 +oid sha256:95d172cd12bb3c818fbccf737e78ab282bc8d0880aa8f45af0562850b0eabe4b +size 31616 diff --git a/Content/Editor/Icons/IconsMaterial.flax b/Content/Editor/Icons/IconsMaterial.flax index dfcfed0b6..b24941463 100644 --- a/Content/Editor/Icons/IconsMaterial.flax +++ b/Content/Editor/Icons/IconsMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6524caaaf72bc30bc32bffcfdf26b4d1d2adc466dd5143c4b1980e62b14b97f -size 30612 +oid sha256:5ca4baa1419080395dcf2b5757676406288f112754bc3cd2f27610b58d199622 +size 31300 diff --git a/Content/Editor/IesProfilePreviewMaterial.flax b/Content/Editor/IesProfilePreviewMaterial.flax index 9f23ac666..99bc2662c 100644 --- a/Content/Editor/IesProfilePreviewMaterial.flax +++ b/Content/Editor/IesProfilePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f796e403ee85d33eb2be0a371e18085a31ca7bf970e26c19c26f9ea2b0224a33 -size 20445 +oid sha256:b3b4c61b04d372d2430a7c08dec612af6caa0e57b1cb47ea44d171d729d3f8f8 +size 20443 diff --git a/Content/Editor/Particles/Particle Material Color.flax b/Content/Editor/Particles/Particle Material Color.flax index 50cf3b09f..19eb7a3c2 100644 --- a/Content/Editor/Particles/Particle Material Color.flax +++ b/Content/Editor/Particles/Particle Material Color.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4fcde3b4d440561997706160c0f10e4b82e30b7c2f8aa732fd1439d9bae160e -size 31020 +oid sha256:6f3b8a7c48c55e33a41f9fe4dbf9b3109b0e734ff154d6cbd3e4101013b01649 +size 31708 diff --git a/Content/Editor/Particles/Smoke Material.flax b/Content/Editor/Particles/Smoke Material.flax index 38b79ec48..527d19842 100644 --- a/Content/Editor/Particles/Smoke Material.flax +++ b/Content/Editor/Particles/Smoke Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a1fdeeb738daa07787556cac664214c33633a1f9a3021aff4dc0727e105ea4c -size 39087 +oid sha256:2275282d4e3b5e012a0bbc93fca0d6ffdad89e5a5f0c289678f70748f2efab56 +size 40655 diff --git a/Content/Editor/SpriteMaterial.flax b/Content/Editor/SpriteMaterial.flax index 2c98b951e..d967a4ea4 100644 --- a/Content/Editor/SpriteMaterial.flax +++ b/Content/Editor/SpriteMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3059c52ee632be69bab545192e170b61ddabcf67d4848bbdb46f4c1da5414072 -size 30502 +oid sha256:6f5e82be7efa6489cfdfd1babeb1fbb90507aaff7c04eb5f64a4971adf0a2164 +size 30734 diff --git a/Content/Editor/Terrain/Circle Brush Material.flax b/Content/Editor/Terrain/Circle Brush Material.flax index 71a54e7f6..6ddc5f3e9 100644 --- a/Content/Editor/Terrain/Circle Brush Material.flax +++ b/Content/Editor/Terrain/Circle Brush Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd3172fc12d5ad7c6cc862f4b62a77b781974242e14518dbf81805605941cd55 -size 27676 +oid sha256:2c7fde7be7d6f9876f9c0db02632c098ab95ade7de57c583d2e495c8ae8665bd +size 28232 diff --git a/Content/Editor/Terrain/Highlight Terrain Material.flax b/Content/Editor/Terrain/Highlight Terrain Material.flax index 863c238b7..c573eb3ee 100644 --- a/Content/Editor/Terrain/Highlight Terrain Material.flax +++ b/Content/Editor/Terrain/Highlight Terrain Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbdc0533affafaaf7f8813cfdbe5a9d5596038e0e5e46ad3e970ec7ffd924fab +oid sha256:9369a554ea1776154f5e39d4aaed044f928d98f1f5955b7590b0972015b07438 size 21179 diff --git a/Content/Editor/TexturePreviewMaterial.flax b/Content/Editor/TexturePreviewMaterial.flax index 2ab0e2c23..2c91f9d8f 100644 --- a/Content/Editor/TexturePreviewMaterial.flax +++ b/Content/Editor/TexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5d4eda6497493dabf6697a9df34ec59b11183648e481399a7b1beae3c8596e1 -size 10744 +oid sha256:4d61f178e72e4d983a919b76368e03c66995ecf50935f6f55b660e34f58755a2 +size 11058 diff --git a/Content/Editor/Wires Debug Material.flax b/Content/Editor/Wires Debug Material.flax index 8c5a07c5d..308a6230a 100644 --- a/Content/Editor/Wires Debug Material.flax +++ b/Content/Editor/Wires Debug Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:037ea2b610ee9c7ceb2cdb680d2a5d898a0600a896df93036565e11aef02a17c -size 30695 +oid sha256:c7a42b1bc5a34f9c47d1aeb773ef26ce470b2d88c2b092828f0fcb439583ef27 +size 31616 diff --git a/Content/Engine/DefaultDeformableMaterial.flax b/Content/Engine/DefaultDeformableMaterial.flax index b3be3fe58..a397d1ad8 100644 --- a/Content/Engine/DefaultDeformableMaterial.flax +++ b/Content/Engine/DefaultDeformableMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4591783ed6e6cca6b8639dd3ebb624101b623c3813b80f75e22ce606d914b8db -size 18985 +oid sha256:be21bb7eecd9c774196dbaa89d1b049b108fc0929d648795056c977fe00364ab +size 19582 diff --git a/Content/Engine/DefaultMaterial.flax b/Content/Engine/DefaultMaterial.flax index 51e67d79f..eddcbace8 100644 --- a/Content/Engine/DefaultMaterial.flax +++ b/Content/Engine/DefaultMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1906849094ff4ad6022e14762961e2a235160d29427f82724d91ca8b8cfb320 -size 31331 +oid sha256:0a8a4ad5e763704263b94a7a7e0cc30ab7b1cd1abcb5ccae2d4c6062a65920df +size 31928 diff --git a/Content/Engine/DefaultRadialMenu.flax b/Content/Engine/DefaultRadialMenu.flax index 8175a130a..60e2ba5f9 100644 --- a/Content/Engine/DefaultRadialMenu.flax +++ b/Content/Engine/DefaultRadialMenu.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ab4c3c9d3f425b136eb0cdee3342b5c99f9372e691d5bf0b1f85c7654362805 -size 20514 +oid sha256:c4151a58e5314937efcd3bdcb9fe0bdd5047b8705931e45e0a4e71a4470e16a0 +size 21700 diff --git a/Content/Engine/DefaultTerrainMaterial.flax b/Content/Engine/DefaultTerrainMaterial.flax index cd1a11e93..b302ade35 100644 --- a/Content/Engine/DefaultTerrainMaterial.flax +++ b/Content/Engine/DefaultTerrainMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04a300665f72ea9543edb0419f660c09bd6d41eb46021a52be4b5bb14fa257a1 -size 23301 +oid sha256:c5cf6924809b9bd7ad3c09722a93f327a0d111676060d136df9c14ab34e8475b +size 23930 diff --git a/Content/Engine/SingleColorMaterial.flax b/Content/Engine/SingleColorMaterial.flax index a9534c2db..d6d179150 100644 --- a/Content/Engine/SingleColorMaterial.flax +++ b/Content/Engine/SingleColorMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5da0e59ceaa1921fce54a8602837fe4782436ba67af4c945b2827cbc672cb362 -size 29507 +oid sha256:750f69ce59ef020d2e2186ed6c4bf7aac67ecb1692287e358eaed969fc36381a +size 29615 diff --git a/Content/Engine/SkyboxMaterial.flax b/Content/Engine/SkyboxMaterial.flax index 7f9545007..cc369ceee 100644 --- a/Content/Engine/SkyboxMaterial.flax +++ b/Content/Engine/SkyboxMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98a0d6b06a90d753e68638ac64836cb96e6edc90e5b13770b722f33512034c09 -size 31650 +oid sha256:3eecc9556af6c2a79d39a7e1c52e4019bdccfb43b074eaddd18600a5854dbffe +size 31974 From abdeaa935494d2b646327f20e0a49e99f925ebf2 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 11 Oct 2025 00:17:41 +0200 Subject: [PATCH 131/137] Update build number --- Flax.flaxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flax.flaxproj b/Flax.flaxproj index 96e09cd3d..284bc0652 100644 --- a/Flax.flaxproj +++ b/Flax.flaxproj @@ -4,7 +4,7 @@ "Major": 1, "Minor": 11, "Revision": 0, - "Build": 6800 + "Build": 6801 }, "Company": "Flax", "Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.", From be7871c29206c0df5cdec0c9d382aa54aacc1d70 Mon Sep 17 00:00:00 2001 From: Saas Date: Sun, 12 Oct 2025 16:50:31 +0200 Subject: [PATCH 132/137] use Render2D based solution rather than shader for alpha grid https://github.com/FlaxEngine/FlaxEngine/pull/3281#issuecomment-3218049398 --- Source/Editor/EditorAssets.cs | 5 ----- Source/Editor/GUI/Input/ColorValueBox.cs | 28 ++++++++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs index d30ca91c0..bdfc7dfa6 100644 --- a/Source/Editor/EditorAssets.cs +++ b/Source/Editor/EditorAssets.cs @@ -134,11 +134,6 @@ namespace FlaxEditor /// public static string FlaxIconBlueTexture = "Engine/Textures/FlaxIconBlue"; - /// - /// The checkboard material used as a background for displaying transparent colors. - /// - public static string ColorAlphaBackgroundGrid = "Editor/AlphaBackgroundGrid"; - /// /// The icon lists used by editor from the SegMDL2 font. /// diff --git a/Source/Editor/GUI/Input/ColorValueBox.cs b/Source/Editor/GUI/Input/ColorValueBox.cs index 1893c4124..d4bc03fd9 100644 --- a/Source/Editor/GUI/Input/ColorValueBox.cs +++ b/Source/Editor/GUI/Input/ColorValueBox.cs @@ -14,12 +14,7 @@ namespace FlaxEditor.GUI.Input [HideInEditor] public class ColorValueBox : Control { - private const String ScaleParamName = "Scale"; - // 4.8 is a magic number that makes the grid fit perfect in the color value box - private const float GridScale = 4.8f; - private bool _isMouseDown; - private MaterialBase checkerMaterial; /// /// Delegate function used for the color picker events handling. @@ -106,9 +101,6 @@ namespace FlaxEditor.GUI.Input public ColorValueBox() : base(0, 0, 32, 18) { - checkerMaterial = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.ColorAlphaBackgroundGrid); - checkerMaterial = checkerMaterial.CreateVirtualInstance(); - checkerMaterial.SetParameterValue(ScaleParamName, GridScale); } /// @@ -146,7 +138,25 @@ namespace FlaxEditor.GUI.Input if (isTransparent) { var alphaRect = new Rectangle(colorRect.Right, 0, Width - colorRect.Right, Height); - Render2D.DrawMaterial(checkerMaterial, alphaRect); + + // Draw checkerboard pattern to part of the color value box + Render2D.FillRectangle(alphaRect, Color.White); + var smallRectSize = 7.9f; + var numHor = Mathf.CeilToInt(alphaRect.Width / smallRectSize); + var numVer = Mathf.CeilToInt(alphaRect.Height / smallRectSize); + for (int i = 0; i < numHor; i++) + { + for (int j = 0; j < numVer; j++) + { + if ((i + j) % 2 == 0) + { + var rect = new Rectangle(alphaRect.X + smallRectSize * i, alphaRect.Y + smallRectSize * j, new Float2(smallRectSize)); + Render2D.PushClip(alphaRect); + Render2D.FillRectangle(rect, Color.Gray); + Render2D.PopClip(); + } + } + } Render2D.FillRectangle(alphaRect, _value); } From 5a9eedfadb64b16fc050c0dbe55c52f507ffae07 Mon Sep 17 00:00:00 2001 From: Saas Date: Sun, 12 Oct 2025 20:14:43 +0200 Subject: [PATCH 133/137] make old/ new editor dialog boxes nicer to read --- Source/Editor/Editor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Editor/Editor.cpp b/Source/Editor/Editor.cpp index 04c6eee71..a8ef8f4e9 100644 --- a/Source/Editor/Editor.cpp +++ b/Source/Editor/Editor.cpp @@ -266,8 +266,8 @@ bool Editor::CheckProjectUpgrade() // Check if last version was older else if (lastVersion.Major < FLAXENGINE_VERSION_MAJOR || (lastVersion.Major == FLAXENGINE_VERSION_MAJOR && lastVersion.Minor < FLAXENGINE_VERSION_MINOR)) { - LOG(Warning, "The project was opened with the older editor version last time"); - const auto result = MessageBox::Show(TEXT("The project was opened with the older editor version last time. Loading it may modify existing data so older editor version won't open it. Do you want to perform a backup before or cancel operation?"), TEXT("Project upgrade"), MessageBoxButtons::YesNoCancel, MessageBoxIcon::Question); + LOG(Warning, "The project was last opened with an older editor version"); + const auto result = MessageBox::Show(TEXT("The project was last opened with an older editor version.\nLoading it may modify existing data, which can result in older editor versions being unable to open it.\n\nDo you want to perform a backup before or cancel the operation?"), TEXT("Project upgrade"), MessageBoxButtons::YesNoCancel, MessageBoxIcon::Question); if (result == DialogResult::Yes) { if (BackupProject()) @@ -289,8 +289,8 @@ bool Editor::CheckProjectUpgrade() // Check if last version was newer else if (lastVersion.Major > FLAXENGINE_VERSION_MAJOR || (lastVersion.Major == FLAXENGINE_VERSION_MAJOR && lastVersion.Minor > FLAXENGINE_VERSION_MINOR)) { - LOG(Warning, "The project was opened with the newer editor version last time"); - const auto result = MessageBox::Show(TEXT("The project was opened with the newer editor version last time. Loading it may fail and corrupt existing data. Do you want to perform a backup before or cancel operation?"), TEXT("Project upgrade"), MessageBoxButtons::YesNoCancel, MessageBoxIcon::Warning); + LOG(Warning, "The project was last opened with a newer editor version"); + const auto result = MessageBox::Show(TEXT("The project was last opened with a newer editor version.\nLoading it may fail and corrupt existing data.\n\nDo you want to perform a backup before loading or cancel the operation?"), TEXT("Project upgrade"), MessageBoxButtons::YesNoCancel, MessageBoxIcon::Warning); if (result == DialogResult::Yes) { if (BackupProject()) From d7a528cdbc65e9c47d6e09595322b962e67bf761 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 12 Oct 2025 22:38:11 +0200 Subject: [PATCH 134/137] Update assets --- Content/Shaders/Reflections.flax | 4 ++-- Content/Shaders/SSR.flax | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Content/Shaders/Reflections.flax b/Content/Shaders/Reflections.flax index a4605e048..d5ac73593 100644 --- a/Content/Shaders/Reflections.flax +++ b/Content/Shaders/Reflections.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5c99a81c70ccb7e9b2e1e4bc5f271c2fe7b36630489fbb269adfaa34de2cc80 -size 3183 +oid sha256:28c80074ac502d5a931b91089fea7bc0c9d573e0bdd317623577833ff328aa8a +size 3107 diff --git a/Content/Shaders/SSR.flax b/Content/Shaders/SSR.flax index 79085c297..1d5932820 100644 --- a/Content/Shaders/SSR.flax +++ b/Content/Shaders/SSR.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9602d25ef9300636aa23112b3ba3a4f45bf1c4c99b1484a86074da5a787abfc -size 11085 +oid sha256:e1a51391e285346f0a67a75ab03b8262cae02d02dddf0d625a6814a51a3b7394 +size 11007 From 7dfc37f65276eae7f9889c454055b59db3b8cd79 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 12 Oct 2025 23:24:34 +0200 Subject: [PATCH 135/137] Adjustments for #3338 --- Source/Engine/Audio/AudioBackend.h | 5 +-- Source/Engine/Audio/AudioListener.cpp | 4 +-- .../Flax.Build/Deps/Dependencies/NvCloth.cs | 2 +- .../Flax.Build/Deps/Dependencies/OpenAL.cs | 35 ++++++++++++------- Source/Tools/Flax.Build/Deps/Dependency.cs | 15 ++++++++ Source/Tools/Flax.Build/Deps/Downloader.cs | 18 ++++++++-- 6 files changed, 58 insertions(+), 21 deletions(-) diff --git a/Source/Engine/Audio/AudioBackend.h b/Source/Engine/Audio/AudioBackend.h index d0cf42fb1..7d3d087a7 100644 --- a/Source/Engine/Audio/AudioBackend.h +++ b/Source/Engine/Audio/AudioBackend.h @@ -4,8 +4,6 @@ #include "Config.h" #include "Types.h" - -#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Types/BaseTypes.h" /// @@ -85,8 +83,7 @@ public: FORCE_INLINE static void VelocityChanged(const Vector3& velocity) { - if (!velocity.IsNanOrInfinity()) - Instance->Listener_VelocityChanged(velocity); + Instance->Listener_VelocityChanged(velocity); } FORCE_INLINE static void TransformChanged(const Vector3& position, const Quaternion& orientation) diff --git a/Source/Engine/Audio/AudioListener.cpp b/Source/Engine/Audio/AudioListener.cpp index 1921bd373..9c5898b4a 100644 --- a/Source/Engine/Audio/AudioListener.cpp +++ b/Source/Engine/Audio/AudioListener.cpp @@ -23,11 +23,11 @@ void AudioListener::Update() { // Update the velocity const Vector3 pos = GetPosition(); - const float dt = Time::Update.UnscaledDeltaTime.GetTotalSeconds(); + const float dt = Math::Max(Time::Update.UnscaledDeltaTime.GetTotalSeconds(), 0.00001f); const auto prevVelocity = _velocity; _velocity = (pos - _prevPos) / dt; _prevPos = pos; - if (_velocity != prevVelocity) + if (_velocity != prevVelocity && !_velocity.IsNanOrInfinity()) { AudioBackend::Listener::VelocityChanged(_velocity); } diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs index 545ef7169..699e40f72 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs @@ -195,7 +195,7 @@ namespace Flax.Deps.Dependencies RunCmake(cmakeFolder, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + cmakeArgs, envVars); // Run build - BuildCmake(cmakeFolder, envVars: envVars); + BuildCmake(cmakeFolder, envVars); // Deploy binaries var libs = new[] diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs index 0f1140583..447b91498 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs @@ -50,8 +50,7 @@ namespace Flax.Deps.Dependencies { var root = options.IntermediateFolder; var version = "1.24.3"; - string configuration = "Release"; - int concurrency = Math.Min(Math.Max(1, (int)(Environment.ProcessorCount * Configuration.ConcurrencyProcessorScale)), Configuration.MaxConcurrency); + var configuration = "Release"; var dstIncludePath = Path.Combine(options.ThirdPartyFolder, "OpenAL"); foreach (var platform in options.Platforms) @@ -123,7 +122,7 @@ namespace Flax.Deps.Dependencies { { "CC", "clang-" + Configuration.LinuxClangMinVer }, { "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer }, - { "CMAKE_BUILD_PARALLEL_LEVEL", concurrency.ToString() }, + { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel }, }; var config = $"-DALSOFT_REQUIRE_ALSA=ON " + $"-DALSOFT_REQUIRE_OSS=ON " + @@ -158,7 +157,11 @@ namespace Flax.Deps.Dependencies { "libopenal.a", }; - var config = "-DALSOFT_REQUIRE_OBOE=OFF -DALSOFT_REQUIRE_OPENSL=ON -DALSOFT_EMBED_HRTF_DATA=YES"; + var envVars = new Dictionary + { + { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel }, + }; + var config = " -DALSOFT_REQUIRE_OBOE=OFF -DALSOFT_REQUIRE_OPENSL=ON -DALSOFT_EMBED_HRTF_DATA=YES"; // Get the source var packagePath = Path.Combine(root, "package.zip"); @@ -181,8 +184,8 @@ namespace Flax.Deps.Dependencies SetupDirectory(buildDir, true); // Build - RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=Release " + config); - BuildCmake(buildDir); + RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=" + configuration + config, envVars); + BuildCmake(buildDir, envVars); var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64); foreach (var file in binariesToCopy) Utilities.FileCopy(Path.Combine(buildDir, file), Path.Combine(depsFolder, file)); @@ -194,7 +197,11 @@ namespace Flax.Deps.Dependencies { "libopenal.a", }; - var config = "-DALSOFT_REQUIRE_COREAUDIO=ON -DALSOFT_EMBED_HRTF_DATA=YES"; + var envVars = new Dictionary + { + { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel }, + }; + var config = " -DALSOFT_REQUIRE_COREAUDIO=ON -DALSOFT_EMBED_HRTF_DATA=YES"; // Get the source var packagePath = Path.Combine(root, "package.zip"); @@ -210,8 +217,8 @@ namespace Flax.Deps.Dependencies foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 }) { SetupDirectory(buildDir, true); - RunCmake(buildDir, platform, architecture, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=Release " + config); - BuildCmake(buildDir); + RunCmake(buildDir, platform, architecture, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=" + configuration + config, envVars); + BuildCmake(buildDir, envVars); var depsFolder = GetThirdPartyFolder(options, platform, architecture); foreach (var file in binariesToCopy) Utilities.FileCopy(Path.Combine(buildDir, file), Path.Combine(depsFolder, file)); @@ -224,7 +231,11 @@ namespace Flax.Deps.Dependencies { "libopenal.a", }; - var config = "-DALSOFT_REQUIRE_COREAUDIO=ON -DALSOFT_EMBED_HRTF_DATA=YES"; + var envVars = new Dictionary + { + { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel }, + }; + var config = " -DALSOFT_REQUIRE_COREAUDIO=ON -DALSOFT_EMBED_HRTF_DATA=YES"; // Get the source var packagePath = Path.Combine(root, "package.zip"); @@ -240,8 +251,8 @@ namespace Flax.Deps.Dependencies // Build for iOS SetupDirectory(buildDir, true); - RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_SYSTEM_NAME=iOS -DALSOFT_OSX_FRAMEWORK=ON -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=Release " + config); - BuildCmake(buildDir); + RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_SYSTEM_NAME=iOS -DALSOFT_OSX_FRAMEWORK=ON -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=" + configuration + config, envVars); + BuildCmake(buildDir, envVars); var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64); foreach (var file in binariesToCopy) Utilities.FileCopy(Path.Combine(buildDir, file), Path.Combine(depsFolder, file)); diff --git a/Source/Tools/Flax.Build/Deps/Dependency.cs b/Source/Tools/Flax.Build/Deps/Dependency.cs index 79d39f2a6..a79a968a3 100644 --- a/Source/Tools/Flax.Build/Deps/Dependency.cs +++ b/Source/Tools/Flax.Build/Deps/Dependency.cs @@ -248,6 +248,21 @@ namespace Flax.Deps Utilities.Run("git", "reset --hard", null, path, Utilities.RunOptions.DefaultTool); } + /// + /// Gets the maximum concurrency level for a cmake command. See CMAKE_BUILD_PARALLEL_LEVEL or -j docs. + /// + public static string CmakeBuildParallel => Math.Min(Math.Max(1, (int)(Environment.ProcessorCount * Configuration.ConcurrencyProcessorScale)), Configuration.MaxConcurrency).ToString(); + + /// + /// Builds the cmake project. + /// + /// The path. + /// Custom environment variables to pass to the child process. + public static void BuildCmake(string path, Dictionary envVars) + { + BuildCmake(path, "Release", envVars); + } + /// /// Builds the cmake project. /// diff --git a/Source/Tools/Flax.Build/Deps/Downloader.cs b/Source/Tools/Flax.Build/Deps/Downloader.cs index 4b8c77da0..57da4a2ee 100644 --- a/Source/Tools/Flax.Build/Deps/Downloader.cs +++ b/Source/Tools/Flax.Build/Deps/Downloader.cs @@ -14,6 +14,7 @@ namespace Flax.Deps /// static class Downloader { + private static bool IgnoreSSL = false; private const string GoogleDriveDomain = "drive.google.com"; private const string GoogleDriveDomain2 = "https://drive.google.com"; @@ -54,7 +55,7 @@ namespace Flax.Deps { if (httpClient == null) { - using (httpClient = new HttpClient()) + using (httpClient = GetHttpClient()) { return DownloadFileFromUrlToPathRaw(url, path, httpClient); } @@ -130,7 +131,7 @@ namespace Flax.Deps // You can comment the statement below if the provided url is guaranteed to be in the following format: // https://drive.google.com/uc?id=FILEID&export=download url = GetGoogleDriveDownloadLinkFromUrl(url); - using (var httpClient = new HttpClient()) + using (var httpClient = GetHttpClient()) { FileInfo downloadedFile; @@ -209,5 +210,18 @@ namespace Flax.Deps return string.Format("https://drive.google.com/uc?id={0}&export=download", url.Substring(index, closingIndex - index)); } + + private static HttpClient GetHttpClient() + { + if (IgnoreSSL) + { + Log.Warning("Accessing HTTP with SSL certificate validation disabled!"); + var handler = new HttpClientHandler(); + handler.ClientCertificateOptions = ClientCertificateOption.Manual; + handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true; + return new HttpClient(handler); + } + return new HttpClient(); + } } } From 212abe7d9061b4b14766e716a58fcea08051642d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 12 Oct 2025 23:25:17 +0200 Subject: [PATCH 136/137] Update OpenAL for Windows and Android #3338 --- .../Platforms/Android/Binaries/ThirdParty/ARM64/libopenal.a | 4 ++-- Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll | 4 ++-- Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Platforms/Android/Binaries/ThirdParty/ARM64/libopenal.a b/Source/Platforms/Android/Binaries/ThirdParty/ARM64/libopenal.a index 5c5eebbb9..6bdec7f7a 100644 --- a/Source/Platforms/Android/Binaries/ThirdParty/ARM64/libopenal.a +++ b/Source/Platforms/Android/Binaries/ThirdParty/ARM64/libopenal.a @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7179291d2efd8d3c8c8cd494a2c65e5b506e52929b962223f0af9faf2ba09382 -size 20142390 +oid sha256:4743608626b06af2df45dfb3af6b5ca97ecf08fd35d2a7dd14ac9f19d3aadd9e +size 34362142 diff --git a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll index e64bb6cd7..c270e6da5 100644 --- a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll +++ b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a54bca64e921d32525ed58c52ce802b4ca2c3f8a92c342296da48c55ec1ea58d -size 1112064 +oid sha256:084675cd25a1090424ae7a31a93d69dd52d2752a9940e28104759e9f87c573b4 +size 1407488 diff --git a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib index ae9715a8b..9acd14199 100644 --- a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib +++ b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a4ac5af61abb19624dc2ae23bc16af09a062655f3eab89fedf6c0ead6cd935a +oid sha256:b58f1412018cc3618ab579e280bf5fc167479494655dcf440d0239948e44a65d size 37562 From b62f331b08342f405df88406e9c6d9dfdccc673f Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 12 Oct 2025 17:04:40 -0500 Subject: [PATCH 137/137] Fix crash when deleting collision data. --- Source/Engine/Physics/Colliders/Collider.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp index f93a9bd88..6980fc4e6 100644 --- a/Source/Engine/Physics/Colliders/Collider.cpp +++ b/Source/Engine/Physics/Colliders/Collider.cpp @@ -244,10 +244,14 @@ void Collider::UpdateGeometry() if (actor) { const auto rigidBody = dynamic_cast(GetParent()); - if (_staticActor != nullptr || (rigidBody && CanAttach(rigidBody))) + if (rigidBody && CanAttach(rigidBody)) { Attach(rigidBody); } + else if (_staticActor != nullptr) + { + PhysicsBackend::AttachShape(_shape, actor); + } else { // Be static triangle mesh