From be319c446dac20eb505e6e97ab475d02a4904605 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 5 Jan 2021 14:14:34 +0100 Subject: [PATCH] Refactor settings types to use scripting API --- .../Settings/AndroidPlatformSettings.cs | 30 -- .../Editor/Content/Settings/AudioSettings.cs | 34 --- .../Editor/Content/Settings/BuildSettings.cs | 67 +---- .../Editor/Content/Settings/GameSettings.cs | 23 +- .../Content/Settings/GraphicsSettings.cs | 61 ----- .../Editor/Content/Settings/InputSettings.cs | 5 +- .../Content/Settings/LayersAndTagsSettings.cs | 5 +- .../Content/Settings/LinuxPlatformSettings.cs | 60 ---- .../Content/Settings/PhysicsSettings.cs | 97 +------ .../Editor/Content/Settings/TimeSettings.cs | 48 ---- .../Content/Settings/UWPPlatformSettings.cs | 97 ------- .../Settings/WindowsPlatformSettings.cs | 90 ------ Source/Editor/Cooker/GameCooker.cpp | 42 --- .../Platform/Android/AndroidPlatformTools.cpp | 20 +- .../Platform/Linux/LinuxPlatformTools.cpp | 6 +- .../Cooker/Platform/UWP/UWPPlatformTools.cpp | 17 +- .../Platform/Windows/WindowsPlatformTools.cpp | 6 +- Source/Editor/Cooker/Steps/CookAssetsStep.cpp | 39 +-- Source/Editor/Cooker/Steps/DeployDataStep.cpp | 5 +- Source/Editor/Cooker/Steps/ValidateStep.cpp | 13 +- Source/Editor/Editor.Build.cs | 2 +- .../Editor/Managed/ManagedEditor.Internal.cpp | 18 +- Source/Editor/Utilities/EditorUtilities.cpp | 6 +- Source/Engine/Audio/Audio.cpp | 22 +- Source/Engine/Audio/AudioSettings.h | 19 +- .../Engine/Audio/OpenAL/AudioBackendOAL.cpp | 2 +- .../Audio/XAudio2/AudioBackendXAudio2.cpp | 2 +- Source/Engine/Content/JsonAsset.cpp | 2 + Source/Engine/Content/JsonAsset.h | 6 +- Source/Engine/Core/Config/BuildSettings.h | 32 ++- Source/Engine/Core/Config/GameSettings.cpp | 259 ++++++++++-------- Source/Engine/Core/Config/GameSettings.h | 56 +++- Source/Engine/Core/Config/GraphicsSettings.h | 29 +- .../Engine/Core/Config/LayersTagsSettings.h | 39 +-- Source/Engine/Core/Config/Settings.h | 85 ++---- Source/Engine/Core/Config/TimeSettings.h | 35 +-- Source/Engine/Core/Math/Math.cpp | 4 +- Source/Engine/Engine/Base/GameBase.cpp | 7 +- Source/Engine/Engine/Engine.cpp | 17 +- Source/Engine/Engine/Linux/LinuxGame.cpp | 4 +- Source/Engine/Engine/Time.cpp | 28 +- Source/Engine/Engine/Time.h | 2 + Source/Engine/Engine/Windows/WindowsGame.cpp | 4 +- .../DirectX/DX11/GPUDeviceDX11.cpp | 2 +- .../DirectX/DX12/GPUDeviceDX12.cpp | 2 +- .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 2 +- Source/Engine/Input/Input.cpp | 6 + Source/Engine/Input/Input.h | 1 - Source/Engine/Input/InputSettings.h | 24 +- Source/Engine/Level/Actor.cpp | 17 +- Source/Engine/Level/Level.cpp | 32 +++ Source/Engine/Level/Level.h | 25 ++ Source/Engine/Navigation/NavMeshBuilder.cpp | 4 +- Source/Engine/Navigation/Navigation.cpp | 6 + .../Engine/Navigation/NavigationSettings.cs | 8 + Source/Engine/Navigation/NavigationSettings.h | 24 +- Source/Engine/Physics/Colliders/Collider.cpp | 2 +- Source/Engine/Physics/PhysicalMaterial.cpp | 52 ---- Source/Engine/Physics/Physics.cpp | 216 ++++++++++++--- Source/Engine/Physics/Physics.h | 5 + Source/Engine/Physics/PhysicsSettings.cpp | 82 ------ Source/Engine/Physics/PhysicsSettings.h | 161 ++++++----- Source/Engine/Physics/Utilities.h | 32 +-- .../Android/AndroidPlatformSettings.h | 24 +- .../Platform/Linux/LinuxPlatformSettings.h | 41 +-- Source/Engine/Platform/Platform.Build.cs | 10 + .../Engine/Platform/UWP/UWPPlatformSettings.h | 27 +- .../Windows/WindowsPlatformSettings.h | 45 +-- Source/Engine/Terrain/Terrain.cpp | 2 +- .../Bindings/BindingsGenerator.CSharp.cs | 14 + .../Bindings/BindingsGenerator.Cpp.cs | 11 +- .../Bindings/BindingsGenerator.Parsing.cs | 3 +- .../Flax.Build/Bindings/BindingsGenerator.cs | 45 +-- Source/Tools/Flax.Build/Bindings/FieldInfo.cs | 5 + Source/Tools/Flax.Build/Build/Module.cs | 11 + 75 files changed, 955 insertions(+), 1431 deletions(-) delete mode 100644 Source/Editor/Content/Settings/AndroidPlatformSettings.cs delete mode 100644 Source/Editor/Content/Settings/AudioSettings.cs delete mode 100644 Source/Editor/Content/Settings/GraphicsSettings.cs delete mode 100644 Source/Editor/Content/Settings/LinuxPlatformSettings.cs delete mode 100644 Source/Editor/Content/Settings/TimeSettings.cs delete mode 100644 Source/Editor/Content/Settings/UWPPlatformSettings.cs delete mode 100644 Source/Editor/Content/Settings/WindowsPlatformSettings.cs create mode 100644 Source/Engine/Navigation/NavigationSettings.cs delete mode 100644 Source/Engine/Physics/PhysicalMaterial.cpp delete mode 100644 Source/Engine/Physics/PhysicsSettings.cpp diff --git a/Source/Editor/Content/Settings/AndroidPlatformSettings.cs b/Source/Editor/Content/Settings/AndroidPlatformSettings.cs deleted file mode 100644 index 2c540109f..000000000 --- a/Source/Editor/Content/Settings/AndroidPlatformSettings.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The Android platform settings asset archetype. Allows to edit asset via editor. - /// - public class AndroidPlatformSettings : SettingsBase - { - /// - /// The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}. - /// - [EditorOrder(0), EditorDisplay("General"), Tooltip("The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}.")] - public string PackageName = "com.${COMPANY_NAME}.${PROJECT_NAME}"; - - /// - /// The application permissions list (eg. android.media.action.IMAGE_CAPTURE). Added to the generated manifest file. - /// - [EditorOrder(100), EditorDisplay("General"), Tooltip("The application permissions list (eg. android.media.action.IMAGE_CAPTURE). Added to the generated manifest file.")] - public string[] Permissions; - - /// - /// Custom icon texture to use for the application (overrides the default one). - /// - [EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")] - public Texture OverrideIcon; - } -} diff --git a/Source/Editor/Content/Settings/AudioSettings.cs b/Source/Editor/Content/Settings/AudioSettings.cs deleted file mode 100644 index f011cad46..000000000 --- a/Source/Editor/Content/Settings/AudioSettings.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using System.ComponentModel; -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The audio payback engine settings container. Allows to edit asset via editor. - /// - public sealed class AudioSettings : SettingsBase - { - /// - /// If checked, audio playback will be disabled in build game. Can be used if game uses custom audio playback engine. - /// - [DefaultValue(false)] - [EditorOrder(0), EditorDisplay("General"), Tooltip("If checked, audio playback will be disabled in build game. Can be used if game uses custom audio playback engine.")] - public bool DisableAudio; - - /// - /// The doppler doppler effect factor. Scale for source and listener velocities. Default is 1. - /// - [DefaultValue(1.0f)] - [EditorOrder(100), EditorDisplay("General"), Limit(0, 10.0f, 0.01f), Tooltip("The doppler doppler effect factor. Scale for source and listener velocities. Default is 1.")] - public float DopplerFactor = 1.0f; - - /// - /// True if mute all audio playback when game has no use focus. - /// - [DefaultValue(true)] - [EditorOrder(200), EditorDisplay("General", "Mute On Focus Loss"), Tooltip("If checked, engine will mute all audio playback when game has no use focus.")] - public bool MuteOnFocusLoss = true; - } -} diff --git a/Source/Editor/Content/Settings/BuildSettings.cs b/Source/Editor/Content/Settings/BuildSettings.cs index e74a5fd41..87530f1fb 100644 --- a/Source/Editor/Content/Settings/BuildSettings.cs +++ b/Source/Editor/Content/Settings/BuildSettings.cs @@ -1,77 +1,12 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; -using System.ComponentModel; using FlaxEngine; namespace FlaxEditor.Content.Settings { - /// - /// The game building settings container. Allows to edit asset via editor. - /// - public sealed class BuildSettings : SettingsBase + partial class BuildSettings { - /// - /// The maximum amount of assets to include into a single assets package. Assets will be split into several packages if need to. - /// - [DefaultValue(4096)] - [EditorOrder(10), Limit(32, short.MaxValue), EditorDisplay("General", "Max assets per package"), Tooltip("The maximum amount of assets to include into a single assets package. Assets will be split into several packages if need to.")] - public int MaxAssetsPerPackage = 4096; - - /// - /// The maximum size of the single assets package (in megabytes). Assets will be split into several packages if need to. - /// - [DefaultValue(1024)] - [EditorOrder(20), Limit(16, short.MaxValue), EditorDisplay("General", "Max package size (in MB)"), Tooltip("The maximum size of the single assets package (in megabytes). Assets will be split into several packages if need to.")] - public int MaxPackageSizeMB = 1024; - - /// - /// The game content cooking Keys. Use the same value for a game and DLC packages to support loading them by the build game. Use 0 to randomize it during building. - /// - [DefaultValue(0)] - [EditorOrder(30), EditorDisplay("General"), Tooltip("The game content cooking Keys. Use the same value for a game and DLC packages to support loading them by the build game. Use 0 to randomize it during building.")] - public int ContentKey = 0; - - /// - /// If checked, the builds produced by the Game Cooker will be treated as for final game distribution (eg. for game store upload). Builds done this way cannot be tested on console devkits (eg. Xbox One, Xbox Scarlett). - /// - [DefaultValue(false)] - [EditorOrder(40), EditorDisplay("General"), Tooltip("If checked, the builds produced by the Game Cooker will be treated as for final game distribution (eg. for game store upload). Builds done this way cannot be tested on console devkits (eg. Xbox One, Xbox Scarlett).")] - public bool ForDistribution; - - /// - /// If checked, the output build files won't be packaged for the destination platform. Useful when debugging build from local PC. - /// - [DefaultValue(false)] - [EditorOrder(50), EditorDisplay("General"), Tooltip("If checked, the output build files won't be packaged for the destination platform. Useful when debugging build from local PC.")] - public bool SkipPackaging; - - /// - /// The additional assets to include into build (into root assets set). - /// - [EditorOrder(1000), EditorDisplay("Additional Data"), Tooltip("The additional assets to include into build (into root assets set).")] - public Asset[] AdditionalAssets; - - /// - /// The additional folders with assets to include into build (into root assets set). List of paths relative to the project directory (or absolute). - /// - [EditorOrder(1010), EditorDisplay("Additional Data"), Tooltip("The additional folders with assets to include into build (to root assets set). List of paths relative to the project directory (or absolute).")] - public string[] AdditionalAssetFolders; - - /// - /// Disables shaders compiler optimizations in cooked game. Can be used to debug shaders on a target platform or to speed up the shaders compilation time. - /// - [DefaultValue(false)] - [EditorOrder(2000), EditorDisplay("Content", "Shaders No Optimize"), Tooltip("Disables shaders compiler optimizations in cooked game. Can be used to debug shaders on a target platform or to speed up the shaders compilation time.")] - public bool ShadersNoOptimize; - - /// - /// Enables shader debug data generation for shaders in cooked game (depends on the target platform rendering backend). - /// - [DefaultValue(false)] - [EditorOrder(2010), EditorDisplay("Content"), Tooltip("Enables shader debug data generation for shaders in cooked game (depends on the target platform rendering backend).")] - public bool ShadersGenerateDebugData; - /// /// The build presets. /// diff --git a/Source/Editor/Content/Settings/GameSettings.cs b/Source/Editor/Content/Settings/GameSettings.cs index 28c13c905..eaca85c55 100644 --- a/Source/Editor/Content/Settings/GameSettings.cs +++ b/Source/Editor/Content/Settings/GameSettings.cs @@ -7,32 +7,11 @@ using FlaxEngine; namespace FlaxEditor.Content.Settings { - /// - /// The game settings asset archetype. Allows to edit asset via editor. - /// - public sealed class GameSettings : SettingsBase + partial class GameSettings { internal const string PS4PlatformSettingsTypename = "FlaxEditor.Content.Settings.PS4PlatformSettings"; internal const string XboxScarlettPlatformSettingsTypename = "FlaxEditor.Content.Settings.XboxScarlettPlatformSettings"; - /// - /// The product full name. - /// - [EditorOrder(0), EditorDisplay("General"), Tooltip("The name of your product.")] - public string ProductName; - - /// - /// The company full name. - /// - [EditorOrder(10), EditorDisplay("General"), Tooltip("The name of your company or organization.")] - public string CompanyName; - - /// - /// The copyright note used for content signing (eg. source code header). - /// - [EditorOrder(15), EditorDisplay("General"), Tooltip("The copyright note used for content signing (eg. source code header).")] - public string CopyrightNotice; - /// /// The default application icon. /// diff --git a/Source/Editor/Content/Settings/GraphicsSettings.cs b/Source/Editor/Content/Settings/GraphicsSettings.cs deleted file mode 100644 index 731bc750d..000000000 --- a/Source/Editor/Content/Settings/GraphicsSettings.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The graphics rendering settings container. Allows to edit asset via editor. To modify those settings at runtime use . - /// - /// - public sealed class GraphicsSettings : SettingsBase - { - /// - /// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts. - /// - [EditorOrder(20), EditorDisplay("General", "Use V-Sync"), Tooltip("Enables rendering synchronization with the refresh rate of the display device to avoid \"tearing\" artifacts.")] - public bool UseVSync = false; - - /// - /// Anti Aliasing quality setting. - /// - [EditorOrder(1000), EditorDisplay("Quality", "AA Quality"), Tooltip("Anti Aliasing quality.")] - public Quality AAQuality = Quality.Medium; - - /// - /// Screen Space Reflections quality. - /// - [EditorOrder(1100), EditorDisplay("Quality", "SSR Quality"), Tooltip("Screen Space Reflections quality.")] - public Quality SSRQuality = Quality.Medium; - - /// - /// Screen Space Ambient Occlusion quality setting. - /// - [EditorOrder(1200), EditorDisplay("Quality", "SSAO Quality"), Tooltip("Screen Space Ambient Occlusion quality setting.")] - public Quality SSAOQuality = Quality.Medium; - - /// - /// Volumetric Fog quality setting. - /// - [EditorOrder(1250), EditorDisplay("Quality", "Volumetric Fog Quality"), Tooltip("Volumetric Fog quality setting.")] - public Quality VolumetricFogQuality = Quality.High; - - /// - /// The shadows quality. - /// - [EditorOrder(1300), EditorDisplay("Quality", "Shadows Quality"), Tooltip("The shadows quality.")] - public Quality ShadowsQuality = Quality.Medium; - - /// - /// The shadow maps quality (textures resolution). - /// - [EditorOrder(1310), EditorDisplay("Quality", "Shadow Maps Quality"), Tooltip("The shadow maps quality (textures resolution).")] - public Quality ShadowMapsQuality = Quality.Medium; - - /// - /// Enables cascades splits blending for directional light shadows. - /// - [EditorOrder(1320), EditorDisplay("Quality", "Allow CSM Blending"), Tooltip("Enables cascades splits blending for directional light shadows.")] - public bool AllowCSMBlending = false; - } -} diff --git a/Source/Editor/Content/Settings/InputSettings.cs b/Source/Editor/Content/Settings/InputSettings.cs index 69a8dfba3..03ed4b7c7 100644 --- a/Source/Editor/Content/Settings/InputSettings.cs +++ b/Source/Editor/Content/Settings/InputSettings.cs @@ -4,10 +4,7 @@ using FlaxEngine; namespace FlaxEditor.Content.Settings { - /// - /// The input settings container. Allows to edit asset via editor. - /// - public sealed class InputSettings : SettingsBase + partial class InputSettings { /// /// Maps a discrete button or key press events to a "friendly name" that will later be bound to event-driven behavior. The end effect is that pressing (and/or releasing) a key, mouse button, or keypad button. diff --git a/Source/Editor/Content/Settings/LayersAndTagsSettings.cs b/Source/Editor/Content/Settings/LayersAndTagsSettings.cs index 5f3884ee1..31e8dfff8 100644 --- a/Source/Editor/Content/Settings/LayersAndTagsSettings.cs +++ b/Source/Editor/Content/Settings/LayersAndTagsSettings.cs @@ -6,10 +6,7 @@ using FlaxEngine; namespace FlaxEditor.Content.Settings { - /// - /// The layers and objects tags settings. Allows to edit asset via editor. - /// - public sealed class LayersAndTagsSettings : SettingsBase + partial class LayersAndTagsSettings { /// /// The tag names. diff --git a/Source/Editor/Content/Settings/LinuxPlatformSettings.cs b/Source/Editor/Content/Settings/LinuxPlatformSettings.cs deleted file mode 100644 index 8b26e77d4..000000000 --- a/Source/Editor/Content/Settings/LinuxPlatformSettings.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The Linux platform settings asset archetype. Allows to edit asset via editor. - /// - public class LinuxPlatformSettings : SettingsBase - { - /// - /// The default game window mode. - /// - [EditorOrder(10), EditorDisplay("Window"), Tooltip("The default game window mode.")] - public GameWindowMode WindowMode = GameWindowMode.Windowed; - - /// - /// The default game window width (in pixels). - /// - [EditorOrder(20), EditorDisplay("Window"), Tooltip("The default game window width (in pixels).")] - public int ScreenWidth = 1280; - - /// - /// The default game window height (in pixels). - /// - [EditorOrder(30), EditorDisplay("Window"), Tooltip("The default game window height (in pixels).")] - public int ScreenHeight = 720; - - /// - /// Enables resizing the game window by the user. - /// - [EditorOrder(40), EditorDisplay("Window"), Tooltip("Enables resizing the game window by the user.")] - public bool ResizableWindow = false; - - /// - /// Enables game running when application window loses focus. - /// - [EditorOrder(1010), EditorDisplay("Other", "Run In Background"), Tooltip("Enables game running when application window loses focus.")] - public bool RunInBackground = false; - - /// - /// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once. - /// - [EditorOrder(1020), EditorDisplay("Other"), Tooltip("Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.")] - public bool ForceSingleInstance = false; - - /// - /// Custom icon texture to use for the application (overrides the default one). - /// - [EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")] - public Texture OverrideIcon; - - /// - /// Enables support for Vulkan. Disabling it reduces compiled shaders count. - /// - [EditorOrder(2020), EditorDisplay("Graphics", "Support Vulkan"), Tooltip("Enables support for Vulkan. Disabling it reduces compiled shaders count.")] - public bool SupportVulkan = true; - } -} diff --git a/Source/Editor/Content/Settings/PhysicsSettings.cs b/Source/Editor/Content/Settings/PhysicsSettings.cs index 540b11772..d217512b3 100644 --- a/Source/Editor/Content/Settings/PhysicsSettings.cs +++ b/Source/Editor/Content/Settings/PhysicsSettings.cs @@ -1,112 +1,17 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. -using System.ComponentModel; using FlaxEngine; namespace FlaxEditor.Content.Settings { - /// - /// The physics simulation settings container. Allows to edit asset via editor. - /// - public sealed class PhysicsSettings : SettingsBase + partial class PhysicsSettings { - /// - /// The default gravity force value (in cm^2/s). - /// - [DefaultValue(typeof(Vector3), "0,-981.0,0")] - [EditorOrder(0), EditorDisplay("Simulation"), Tooltip("The default gravity force value (in cm^2/s).")] - public Vector3 DefaultGravity = new Vector3(0, -981.0f, 0); - - /// - /// If enabled, any Raycast or other scene query that intersects with a Collider marked as a Trigger will returns with a hit. Individual raycasts can override this behavior. - /// - [DefaultValue(true)] - [EditorOrder(10), EditorDisplay("Simulation"), Tooltip("If enabled, any Raycast or other scene query that intersects with a Collider marked as a Trigger will returns with a hit. Individual raycasts can override this behavior.")] - public bool QueriesHitTriggers = true; - - /// - /// Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable. - /// - [DefaultValue(5.0f)] - [EditorOrder(20), EditorDisplay("Simulation"), Limit(-1, 10), Tooltip("Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable.")] - public float TriangleMeshTriangleMinAreaThreshold = 5.0f; - - /// - /// Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity - /// - [DefaultValue(200.0f)] - [EditorOrder(30), EditorDisplay("Simulation"), Limit(0), Tooltip("Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity")] - public float BounceThresholdVelocity = 200.0f; - - /// - /// Default friction combine mode, controls how friction is computed for multiple materials. - /// - [DefaultValue(PhysicsCombineMode.Average)] - [EditorOrder(40), EditorDisplay("Simulation"), Tooltip("Default friction combine mode, controls how friction is computed for multiple materials.")] - public PhysicsCombineMode FrictionCombineMode = PhysicsCombineMode.Average; - - /// - /// Default restitution combine mode, controls how restitution is computed for multiple materials. - /// - [DefaultValue(PhysicsCombineMode.Average)] - [EditorOrder(50), EditorDisplay("Simulation"), Tooltip("Default restitution combine mode, controls how restitution is computed for multiple materials.")] - public PhysicsCombineMode RestitutionCombineMode = PhysicsCombineMode.Average; - - /// - /// If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for PhysX to check it internally. - /// - [DefaultValue(false)] - [EditorOrder(70), EditorDisplay("Simulation", "Disable CCD"), Tooltip("If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for PhysX to check it internally.")] - public bool DisableCCD; - - /// - /// Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts. - /// - [DefaultValue(false)] - [EditorOrder(80), EditorDisplay("Simulation"), Tooltip("Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts.")] - public bool EnableAdaptiveForce; - - /// - /// The maximum allowed delta time (in seconds) for the physics simulation step. - /// - [DefaultValue(1.0f / 10.0f)] - [EditorOrder(1000), EditorDisplay("Framerate"), Limit(0.0013f, 2.0f), Tooltip("The maximum allowed delta time (in seconds) for the physics simulation step.")] - public float MaxDeltaTime = 1.0f / 10.0f; - - /// - /// Whether to substep the physics simulation. - /// - [DefaultValue(false)] - [EditorOrder(1005), EditorDisplay("Framerate"), Tooltip("Whether to substep the physics simulation.")] - public bool EnableSubstepping; - - /// - /// Delta time (in seconds) for an individual simulation substep. - /// - [DefaultValue(1.0f / 120.0f)] - [EditorOrder(1010), EditorDisplay("Framerate"), Limit(0.0013f, 1.0f), Tooltip("Delta time (in seconds) for an individual simulation substep.")] - public float SubstepDeltaTime = 1.0f / 120.0f; - - /// - /// The maximum number of substeps for physics simulation. - /// - [DefaultValue(5)] - [EditorOrder(1020), EditorDisplay("Framerate"), Limit(1, 16), Tooltip("The maximum number of substeps for physics simulation.")] - public int MaxSubsteps = 5; - /// /// The collision layers masks. Used to define layer-based collision detection. /// [EditorOrder(1040), EditorDisplay("Layers Matrix"), CustomEditor(typeof(FlaxEditor.CustomEditors.Dedicated.LayersMatrixEditor))] public uint[] LayerMasks = new uint[32]; - /// - /// Enables support for cooking physical collision shapes geometry at runtime. Use it to enable generating runtime terrain collision or convex mesh colliders. - /// - [DefaultValue(false)] - [EditorOrder(1100), EditorDisplay("Other", "Support Cooking At Runtime"), Tooltip("Enables support for cooking physical collision shapes geometry at runtime. Use it to enable generating runtime terrain collision or convex mesh colliders.")] - public bool SupportCookingAtRuntime; - /// /// Initializes a new instance of the class. /// diff --git a/Source/Editor/Content/Settings/TimeSettings.cs b/Source/Editor/Content/Settings/TimeSettings.cs deleted file mode 100644 index af352f5e1..000000000 --- a/Source/Editor/Content/Settings/TimeSettings.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using System.ComponentModel; -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The time settings asset archetype. Allows to edit asset via editor. - /// - public sealed class TimeSettings : SettingsBase - { - /// - /// The target amount of the game logic updates per second (script updates frequency). Use 0 for infinity. - /// - [DefaultValue(30.0f)] - [EditorOrder(1), Limit(0, 1000), EditorDisplay(null, "Update FPS"), Tooltip("Target amount of the game logic updates per second (script updates frequency). Use 0 for infinity.")] - public float UpdateFPS = 30.0f; - - /// - /// The target amount of the physics simulation updates per second (also fixed updates frequency). Use 0 for infinity. - /// - [DefaultValue(60.0f)] - [EditorOrder(2), Limit(0, 1000), EditorDisplay(null, "Physics FPS"), Tooltip("Target amount of the physics simulation updates per second (also fixed updates frequency). Use 0 for infinity.")] - public float PhysicsFPS = 60.0f; - - /// - /// The target amount of the frames rendered per second (actual game FPS). Use 0 for infinity. - /// - [DefaultValue(60.0f)] - [EditorOrder(3), Limit(0, 1000), EditorDisplay(null, "Draw FPS"), Tooltip("Target amount of the frames rendered per second (actual game FPS). Use 0 for infinity.")] - public float DrawFPS = 60.0f; - - /// - /// The game time scale factor. Default is 1. - /// - [DefaultValue(1.0f)] - [EditorOrder(10), Limit(0, 1000.0f, 0.1f), Tooltip("Game time scaling factor. Default is 1 for real-time simulation.")] - public float TimeScale = 1.0f; - - /// - /// The maximum allowed delta time (in seconds) for the game logic update step. - /// - [DefaultValue(1.0f / 10.0f)] - [EditorOrder(20), Limit(0.1f, 1000.0f, 0.01f), Tooltip("The maximum allowed delta time (in seconds) for the game logic update step.")] - public float MaxUpdateDeltaTime = 1.0f / 10.0f; - } -} diff --git a/Source/Editor/Content/Settings/UWPPlatformSettings.cs b/Source/Editor/Content/Settings/UWPPlatformSettings.cs deleted file mode 100644 index 5c5696936..000000000 --- a/Source/Editor/Content/Settings/UWPPlatformSettings.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using System; -using System.ComponentModel; -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The Universal Windows Platform (UWP) platform settings asset archetype. Allows to edit asset via editor. - /// - public class UWPPlatformSettings : SettingsBase - { - /// - /// The preferred launch windowing mode. - /// - public enum WindowMode - { - /// - /// The full screen mode - /// - FullScreen = 0, - - /// - /// The view size. - /// - ViewSize = 1, - } - - /// - /// The display orientation modes. Can be combined as flags. - /// - [Flags] - public enum DisplayOrientations - { - /// - /// The none. - /// - None = 0, - - /// - /// The landscape. - /// - Landscape = 1, - - /// - /// The landscape flipped. - /// - LandscapeFlipped = 2, - - /// - /// The portrait. - /// - Portrait = 4, - - /// - /// The portrait flipped. - /// - PortraitFlipped = 8, - } - - /// - /// The preferred launch windowing mode. Always fullscreen on Xbox. - /// - [DefaultValue(WindowMode.FullScreen)] - [EditorOrder(10), EditorDisplay("Window"), Tooltip("The preferred launch windowing mode. Always fullscreen on Xbox.")] - public WindowMode PreferredLaunchWindowingMode = WindowMode.FullScreen; - - /// - /// The display orientation modes. Can be combined as flags. - /// - [DefaultValue(DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped | DisplayOrientations.Portrait | DisplayOrientations.PortraitFlipped)] - [EditorOrder(20), EditorDisplay("Window"), Tooltip("The display orientation modes. Can be combined as flags.")] - public DisplayOrientations AutoRotationPreferences = DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped | DisplayOrientations.Portrait | DisplayOrientations.PortraitFlipped; - - /// - /// The location of the package certificate (relative to the project). - /// - [DefaultValue("")] - [EditorOrder(1010), EditorDisplay("Other"), Tooltip("The location of the package certificate (relative to the project).")] - public string CertificateLocation = string.Empty; - - /// - /// Enables support for DirectX 11. Disabling it reduces compiled shaders count. - /// - [DefaultValue(true)] - [EditorOrder(2000), EditorDisplay("Graphics", "Support DirectX 11"), Tooltip("Enables support for DirectX 11. Disabling it reduces compiled shaders count.")] - public bool SupportDX11 = true; - - /// - /// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count. - /// - [DefaultValue(false)] - [EditorOrder(2010), EditorDisplay("Graphics", "Support DirectX 10"), Tooltip("Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.")] - public bool SupportDX10 = false; - } -} diff --git a/Source/Editor/Content/Settings/WindowsPlatformSettings.cs b/Source/Editor/Content/Settings/WindowsPlatformSettings.cs deleted file mode 100644 index dc873e9f4..000000000 --- a/Source/Editor/Content/Settings/WindowsPlatformSettings.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -using System.ComponentModel; -using FlaxEngine; - -namespace FlaxEditor.Content.Settings -{ - /// - /// The Windows platform settings asset archetype. Allows to edit asset via editor. - /// - public class WindowsPlatformSettings : SettingsBase - { - /// - /// The default game window mode. - /// - [DefaultValue(GameWindowMode.Windowed)] - [EditorOrder(10), EditorDisplay("Window"), Tooltip("The default game window mode.")] - public GameWindowMode WindowMode = GameWindowMode.Windowed; - - /// - /// The default game window width (in pixels). - /// - [DefaultValue(1280)] - [EditorOrder(20), EditorDisplay("Window"), Tooltip("The default game window width (in pixels).")] - public int ScreenWidth = 1280; - - /// - /// The default game window height (in pixels). - /// - [DefaultValue(720)] - [EditorOrder(30), EditorDisplay("Window"), Tooltip("The default game window height (in pixels).")] - public int ScreenHeight = 720; - - /// - /// Enables resizing the game window by the user. - /// - [DefaultValue(false)] - [EditorOrder(40), EditorDisplay("Window"), Tooltip("Enables resizing the game window by the user.")] - public bool ResizableWindow = false; - - /// - /// Enables game running when application window loses focus. - /// - [DefaultValue(false)] - [EditorOrder(1010), EditorDisplay("Other", "Run In Background"), Tooltip("Enables game running when application window loses focus.")] - public bool RunInBackground = false; - - /// - /// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once. - /// - [DefaultValue(false)] - [EditorOrder(1020), EditorDisplay("Other"), Tooltip("Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.")] - public bool ForceSingleInstance = false; - - /// - /// Custom icon texture to use for the application (overrides the default one). - /// - [DefaultValue(null)] - [EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")] - public Texture OverrideIcon; - - /// - /// Enables support for DirectX 12. Disabling it reduces compiled shaders count. - /// - [DefaultValue(false)] - [EditorOrder(2000), EditorDisplay("Graphics", "Support DirectX 12"), Tooltip("Enables support for DirectX 12. Disabling it reduces compiled shaders count.")] - public bool SupportDX12 = false; - - /// - /// Enables support for DirectX 11. Disabling it reduces compiled shaders count. - /// - [DefaultValue(true)] - [EditorOrder(2010), EditorDisplay("Graphics", "Support DirectX 11"), Tooltip("Enables support for DirectX 11. Disabling it reduces compiled shaders count.")] - public bool SupportDX11 = true; - - /// - /// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count. - /// - [DefaultValue(false)] - [EditorOrder(2020), EditorDisplay("Graphics", "Support DirectX 10"), Tooltip("Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.")] - public bool SupportDX10 = false; - - /// - /// Enables support for Vulkan. Disabling it reduces compiled shaders count. - /// - [DefaultValue(false)] - [EditorOrder(2030), EditorDisplay("Graphics", "Support Vulkan"), Tooltip("Enables support for Vulkan. Disabling it reduces compiled shaders count.")] - public bool SupportVulkan = false; - } -} diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp index 1fdf0755f..d68ca587a 100644 --- a/Source/Editor/Cooker/GameCooker.cpp +++ b/Source/Editor/Cooker/GameCooker.cpp @@ -43,53 +43,11 @@ #endif #if PLATFORM_TOOLS_XBOX_SCARLETT #include "Platforms/XboxScarlett/Editor/PlatformTools/XboxScarlettPlatformTools.h" -#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettPlatformSettings.h" #endif #if PLATFORM_TOOLS_ANDROID #include "Platform/Android/AndroidPlatformTools.h" -#include "Engine/Platform/Android/AndroidPlatformSettings.h" #endif -void LoadPlatformSettingsEditor(ISerializable::DeserializeStream& data) -{ -#define LOAD_SETTINGS(nodeName, settingsType) \ - { \ - Guid id = JsonTools::GetGuid(data, nodeName); \ - if (id.IsValid()) \ - { \ - AssetReference subAsset = Content::LoadAsync(id); \ - if (subAsset) \ - { \ - if (!subAsset->WaitForLoaded()) \ - { \ - settingsType::Instance()->Deserialize(*subAsset->Data, nullptr); \ - settingsType::Instance()->Apply(); \ - } \ - } \ - else \ - { LOG(Warning, "Cannot load " nodeName " settings"); } \ - } \ - } -#if PLATFORM_TOOLS_WINDOWS - LOAD_SETTINGS("WindowsPlatform", WindowsPlatformSettings); -#endif -#if PLATFORM_TOOLS_UWP || PLATFORM_TOOLS_XBOX_ONE - LOAD_SETTINGS("UWPPlatform", UWPPlatformSettings); -#endif -#if PLATFORM_TOOLS_LINUX - LOAD_SETTINGS("LinuxPlatform", LinuxPlatformSettings); -#endif -#if PLATFORM_TOOLS_PS4 - LOAD_SETTINGS("PS4Platform", PS4PlatformSettings); -#endif -#if PLATFORM_TOOLS_XBOX_SCARLETT - LOAD_SETTINGS("XboxScarlettPlatform", XboxScarlettPlatformSettings); -#endif -#if PLATFORM_TOOLS_ANDROID - LOAD_SETTINGS("AndroidPlatform", AndroidPlatformSettings); -#endif -} - namespace GameCookerImpl { MMethod* Internal_OnEvent = nullptr; diff --git a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp index bce6aa860..b687e5a2b 100644 --- a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp @@ -12,6 +12,10 @@ #include "Engine/Core/Config/GameSettings.h" #include "Engine/Core/Config/BuildSettings.h" #include "Editor/Utilities/EditorUtilities.h" +#include "Engine/Content/Content.h" +#include "Engine/Content/JsonAsset.h" + +IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform); namespace { @@ -106,7 +110,8 @@ void AndroidPlatformTools::OnBuildStarted(CookingData& data) bool AndroidPlatformTools::OnPostProcess(CookingData& data) { - const auto platformSettings = AndroidPlatformSettings::Instance(); + const auto gameSettings = GameSettings::Get(); + const auto platformSettings = AndroidPlatformSettings::Get(); const auto platformDataPath = data.GetPlatformBinariesRoot(); const auto assetsPath = data.OutputPath; const auto jniLibsPath = data.OriginalOutputPath / TEXT("app/jniLibs"); @@ -125,11 +130,11 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) // Setup package name (eg. com.company.project) String packageName = platformSettings->PackageName; { - String productName = GameSettings::ProductName; + String productName = gameSettings->ProductName; productName.Replace(TEXT(" "), TEXT("")); productName.Replace(TEXT("."), TEXT("")); productName.Replace(TEXT("-"), TEXT("")); - String companyName = GameSettings::CompanyName; + String companyName = gameSettings->CompanyName; companyName.Replace(TEXT(" "), TEXT("")); companyName.Replace(TEXT("."), TEXT("")); companyName.Replace(TEXT("-"), TEXT("")); @@ -235,7 +240,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) EditorUtilities::ReplaceInFile(manifestPath, TEXT("${AndroidPermissions}"), permissions); EditorUtilities::ReplaceInFile(manifestPath, TEXT("${AndroidAttributes}"), attributes); const String stringsPath = data.OriginalOutputPath / TEXT("app/src/main/res/values/strings.xml"); - EditorUtilities::ReplaceInFile(stringsPath, TEXT("${ProjectName}"), GameSettings::ProductName); + EditorUtilities::ReplaceInFile(stringsPath, TEXT("${ProjectName}"), gameSettings->ProductName); // Deploy native binaries to the output location (per-ABI) const String abiBinariesPath = jniLibsPath / abi; @@ -256,7 +261,8 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) // TODO: expose event to inject custom gradle and manifest options or custom binaries into app - if (BuildSettings::Instance()->SkipPackaging) + const auto buildSettings = BuildSettings::Get(); + if (buildSettings->SkipPackaging) { return false; } @@ -286,7 +292,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) #else const Char* gradlew = TEXT("gradlew"); #endif - const bool distributionPackage = BuildSettings::Instance()->ForDistribution; + const bool distributionPackage = buildSettings->ForDistribution; const String gradleCommand = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug")); const int32 result = Platform::RunProcess(gradleCommand, data.OriginalOutputPath, envVars, true); if (result != 0) @@ -297,7 +303,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data) // Copy result package const String apk = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/apk/release/app-release-unsigned.apk") : TEXT("app/build/outputs/apk/debug/app-debug.apk")); - const String outputApk = data.OriginalOutputPath / GameSettings::ProductName + TEXT(".apk"); + const String outputApk = data.OriginalOutputPath / gameSettings->ProductName + TEXT(".apk"); if (FileSystem::CopyFile(outputApk, apk)) { LOG(Error, "Failed to copy package from {0} to {1}", apk, outputApk); diff --git a/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp b/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp index eccc299bb..0f650da2c 100644 --- a/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp @@ -9,6 +9,10 @@ #include "Editor/Utilities/EditorUtilities.h" #include "Engine/Tools/TextureTool/TextureTool.h" #include "Engine/Graphics/Textures/TextureData.h" +#include "Engine/Content/Content.h" +#include "Engine/Content/JsonAsset.h" + +IMPLEMENT_SETTINGS_GETTER(LinuxPlatformSettings, LinuxPlatform); const Char* LinuxPlatformTools::GetDisplayName() const { @@ -32,7 +36,7 @@ ArchitectureType LinuxPlatformTools::GetArchitecture() const bool LinuxPlatformTools::OnDeployBinaries(CookingData& data) { - const auto platformSettings = LinuxPlatformSettings::Instance(); + const auto platformSettings = LinuxPlatformSettings::Get(); const auto outputPath = data.OutputPath; // Copy binaries diff --git a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp index f6c846fed..7f7851941 100644 --- a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp @@ -11,6 +11,10 @@ #include "Engine/Serialization/FileWriteStream.h" #include "Editor/Utilities/EditorUtilities.h" #include "Engine/Engine/Globals.h" +#include "Engine/Content/Content.h" +#include "Engine/Content/JsonAsset.h" + +IMPLEMENT_SETTINGS_GETTER(UWPPlatformSettings, UWPPlatform); bool UWPPlatformTools::UseAOT() const { @@ -37,7 +41,8 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data) bool isXboxOne = data.Platform == BuildPlatform::XboxOne; const auto platformDataPath = Globals::StartupFolder / TEXT("Source/Platforms"); const auto uwpDataPath = platformDataPath / (isXboxOne ? TEXT("XboxOne") : TEXT("UWP")) / TEXT("Binaries"); - const auto platformSettings = UWPPlatformSettings::Instance(); + const auto gameSettings = GameSettings::Get(); + const auto platformSettings = UWPPlatformSettings::Get(); Array fileTemplate; // Copy binaries @@ -66,7 +71,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data) } } - const auto projectName = GameSettings::ProductName; + const auto projectName = gameSettings->ProductName; auto defaultNamespace = projectName; ScriptsBuilder::FilterNamespaceText(defaultNamespace); const StringAnsi projectGuid = "{3A9A2246-71DD-4567-9ABF-3E040310E30E}"; @@ -102,7 +107,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data) // Generate new temp cert if missing if (!FileSystem::FileExists(dstCertificatePath)) { - if (EditorUtilities::GenerateCertificate(GameSettings::CompanyName, dstCertificatePath)) + if (EditorUtilities::GenerateCertificate(gameSettings->CompanyName, dstCertificatePath)) { LOG(Warning, "Failed to create certificate."); } @@ -159,8 +164,8 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data) auto now = DateTime::Now(); file->WriteTextFormatted( (char*)fileTemplate.Get() - , GameSettings::ProductName.ToStringAnsi() - , GameSettings::CompanyName.ToStringAnsi() + , gameSettings->ProductName.ToStringAnsi() + , gameSettings->CompanyName.ToStringAnsi() , now.GetYear() ); hasError = file->HasError(); @@ -382,7 +387,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data) file->WriteTextFormatted( (char*)fileTemplate.Get() , projectName.ToStringAnsi() // {0} Display Name - , GameSettings::CompanyName.ToStringAnsi() // {1} Company Name + , gameSettings->CompanyName.ToStringAnsi() // {1} Company Name , productId.ToStringAnsi() // {2} Product ID , defaultNamespace.ToStringAnsi() // {3} Default Namespace ); diff --git a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp index 35ed27639..348930dd5 100644 --- a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp @@ -8,6 +8,10 @@ #include "Engine/Core/Config/GameSettings.h" #include "Editor/Utilities/EditorUtilities.h" #include "Engine/Graphics/Textures/TextureData.h" +#include "Engine/Content/Content.h" +#include "Engine/Content/JsonAsset.h" + +IMPLEMENT_SETTINGS_GETTER(WindowsPlatformSettings, WindowsPlatform); const Char* WindowsPlatformTools::GetDisplayName() const { @@ -31,7 +35,7 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const bool WindowsPlatformTools::OnDeployBinaries(CookingData& data) { - const auto platformSettings = WindowsPlatformSettings::Instance(); + const auto platformSettings = WindowsPlatformSettings::Get(); const auto& outputPath = data.OutputPath; // Apply executable icon diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp index 396626fc1..af6f003b8 100644 --- a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp +++ b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp @@ -160,8 +160,9 @@ void CookAssetsStep::CacheData::Load(CookingData& data) // Invalidate shaders and assets with shaders if need to rebuild them bool invalidateShaders = false; - const bool shadersNoOptimize = BuildSettings::Instance()->ShadersNoOptimize; - const bool shadersGenerateDebugData = BuildSettings::Instance()->ShadersGenerateDebugData; + const auto buildSettings = BuildSettings::Get(); + const bool shadersNoOptimize = buildSettings->ShadersNoOptimize; + const bool shadersGenerateDebugData = buildSettings->ShadersGenerateDebugData; if (shadersNoOptimize != Settings.Global.ShadersNoOptimize) { LOG(Info, "ShadersNoOptimize option has been modified."); @@ -175,7 +176,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data) #if PLATFORM_TOOLS_WINDOWS if (data.Platform == BuildPlatform::Windows32 || data.Platform == BuildPlatform::Windows64) { - const auto settings = WindowsPlatformSettings::Instance(); + const auto settings = WindowsPlatformSettings::Get(); const bool modified = Settings.Windows.SupportDX11 != settings->SupportDX11 || Settings.Windows.SupportDX10 != settings->SupportDX10 || @@ -190,7 +191,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data) #if PLATFORM_TOOLS_UWP if (data.Platform == BuildPlatform::UWPx86 || data.Platform == BuildPlatform::UWPx64) { - const auto settings = UWPPlatformSettings::Instance(); + const auto settings = UWPPlatformSettings::Get(); const bool modified = Settings.UWP.SupportDX11 != settings->SupportDX11 || Settings.UWP.SupportDX10 != settings->SupportDX10; @@ -204,7 +205,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data) #if PLATFORM_TOOLS_LINUX if (data.Platform == BuildPlatform::LinuxX64) { - const auto settings = LinuxPlatformSettings::Instance(); + const auto settings = LinuxPlatformSettings::Get(); const bool modified = Settings.Linux.SupportVulkan != settings->SupportVulkan; if (modified) @@ -369,7 +370,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass case BuildPlatform::Windows64: { const char* platformDefineName = "PLATFORM_WINDOWS"; - const auto settings = WindowsPlatformSettings::Instance(); + const auto settings = WindowsPlatformSettings::Get(); if (settings->SupportDX12) { COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE); @@ -393,7 +394,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass case BuildPlatform::UWPx64: { const char* platformDefineName = "PLATFORM_UWP"; - const auto settings = UWPPlatformSettings::Instance(); + const auto settings = UWPPlatformSettings::Get(); if (settings->SupportDX11) { COMPILE_PROFILE(DirectX_SM5, SHADER_FILE_CHUNK_INTERNAL_D3D_SM5_CACHE); @@ -415,7 +416,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass case BuildPlatform::LinuxX64: { const char* platformDefineName = "PLATFORM_LINUX"; - const auto settings = LinuxPlatformSettings::Instance(); + const auto settings = LinuxPlatformSettings::Get(); if (settings->SupportVulkan) { COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE); @@ -881,7 +882,8 @@ bool CookAssetsStep::Perform(CookingData& data) data.StepProgress(TEXT("Loading build cache"), 0); // Prepare - const auto buildSettings = BuildSettings::Instance(); + const auto gameSettings = GameSettings::Get(); + const auto buildSettings = BuildSettings::Get(); const int32 contentKey = buildSettings->ContentKey == 0 ? rand() : buildSettings->ContentKey; AssetsRegistry.Clear(); AssetPathsMapping.Clear(); @@ -892,22 +894,21 @@ bool CookAssetsStep::Perform(CookingData& data) // Update build settings { - const auto settings = WindowsPlatformSettings::Instance(); + const auto settings = WindowsPlatformSettings::Get(); cache.Settings.Windows.SupportDX11 = settings->SupportDX11; cache.Settings.Windows.SupportDX10 = settings->SupportDX10; cache.Settings.Windows.SupportVulkan = settings->SupportVulkan; } { - const auto settings = UWPPlatformSettings::Instance(); + const auto settings = UWPPlatformSettings::Get(); cache.Settings.UWP.SupportDX11 = settings->SupportDX11; cache.Settings.UWP.SupportDX10 = settings->SupportDX10; } { - const auto settings = LinuxPlatformSettings::Instance(); + const auto settings = LinuxPlatformSettings::Get(); cache.Settings.Linux.SupportVulkan = settings->SupportVulkan; } { - const auto buildSettings = BuildSettings::Instance(); cache.Settings.Global.ShadersNoOptimize = buildSettings->ShadersNoOptimize; cache.Settings.Global.ShadersGenerateDebugData = buildSettings->ShadersGenerateDebugData; } @@ -1004,7 +1005,7 @@ bool CookAssetsStep::Perform(CookingData& data) // Create build game header { GameHeaderFlags gameFlags = GameHeaderFlags::None; - if (!GameSettings::NoSplashScreen) + if (!gameSettings->NoSplashScreen) gameFlags |= GameHeaderFlags::ShowSplashScreen; // Open file @@ -1022,17 +1023,17 @@ bool CookAssetsStep::Perform(CookingData& data) Array bytes; bytes.Resize(808 + sizeof(Guid)); Platform::MemoryClear(bytes.Get(), bytes.Count()); - int32 length = sizeof(Char) * GameSettings::ProductName.Length(); - Platform::MemoryCopy(bytes.Get() + 0, GameSettings::ProductName.Get(), length); + int32 length = sizeof(Char) * gameSettings->ProductName.Length(); + Platform::MemoryCopy(bytes.Get() + 0, gameSettings->ProductName.Get(), length); bytes[length] = 0; bytes[length + 1] = 0; - length = sizeof(Char) * GameSettings::CompanyName.Length(); - Platform::MemoryCopy(bytes.Get() + 400, GameSettings::CompanyName.Get(), length); + length = sizeof(Char) * gameSettings->CompanyName.Length(); + Platform::MemoryCopy(bytes.Get() + 400, gameSettings->CompanyName.Get(), length); bytes[length + 400] = 0; bytes[length + 401] = 0; *(int32*)(bytes.Get() + 800) = (int32)gameFlags; *(int32*)(bytes.Get() + 804) = contentKey; - *(Guid*)(bytes.Get() + 808) = GameSettings::SplashScreen; + *(Guid*)(bytes.Get() + 808) = gameSettings->SplashScreen; Encryption::EncryptBytes(bytes.Get(), bytes.Count()); stream->WriteArray(bytes); diff --git a/Source/Editor/Cooker/Steps/DeployDataStep.cpp b/Source/Editor/Cooker/Steps/DeployDataStep.cpp index b5ea2d268..9ce3a8a5d 100644 --- a/Source/Editor/Cooker/Steps/DeployDataStep.cpp +++ b/Source/Editor/Cooker/Steps/DeployDataStep.cpp @@ -12,6 +12,7 @@ bool DeployDataStep::Perform(CookingData& data) { data.StepProgress(TEXT("Deploying engine data"), 0); const String depsRoot = data.GetPlatformBinariesRoot(); + const auto gameSettings = GameSettings::Get(); // Setup output folders and copy required data const auto contentDir = data.OutputPath / TEXT("Content"); @@ -74,7 +75,7 @@ bool DeployDataStep::Perform(CookingData& data) data.AddRootEngineAsset(TEXT("Shaders/VolumetricFog")); data.AddRootEngineAsset(TEXT("Engine/DefaultMaterial")); data.AddRootEngineAsset(TEXT("Engine/DefaultTerrainMaterial")); - if (!GameSettings::NoSplashScreen && !GameSettings::SplashScreen.IsValid()) + if (!gameSettings->NoSplashScreen && !gameSettings->SplashScreen.IsValid()) data.AddRootEngineAsset(TEXT("Engine/Textures/Logo")); data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture")); data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture")); @@ -98,7 +99,7 @@ bool DeployDataStep::Perform(CookingData& data) // Register game assets data.StepProgress(TEXT("Deploying game data"), 50); - auto& buildSettings = *BuildSettings::Instance(); + auto& buildSettings = *BuildSettings::Get(); for (auto& e : buildSettings.AdditionalAssets) data.AddRootAsset(e.GetID()); Array files; diff --git a/Source/Editor/Cooker/Steps/ValidateStep.cpp b/Source/Editor/Cooker/Steps/ValidateStep.cpp index 219301544..625957fae 100644 --- a/Source/Editor/Cooker/Steps/ValidateStep.cpp +++ b/Source/Editor/Cooker/Steps/ValidateStep.cpp @@ -38,18 +38,23 @@ bool ValidateStep::Perform(CookingData& data) #endif // Load game settings (may be modified via editor) - GameSettings::Load(); + if (GameSettings::Load()) + { + data.Error(TEXT("Failed to load game settings.")); + return true; + } data.AddRootAsset(Globals::ProjectContentFolder / TEXT("GameSettings.json")); // Validate game settings + auto gameSettings = GameSettings::Get(); { - if (GameSettings::ProductName.IsEmpty()) + if (gameSettings->ProductName.IsEmpty()) { data.Error(TEXT("Missing product name.")); return true; } - if (GameSettings::CompanyName.IsEmpty()) + if (gameSettings->CompanyName.IsEmpty()) { data.Error(TEXT("Missing company name.")); return true; @@ -58,7 +63,7 @@ bool ValidateStep::Perform(CookingData& data) // TODO: validate version AssetInfo info; - if (!Content::GetAssetInfo(GameSettings::FirstScene, info)) + if (!Content::GetAssetInfo(gameSettings->FirstScene, info)) { data.Error(TEXT("Missing first scene.")); return true; diff --git a/Source/Editor/Editor.Build.cs b/Source/Editor/Editor.Build.cs index a767ecac9..4d7d33d65 100644 --- a/Source/Editor/Editor.Build.cs +++ b/Source/Editor/Editor.Build.cs @@ -26,7 +26,7 @@ public class Editor : EditorModule // Platform Tools inside external platform implementation location options.PrivateDefinitions.Add(macro); options.SourcePaths.Add(externalPath); - options.SourceFiles.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", platform, "Engine", "Platform", platform + "PlatformSettings.cs")); + AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", platform, "Engine", "Platform", platform + "PlatformSettings.cs")); } } } diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp index 4084c7f01..28d4df32a 100644 --- a/Source/Editor/Managed/ManagedEditor.Internal.cpp +++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp @@ -24,7 +24,7 @@ #include "Engine/ContentImporters/ImportAudio.h" #include "Engine/ContentImporters/CreateCollisionData.h" #include "Engine/ContentImporters/CreateJson.h" -#include "Engine/Core/Config/LayersTagsSettings.h" +#include "Engine/Level/Level.h" #include "Engine/Core/Config/GameSettings.h" #include "Engine/Core/Cache.h" #include "Engine/CSG/CSGBuilder.h" @@ -302,22 +302,20 @@ namespace CustomEditorsUtilInternal } } -namespace LayersAndTagsSettingsInternal +namespace LayersAndTagsSettingsInternal1 { MonoArray* GetCurrentTags() { - auto settings = LayersAndTagsSettings::Instance(); - return MUtils::ToArray(settings->Tags); + return MUtils::ToArray(Level::Tags); } MonoArray* GetCurrentLayers() { - const auto settings = LayersAndTagsSettings::Instance(); - return MUtils::ToArray(Span(settings->Layers, Math::Max(1, settings->GetNonEmptyLayerNamesCount()))); + return MUtils::ToArray(Span(Level::Layers, Math::Max(1, Level::GetNonEmptyLayerNamesCount()))); } } -namespace GameSettingsInternal +namespace GameSettingsInternal1 { void Apply() { @@ -1054,9 +1052,9 @@ public: ADD_INTERNAL_CALL("FlaxEditor.Content.Import.TextureImportEntry::Internal_GetTextureImportOptions", &GetTextureImportOptions); ADD_INTERNAL_CALL("FlaxEditor.Content.Import.ModelImportEntry::Internal_GetModelImportOptions", &GetModelImportOptions); ADD_INTERNAL_CALL("FlaxEditor.Content.Import.AudioImportEntry::Internal_GetAudioImportOptions", &GetAudioImportOptions); - ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.LayersAndTagsSettings::GetCurrentTags", &LayersAndTagsSettingsInternal::GetCurrentTags); - ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.LayersAndTagsSettings::GetCurrentLayers", &LayersAndTagsSettingsInternal::GetCurrentLayers); - ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.GameSettings::Apply", &GameSettingsInternal::Apply); + ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.LayersAndTagsSettings::GetCurrentTags", &LayersAndTagsSettingsInternal1::GetCurrentTags); + ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.LayersAndTagsSettings::GetCurrentLayers", &LayersAndTagsSettingsInternal1::GetCurrentLayers); + ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.GameSettings::Apply", &GameSettingsInternal1::Apply); ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CloseSplashScreen", &CloseSplashScreen); ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CreateAsset", &CreateAsset); ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CreateVisualScript", &CreateVisualScript); diff --git a/Source/Editor/Utilities/EditorUtilities.cpp b/Source/Editor/Utilities/EditorUtilities.cpp index 1571c39d1..541c8892a 100644 --- a/Source/Editor/Utilities/EditorUtilities.cpp +++ b/Source/Editor/Utilities/EditorUtilities.cpp @@ -507,7 +507,11 @@ bool EditorUtilities::GetApplicationImage(const Guid& imageId, TextureData& imag AssetReference icon = Content::LoadAsync(imageId); if (icon == nullptr) { - icon = Content::LoadAsync(GameSettings::Icon); + const auto gameSettings = GameSettings::Get(); + if (gameSettings) + { + icon = Content::LoadAsync(gameSettings->Icon); + } } if (icon == nullptr) { diff --git a/Source/Engine/Audio/Audio.cpp b/Source/Engine/Audio/Audio.cpp index 1dd0393b4..51f674e73 100644 --- a/Source/Engine/Audio/Audio.cpp +++ b/Source/Engine/Audio/Audio.cpp @@ -44,9 +44,14 @@ Array Audio::Devices; Action Audio::DevicesChanged; Action Audio::ActiveDeviceChanged; AudioBackend* AudioBackend::Instance = nullptr; -float MasterVolume = 1.0f; -float Volume = 1.0f; -int32 ActiveDeviceIndex = -1; + +namespace +{ + float MasterVolume = 1.0f; + float Volume = 1.0f; + int32 ActiveDeviceIndex = -1; + bool MuteOnFocusLoss = true; +} class AudioService : public EngineService { @@ -77,6 +82,11 @@ namespace } } +void AudioSettings::Apply() +{ + ::MuteOnFocusLoss = MuteOnFocusLoss; +} + AudioDevice* Audio::GetActiveDevice() { return &Devices[ActiveDeviceIndex]; @@ -161,7 +171,7 @@ void Audio::OnRemoveSource(AudioSource* source) bool AudioService::Init() { - const auto settings = AudioSettings::Instance(); + const auto settings = AudioSettings::Get(); const bool mute = CommandLine::Options.Mute.IsTrue() || settings->DisableAudio; // Pick a backend to use @@ -225,11 +235,9 @@ void AudioService::Update() { PROFILE_CPU(); - const auto settings = AudioSettings::Instance(); - // Update the master volume float masterVolume = MasterVolume; - if (settings->MuteOnFocusLoss && !Engine::HasFocus) + if (MuteOnFocusLoss && !Engine::HasFocus) { // Mute audio if app has no user focus masterVolume = 0.0f; diff --git a/Source/Engine/Audio/AudioSettings.h b/Source/Engine/Audio/AudioSettings.h index e976c9953..b5efe9524 100644 --- a/Source/Engine/Audio/AudioSettings.h +++ b/Source/Engine/Audio/AudioSettings.h @@ -8,35 +8,38 @@ /// /// Audio settings container. /// -/// -class AudioSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API AudioSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(AudioSettings); public: /// /// If checked, audio playback will be disabled in build game. Can be used if game uses custom audio playback engine. /// + API_FIELD(Attributes="EditorOrder(0), DefaultValue(false), EditorDisplay(\"General\")") bool DisableAudio = false; /// /// The doppler effect factor. Scale for source and listener velocities. Default is 1. /// + API_FIELD(Attributes="EditorOrder(100), DefaultValue(1.0f), EditorDisplay(\"General\")") float DopplerFactor = 1.0f; /// /// True if mute all audio playback when game has no use focus. /// + API_FIELD(Attributes="EditorOrder(200), DefaultValue(true), EditorDisplay(\"General\", \"Mute On Focus Loss\")") bool MuteOnFocusLoss = true; public: + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static AudioSettings* Get(); + // [SettingsBase] - void RestoreDefault() final override - { - DisableAudio = false; - DopplerFactor = 1.0f; - MuteOnFocusLoss = true; - } + void Apply() override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp index e06ab35aa..89c8f3d02 100644 --- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp +++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp @@ -878,7 +878,7 @@ bool AudioBackendOAL::Base_Init() // Init ALC::AL_EXT_float32 = ALC::IsExtensionSupported("AL_EXT_float32"); - SetDopplerFactor(AudioSettings::Instance()->DopplerFactor); + SetDopplerFactor(AudioSettings::Get()->DopplerFactor); ALC::RebuildContexts(true); Audio::SetActiveDeviceIndex(activeDeviceIndex); diff --git a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp index a201253ac..aac3979ce 100644 --- a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp +++ b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp @@ -794,7 +794,7 @@ void AudioBackendXAudio2::Base_Update() } // Update dirty voices - const float dopplerFactor = AudioSettings::Instance()->DopplerFactor; + const float dopplerFactor = AudioSettings::Get()->DopplerFactor; X3DAUDIO_DSP_SETTINGS dsp = { 0 }; dsp.DstChannelCount = XAudio2::Channels; dsp.pMatrixCoefficients = XAudio2::MatrixCoefficients; diff --git a/Source/Engine/Content/JsonAsset.cpp b/Source/Engine/Content/JsonAsset.cpp index 6618336d4..821c43f87 100644 --- a/Source/Engine/Content/JsonAsset.cpp +++ b/Source/Engine/Content/JsonAsset.cpp @@ -214,6 +214,7 @@ Asset::LoadResult JsonAsset::loadAsset() if (!instance) return LoadResult::Failed; Instance = instance; + InstanceType = typeHandle; _dtor = type.Class.Dtor; type.Class.Ctor(instance); @@ -238,6 +239,7 @@ void JsonAsset::unload(bool isReloading) if (Instance) { + InstanceType = ScriptingTypeHandle(); _dtor(Instance); Allocator::Free(Instance); Instance = nullptr; diff --git a/Source/Engine/Content/JsonAsset.h b/Source/Engine/Content/JsonAsset.h index c790bb6b9..b9edd67ea 100644 --- a/Source/Engine/Content/JsonAsset.h +++ b/Source/Engine/Content/JsonAsset.h @@ -74,7 +74,6 @@ protected: /// /// Generic type of Json-format asset. It provides the managed representation of this resource data so it can be accessed via C# API. /// -/// API_CLASS(NoSpawn) class JsonAsset : public JsonAssetBase { DECLARE_ASSET_HEADER(JsonAsset); @@ -83,6 +82,11 @@ private: public: + /// + /// The scripting type of the deserialized unmanaged object instance (e.g. PhysicalMaterial). + /// + ScriptingTypeHandle InstanceType; + /// /// The deserialized unmanaged object instance (e.g. PhysicalMaterial). /// diff --git a/Source/Engine/Core/Config/BuildSettings.h b/Source/Engine/Core/Config/BuildSettings.h index ac0a36f02..529171639 100644 --- a/Source/Engine/Core/Config/BuildSettings.h +++ b/Source/Engine/Core/Config/BuildSettings.h @@ -10,71 +10,73 @@ /// /// The game building rendering settings. /// -class BuildSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API BuildSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(BuildSettings); public: /// /// The maximum amount of assets to include into a single assets package. Asset packages will split into several packages if need to. /// - int32 MaxAssetsPerPackage = 1024; + API_FIELD(Attributes="EditorOrder(10), DefaultValue(4096), Limit(1, 32, ushort.MaxValue), EditorDisplay(\"General\", \"Max assets per package\")") + int32 MaxAssetsPerPackage = 4096; /// /// The maximum size of the single assets package (in megabytes). Asset packages will split into several packages if need to. /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(1024), Limit(1, 16, ushort.MaxValue), EditorDisplay(\"General\", \"Max package size (in MB)\")") int32 MaxPackageSizeMB = 1024; /// /// The game content cooking keycode. Use the same value for a game and DLC packages to support loading them by the build game. Use 0 to randomize it during building. /// + API_FIELD(Attributes="EditorOrder(30), DefaultValue(0), Limit(1, 16, ushort.MaxValue), EditorDisplay(\"General\")") int32 ContentKey = 0; /// /// If checked, the builds produced by the Game Cooker will be treated as for final game distribution (eg. for game store upload). Builds done this way cannot be tested on console devkits (eg. Xbox One, Xbox Scarlett). /// + API_FIELD(Attributes="EditorOrder(40), DefaultValue(false), EditorDisplay(\"General\")") bool ForDistribution = false; /// /// If checked, the output build files won't be packaged for the destination platform. Useful when debugging build from local PC. /// + API_FIELD(Attributes="EditorOrder(50), DefaultValue(false), EditorDisplay(\"General\")") bool SkipPackaging = false; /// /// The list of additional assets to include into build (into root assets set). /// + API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Additional Data\")") Array> AdditionalAssets; /// /// The list of additional folders with assets to include into build (into root assets set). Paths relative to the project directory (or absolute). /// + API_FIELD(Attributes="EditorOrder(1010), EditorDisplay(\"Additional Data\")") Array AdditionalAssetFolders; /// /// Disables shaders compiler optimizations in cooked game. Can be used to debug shaders on a target platform or to speed up the shaders compilation time. /// + API_FIELD(Attributes="EditorOrder(2000), DefaultValue(false), EditorDisplay(\"Content\", \"Shaders No Optimize\")") bool ShadersNoOptimize = false; /// /// Enables shader debug data generation for shaders in cooked game (depends on the target platform rendering backend). /// + API_FIELD(Attributes="EditorOrder(2010), DefaultValue(false), EditorDisplay(\"Content\")") bool ShadersGenerateDebugData = false; public: - // [SettingsBase] - void RestoreDefault() final override - { - MaxAssetsPerPackage = 1024; - MaxPackageSizeMB = 1024; - ContentKey = 0; - ForDistribution = false; - SkipPackaging = false; - AdditionalAssets.Clear(); - AdditionalAssetFolders.Clear(); - ShadersNoOptimize = false; - ShadersGenerateDebugData = false; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static BuildSettings* Get(); + // [SettingsBase] void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(MaxAssetsPerPackage); diff --git a/Source/Engine/Core/Config/GameSettings.cpp b/Source/Engine/Core/Config/GameSettings.cpp index 9899ced75..5ea356d61 100644 --- a/Source/Engine/Core/Config/GameSettings.cpp +++ b/Source/Engine/Core/Config/GameSettings.cpp @@ -2,6 +2,7 @@ #include "GameSettings.h" #include "Engine/Serialization/JsonTools.h" +#include "Engine/Scripting/ScriptingType.h" #include "Engine/Physics/PhysicsSettings.h" #include "Engine/Core/Log.h" #include "LayersTagsSettings.h" @@ -17,30 +18,6 @@ #include "Engine/Content/AssetReference.h" #include "Engine/Engine/EngineService.h" #include "Engine/Engine/Globals.h" -#include "Engine/Engine/Time.h" - -String GameSettings::ProductName; -String GameSettings::CompanyName; -String GameSettings::CopyrightNotice; -Guid GameSettings::Icon; -Guid GameSettings::FirstScene; -bool GameSettings::NoSplashScreen = false; -Guid GameSettings::SplashScreen; -Dictionary GameSettings::CustomSettings; - -Array Settings::Containers(32); - -#if USE_EDITOR -extern void LoadPlatformSettingsEditor(ISerializable::DeserializeStream& data); -#endif - -void TimeSettings::Apply() -{ - Time::UpdateFPS = UpdateFPS; - Time::PhysicsFPS = PhysicsFPS; - Time::DrawFPS = DrawFPS; - Time::TimeScale = TimeScale; -} class GameSettingsService : public EngineService { @@ -49,9 +26,6 @@ public: GameSettingsService() : EngineService(TEXT("GameSettings"), -70) { - GameSettings::Icon = Guid::Empty; - GameSettings::FirstScene = Guid::Empty; - GameSettings::SplashScreen = Guid::Empty; } bool Init() override @@ -60,62 +34,141 @@ public: } }; +IMPLEMENT_SETTINGS_GETTER(BuildSettings, GameCooking); +IMPLEMENT_SETTINGS_GETTER(GraphicsSettings, Graphics); +IMPLEMENT_SETTINGS_GETTER(LayersAndTagsSettings, LayersAndTags); +IMPLEMENT_SETTINGS_GETTER(TimeSettings, Time); +IMPLEMENT_SETTINGS_GETTER(AudioSettings, Audio); +IMPLEMENT_SETTINGS_GETTER(PhysicsSettings, Physics); +IMPLEMENT_SETTINGS_GETTER(InputSettings, Input); + +#if !USE_EDITOR +#if PLATFORM_WINDOWS +IMPLEMENT_SETTINGS_GETTER(WindowsPlatformSettings, WindowsPlatform); +#elif PLATFORM_UWP || PLATFORM_XBOX_ONE +IMPLEMENT_SETTINGS_GETTER(UWPPlatformSettings, UWPPlatform); +#elif PLATFORM_LINUX +IMPLEMENT_SETTINGS_GETTER(LinuxPlatformSettings, LinuxPlatform); +#elif PLATFORM_PS4 +IMPLEMENT_SETTINGS_GETTER(PS4PlatformSettings, PS4Platform); +#elif PLATFORM_XBOX_SCARLETT +IMPLEMENT_SETTINGS_GETTER(XboxScarlettPlatformSettings, XboxScarlettPlatform); +#elif PLATFORM_ANDROID +IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform); +#else +#error Unknown platform +#endif +#endif + GameSettingsService GameSettingsServiceInstance; +AssetReference GameSettingsAsset; + +GameSettings* GameSettings::Get() +{ + if (!GameSettingsAsset) + { + // Load root game settings asset. + // It may be missing in editor during dev but must be ready in the build game. + const auto assetPath = Globals::ProjectContentFolder / TEXT("GameSettings.json"); + GameSettingsAsset = Content::LoadAsync(assetPath); + if (GameSettingsAsset == nullptr) + { + LOG(Error, "Missing game settings asset."); + return nullptr; + } + if (GameSettingsAsset->WaitForLoaded()) + { + return nullptr; + } + if (GameSettingsAsset->InstanceType != GameSettings::TypeInitializer) + { + LOG(Error, "Invalid game settings asset data type."); + return nullptr; + } + } + auto asset = GameSettingsAsset.Get(); + if (asset && asset->WaitForLoaded()) + asset = nullptr; + return asset ? (GameSettings*)asset->Instance : nullptr; +} bool GameSettings::Load() { + // Load main settings asset + auto settings = Get(); + if (!settings) + { + return true; + } + + // Preload all settings assets +#define PRELOAD_SETTINGS(type) \ + { \ + if (settings->type) \ + { \ + Content::LoadAsync(settings->type); \ + } \ + else \ + { \ + LOG(Warning, "Missing {0} settings", TEXT(#type)); \ + } \ + } + PRELOAD_SETTINGS(Time); + PRELOAD_SETTINGS(Audio); + PRELOAD_SETTINGS(LayersAndTags); + PRELOAD_SETTINGS(Physics); + PRELOAD_SETTINGS(Input); + PRELOAD_SETTINGS(Graphics); + PRELOAD_SETTINGS(Navigation); + PRELOAD_SETTINGS(GameCooking); +#undef PRELOAD_SETTINGS + + // Apply the game settings to the engine + settings->Apply(); + + return false; +} + +void GameSettings::Apply() +{ + // TODO: impl this +#define APPLY_SETTINGS(type) \ + { \ + type* obj = type::Get(); \ + if (obj) \ + { \ + obj->Apply(); \ + } \ + else \ + { \ + LOG(Warning, "Missing {0} settings", TEXT(#type)); \ + } \ + } + APPLY_SETTINGS(TimeSettings); + APPLY_SETTINGS(AudioSettings); + APPLY_SETTINGS(LayersAndTagsSettings); + APPLY_SETTINGS(PhysicsSettings); + APPLY_SETTINGS(InputSettings); + APPLY_SETTINGS(GraphicsSettings); + APPLY_SETTINGS(NavigationSettings); + APPLY_SETTINGS(BuildSettings); + APPLY_SETTINGS(PlatformSettings); +#undef APPLY_SETTINGS +} + +void GameSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) +{ + // Load properties + ProductName = JsonTools::GetString(stream, "ProductName"); + CompanyName = JsonTools::GetString(stream, "CompanyName"); + CopyrightNotice = JsonTools::GetString(stream, "CopyrightNotice"); + Icon = JsonTools::GetGuid(stream, "Icon"); + FirstScene = JsonTools::GetGuid(stream, "FirstScene"); + NoSplashScreen = JsonTools::GetBool(stream, "NoSplashScreen", NoSplashScreen); + SplashScreen = JsonTools::GetGuid(stream, "SplashScreen"); CustomSettings.Clear(); - -#if USE_EDITOR -#define END_POINT(msg) LOG(Warning, msg " Using default values."); return false -#else -#define END_POINT(msg) LOG(Fatal, msg); return true -#endif - -#define LOAD_SETTINGS(nodeName, settingsType) \ - { \ - Guid id = JsonTools::GetGuid(data, nodeName); \ - if (id.IsValid()) \ - { \ - AssetReference subAsset = Content::LoadAsync(id); \ - if (subAsset && !subAsset->WaitForLoaded()) \ - { \ - settingsType::Instance()->Deserialize(*subAsset->Data, nullptr); \ - settingsType::Instance()->Apply(); \ - } \ - else \ - { LOG(Warning, "Cannot load " nodeName " settings"); } \ - } \ - else \ - { LOG(Warning, "Missing " nodeName " settings"); } \ - } - - // Load root game settings asset. - // It may be missing in editor during dev but must be ready in the build game. - const auto assetPath = Globals::ProjectContentFolder / TEXT("GameSettings.json"); - AssetReference asset = Content::LoadAsync(assetPath); - if (asset == nullptr) - { - END_POINT("Missing game settings asset."); - } - if (asset->WaitForLoaded() - || asset->DataTypeName != TEXT("FlaxEditor.Content.Settings.GameSettings") - || asset->Data == nullptr) - { - END_POINT("Cannot load game settings asset."); - } - auto& data = *asset->Data; - - // Load settings - ProductName = JsonTools::GetString(data, "ProductName"); - CompanyName = JsonTools::GetString(data, "CompanyName"); - CopyrightNotice = JsonTools::GetString(data, "CopyrightNotice"); - Icon = JsonTools::GetGuid(data, "Icon"); - FirstScene = JsonTools::GetGuid(data, "FirstScene"); - NoSplashScreen = JsonTools::GetBool(data, "NoSplashScreen", NoSplashScreen); - SplashScreen = JsonTools::GetGuid(data, "SplashScreen"); - const auto customSettings = data.FindMember("CustomSettings"); - if (customSettings != data.MemberEnd()) + const auto customSettings = stream.FindMember("CustomSettings"); + if (customSettings != stream.MemberEnd()) { auto& items = customSettings->value; for (auto it = items.MemberBegin(); it != items.MemberEnd(); ++it) @@ -129,39 +182,21 @@ bool GameSettings::Load() } } - // Load child settings - LOAD_SETTINGS("Time", TimeSettings); - LOAD_SETTINGS("Physics", PhysicsSettings); - LOAD_SETTINGS("LayersAndTags", LayersAndTagsSettings); - LOAD_SETTINGS("Graphics", GraphicsSettings); - LOAD_SETTINGS("GameCooking", BuildSettings); - LOAD_SETTINGS("Input", InputSettings); - LOAD_SETTINGS("Audio", AudioSettings); - LOAD_SETTINGS("Navigation", NavigationSettings); + // Settings containers + DESERIALIZE(Time); + DESERIALIZE(Audio); + DESERIALIZE(LayersAndTags); + DESERIALIZE(Physics); + DESERIALIZE(Input); + DESERIALIZE(Graphics); + DESERIALIZE(Navigation); + DESERIALIZE(GameCooking); - // Load platform settings -#if PLATFORM_WINDOWS - LOAD_SETTINGS("WindowsPlatform", WindowsPlatformSettings); -#endif -#if PLATFORM_UWP - LOAD_SETTINGS("UWPPlatform", UWPPlatformSettings); -#endif -#if PLATFORM_LINUX - LOAD_SETTINGS("LinuxPlatform", LinuxPlatformSettings); -#endif -#if PLATFORM_PS4 - LOAD_SETTINGS("PS4Platform", PS4PlatformSettings); -#endif -#if PLATFORM_XBOX_SCARLETT - LOAD_SETTINGS("XboxScarlettPlatform", XboxScarlettPlatformSettings); -#endif -#if PLATFORM_ANDROID - LOAD_SETTINGS("AndroidPlatform", AndroidPlatformSettings); -#endif -#if USE_EDITOR - LoadPlatformSettingsEditor(data); -#endif - - return false; -#undef END_POINT + // Per-platform settings containers + DESERIALIZE(WindowsPlatform); + DESERIALIZE(UWPPlatform); + DESERIALIZE(LinuxPlatform); + DESERIALIZE(PS4Platform); + DESERIALIZE(XboxScarlettPlatform); + DESERIALIZE(AndroidPlatform); } diff --git a/Source/Engine/Core/Config/GameSettings.h b/Source/Engine/Core/Config/GameSettings.h index 6870d8c22..16e1fe7b5 100644 --- a/Source/Engine/Core/Config/GameSettings.h +++ b/Source/Engine/Core/Config/GameSettings.h @@ -2,60 +2,96 @@ #pragma once +#include "Settings.h" #include "Engine/Core/Types/Guid.h" #include "Engine/Core/Types/String.h" #include "Engine/Core/Collections/Dictionary.h" /// -/// Main engine configuration service. Loads and applies game configuration. +/// The main game engine configuration service. Loads and applies game configuration. /// -class GameSettings +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API GameSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(GameSettings); public: /// /// The product full name. /// - static String ProductName; + API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"General\")") + String ProductName; /// /// The company full name. /// - static String CompanyName; + API_FIELD(Attributes="EditorOrder(10), EditorDisplay(\"General\")") + String CompanyName; /// /// The copyright note used for content signing (eg. source code header). /// - static String CopyrightNotice; + API_FIELD(Attributes="EditorOrder(15), EditorDisplay(\"General\")") + String CopyrightNotice; /// /// The default application icon. /// - static Guid Icon; + Guid Icon = Guid::Empty; /// /// Reference to the first scene to load on a game startup. /// - static Guid FirstScene; + Guid FirstScene = Guid::Empty; /// /// True if skip showing splash screen image on the game startup. /// - static bool NoSplashScreen; + bool NoSplashScreen = false; /// /// Reference to the splash screen image to show on a game startup. /// - static Guid SplashScreen; + Guid SplashScreen = Guid::Empty; /// /// The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair). /// - static Dictionary CustomSettings; + Dictionary CustomSettings; + +public: + + // Settings containers + Guid Time; + Guid Audio; + Guid LayersAndTags; + Guid Physics; + Guid Input; + Guid Graphics; + Guid Navigation; + Guid GameCooking; + + // Per-platform settings containers + Guid WindowsPlatform; + Guid UWPPlatform; + Guid LinuxPlatform; + Guid PS4Platform; + Guid XboxScarlettPlatform; + Guid AndroidPlatform; + +public: + + /// + /// Gets the instance of the game settings asset (null if missing). Object returned by this method is always loaded with valid data to use. + /// + static GameSettings* Get(); /// /// Loads the game settings (including other settings such as Physics, Input, etc.). /// /// True if failed, otherwise false. static bool Load(); + + // [SettingsBase] + void Apply() override; + void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override; }; diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h index 4e120fdff..17c342e89 100644 --- a/Source/Engine/Core/Config/GraphicsSettings.h +++ b/Source/Engine/Core/Config/GraphicsSettings.h @@ -9,67 +9,68 @@ /// /// Graphics rendering settings. /// -class GraphicsSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API GraphicsSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(GraphicsSettings); public: /// /// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts. /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(false), EditorDisplay(\"General\", \"Use V-Sync\")") bool UseVSync = false; /// /// Anti Aliasing quality setting. /// + API_FIELD(Attributes="EditorOrder(1000), DefaultValue(Quality.Medium), EditorDisplay(\"Quality\", \"AA Quality\")") Quality AAQuality = Quality::Medium; /// /// Screen Space Reflections quality setting. /// + API_FIELD(Attributes="EditorOrder(1100), DefaultValue(Quality.Medium), EditorDisplay(\"Quality\", \"SSR Quality\")") Quality SSRQuality = Quality::Medium; /// /// Screen Space Ambient Occlusion quality setting. /// + API_FIELD(Attributes="EditorOrder(1200), DefaultValue(Quality.Medium), EditorDisplay(\"Quality\", \"SSAO Quality\")") Quality SSAOQuality = Quality::Medium; /// /// Volumetric Fog quality setting. /// + API_FIELD(Attributes="EditorOrder(1250), DefaultValue(Quality.High), EditorDisplay(\"Quality\")") Quality VolumetricFogQuality = Quality::High; /// /// The shadows quality. /// + API_FIELD(Attributes="EditorOrder(1300), DefaultValue(Quality.Medium), EditorDisplay(\"Quality\")") Quality ShadowsQuality = Quality::Medium; /// /// The shadow maps quality (textures resolution). /// + API_FIELD(Attributes="EditorOrder(1310), DefaultValue(Quality.Medium), EditorDisplay(\"Quality\")") Quality ShadowMapsQuality = Quality::Medium; /// /// Enables cascades splits blending for directional light shadows. /// + API_FIELD(Attributes="EditorOrder(1320), DefaultValue(false), EditorDisplay(\"Quality\", \"Allow CSM Blending\")") bool AllowCSMBlending = false; public: + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static GraphicsSettings* Get(); + // [SettingsBase] void Apply() override; - - void RestoreDefault() final override - { - UseVSync = false; - AAQuality = Quality::Medium; - SSRQuality = Quality::Medium; - SSAOQuality = Quality::Medium; - VolumetricFogQuality = Quality::High; - ShadowsQuality = Quality::Medium; - ShadowMapsQuality = Quality::Medium; - AllowCSMBlending = false; - } - void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(UseVSync); diff --git a/Source/Engine/Core/Config/LayersTagsSettings.h b/Source/Engine/Core/Config/LayersTagsSettings.h index ee09d9250..44bca9231 100644 --- a/Source/Engine/Core/Config/LayersTagsSettings.h +++ b/Source/Engine/Core/Config/LayersTagsSettings.h @@ -7,8 +7,9 @@ /// /// Layers and objects tags settings. /// -class LayersAndTagsSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API LayersAndTagsSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(LayersAndTagsSettings); public: /// @@ -24,43 +25,11 @@ public: public: /// - /// Gets or adds the tag (returns the tag index). + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. /// - /// The tag. - /// The tag index. - int32 GetOrAddTag(const String& tag) - { - int32 index = Tags.Find(tag); - if (index == INVALID_INDEX) - { - index = Tags.Count(); - Tags.Add(tag); - } - return index; - } - - /// - /// Gets the amount of non empty layer names (from the beginning, trims the last ones). - /// - /// The layers count. - int32 GetNonEmptyLayerNamesCount() const - { - int32 result = 31; - while (result >= 0 && Layers[result].IsEmpty()) - result--; - return result + 1; - } - -public: + static LayersAndTagsSettings* Get(); // [SettingsBase] - void RestoreDefault() override - { - Tags.Clear(); - for (int32 i = 0; i < 32; i++) - Layers[i].Clear(); - } - void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { const auto tags = stream.FindMember("Tags"); diff --git a/Source/Engine/Core/Config/Settings.h b/Source/Engine/Core/Config/Settings.h index fe594d5ae..2822f4a6a 100644 --- a/Source/Engine/Core/Config/Settings.h +++ b/Source/Engine/Core/Config/Settings.h @@ -2,81 +2,46 @@ #pragma once -#include "Engine/Core/Singleton.h" -#include "Engine/Core/Collections/Array.h" #include "Engine/Serialization/ISerializable.h" /// /// Base class for all global settings containers for the engine. Helps to apply, store and expose properties to engine/game. /// -class FLAXENGINE_API Settings +API_CLASS(Abstract) class FLAXENGINE_API SettingsBase : public ISerializable { +DECLARE_SCRIPTING_TYPE_MINIMAL(SettingsBase); public: /// - /// The settings containers. - /// - static Array Containers; - - /// - /// Restores the default settings for all the registered containers. - /// - static void RestoreDefaultAll() - { - for (int32 i = 0; i < Containers.Count(); i++) - Containers[i]->RestoreDefault(); - } - -private: - - // Disable copy/move - Settings(const Settings&) = delete; - Settings& operator=(const Settings&) = delete; - -protected: - - Settings() - { - Containers.Add(this); - } - -public: - - virtual ~Settings() = default; - -public: - - typedef ISerializable::DeserializeStream DeserializeStream; - - /// - /// Applies the settings to the target services. + /// Applies the settings to the target system. /// virtual void Apply() { } - /// - /// Restores the default settings. - /// - virtual void RestoreDefault() = 0; +public: - /// - /// Deserializes the settings container. - /// - /// The input data stream. - /// The deserialization modifier object. Always valid. - virtual void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) = 0; -}; - -/// -/// Base class for all global settings containers for the engine. Helps to apply, store and expose properties to engine/game. -/// -template -class SettingsBase : public Settings, public Singleton -{ -protected: - - SettingsBase() + // [ISerializable] + void Serialize(SerializeStream& stream, const void* otherObj) override { + // Not supported (Editor C# edits settings data) } }; + +// Helper utility define for settings getter implementation code +#define IMPLEMENT_SETTINGS_GETTER(type, field) \ + type* type::Get() \ + { \ + static type DefaultInstance; \ + type* result = &DefaultInstance; \ + const auto gameSettings = GameSettings::Get(); \ + if (gameSettings) \ + { \ + const auto asset = Content::Load(gameSettings->field); \ + if (asset && asset->Instance && asset->InstanceType == type::TypeInitializer) \ + { \ + result = static_cast(asset->Instance); \ + } \ + } \ + return result; \ + } diff --git a/Source/Engine/Core/Config/TimeSettings.h b/Source/Engine/Core/Config/TimeSettings.h index 4b4deaaf8..7e383380f 100644 --- a/Source/Engine/Core/Config/TimeSettings.h +++ b/Source/Engine/Core/Config/TimeSettings.h @@ -3,60 +3,53 @@ #pragma once #include "Engine/Core/Config/Settings.h" -#include "Engine/Serialization/Serialization.h" /// /// Time and game simulation settings container. /// -class TimeSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API TimeSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(TimeSettings); public: /// /// The target amount of the game logic updates per second (script updates frequency). /// + API_FIELD(Attributes="EditorOrder(1), DefaultValue(30.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Update FPS\")") float UpdateFPS = 30.0f; /// /// The target amount of the physics simulation updates per second (also fixed updates frequency). /// + API_FIELD(Attributes="EditorOrder(2), DefaultValue(60.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Physics FPS\")") float PhysicsFPS = 60.0f; /// /// The target amount of the frames rendered per second (actual game FPS). /// + API_FIELD(Attributes="EditorOrder(3), DefaultValue(60.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Draw FPS\")") float DrawFPS = 60.0f; /// /// The game time scale factor. Default is 1. /// + API_FIELD(Attributes="EditorOrder(10), DefaultValue(1.0f), Limit(0, 1000.0f, 0.1f), EditorDisplay(\"General\")") float TimeScale = 1.0f; /// /// The maximum allowed delta time (in seconds) for the game logic update step. /// - float MaxUpdateDeltaTime = (1.0f / 10.0f); + API_FIELD(Attributes="EditorOrder(20), DefaultValue(0.1f), Limit(0.1f, 1000.0f, 0.01f), EditorDisplay(\"General\")") + float MaxUpdateDeltaTime = 0.1f; public: + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static TimeSettings* Get(); + // [SettingsBase] void Apply() override; - - void RestoreDefault() override - { - UpdateFPS = 30.0f; - PhysicsFPS = 60.0f; - DrawFPS = 60.0f; - TimeScale = 1.0f; - MaxUpdateDeltaTime = 1.0f / 10.0f; - } - - void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override - { - DESERIALIZE(UpdateFPS); - DESERIALIZE(PhysicsFPS); - DESERIALIZE(DrawFPS); - DESERIALIZE(TimeScale); - DESERIALIZE(MaxUpdateDeltaTime); - } + void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override; }; diff --git a/Source/Engine/Core/Math/Math.cpp b/Source/Engine/Core/Math/Math.cpp index 4075bcbda..d0642d7ca 100644 --- a/Source/Engine/Core/Math/Math.cpp +++ b/Source/Engine/Core/Math/Math.cpp @@ -5,8 +5,8 @@ void Math::SinCos(float angle, float& sine, float& cosine) { - sine = sin(angle); - cosine = cos(angle); + sine = Math::Sin(angle); + cosine = Math::Cos(angle); } uint32 Math::FloorLog2(uint32 value) diff --git a/Source/Engine/Engine/Base/GameBase.cpp b/Source/Engine/Engine/Base/GameBase.cpp index 6c02ce1d1..c313b0737 100644 --- a/Source/Engine/Engine/Base/GameBase.cpp +++ b/Source/Engine/Engine/Base/GameBase.cpp @@ -119,7 +119,10 @@ bool GameBase::Init() } // Preload first scene asset data - GameBaseImpl::FirstScene = GameSettings::FirstScene; + const auto gameSettings = GameSettings::Get(); + if (!gameSettings) + return true; + GameBaseImpl::FirstScene = gameSettings->FirstScene; return false; } @@ -261,8 +264,8 @@ void GameBaseImpl::OnSplashScreenEnd() // Load the first scene LOG(Info, "Loading the first scene"); + const auto sceneId = FirstScene ? FirstScene.GetID() : Guid::Empty; FirstScene.Unlink(); - const auto sceneId = GameSettings::FirstScene; if (Level::LoadSceneAsync(sceneId)) { LOG(Fatal, "Cannot load the first scene."); diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp index ebf268957..f9313b1b4 100644 --- a/Source/Engine/Engine/Engine.cpp +++ b/Source/Engine/Engine/Engine.cpp @@ -51,6 +51,9 @@ namespace EngineImpl { bool IsReady = false; +#if !USE_EDITOR + bool RunInBackground = false; +#endif String CommandLine = nullptr; int32 Fps = 0, FpsAccumulatedFrames = 0; double FpsAccumulated = 0.0; @@ -133,6 +136,9 @@ int32 Engine::Main(const Char* cmdLine) Platform::BeforeRun(); EngineImpl::InitMainWindow(); Application::BeforeRun(); +#if !USE_EDITOR && (PLATFORM_WINDOWS || PLATFORM_LINUX) + EngineImpl::RunInBackground = PlatformSettings::Get()->RunInBackground; +#endif Log::Logger::WriteFloor(); LOG_FLUSH(); Time::OnBeforeRun(); @@ -279,11 +285,7 @@ void Engine::OnUpdate() bool isGameRunning = true; if (mainWindow && !mainWindow->IsFocused()) { -#if PLATFORM_WINDOWS || PLATFORM_LINUX - isGameRunning = PlatformSettings::Instance()->RunInBackground; -#else - isGameRunning = false; -#endif + isGameRunning = EngineImpl::RunInBackground; } Time::SetGamePaused(!isGameRunning); #endif @@ -393,8 +395,11 @@ const String& Engine::GetCommandLine() JsonAsset* Engine::GetCustomSettings(const StringView& key) { + const auto settings = GameSettings::Get(); + if (!settings) + return nullptr; Guid assetId = Guid::Empty; - GameSettings::CustomSettings.TryGet(key, assetId); + settings->CustomSettings.TryGet(key, assetId); return Content::LoadAsync(assetId); } diff --git a/Source/Engine/Engine/Linux/LinuxGame.cpp b/Source/Engine/Engine/Linux/LinuxGame.cpp index 43bfe4a6e..1f59a66a9 100644 --- a/Source/Engine/Engine/Linux/LinuxGame.cpp +++ b/Source/Engine/Engine/Linux/LinuxGame.cpp @@ -16,7 +16,7 @@ void LinuxGame::InitMainWindowSettings(CreateWindowSettings& settings) { // TODO: restore window size and fullscreen mode from the cached local settings saved after previous session - const auto platformSettings = LinuxPlatformSettings::Instance(); + const auto platformSettings = LinuxPlatformSettings::Get(); auto windowMode = platformSettings->WindowMode; // Use command line switches @@ -54,7 +54,7 @@ void LinuxGame::InitMainWindowSettings(CreateWindowSettings& settings) bool LinuxGame::Init() { - const auto platformSettings = LinuxPlatformSettings::Instance(); + const auto platformSettings = LinuxPlatformSettings::Get(); // Create mutex if need to if (platformSettings->ForceSingleInstance) diff --git a/Source/Engine/Engine/Time.cpp b/Source/Engine/Engine/Time.cpp index 1afe7e05a..f26f4f759 100644 --- a/Source/Engine/Engine/Time.cpp +++ b/Source/Engine/Engine/Time.cpp @@ -3,17 +3,19 @@ #include "Time.h" #include "EngineService.h" #include "Engine/Core/Math/Math.h" -#include "Engine/Core/Config/TimeSettings.h" #include "Engine/Platform/Platform.h" -#include "Engine/Physics/PhysicsSettings.h" +#include "Engine/Core/Config/TimeSettings.h" +#include "Engine/Serialization/Serialization.h" namespace { bool FixedDeltaTimeEnable; float FixedDeltaTimeValue; + float MaxUpdateDeltaTime = 0.1f; } bool Time::_gamePaused = false; +float Time::_physicsMaxDeltaTime = 0.1f; DateTime Time::StartupTime; float Time::UpdateFPS = 30.0f; float Time::PhysicsFPS = 60.0f; @@ -43,6 +45,24 @@ public: TimeService TimeServiceInstance; +void TimeSettings::Apply() +{ + Time::UpdateFPS = UpdateFPS; + Time::PhysicsFPS = PhysicsFPS; + Time::DrawFPS = DrawFPS; + Time::TimeScale = TimeScale; + ::MaxUpdateDeltaTime = MaxUpdateDeltaTime; +} + +void TimeSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) +{ + DESERIALIZE(UpdateFPS); + DESERIALIZE(PhysicsFPS); + DESERIALIZE(DrawFPS); + DESERIALIZE(TimeScale); + DESERIALIZE(MaxUpdateDeltaTime); +} + void Time::TickData::OnBeforeRun(float targetFps, double currentTime) { Time = UnscaledTime = TimeSpan::Zero(); @@ -219,7 +239,7 @@ void Time::OnBeforeRun() bool Time::OnBeginUpdate() { - if (Update.OnTickBegin(UpdateFPS, TimeSettings::Instance()->MaxUpdateDeltaTime)) + if (Update.OnTickBegin(UpdateFPS, MaxUpdateDeltaTime)) { Current = &Update; return true; @@ -229,7 +249,7 @@ bool Time::OnBeginUpdate() bool Time::OnBeginPhysics() { - if (Physics.OnTickBegin(PhysicsFPS, PhysicsSettings::Instance()->MaxDeltaTime)) + if (Physics.OnTickBegin(PhysicsFPS, _physicsMaxDeltaTime)) { Current = &Physics; return true; diff --git a/Source/Engine/Engine/Time.h b/Source/Engine/Engine/Time.h index 0e8c25806..0d44afa22 100644 --- a/Source/Engine/Engine/Time.h +++ b/Source/Engine/Engine/Time.h @@ -15,6 +15,7 @@ API_CLASS(Static) class FLAXENGINE_API Time DECLARE_SCRIPTING_TYPE_NO_SPAWN(Time); friend class Engine; friend class TimeService; + friend class PhysicsSettings; public: /// @@ -100,6 +101,7 @@ public: private: static bool _gamePaused; + static float _physicsMaxDeltaTime; public: diff --git a/Source/Engine/Engine/Windows/WindowsGame.cpp b/Source/Engine/Engine/Windows/WindowsGame.cpp index da82cc7fc..4b7496481 100644 --- a/Source/Engine/Engine/Windows/WindowsGame.cpp +++ b/Source/Engine/Engine/Windows/WindowsGame.cpp @@ -11,7 +11,7 @@ void WindowsGame::InitMainWindowSettings(CreateWindowSettings& settings) { // TODO: restore window size and fullscreen mode from the cached local settings saved after previous session - const auto platformSettings = WindowsPlatformSettings::Instance(); + const auto platformSettings = WindowsPlatformSettings::Get(); auto windowMode = platformSettings->WindowMode; // Use command line switches @@ -45,7 +45,7 @@ void WindowsGame::InitMainWindowSettings(CreateWindowSettings& settings) bool WindowsGame::Init() { - const auto platformSettings = WindowsPlatformSettings::Instance(); + const auto platformSettings = WindowsPlatformSettings::Get(); // Create mutex if need to if (platformSettings->ForceSingleInstance) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 64151749b..e9da74a99 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -91,7 +91,7 @@ GPUDevice* GPUDeviceDX11::Create() else if (CommandLine::Options.D3D11) maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_11_0; #if !USE_EDITOR && PLATFORM_WINDOWS - auto winSettings = WindowsPlatformSettings::Instance(); + auto winSettings = WindowsPlatformSettings::Get(); if (!winSettings->SupportDX11 && !winSettings->SupportDX10) { // Skip if there is no support diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 29d417834..317a6e9aa 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -45,7 +45,7 @@ GPUDevice* GPUDeviceDX12::Create() selectedAdapter.Description.VendorId = GPU_VENDOR_ID_AMD; #else #if !USE_EDITOR && PLATFORM_WINDOWS - auto winSettings = WindowsPlatformSettings::Instance(); + auto winSettings = WindowsPlatformSettings::Get(); if (!winSettings->SupportDX12) { // Skip if there is no support diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 33df0db47..85fc3dcd0 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -1076,7 +1076,7 @@ GPUDeviceVulkan::GPUDeviceVulkan(ShaderProfile shaderProfile, GPUAdapterVulkan* GPUDevice* GPUDeviceVulkan::Create() { #if !USE_EDITOR && (PLATFORM_WINDOWS || PLATFORM_LINUX) - auto settings = PlatformSettings::Instance(); + auto settings = PlatformSettings::Get(); if (!settings->SupportVulkan) { // Skip if there is no support diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index 1dfa0e5fe..be11f091d 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -98,6 +98,12 @@ Delegate Input::ActionTriggered; Array Input::ActionMappings; Array Input::AxisMappings; +void InputSettings::Apply() +{ + Input::ActionMappings = ActionMappings; + Input::AxisMappings = AxisMappings; +} + int32 Input::GetGamepadsCount() { return Gamepads.Count(); diff --git a/Source/Engine/Input/Input.h b/Source/Engine/Input/Input.h index 33852f9ec..4ef7bfffb 100644 --- a/Source/Engine/Input/Input.h +++ b/Source/Engine/Input/Input.h @@ -21,7 +21,6 @@ class InputDevice; API_CLASS(Static) class FLAXENGINE_API Input { DECLARE_SCRIPTING_TYPE_NO_SPAWN(Input); -public: /// /// Gets the mouse (null if platform does not support mouse or it is not connected). diff --git a/Source/Engine/Input/InputSettings.h b/Source/Engine/Input/InputSettings.h index df1f4d60c..7771028e8 100644 --- a/Source/Engine/Input/InputSettings.h +++ b/Source/Engine/Input/InputSettings.h @@ -5,14 +5,13 @@ #include "Engine/Core/Config/Settings.h" #include "Engine/Serialization/JsonTools.h" #include "VirtualInput.h" -#include "Input.h" /// /// Input settings container. /// -/// -class InputSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API InputSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(InputSettings); public: /// @@ -27,19 +26,14 @@ public: public: - // [SettingsBase] - void Apply() override - { - Input::ActionMappings = ActionMappings; - Input::AxisMappings = AxisMappings; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static InputSettings* Get(); + + // [SettingsBase] + void Apply() override; - void RestoreDefault() override - { - ActionMappings.Resize(0); - AxisMappings.Resize(0); - } - void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { const auto actionMappings = stream.FindMember("ActionMappings"); diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index 81a5b3155..900d802ed 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -8,7 +8,6 @@ #include "Prefabs/Prefab.h" #include "Prefabs/PrefabManager.h" #include "Engine/Core/Log.h" -#include "Engine/Core/Config/LayersTagsSettings.h" #include "Engine/Scripting/Script.h" #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Threading/Threading.h" @@ -386,21 +385,19 @@ Actor* Actor::GetChildByPrefabObjectId(const Guid& prefabObjectId) const bool Actor::HasTag(const StringView& tag) const { - return HasTag() && tag == LayersAndTagsSettings::Instance()->Tags[_tag]; + return HasTag() && tag == Level::Tags[_tag]; } const String& Actor::GetLayerName() const { - const auto settings = LayersAndTagsSettings::Instance(); - return settings->Layers[_layer]; + return Level::Layers[_layer]; } const String& Actor::GetTag() const { if (HasTag()) { - const auto settings = LayersAndTagsSettings::Instance(); - return settings->Tags[_tag]; + return Level::Tags[_tag]; } return String::Empty; } @@ -420,13 +417,13 @@ void Actor::SetTagIndex(int32 tagIndex) if (tagIndex == ACTOR_TAG_INVALID) { } - else if (LayersAndTagsSettings::Instance()->Tags.IsEmpty()) + else if (Level::Tags.IsEmpty()) { tagIndex = ACTOR_TAG_INVALID; } else { - tagIndex = tagIndex < 0 ? ACTOR_TAG_INVALID : Math::Min(tagIndex, LayersAndTagsSettings::Instance()->Tags.Count() - 1); + tagIndex = tagIndex < 0 ? ACTOR_TAG_INVALID : Math::Min(tagIndex, Level::Tags.Count() - 1); } if (tagIndex == _tag) return; @@ -444,7 +441,7 @@ void Actor::SetTag(const StringView& tagName) } else { - tagIndex = LayersAndTagsSettings::Instance()->Tags.Find(tagName); + tagIndex = Level::Tags.Find(tagName); if (tagIndex == -1) { LOG(Error, "Cannot change actor tag. Given value is invalid."); @@ -971,7 +968,7 @@ void Actor::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) if (tag->value.IsString() && tag->value.GetStringLength()) { const String tagName = tag->value.GetText(); - _tag = LayersAndTagsSettings::Instance()->GetOrAddTag(tagName); + _tag = Level::GetOrAddTag(tagName); } } diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index 18d9d4a52..7d257e104 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -9,6 +9,7 @@ #include "Engine/Core/Cache.h" #include "Engine/Core/Collections/CollectionPoolCache.h" #include "Engine/Core/ObjectsRemovalService.h" +#include "Engine/Core/Config/LayersTagsSettings.h" #include "Engine/Debug/Exceptions/ArgumentException.h" #include "Engine/Debug/Exceptions/ArgumentNullException.h" #include "Engine/Debug/Exceptions/InvalidOperationException.h" @@ -97,6 +98,7 @@ public: { } + bool Init() override; void Update() override; void LateUpdate() override; void FixedUpdate() override; @@ -124,6 +126,8 @@ Delegate Level::SceneUnloaded; Action Level::ScriptsReloadStart; Action Level::ScriptsReload; Action Level::ScriptsReloadEnd; +Array Level::Tags; +String Level::Layers[32]; bool LevelImpl::spawnActor(Actor* actor, Actor* parent) { @@ -158,6 +162,15 @@ bool LevelImpl::deleteActor(Actor* actor) return false; } +bool LevelService::Init() +{ + auto& settings = *LayersAndTagsSettings::Get(); + Level::Tags = settings.Tags; + for (int32 i = 0; i < ARRAY_COUNT(Level::Layers); i++) + Level::Layers[i] = settings.Layers[i]; + return false; +} + void LevelService::Update() { PROFILE_CPU(); @@ -642,6 +655,25 @@ void LevelImpl::CallSceneEvent(SceneEventType eventType, Scene* scene, Guid scen } } +int32 Level::GetOrAddTag(const StringView& tag) +{ + int32 index = Tags.Find(tag); + if (index == INVALID_INDEX) + { + index = Tags.Count(); + Tags.AddOne() = tag; + } + return index; +} + +int32 Level::GetNonEmptyLayerNamesCount() +{ + int32 result = 31; + while (result >= 0 && Layers[result].IsEmpty()) + result--; + return result + 1; +} + void Level::callActorEvent(ActorEventType eventType, Actor* a, Actor* b) { PROFILE_CPU(); diff --git a/Source/Engine/Level/Level.h b/Source/Engine/Level/Level.h index b1ee090f4..a1e1d73cd 100644 --- a/Source/Engine/Level/Level.h +++ b/Source/Engine/Level/Level.h @@ -420,6 +420,31 @@ public: /// Output array with only parents static void ConstructParentActorsTreeList(const Array& input, Array& output); +public: + + /// + /// The tags names. + /// + static Array Tags; + + /// + /// The layers names. + /// + static String Layers[32]; + + /// + /// Gets or adds the tag (returns the tag index). + /// + /// The tag. + /// The tag index. + static int32 GetOrAddTag(const StringView& tag); + + /// + /// Gets the amount of non empty layer names (from the beginning, trims the last ones). + /// + /// The layers count. + static int32 GetNonEmptyLayerNamesCount(); + private: // Actor API diff --git a/Source/Engine/Navigation/NavMeshBuilder.cpp b/Source/Engine/Navigation/NavMeshBuilder.cpp index b2679f861..caa2513d2 100644 --- a/Source/Engine/Navigation/NavMeshBuilder.cpp +++ b/Source/Engine/Navigation/NavMeshBuilder.cpp @@ -461,13 +461,13 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou float GetTileSize() { - auto& settings = *NavigationSettings::Instance(); + auto& settings = *NavigationSettings::Get(); return settings.CellSize * settings.TileSize; } void InitConfig(rcConfig& config) { - auto& settings = *NavigationSettings::Instance(); + auto& settings = *NavigationSettings::Get(); config.cs = settings.CellSize; config.ch = settings.CellHeight; diff --git a/Source/Engine/Navigation/Navigation.cpp b/Source/Engine/Navigation/Navigation.cpp index 143449547..6decb4be7 100644 --- a/Source/Engine/Navigation/Navigation.cpp +++ b/Source/Engine/Navigation/Navigation.cpp @@ -1,8 +1,12 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "Navigation.h" +#include "NavigationSettings.h" #include "NavMeshRuntime.h" #include "NavMeshBuilder.h" +#include "Engine/Core/Config/GameSettings.h" +#include "Engine/Content/Content.h" +#include "Engine/Content/JsonAsset.h" #include "Engine/Threading/Threading.h" #include "Engine/Level/Scene/Scene.h" #include "Engine/Engine/EngineService.h" @@ -55,6 +59,8 @@ void* rcAllocDefault(size_t size, rcAllocHint) return Allocator::Allocate(size); } +IMPLEMENT_SETTINGS_GETTER(NavigationSettings, Navigation); + bool NavigationService::Init() { // Link memory allocation calls to use engine default allocator diff --git a/Source/Engine/Navigation/NavigationSettings.cs b/Source/Engine/Navigation/NavigationSettings.cs new file mode 100644 index 000000000..ff6f2aa4a --- /dev/null +++ b/Source/Engine/Navigation/NavigationSettings.cs @@ -0,0 +1,8 @@ +// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. + +namespace FlaxEditor.Content.Settings +{ + partial class NavigationSettings + { + } +} diff --git a/Source/Engine/Navigation/NavigationSettings.h b/Source/Engine/Navigation/NavigationSettings.h index d7c3aa205..fe4189955 100644 --- a/Source/Engine/Navigation/NavigationSettings.h +++ b/Source/Engine/Navigation/NavigationSettings.h @@ -9,7 +9,7 @@ /// /// The navigation system settings container. /// -API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API NavigationSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API NavigationSettings : public SettingsBase { DECLARE_SCRIPTING_TYPE_MINIMAL(NavigationSettings); public: @@ -94,24 +94,12 @@ public: public: - // [SettingsBase] - void RestoreDefault() final override - { - CellHeight = 10.0f; - CellSize = 30.0f; - TileSize = 64; - MinRegionArea = 0; - MergeRegionArea = 20; - MaxEdgeLen = 1200.0f; - MaxEdgeError = 1.3f; - DetailSamplingDist = 600.0f; - MaxDetailSamplingError = 1.0f; - WalkableRadius = 34.0f; - WalkableHeight = 144.0f; - WalkableMaxClimb = 35.0f; - WalkableMaxSlopeAngle = 60.0f; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static NavigationSettings* Get(); + // [SettingsBase] void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(CellHeight); diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp index e73963c7c..2eeb266aa 100644 --- a/Source/Engine/Physics/Colliders/Collider.cpp +++ b/Source/Engine/Physics/Colliders/Collider.cpp @@ -232,7 +232,7 @@ void Collider::UpdateLayerBits() filterData.word0 = GetLayerMask(); // Own layer mask - filterData.word1 = PhysicsSettings::Instance()->LayerMasks[GetLayer()]; + filterData.word1 = Physics::LayerMasks[GetLayer()]; _shape->setSimulationFilterData(filterData); _shape->setQueryFilterData(filterData); diff --git a/Source/Engine/Physics/PhysicalMaterial.cpp b/Source/Engine/Physics/PhysicalMaterial.cpp deleted file mode 100644 index 9870bfc65..000000000 --- a/Source/Engine/Physics/PhysicalMaterial.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -#include "PhysicalMaterial.h" -#include "PhysicsSettings.h" -#include "Physics.h" -#include -#include - -PhysicalMaterial::PhysicalMaterial() - : _material(nullptr) -{ -} - -PhysicalMaterial::~PhysicalMaterial() -{ - if (_material) - { - Physics::RemoveMaterial(_material); - } -} - -PxMaterial* PhysicalMaterial::GetPhysXMaterial() -{ - if (_material == nullptr && CPhysX) - { - _material = CPhysX->createMaterial(Friction, Friction, Restitution); - _material->userData = this; - - const PhysicsCombineMode useFrictionCombineMode = (OverrideFrictionCombineMode ? FrictionCombineMode : PhysicsSettings::Instance()->FrictionCombineMode); - _material->setFrictionCombineMode(static_cast(useFrictionCombineMode)); - - const PhysicsCombineMode useRestitutionCombineMode = (OverrideRestitutionCombineMode ? RestitutionCombineMode : PhysicsSettings::Instance()->RestitutionCombineMode); - _material->setRestitutionCombineMode(static_cast(useRestitutionCombineMode)); - } - - return _material; -} - -void PhysicalMaterial::UpdatePhysXMaterial() -{ - if (_material != nullptr) - { - _material->setStaticFriction(Friction); - _material->setDynamicFriction(Friction); - const PhysicsCombineMode useFrictionCombineMode = (OverrideFrictionCombineMode ? FrictionCombineMode : PhysicsSettings::Instance()->FrictionCombineMode); - _material->setFrictionCombineMode(static_cast(useFrictionCombineMode)); - - _material->setRestitution(Restitution); - const PhysicsCombineMode useRestitutionCombineMode = (OverrideRestitutionCombineMode ? RestitutionCombineMode : PhysicsSettings::Instance()->RestitutionCombineMode); - _material->setRestitutionCombineMode(static_cast(useRestitutionCombineMode)); - } -} diff --git a/Source/Engine/Physics/Physics.cpp b/Source/Engine/Physics/Physics.cpp index 2daa47010..98237948f 100644 --- a/Source/Engine/Physics/Physics.cpp +++ b/Source/Engine/Physics/Physics.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "Physics.h" +#include "PhysicalMaterial.h" #include "Engine/Core/Log.h" #include "Engine/Threading/Threading.h" #include "Engine/Platform/CPUInfo.h" @@ -13,6 +14,8 @@ #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Core/Memory/Memory.h" #include "Engine/Engine/EngineService.h" +#include "Engine/Serialization/Serialization.h" +#include "Engine/Engine/Time.h" #include #include #if WITH_PVD @@ -110,34 +113,43 @@ struct ActionData }; PxPhysics* CPhysX = nullptr; -PhysXAllocator PhysXAllocatorCallback; -PhysXError PhysXErrorCallback; -PxSimulationFilterShader PhysXDefaultFilterShader = PxDefaultSimulationFilterShader; #if WITH_PVD PxPvd* CPVD = nullptr; #endif -PxTolerancesScale ToleranceScale; -SimulationEventCallback EventsCallback; -void* ScratchMemory = nullptr; -FixedStepper* Stepper = nullptr; -CriticalSection FlushLocker; -Array NewActors; -Array Actions; -Array DeadActors; -Array DeadMaterials; -Array _deadObjects; -Array DeadColliders; -Array DeadJoints; -bool _isDuringSimulation = false; -PxFoundation* _foundation = nullptr; + +namespace +{ + PhysXAllocator PhysXAllocatorCallback; + PhysXError PhysXErrorCallback; + PxSimulationFilterShader PhysXDefaultFilterShader = PxDefaultSimulationFilterShader; + PxTolerancesScale ToleranceScale; + SimulationEventCallback EventsCallback; + void* ScratchMemory = nullptr; + FixedStepper* Stepper = nullptr; + CriticalSection FlushLocker; + Array NewActors; + Array Actions; + Array DeadActors; + Array DeadMaterials; + Array _deadObjects; + Array DeadColliders; + Array DeadJoints; + bool _queriesHitTriggers = true; + bool _isDuringSimulation = false; + PhysicsCombineMode _frictionCombineMode = PhysicsCombineMode::Average; + PhysicsCombineMode _restitutionCombineMode = PhysicsCombineMode::Average; + PxFoundation* _foundation = nullptr; #if COMPILE_WITH_PHYSICS_COOKING -PxCooking* Cooking = nullptr; + PxCooking* Cooking = nullptr; #endif -PxScene* PhysicsScene = nullptr; -PxMaterial* DefaultMaterial = nullptr; -PxControllerManager* ControllerManager = nullptr; -PxCpuDispatcher* CpuDispatcher = nullptr; + PxScene* PhysicsScene = nullptr; + PxMaterial* DefaultMaterial = nullptr; + PxControllerManager* ControllerManager = nullptr; + PxCpuDispatcher* CpuDispatcher = nullptr; +} + bool Physics::AutoSimulation = true; +uint32 Physics::LayerMasks[32]; class PhysicsService : public EngineService { @@ -146,6 +158,8 @@ public: PhysicsService() : EngineService(TEXT("Physics"), 0) { + for (int32 i = 0; i < 32; i++) + Physics::LayerMasks[i] = MAX_uint32; } bool Init() override; @@ -155,12 +169,146 @@ public: PhysicsService PhysicsServiceInstance; +PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled) +{ +#if WITH_PVD + PxShapeFlags flags = PxShapeFlag::eVISUALIZATION; +#else + PxShapeFlags flags = static_cast(0); +#endif + + if (isEnabled) + { + if (isTrigger) + { + flags |= PxShapeFlag::eTRIGGER_SHAPE; + if (_queriesHitTriggers) + flags |= PxShapeFlag::eSCENE_QUERY_SHAPE; + } + else + { + flags = PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eSCENE_QUERY_SHAPE; + } + } + + return flags; +} + +void PhysicsSettings::Apply() +{ + Time::_physicsMaxDeltaTime = MaxDeltaTime; + _queriesHitTriggers = QueriesHitTriggers; + _frictionCombineMode = FrictionCombineMode; + _restitutionCombineMode = RestitutionCombineMode; + Platform::MemoryCopy(Physics::LayerMasks, LayerMasks, sizeof(LayerMasks)); + Physics::SetGravity(DefaultGravity); + Physics::SetBounceThresholdVelocity(BounceThresholdVelocity); + Physics::SetEnableCCD(!DisableCCD); + + // TODO: setting eADAPTIVE_FORCE requires PxScene setup (physx docs: This flag is not mutable, and must be set in PxSceneDesc at scene creation.) + // TODO: update all shapes filter data + // TODO: update all shapes flags + + /* + { + get all actors and then: + + const PxU32 numShapes = actor->getNbShapes(); + PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*numShapes); + actor->getShapes(shapes, numShapes); + for (PxU32 i = 0; i < numShapes; i++) + { + .. + } + SAMPLE_FREE(shapes); + }*/ +} + +PhysicsSettings::PhysicsSettings() +{ + for (int32 i = 0; i < 32; i++) + LayerMasks[i] = MAX_uint32; +} + +void PhysicsSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) +{ + DESERIALIZE(DefaultGravity); + DESERIALIZE(TriangleMeshTriangleMinAreaThreshold); + DESERIALIZE(BounceThresholdVelocity); + DESERIALIZE(FrictionCombineMode); + DESERIALIZE(RestitutionCombineMode); + DESERIALIZE(DisableCCD); + DESERIALIZE(EnableAdaptiveForce); + DESERIALIZE(MaxDeltaTime); + DESERIALIZE(EnableSubstepping); + DESERIALIZE(SubstepDeltaTime); + DESERIALIZE(MaxSubsteps); + DESERIALIZE(QueriesHitTriggers); + DESERIALIZE(SupportCookingAtRuntime); + + const auto layers = stream.FindMember("LayerMasks"); + if (layers != stream.MemberEnd()) + { + auto& layersArray = layers->value; + ASSERT(layersArray.IsArray()); + for (uint32 i = 0; i < layersArray.Size() && i < 32; i++) + { + LayerMasks[i] = layersArray[i].GetUint(); + } + } +} + +PhysicalMaterial::PhysicalMaterial() + : _material(nullptr) +{ +} + +PhysicalMaterial::~PhysicalMaterial() +{ + if (_material) + { + Physics::RemoveMaterial(_material); + } +} + +PxMaterial* PhysicalMaterial::GetPhysXMaterial() +{ + if (_material == nullptr && CPhysX) + { + _material = CPhysX->createMaterial(Friction, Friction, Restitution); + _material->userData = this; + + const PhysicsCombineMode useFrictionCombineMode = OverrideFrictionCombineMode ? FrictionCombineMode : _frictionCombineMode; + _material->setFrictionCombineMode(static_cast(useFrictionCombineMode)); + + const PhysicsCombineMode useRestitutionCombineMode = OverrideRestitutionCombineMode ? RestitutionCombineMode : _restitutionCombineMode; + _material->setRestitutionCombineMode(static_cast(useRestitutionCombineMode)); + } + + return _material; +} + +void PhysicalMaterial::UpdatePhysXMaterial() +{ + if (_material != nullptr) + { + _material->setStaticFriction(Friction); + _material->setDynamicFriction(Friction); + const PhysicsCombineMode useFrictionCombineMode = OverrideFrictionCombineMode ? FrictionCombineMode : _frictionCombineMode; + _material->setFrictionCombineMode(static_cast(useFrictionCombineMode)); + + _material->setRestitution(Restitution); + const PhysicsCombineMode useRestitutionCombineMode = OverrideRestitutionCombineMode ? RestitutionCombineMode : _restitutionCombineMode; + _material->setRestitutionCombineMode(static_cast(useRestitutionCombineMode)); + } +} + bool PhysicsService::Init() { #define CHECK_INIT(value, msg) if(!value) { LOG(Error, msg); return true; } auto cpuInfo = Platform::GetCPUInfo(); - auto settings = PhysicsSettings::Instance(); + auto& settings = *PhysicsSettings::Get(); // Send info LOG(Info, "Setup NVIDIA PhysX {0}.{1}.{2}", PX_PHYSICS_VERSION_MAJOR, PX_PHYSICS_VERSION_MINOR, PX_PHYSICS_VERSION_BUGFIX); @@ -220,7 +368,7 @@ bool PhysicsService::Init() #if COMPILE_WITH_PHYSICS_COOKING #if !USE_EDITOR - if (settings->SupportCookingAtRuntime) + if (settings.SupportCookingAtRuntime) #endif { // Init cooking @@ -235,16 +383,16 @@ bool PhysicsService::Init() // Create scene description PxSceneDesc sceneDesc(CPhysX->getTolerancesScale()); - sceneDesc.gravity = C2P(settings->DefaultGravity); + sceneDesc.gravity = C2P(settings.DefaultGravity); sceneDesc.flags |= PxSceneFlag::eENABLE_ACTIVE_ACTORS; //sceneDesc.flags |= PxSceneFlag::eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS; // TODO: set it? - if (!settings->DisableCCD) + if (!settings.DisableCCD) sceneDesc.flags |= PxSceneFlag::eENABLE_CCD; - if (settings->EnableAdaptiveForce) + if (settings.EnableAdaptiveForce) sceneDesc.flags |= PxSceneFlag::eADAPTIVE_FORCE; sceneDesc.simulationEventCallback = &EventsCallback; sceneDesc.filterShader = PhysiXFilterShader; - sceneDesc.bounceThresholdVelocity = settings->BounceThresholdVelocity; + sceneDesc.bounceThresholdVelocity = settings.BounceThresholdVelocity; if (sceneDesc.cpuDispatcher == nullptr) { CpuDispatcher = PxDefaultCpuDispatcherCreate(Math::Clamp(cpuInfo.ProcessorCoreCount - 1, 1, 4)); @@ -366,7 +514,7 @@ void Physics::SetGravity(const Vector3& value) bool Physics::GetEnableCCD() { - return PhysicsScene ? (PhysicsScene->getFlags() & PxSceneFlag::eENABLE_CCD) == PxSceneFlag::eENABLE_CCD : !PhysicsSettings_DisableCCD; + return PhysicsScene ? (PhysicsScene->getFlags() & PxSceneFlag::eENABLE_CCD) == PxSceneFlag::eENABLE_CCD : !PhysicsSettings::Get()->DisableCCD; } void Physics::SetEnableCCD(const bool value) @@ -377,7 +525,7 @@ void Physics::SetEnableCCD(const bool value) float Physics::GetBounceThresholdVelocity() { - return PhysicsScene ? PhysicsScene->getBounceThresholdVelocity() : PhysicsSettings_BounceThresholdVelocity; + return PhysicsScene ? PhysicsScene->getBounceThresholdVelocity() : PhysicsSettings::Get()->BounceThresholdVelocity; } void Physics::SetBounceThresholdVelocity(const float value) @@ -390,13 +538,13 @@ void Physics::Simulate(float dt) { ASSERT(IsInMainThread() && !_isDuringSimulation); ASSERT(CPhysX); - const auto settings = PhysicsSettings::Instance(); + const auto& settings = *PhysicsSettings::Get(); // Flush the old/new objects and the other requests before the simulation FlushRequests(); // Clamp delta - dt = Math::Clamp(dt, 0.0f, settings->MaxDeltaTime); + dt = Math::Clamp(dt, 0.0f, settings.MaxDeltaTime); // Prepare util objects if (ScratchMemory == nullptr) @@ -407,10 +555,10 @@ void Physics::Simulate(float dt) { Stepper = New(); } - if (settings->EnableSubstepping) + if (settings.EnableSubstepping) { // Use substeps - Stepper->Setup(settings->SubstepDeltaTime, settings->MaxSubsteps); + Stepper->Setup(settings.SubstepDeltaTime, settings.MaxSubsteps); } else { diff --git a/Source/Engine/Physics/Physics.h b/Source/Engine/Physics/Physics.h index bdc1326d3..05b64cb0f 100644 --- a/Source/Engine/Physics/Physics.h +++ b/Source/Engine/Physics/Physics.h @@ -155,6 +155,11 @@ public: /// API_PROPERTY() static void SetBounceThresholdVelocity(float value); + /// + /// The collision layers masks. Used to define layer-based collision detection. + /// + static uint32 LayerMasks[32]; + public: /// diff --git a/Source/Engine/Physics/PhysicsSettings.cpp b/Source/Engine/Physics/PhysicsSettings.cpp deleted file mode 100644 index be8bff331..000000000 --- a/Source/Engine/Physics/PhysicsSettings.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. - -#include "PhysicsSettings.h" -#include "Engine/Serialization/Serialization.h" -#include "Physics.h" - -void PhysicsSettings::Apply() -{ - // Set simulation parameters - Physics::SetGravity(DefaultGravity); - Physics::SetBounceThresholdVelocity(BounceThresholdVelocity); - Physics::SetEnableCCD(!DisableCCD); - - // TODO: setting eADAPTIVE_FORCE requires PxScene setup (physx docs: This flag is not mutable, and must be set in PxSceneDesc at scene creation.) - - // Update all shapes - - // TODO: update all shapes filter data - // TODO: update all shapes flags - - /* - { - get all actors and then: - - const PxU32 numShapes = actor->getNbShapes(); - PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*numShapes); - actor->getShapes(shapes, numShapes); - for (PxU32 i = 0; i < numShapes; i++) - { - .. - } - SAMPLE_FREE(shapes); - }*/ -} - -void PhysicsSettings::RestoreDefault() -{ - DefaultGravity = PhysicsSettings_DefaultGravity; - TriangleMeshTriangleMinAreaThreshold = PhysicsSettings_TriangleMeshTriangleMinAreaThreshold; - BounceThresholdVelocity = PhysicsSettings_BounceThresholdVelocity; - FrictionCombineMode = PhysicsSettings_FrictionCombineMode; - RestitutionCombineMode = PhysicsSettings_RestitutionCombineMode; - DisableCCD = PhysicsSettings_DisableCCD; - EnableAdaptiveForce = PhysicsSettings_EnableAdaptiveForce; - MaxDeltaTime = PhysicsSettings_MaxDeltaTime; - EnableSubstepping = PhysicsSettings_EnableSubstepping; - SubstepDeltaTime = PhysicsSettings_SubstepDeltaTime; - MaxSubsteps = PhysicsSettings_MaxSubsteps; - QueriesHitTriggers = PhysicsSettings_QueriesHitTriggers; - SupportCookingAtRuntime = PhysicsSettings_SupportCookingAtRuntime; - - for (int32 i = 0; i < 32; i++) - LayerMasks[i] = MAX_uint32; -} - -void PhysicsSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) -{ - DESERIALIZE(DefaultGravity); - DESERIALIZE(TriangleMeshTriangleMinAreaThreshold); - DESERIALIZE(BounceThresholdVelocity); - DESERIALIZE(FrictionCombineMode); - DESERIALIZE(RestitutionCombineMode); - DESERIALIZE(DisableCCD); - DESERIALIZE(EnableAdaptiveForce); - DESERIALIZE(MaxDeltaTime); - DESERIALIZE(EnableSubstepping); - DESERIALIZE(SubstepDeltaTime); - DESERIALIZE(MaxSubsteps); - DESERIALIZE(QueriesHitTriggers); - DESERIALIZE(SupportCookingAtRuntime); - - const auto layers = stream.FindMember("LayerMasks"); - if (layers != stream.MemberEnd()) - { - auto& layersArray = layers->value; - ASSERT(layersArray.IsArray()); - for (uint32 i = 0; i < layersArray.Size() && i < 32; i++) - { - LayerMasks[i] = layersArray[i].GetUint(); - } - } -} diff --git a/Source/Engine/Physics/PhysicsSettings.h b/Source/Engine/Physics/PhysicsSettings.h index 3bf19bcb8..214c86558 100644 --- a/Source/Engine/Physics/PhysicsSettings.h +++ b/Source/Engine/Physics/PhysicsSettings.h @@ -6,105 +6,91 @@ #include "Engine/Core/Math/Vector3.h" #include "Types.h" -// Default values for the physics settings - -#define PhysicsSettings_DefaultGravity Vector3(0, -981.0f, 0) -#define PhysicsSettings_TriangleMeshTriangleMinAreaThreshold (5.0f) -#define PhysicsSettings_BounceThresholdVelocity (200.0f) -#define PhysicsSettings_FrictionCombineMode PhysicsCombineMode::Average -#define PhysicsSettings_RestitutionCombineMode PhysicsCombineMode::Average -#define PhysicsSettings_DisableCCD false -#define PhysicsSettings_EnableAdaptiveForce false -#define PhysicsSettings_MaxDeltaTime (1.0f / 10.0f) -#define PhysicsSettings_EnableSubstepping false -#define PhysicsSettings_SubstepDeltaTime (1.0f / 120.0f) -#define PhysicsSettings_MaxSubsteps 5 -#define PhysicsSettings_QueriesHitTriggers true -#define PhysicsSettings_SupportCookingAtRuntime false - /// /// Physics simulation settings container. /// -/// -class PhysicsSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class FLAXENGINE_API PhysicsSettings : public SettingsBase { -public: - - /// - /// Initializes a new instance of the class. - /// - PhysicsSettings() - { - for (int32 i = 0; i < 32; i++) - LayerMasks[i] = MAX_uint32; - } - +DECLARE_SCRIPTING_TYPE_MINIMAL(PhysicsSettings); public: /// /// The default gravity force value (in cm^2/s). /// - Vector3 DefaultGravity = PhysicsSettings_DefaultGravity; - - /// - /// Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable. - /// - float TriangleMeshTriangleMinAreaThreshold = PhysicsSettings_TriangleMeshTriangleMinAreaThreshold; - - /// - /// Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity - /// - float BounceThresholdVelocity = PhysicsSettings_BounceThresholdVelocity; - - /// - /// Default friction combine mode, controls how friction is computed for multiple materials. - /// - PhysicsCombineMode FrictionCombineMode = PhysicsSettings_FrictionCombineMode; - - /// - /// Default restitution combine mode, controls how restitution is computed for multiple materials. - /// - PhysicsCombineMode RestitutionCombineMode = PhysicsSettings_RestitutionCombineMode; - - /// - /// If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for physx to check it internally. - /// - bool DisableCCD = PhysicsSettings_DisableCCD; - - /// - /// Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts. - /// - bool EnableAdaptiveForce = PhysicsSettings_EnableAdaptiveForce; - - /// - /// The maximum allowed delta time (in seconds) for the physics simulation step. - /// - float MaxDeltaTime = PhysicsSettings_MaxDeltaTime; - - /// - /// Whether to substep the physics simulation. - /// - bool EnableSubstepping = PhysicsSettings_EnableSubstepping; - - /// - /// Delta time (in seconds) for an individual simulation substep. - /// - float SubstepDeltaTime = PhysicsSettings_SubstepDeltaTime; - - /// - /// The maximum number of substeps for physics simulation. - /// - int32 MaxSubsteps = PhysicsSettings_MaxSubsteps; + API_FIELD(Attributes="EditorOrder(0), DefaultValue(typeof(Vector3), \"0,-981.0,0\"), EditorDisplay(\"Simulation\")") + Vector3 DefaultGravity = Vector3(0, -981.0f, 0); /// /// If enabled, any Raycast or other scene query that intersects with a Collider marked as a Trigger will returns with a hit. Individual raycasts can override this behavior. /// - bool QueriesHitTriggers = PhysicsSettings_QueriesHitTriggers; + API_FIELD(Attributes="EditorOrder(10), DefaultValue(true), EditorDisplay(\"Framerate\")") + bool QueriesHitTriggers = true; + + /// + /// Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable. + /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(5.0f), EditorDisplay(\"Simulation\")") + float TriangleMeshTriangleMinAreaThreshold = 5.0f; + + /// + /// Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity + /// + API_FIELD(Attributes="EditorOrder(30), DefaultValue(200.0f), EditorDisplay(\"Simulation\")") + float BounceThresholdVelocity = 200.0f; + + /// + /// Default friction combine mode, controls how friction is computed for multiple materials. + /// + API_FIELD(Attributes="EditorOrder(40), DefaultValue(PhysicsCombineMode.Average), EditorDisplay(\"Simulation\")") + PhysicsCombineMode FrictionCombineMode = PhysicsCombineMode::Average; + + /// + /// Default restitution combine mode, controls how restitution is computed for multiple materials. + /// + API_FIELD(Attributes="EditorOrder(40), DefaultValue(PhysicsCombineMode.Average), EditorDisplay(\"Simulation\")") + PhysicsCombineMode RestitutionCombineMode = PhysicsCombineMode::Average; + + /// + /// If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for physx to check it internally. + /// + API_FIELD(Attributes="EditorOrder(70), DefaultValue(false), EditorDisplay(\"Simulation\")") + bool DisableCCD = false; + + /// + /// Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts. + /// + API_FIELD(Attributes="EditorOrder(80), DefaultValue(false), EditorDisplay(\"Simulation\")") + bool EnableAdaptiveForce = false; + + /// + /// The maximum allowed delta time (in seconds) for the physics simulation step. + /// + API_FIELD(Attributes="EditorOrder(1000), DefaultValue(1.0f / 10.0f), EditorDisplay(\"Framerate\")") + float MaxDeltaTime = 1.0f / 10.0f; + + /// + /// Whether to substep the physics simulation. + /// + API_FIELD(Attributes="EditorOrder(1005), DefaultValue(false), EditorDisplay(\"Framerate\")") + bool EnableSubstepping = false; + + /// + /// Delta time (in seconds) for an individual simulation substep. + /// + API_FIELD(Attributes="EditorOrder(1010), DefaultValue(1.0f / 120.0f), EditorDisplay(\"Framerate\")") + float SubstepDeltaTime = 1.0f / 120.0f; + + /// + /// The maximum number of substeps for physics simulation. + /// + API_FIELD(Attributes="EditorOrder(1020), DefaultValue(5), EditorDisplay(\"Framerate\")") + int32 MaxSubsteps = 5; /// /// Enables support for cooking physical collision shapes geometry at runtime. Use it to enable generating runtime terrain collision or convex mesh colliders. /// - bool SupportCookingAtRuntime = PhysicsSettings_SupportCookingAtRuntime; + API_FIELD(Attributes="EditorOrder(1100), DefaultValue(false), EditorDisplay(\"Other\")") + bool SupportCookingAtRuntime = false; public: @@ -115,8 +101,17 @@ public: public: + /// + /// Initializes a new instance of the class. + /// + PhysicsSettings(); + + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static PhysicsSettings* Get(); + // [SettingsBase] void Apply() override; - void RestoreDefault() override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override; }; diff --git a/Source/Engine/Physics/Utilities.h b/Source/Engine/Physics/Utilities.h index 11914277f..34ee7f66d 100644 --- a/Source/Engine/Physics/Utilities.h +++ b/Source/Engine/Physics/Utilities.h @@ -14,9 +14,6 @@ #include #include #include -#include "PhysicsSettings.h" - -//////////////////////////// Conversion between PhysX and Flax types inline PxVec2& C2P(const Vector2& v) { @@ -43,8 +40,6 @@ inline PxBounds3& C2P(const BoundingBox& v) return *(PxBounds3*)&v; } -//////////////////////////// - inline Vector2& P2C(const PxVec2& v) { return *(Vector2*)&v; @@ -79,29 +74,4 @@ inline Vector3 P2C(const PxExtendedVec3& v) #endif } -//////////////////////////// - -inline PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled) -{ -#if WITH_PVD - PxShapeFlags flags = PxShapeFlag::eVISUALIZATION; -#else - PxShapeFlags flags = static_cast(0); -#endif - - if (isEnabled) - { - if (isTrigger) - { - flags |= PxShapeFlag::eTRIGGER_SHAPE; - if (PhysicsSettings::Instance()->QueriesHitTriggers) - flags |= PxShapeFlag::eSCENE_QUERY_SHAPE; - } - else - { - flags = PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eSCENE_QUERY_SHAPE; - } - } - - return flags; -} +extern PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled); diff --git a/Source/Engine/Platform/Android/AndroidPlatformSettings.h b/Source/Engine/Platform/Android/AndroidPlatformSettings.h index 1c761259b..8805b2180 100644 --- a/Source/Engine/Platform/Android/AndroidPlatformSettings.h +++ b/Source/Engine/Platform/Android/AndroidPlatformSettings.h @@ -9,41 +9,37 @@ /// /// Android platform settings. /// -/// -class AndroidPlatformSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API AndroidPlatformSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(AndroidPlatformSettings); public: /// /// The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}. /// - String PackageName; + API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"General\")") + String PackageName = TEXT("com.${COMPANY_NAME}.${PROJECT_NAME}"); /// /// The application permissions list (eg. android.media.action.IMAGE_CAPTURE). Added to the generated manifest file. /// + API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"General\")") Array Permissions; /// /// Custom icon texture (asset id) to use for the application (overrides the default one). /// + API_FIELD(Attributes="EditorOrder(1030), AssetReference(typeof(Texture)), EditorDisplay(\"Other\")") Guid OverrideIcon; public: - AndroidPlatformSettings() - { - RestoreDefault(); - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static AndroidPlatformSettings* Get(); // [SettingsBase] - void RestoreDefault() final override - { - PackageName = TEXT("com.${COMPANY_NAME}.${PROJECT_NAME}"); - Permissions.Clear(); - OverrideIcon = Guid::Empty; - } - void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(PackageName); diff --git a/Source/Engine/Platform/Linux/LinuxPlatformSettings.h b/Source/Engine/Platform/Linux/LinuxPlatformSettings.h index 4c602224a..7da0ec406 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatformSettings.h +++ b/Source/Engine/Platform/Linux/LinuxPlatformSettings.h @@ -9,66 +9,67 @@ /// /// Linux platform settings. /// -/// -class LinuxPlatformSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API LinuxPlatformSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(LinuxPlatformSettings); public: /// /// The default game window mode. /// + API_FIELD(Attributes="EditorOrder(10), DefaultValue(GameWindowMode.Windowed), EditorDisplay(\"Window\")") GameWindowMode WindowMode = GameWindowMode::Windowed; /// /// The default game window width (in pixels). /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(1280), EditorDisplay(\"Window\")") int32 ScreenWidth = 1280; /// /// The default game window height (in pixels). /// + API_FIELD(Attributes="EditorOrder(30), DefaultValue(720), EditorDisplay(\"Window\")") int32 ScreenHeight = 720; - /// - /// Enables game running when application window loses focus. - /// - bool RunInBackground = false; - /// /// Enables resizing the game window by the user. /// + API_FIELD(Attributes="EditorOrder(40), DefaultValue(false), EditorDisplay(\"Window\")") bool ResizableWindow = false; + /// + /// Enables game running when application window loses focus. + /// + API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")") + bool RunInBackground = false; + /// /// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once. /// + API_FIELD(Attributes="EditorOrder(1020), DefaultValue(false), EditorDisplay(\"Other\")") bool ForceSingleInstance = false; /// /// Custom icon texture (asset id) to use for the application (overrides the default one). /// - Guid OverrideIcon = Guid::Empty; + API_FIELD(Attributes="EditorOrder(1030), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.AssetRefEditor\"), AssetReference(typeof(Texture)), EditorDisplay(\"Other\")") + Guid OverrideIcon; /// /// Enables support for Vulkan. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2000), DefaultValue(true), EditorDisplay(\"Graphics\")") bool SupportVulkan = true; public: - // [SettingsBase] - void RestoreDefault() final override - { - WindowMode = GameWindowMode::Windowed; - ScreenWidth = 1280; - ScreenHeight = 720; - RunInBackground = false; - ResizableWindow = false; - ForceSingleInstance = false; - OverrideIcon = Guid::Empty; - SupportVulkan = true; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static LinuxPlatformSettings* Get(); + // [SettingsBase] void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(WindowMode); diff --git a/Source/Engine/Platform/Platform.Build.cs b/Source/Engine/Platform/Platform.Build.cs index b7a2baa97..72a706685 100644 --- a/Source/Engine/Platform/Platform.Build.cs +++ b/Source/Engine/Platform/Platform.Build.cs @@ -62,5 +62,15 @@ public class Platform : EngineModule break; default: throw new InvalidPlatformException(options.Platform.Target); } + if (options.Target.IsEditor) + { + // Include platform settings headers + options.SourceFiles.Add(Path.Combine(FolderPath, "Windows", "WindowsPlatformSettings.h")); + options.SourceFiles.Add(Path.Combine(FolderPath, "UWP", "UWPPlatformSettings.h")); + options.SourceFiles.Add(Path.Combine(FolderPath, "Linux", "LinuxPlatformSettings.h")); + options.SourceFiles.Add(Path.Combine(FolderPath, "Android", "AndroidPlatformSettings.h")); + AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxScarlett", "Engine", "Platform", "XboxScarlettPlatformSettings.h")); + AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Platform", "PS4PlatformSettings.h")); + } } } diff --git a/Source/Engine/Platform/UWP/UWPPlatformSettings.h b/Source/Engine/Platform/UWP/UWPPlatformSettings.h index 706cad89c..e600cead7 100644 --- a/Source/Engine/Platform/UWP/UWPPlatformSettings.h +++ b/Source/Engine/Platform/UWP/UWPPlatformSettings.h @@ -9,15 +9,15 @@ /// /// Universal Windows Platform settings. /// -/// -class UWPPlatformSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API UWPPlatformSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(UWPPlatformSettings); public: /// /// The preferred launch windowing mode. /// - enum class WindowMode + API_ENUM() enum class WindowMode { /// /// The full screen mode @@ -33,7 +33,7 @@ public: /// /// The display orientation modes. Can be combined as flags. /// - enum class DisplayOrientations + API_ENUM(Attributes="Flags") enum class DisplayOrientations { /// /// The none. @@ -71,40 +71,41 @@ public: /// /// The preferred launch windowing mode. Always fullscreen on Xbox. /// + API_FIELD(Attributes="EditorOrder(10), DefaultValue(WindowMode.FullScreen), EditorDisplay(\"Window\")") WindowMode PreferredLaunchWindowingMode = WindowMode::FullScreen; /// /// The display orientation modes. Can be combined as flags. /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(DisplayOrientations.All), EditorDisplay(\"Window\")") DisplayOrientations AutoRotationPreferences = DisplayOrientations::All; /// /// The location of the package certificate (relative to the project). /// + API_FIELD(Attributes="EditorOrder(1010), DefaultValue(\"\"), EditorDisplay(\"Other\")") String CertificateLocation; /// /// Enables support for DirectX 11. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2000), DefaultValue(true), EditorDisplay(\"Graphics\", \"Support DirectX 11\")") bool SupportDX11 = true; /// /// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2010), DefaultValue(false), EditorDisplay(\"Graphics\", \"Support DirectX 10\")") bool SupportDX10 = false; public: - // [SettingsBase] - void RestoreDefault() final override - { - PreferredLaunchWindowingMode = WindowMode::FullScreen; - AutoRotationPreferences = DisplayOrientations::All; - CertificateLocation.Clear(); - SupportDX11 = true; - SupportDX10 = false; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static UWPPlatformSettings* Get(); + // [SettingsBase] void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(PreferredLaunchWindowingMode); diff --git a/Source/Engine/Platform/Windows/WindowsPlatformSettings.h b/Source/Engine/Platform/Windows/WindowsPlatformSettings.h index 3da8dc2b8..48a39444a 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatformSettings.h +++ b/Source/Engine/Platform/Windows/WindowsPlatformSettings.h @@ -9,84 +9,85 @@ /// /// Windows platform settings. /// -/// -class WindowsPlatformSettings : public SettingsBase +API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API WindowsPlatformSettings : public SettingsBase { +DECLARE_SCRIPTING_TYPE_MINIMAL(WindowsPlatformSettings); public: /// /// The default game window mode. /// + API_FIELD(Attributes="EditorOrder(10), DefaultValue(GameWindowMode.Windowed), EditorDisplay(\"Window\")") GameWindowMode WindowMode = GameWindowMode::Windowed; /// /// The default game window width (in pixels). /// + API_FIELD(Attributes="EditorOrder(20), DefaultValue(1280), EditorDisplay(\"Window\")") int32 ScreenWidth = 1280; /// /// The default game window height (in pixels). /// + API_FIELD(Attributes="EditorOrder(30), DefaultValue(720), EditorDisplay(\"Window\")") int32 ScreenHeight = 720; - /// - /// Enables game running when application window loses focus. - /// - bool RunInBackground = false; - /// /// Enables resizing the game window by the user. /// + API_FIELD(Attributes="EditorOrder(40), DefaultValue(false), EditorDisplay(\"Window\")") bool ResizableWindow = false; + /// + /// Enables game running when application window loses focus. + /// + API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")") + bool RunInBackground = false; + /// /// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once. /// + API_FIELD(Attributes="EditorOrder(1020), DefaultValue(false), EditorDisplay(\"Other\")") bool ForceSingleInstance = false; /// /// Custom icon texture (asset id) to use for the application (overrides the default one). /// + API_FIELD(Attributes="EditorOrder(1030), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.AssetRefEditor\"), AssetReference(typeof(Texture)), EditorDisplay(\"Other\")") Guid OverrideIcon; /// /// Enables support for DirectX 12. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2000), DefaultValue(false), EditorDisplay(\"Graphics\", \"Support DirectX 12\")") bool SupportDX12 = false; /// /// Enables support for DirectX 11. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2010), DefaultValue(true), EditorDisplay(\"Graphics\", \"Support DirectX 11\")") bool SupportDX11 = true; /// /// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2020), DefaultValue(false), EditorDisplay(\"Graphics\", \"Support DirectX 10\")") bool SupportDX10 = false; /// /// Enables support for Vulkan. Disabling it reduces compiled shaders count. /// + API_FIELD(Attributes="EditorOrder(2030), DefaultValue(false), EditorDisplay(\"Graphics\")") bool SupportVulkan = false; public: - // [SettingsBase] - void RestoreDefault() final override - { - WindowMode = GameWindowMode::Windowed; - ScreenWidth = 1280; - ScreenHeight = 720; - RunInBackground = false; - ResizableWindow = false; - ForceSingleInstance = false; - OverrideIcon = Guid::Empty; - SupportDX12 = false; - SupportDX11 = true; - SupportDX10 = false; - SupportVulkan = false; - } + /// + /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use. + /// + static WindowsPlatformSettings* Get(); + // [SettingsBase] void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override { DESERIALIZE(WindowMode); diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp index d15dd4cfa..9dabe1af0 100644 --- a/Source/Engine/Terrain/Terrain.cpp +++ b/Source/Engine/Terrain/Terrain.cpp @@ -69,7 +69,7 @@ void Terrain::UpdateLayerBits() filterData.word0 = GetLayerMask(); // Own layer mask - filterData.word1 = PhysicsSettings::Instance()->LayerMasks[GetLayer()]; + filterData.word1 = Physics::LayerMasks[GetLayer()]; // Update the shapes layer bits for (int32 pathIndex = 0; pathIndex < _patches.Count(); pathIndex++) diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 966737e95..2c3e1c837 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -66,6 +66,14 @@ namespace Flax.Build.Bindings return null; } + // Special case for Engine TEXT macro + if (value.Contains("TEXT(\"")) + return value.Replace("TEXT(\"", "(\""); + + // Special case for value constructors + if (value.Contains('(') && value.Contains(')')) + return "new " + value; + // Convert from C++ to C# switch (value) { @@ -611,6 +619,12 @@ namespace Flax.Build.Bindings contents.Append(returnValueType).Append(' ').Append(fieldInfo.Name); if (!useUnmanaged) { + if (fieldInfo.DefaultValue != null) + { + var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, fieldInfo.DefaultValue, classInfo); + if (!string.IsNullOrEmpty(defaultValue)) + contents.Append(" = ").Append(defaultValue); + } contents.AppendLine(";"); continue; } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs index b9096b3bb..c8a6a55df 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs @@ -1310,7 +1310,7 @@ namespace Flax.Build.Bindings contents.AppendLine(" }").AppendLine(); - if (!useScripting) + if (!useScripting && !classInfo.IsAbstract) { // Constructor contents.AppendLine(" static void Ctor(void* ptr)"); @@ -1350,7 +1350,14 @@ namespace Flax.Build.Bindings } else { - contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor, nullptr"); + if (classInfo.IsAbstract) + contents.Append("nullptr, nullptr, "); + else + contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor, "); + if (classInfo.BaseType != null) + contents.Append($"&{classInfo.BaseType}::TypeInitializer"); + else + contents.Append("nullptr"); } contents.Append(", ").Append(interfacesTable); contents.Append(");"); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index da337e746..916916995 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -1038,8 +1038,7 @@ namespace Flax.Build.Bindings var token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.Equal, TokenType.LeftBracket, TokenType.Colon }); if (token.Type == TokenType.Equal) { - //context.Tokenizer.SkipUntil(TokenType.SemiColon, out var defaultValue); - context.Tokenizer.SkipUntil(TokenType.SemiColon); + context.Tokenizer.SkipUntil(TokenType.SemiColon, out desc.DefaultValue); } else if (token.Type == TokenType.LeftBracket) { diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs index ea8cfb559..419820f56 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs @@ -87,6 +87,8 @@ namespace Flax.Build.Bindings if (headerFiles.Count == 0) return moduleInfo; + // TODO: use aynsc tasks or thread pool to load and parse multiple header files at once using multi-threading + // Find and load files with API tags string[] headerFilesContents = null; //using (new ProfileEventScope("LoadHeaderFiles")) @@ -94,9 +96,8 @@ namespace Flax.Build.Bindings var anyApi = false; for (int i = 0; i < headerFiles.Count; i++) { - // Skip scripting types definitions file - if (headerFiles[i].Replace('\\', '/').EndsWith("Engine/Core/Config.h", StringComparison.Ordinal) || - headerFiles[i].EndsWith("EditorContextAPI.h", StringComparison.Ordinal)) + // Skip scripting tags definitions file + if (headerFiles[i].Replace('\\', '/').EndsWith("Engine/Core/Config.h", StringComparison.Ordinal)) continue; // Check if file contains any valid API tag @@ -320,24 +321,36 @@ namespace Flax.Build.Bindings token = tokenizer.NextToken(true); while (token.Type != TokenType.Newline) { - condition += token.Value; + var tokenValue = token.Value.Trim(); + if (tokenValue.Length == 0) + { + token = tokenizer.NextToken(true); + continue; + } + + // Very simple defines processing + tokenValue = ReplacePreProcessorDefines(tokenValue, context.PreprocessorDefines.Keys); + tokenValue = ReplacePreProcessorDefines(tokenValue, moduleOptions.PublicDefinitions); + tokenValue = ReplacePreProcessorDefines(tokenValue, moduleOptions.PrivateDefinitions); + tokenValue = ReplacePreProcessorDefines(tokenValue, moduleOptions.CompileEnv.PreprocessorDefinitions); + tokenValue = tokenValue.Replace("false", "0"); + tokenValue = tokenValue.Replace("true", "1"); + tokenValue = tokenValue.Replace("||", "|"); + if (tokenValue.Length != 0 && tokenValue != "1" && tokenValue != "0" && tokenValue != "|") + tokenValue = "0"; + + condition += tokenValue; token = tokenizer.NextToken(true); } - // Replace contents with defines - condition = condition.Trim(); - condition = ReplacePreProcessorDefines(condition, context.PreprocessorDefines.Keys); - condition = ReplacePreProcessorDefines(condition, moduleOptions.PublicDefinitions); - condition = ReplacePreProcessorDefines(condition, moduleOptions.PrivateDefinitions); - condition = ReplacePreProcessorDefines(condition, moduleOptions.CompileEnv.PreprocessorDefinitions); - condition = condition.Replace("false", "0"); - condition = condition.Replace("true", "1"); + // Filter condition + condition = condition.Replace("1|1", "1"); + condition = condition.Replace("1|0", "1"); + condition = condition.Replace("0|1", "1"); - // Check condition - // TODO: support expressions in preprocessor defines in API headers? + // Skip chunk of code of condition fails if (condition != "1") { - // Skip chunk of code ParsePreprocessorIf(fileInfo, tokenizer, ref token); } @@ -404,7 +417,7 @@ namespace Flax.Build.Bindings { foreach (var define in defines) { - if (text.Contains(define)) + if (string.Equals(text, define, StringComparison.Ordinal)) text = text.Replace(define, "1"); } return text; diff --git a/Source/Tools/Flax.Build/Bindings/FieldInfo.cs b/Source/Tools/Flax.Build/Bindings/FieldInfo.cs index 509c1d6e6..b1488ed09 100644 --- a/Source/Tools/Flax.Build/Bindings/FieldInfo.cs +++ b/Source/Tools/Flax.Build/Bindings/FieldInfo.cs @@ -12,6 +12,9 @@ namespace Flax.Build.Bindings public bool NoArray; public FunctionInfo Getter; public FunctionInfo Setter; + public string DefaultValue; + + public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue); public override string ToString() { @@ -19,6 +22,8 @@ namespace Flax.Build.Bindings if (IsStatic) result += "static "; result += Type + " " + Name; + if (HasDefaultValue) + result += " = " + DefaultValue; return result; } } diff --git a/Source/Tools/Flax.Build/Build/Module.cs b/Source/Tools/Flax.Build/Build/Module.cs index dae700728..726cbf946 100644 --- a/Source/Tools/Flax.Build/Build/Module.cs +++ b/Source/Tools/Flax.Build/Build/Module.cs @@ -111,5 +111,16 @@ namespace Flax.Build // By default deploy all C++ header files files.AddRange(Directory.GetFiles(FolderPath, "*.h", SearchOption.AllDirectories)); } + + /// + /// Adds the file to the build sources if exists. + /// + /// The options. + /// The source file path. + protected void AddSourceFileIfExists(BuildOptions options, string path) + { + if (File.Exists(path)) + options.SourceFiles.Add(path); + } } }