50 Commits

Author SHA1 Message Date
43c4d45080 prog
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2026-01-05 15:01:51 +02:00
56a85f6ac0 Use float.Equals in equality checks to handle NaN cases
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2026-01-04 03:09:17 +02:00
1b8e25cb86 some 2026-01-04 02:57:02 +02:00
7088ce8742 initial nativestring and nativearray marshalling
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2026-01-03 16:00:55 +02:00
c7326ea483 _prog
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-12-27 17:59:40 +02:00
523cad3b2c Skip including known non-code subfolders from Source folder 2025-12-27 17:59:33 +02:00
ff6816396c _Formatting flags 2025-12-26 21:49:13 +02:00
24b8ad77fe Fix managed wrapper function parameter handling for BytesContainer 2025-12-23 00:36:57 +02:00
3008d8037d _unbox
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-12-21 20:17:24 +02:00
0973363c64 wip 2 no leaks 2025-12-21 17:45:46 +02:00
5d45b9ea1c Fix managed boolean array conversion to native array 2025-12-20 01:51:37 +02:00
c40f7c12f2 Fix incorrect class namespace in bindings class name lookups 2025-12-19 23:57:31 +02:00
1b2d6372b2 Fix warnings 2025-12-19 13:16:35 +02:00
0782ea889c Fix command-line parsing for SDL CreateProcess arguments 2025-12-19 13:16:35 +02:00
ef89501111 Add function for parsing command-line arguments into argument list 2025-12-19 13:16:35 +02:00
608353b996 _managed handle pool start 2025-12-19 13:14:11 +02:00
221325ef09 _freemanaged dllexport used 2025-12-19 13:14:10 +02:00
8f57c91a9e _track disabled 2025-12-19 13:14:10 +02:00
968de34cae _wip 2025-12-19 13:14:10 +02:00
6586a98f8d Ensure managed converter functions are exported with optimizations 2025-12-19 13:14:10 +02:00
b3510b0e44 Add USED attribute for forcing compiler to emit the symbol 2025-12-19 13:14:10 +02:00
d5a92c1942 Fix missing exports for managed converter structures 2025-12-19 13:14:10 +02:00
417f82826f Expose RenderContext to scripting API 2025-12-19 13:14:10 +02:00
63bed0986a Fix clang bindings code generation for non-const ref parameters 2025-12-19 13:14:10 +02:00
c40eefc79d Fix compilation errors with /permissive- standard conformance mode 2025-12-19 13:14:10 +02:00
d68631dd20 Fix Editor project file generation to use custom code editor arguments 2025-12-19 13:14:10 +02:00
e77b772010 Get code editor name through CodeEditingManager 2025-12-19 13:14:10 +02:00
e41e956386 Fix default code editor not using Visual Studio as fallback editor 2025-12-19 13:14:10 +02:00
33e47c646b Fix invalid code editor when selected editor is not detected 2025-12-19 13:14:10 +02:00
b30ce6b84f Support Visual Studio 2026 as a generator for CMake dependencies 2025-12-19 01:31:42 +02:00
02f67b25f3 Verify the last project path before using it 2025-12-19 01:31:42 +02:00
469a422681 Add -lastproject editor command-line option to open the last project 2025-12-19 01:31:41 +02:00
42fa0ffdd1 Use last opened project as initial directory in project file dialog 2025-12-19 01:31:41 +02:00
f97ee72f1c Fix SpecialFolder::AppData on Apple systems 2025-12-19 01:31:41 +02:00
89c93dd4f7 Use XDG user directories on Linux special paths 2025-12-19 01:31:40 +02:00
60cd8f702e Fix Flax C#-project launchSettings.json to launch without project 2025-12-19 01:31:40 +02:00
f376ec5c8a Launch editor when debugging C++ projects in Rider Linux/macOS 2025-12-19 01:31:40 +02:00
82bb297119 Use standard output for logging by default 2025-12-16 21:16:05 +02:00
ed994cb560 Run editor with selected project configuration in launchSettings.json 2025-12-16 21:16:05 +02:00
8efe2134f0 Fix duplicate properties for default configuration in C# projects 2025-12-16 21:16:05 +02:00
8efc4715c6 Improve Linux .NET runtime identifier detection
Use the runtime identifier detected during runtime instead of
calling the dotnet tool in order to query it.
2025-12-16 00:15:40 +02:00
48c60144ae Set C# language version to 14 with .NET 10 2025-12-16 00:15:40 +02:00
249cde467e Improve installed .NET runtime version detection 2025-12-16 00:15:40 +02:00
e2eadc87b6 Fix Editor state after loading a scene without compiled game modules 2025-12-16 00:15:40 +02:00
bc4b94d2bc Use in over ref modifier in Math functions input parameters 2025-12-16 00:15:30 +02:00
ecf074801f Fix ref usage warnings with in-parameters 2025-12-16 00:15:30 +02:00
74bac97f44 Deprecate UseFastPDBLinking
This is no longer supported in VS2026
2025-12-16 00:15:30 +02:00
d7eebb699c Pass const ref parameters as in parameters in C# bindings
_amend in parameters
2025-12-16 00:15:29 +02:00
dde07bac8d Fix mixed newline characters in generated bindings 2025-12-16 00:14:16 +02:00
5c8e593d89 Show properties without getter in generic editor 2025-12-16 00:14:16 +02:00
1161 changed files with 18489 additions and 144355 deletions

17
.github/data/bt.sh vendored
View File

@@ -1,17 +0,0 @@
#!/bin/sh
# https://gist.github.com/ongardie/aa15f1f0d0e6b59890a9
gdb -q --batch \
-ex 'handle SIGHUP nostop pass' \
-ex 'handle SIGQUIT nostop pass' \
-ex 'handle SIGPIPE nostop pass' \
-ex 'handle SIGALRM nostop pass' \
-ex 'handle SIGTERM nostop pass' \
-ex 'handle SIGUSR1 nostop pass' \
-ex 'handle SIGUSR2 nostop pass' \
-ex 'handle SIGCHLD nostop pass' \
-ex 'set print thread-events off' \
-return-child-result \
-ex 'run' \
-ex 'thread apply all bt' \
--tty=/dev/stdout \
--args $*

View File

@@ -16,8 +16,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Setup Vulkan - name: Setup Vulkan
uses: ./.github/actions/vulkan uses: ./.github/actions/vulkan
- name: Setup .NET - name: Setup .NET
@@ -45,8 +44,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev libwayland-dev
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Setup Vulkan - name: Setup Vulkan
uses: ./.github/actions/vulkan uses: ./.github/actions/vulkan
- name: Setup .NET - name: Setup .NET

View File

@@ -87,8 +87,7 @@ jobs:
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Setup Vulkan - name: Setup Vulkan
uses: ./.github/actions/vulkan uses: ./.github/actions/vulkan
- name: Setup .NET - name: Setup .NET
@@ -119,8 +118,7 @@ jobs:
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Setup Vulkan - name: Setup Vulkan
uses: ./.github/actions/vulkan uses: ./.github/actions/vulkan
- name: Setup .NET - name: Setup .NET

View File

@@ -28,23 +28,25 @@ jobs:
git lfs pull git lfs pull
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev gdb
chmod +x .github/data/bt.sh
- name: Build - name: Build
run: | run: |
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8 ./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8
./Development/Scripts/Linux/CallBuildTool.sh -build -log -dotnet=8 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true ./Development/Scripts/Linux/CallBuildTool.sh -build -log -dotnet=8 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
- name: Test - name: Test
run: | run: |
${GITHUB_WORKSPACE}/.github/data/bt.sh ./Binaries/Editor/Linux/Development/FlaxTests -headless ${GITHUB_WORKSPACE}/Binaries/Editor/Linux/Development/FlaxTests
dotnet test -f net8.0 Binaries/Tests/Flax.Build.Tests.dll dotnet test -f net8.0 Binaries/Tests/Flax.Build.Tests.dll
cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.dll Binaries/Tests cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.dll Binaries/Tests
cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.runtimeconfig.json Binaries/Tests cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.runtimeconfig.json Binaries/Tests
cp Binaries/Editor/Linux/Development/Newtonsoft.Json.dll Binaries/Tests cp Binaries/Editor/Linux/Development/Newtonsoft.Json.dll Binaries/Tests
dotnet test -f net8.0 Binaries/Tests/FlaxEngine.CSharp.dll dotnet test -f net8.0 Binaries/Tests/FlaxEngine.CSharp.dll
- name: Test UseLargeWorlds
run: |
./Development/Scripts/Linux/CallBuildTool.sh -build -log -dotnet=8 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true
${GITHUB_WORKSPACE}/Binaries/Editor/Linux/Development/FlaxTests
# Tests on Windows # Tests on Windows
tests-windows: tests-windows:
@@ -74,7 +76,7 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
.\Binaries\Editor\Win64\Development\FlaxTests.exe -headless .\Binaries\Editor\Win64\Development\FlaxTests.exe
if(!$?) { Write-Host "Tests failed with exit code $LastExitCode" -ForegroundColor Red; Exit $LastExitCode } if(!$?) { Write-Host "Tests failed with exit code $LastExitCode" -ForegroundColor Red; Exit $LastExitCode }
dotnet test -f net8.0 Binaries\Tests\Flax.Build.Tests.dll dotnet test -f net8.0 Binaries\Tests\Flax.Build.Tests.dll
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server # Redirect to our own Git LFS server
[lfs] [lfs]
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs" url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false locksverify = false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -42,10 +42,10 @@ struct MaterialInput
float2 SvPositionToDecalUV(float4 svPosition) float2 SvPositionToDecalUV(float4 svPosition)
{ {
float2 screenUV = svPosition.xy * ScreenSize.zw; float2 screenUV = svPosition.xy * ScreenSize.zw;
svPosition.z = SAMPLE_RT_DEPTH(DepthBuffer, screenUV); svPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = PROJECT_POINT(float4(svPosition.xyz, 1), SvPositionToWorld); float4 positionHS = mul(float4(svPosition.xyz, 1), SvPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w; float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = PROJECT_POINT(float4(positionWS, 1), InvWorld).xyz; float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
return positionOS.xz + 0.5f; return positionOS.xz + 0.5f;
} }
@@ -182,10 +182,10 @@ META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
void VS_Decal(in float3 Position : POSITION0, out float4 SvPosition : SV_Position) void VS_Decal(in float3 Position : POSITION0, out float4 SvPosition : SV_Position)
{ {
// Compute world space vertex position // Compute world space vertex position
float3 worldPosition = PROJECT_POINT(float4(Position.xyz, 1), WorldMatrix).xyz; float3 worldPosition = mul(float4(Position.xyz, 1), WorldMatrix).xyz;
// Compute clip space position // Compute clip space position
SvPosition = PROJECT_POINT(float4(worldPosition.xyz, 1), ViewProjectionMatrix); SvPosition = mul(float4(worldPosition.xyz, 1), ViewProjectionMatrix);
} }
// Pixel Shader function for decals rendering // Pixel Shader function for decals rendering
@@ -213,11 +213,11 @@ void PS_Decal(
} }
float2 screenUV = SvPosition.xy * ScreenSize.zw; float2 screenUV = SvPosition.xy * ScreenSize.zw;
SvPosition.z = SAMPLE_RT_DEPTH(DepthBuffer, screenUV); SvPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = PROJECT_POINT(float4(SvPosition.xyz, 1), SvPositionToWorld); float4 positionHS = mul(float4(SvPosition.xyz, 1), SvPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w; float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = PROJECT_POINT(float4(positionWS, 1), InvWorld).xyz; float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
clip(0.5 - abs(positionOS.xyz)); clip(0.5 - abs(positionOS.xyz));
float2 decalUVs = positionOS.xz + 0.5f; float2 decalUVs = positionOS.xz + 0.5f;

View File

@@ -308,7 +308,7 @@ VertexOutput VS_SplineModel(ModelInput input)
world = mul(world, WorldMatrix); world = mul(world, WorldMatrix);
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.Geometry.TexCoord = input.TexCoord0; output.Geometry.TexCoord = input.TexCoord0;
@@ -338,7 +338,7 @@ VertexOutput VS_SplineModel(ModelInput input)
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset; output.Geometry.WorldPosition += material.PositionOffset;
output.Geometry.PrevWorldPosition += material.PositionOffset; output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif #endif
// Get tessalation multiplier (per vertex) // Get tessalation multiplier (per vertex)

View File

@@ -4,8 +4,8 @@
#define MAX_LOCAL_LIGHTS 4 #define MAX_LOCAL_LIGHTS 4
@1// Forward Shading: Includes @1// Forward Shading: Includes
#include "./Flax/LightingCommon.hlsl" #include "./Flax/LightingCommon.hlsl"
#include "./Flax/ReflectionsCommon.hlsl"
#if USE_REFLECTIONS #if USE_REFLECTIONS
#include "./Flax/ReflectionsCommon.hlsl"
#define MATERIAL_REFLECTIONS_SSR 1 #define MATERIAL_REFLECTIONS_SSR 1
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR #if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
#include "./Flax/SSR.hlsl" #include "./Flax/SSR.hlsl"
@@ -14,13 +14,11 @@
#include "./Flax/Lighting.hlsl" #include "./Flax/Lighting.hlsl"
#include "./Flax/ShadowsSampling.hlsl" #include "./Flax/ShadowsSampling.hlsl"
#include "./Flax/ExponentialHeightFog.hlsl" #include "./Flax/ExponentialHeightFog.hlsl"
#include "./Flax/VolumetricFog.hlsl"
@2// Forward Shading: Constants @2// Forward Shading: Constants
LightData DirectionalLight; LightData DirectionalLight;
LightData SkyLight; LightData SkyLight;
EnvProbeData EnvironmentProbe; ProbeData EnvironmentProbe;
ExponentialHeightFogData ExponentialHeightFog; ExponentialHeightFogData ExponentialHeightFog;
VolumetricFogData VolumetricFog;
float3 Dummy2; float3 Dummy2;
uint LocalLightsCount; uint LocalLightsCount;
LightData LocalLights[MAX_LOCAL_LIGHTS]; LightData LocalLights[MAX_LOCAL_LIGHTS];
@@ -30,14 +28,12 @@ TextureCube SkyLightTexture : register(t__SRV__);
Buffer<float4> ShadowsBuffer : register(t__SRV__); Buffer<float4> ShadowsBuffer : register(t__SRV__);
Texture2D<float> ShadowMap : register(t__SRV__); Texture2D<float> ShadowMap : register(t__SRV__);
Texture3D VolumetricFogTexture : register(t__SRV__); Texture3D VolumetricFogTexture : register(t__SRV__);
Texture2D PreIntegratedGF : register(t__SRV__);
@4// Forward Shading: Utilities @4// Forward Shading: Utilities
// Public accessors for lighting data, use them as data binding might change but those methods will remain. // Public accessors for lighting data, use them as data binding might change but those methods will remain.
LightData GetDirectionalLight() { return DirectionalLight; } LightData GetDirectionalLight() { return DirectionalLight; }
LightData GetSkyLight() { return SkyLight; } LightData GetSkyLight() { return SkyLight; }
EnvProbeData GetEnvironmentProbe() { return EnvironmentProbe; } ProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; } ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
VolumetricFogData GetVolumetricFog() { return VolumetricFog; }
uint GetLocalLightsCount() { return LocalLightsCount; } uint GetLocalLightsCount() { return LocalLightsCount; }
LightData GetLocalLight(uint i) { return LocalLights[i]; } LightData GetLocalLight(uint i) { return LocalLights[i]; }
@5// Forward Shading: Shaders @5// Forward Shading: Shaders
@@ -112,8 +108,7 @@ void PS_Forward(
// Calculate reflections // Calculate reflections
#if USE_REFLECTIONS #if USE_REFLECTIONS
float4 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness); float3 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness).rgb;
reflections.rgb *= reflections.a;
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR #if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
// Screen Space Reflections // Screen Space Reflections
@@ -121,7 +116,7 @@ void PS_Forward(
Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR; Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR;
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw; float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
float stepSize = ScreenSize.z; // 1 / screenWidth float stepSize = ScreenSize.z; // 1 / screenWidth
float maxSamples = 50; float maxSamples = 48;
float worldAntiSelfOcclusionBias = 0.1f; float worldAntiSelfOcclusionBias = 0.1f;
float brdfBias = 0.82f; float brdfBias = 0.82f;
float drawDistance = 5000.0f; float drawDistance = 5000.0f;
@@ -129,7 +124,7 @@ void PS_Forward(
if (hit.z > 0) if (hit.z > 0)
{ {
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
reflections.rgb = lerp(reflections.rgb, screenColor, hit.z); reflections = lerp(reflections, screenColor, hit.z);
} }
// Fallback to software tracing if possible // Fallback to software tracing if possible
@@ -141,17 +136,17 @@ void PS_Forward(
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas)) if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
{ {
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
reflections.rgb = lerp(surfaceAtlas, float4(screenColor, 1), hit.z); reflections = lerp(surfaceAtlas, float4(screenColor, 1), hit.z);
} }
} }
#endif #endif
#endif #endif
light.rgb += reflections.rgb * GetReflectionSpecularLighting(PreIntegratedGF, ViewPos, gBuffer); light.rgb += reflections * GetReflectionSpecularLighting(ViewPos, gBuffer) * light.a;
#endif #endif
// Add lighting // Add lighting (apply ambient occlusion)
output.rgb += light.rgb; output.rgb += light.rgb * gBuffer.AO;
#endif #endif
@@ -163,13 +158,17 @@ void PS_Forward(
#else #else
float fogSceneDistance = gBuffer.ViewPos.z; float fogSceneDistance = gBuffer.ViewPos.z;
#endif #endif
float fogSkipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0); float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, fogSceneDistance);
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, fogSkipDistance, fogSceneDistance);
if (ExponentialHeightFog.VolumetricFogMaxDistance > 0) if (ExponentialHeightFog.VolumetricFogMaxDistance > 0)
{ {
// Sample volumetric fog and mix it in // Sample volumetric fog and mix it in
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw; float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
float4 volumetricFog = SampleVolumetricFog(VolumetricFogTexture, VolumetricFog, materialInput.WorldPosition - ViewPos, screenUV, TemporalAAJitter); float3 viewVector = materialInput.WorldPosition - ViewPos;
float sceneDepth = length(viewVector);
float depthSlice = sceneDepth / ExponentialHeightFog.VolumetricFogMaxDistance;
float3 volumeUV = float3(screenUV, depthSlice);
float4 volumetricFog = VolumetricFogTexture.SampleLevel(SamplerLinearClamp, volumeUV, 0);
fog = CombineVolumetricFog(fog, volumetricFog); fog = CombineVolumetricFog(fog, volumetricFog);
} }

View File

@@ -67,7 +67,7 @@ float Rand(inout uint seed)
float3 ReprojectPosition(float2 uv, float rawDepth) float3 ReprojectPosition(float2 uv, float rawDepth)
{ {
uv = uv * float2(2.0, -2.0) + float2(-1.0, 1.0); uv = uv * float2(2.0, -2.0) + float2(-1.0, 1.0);
float4 pos = PROJECT_POINT(float4(uv.x, uv.y, rawDepth, 1.0f), InvViewProjectionMatrix); float4 pos = mul(float4(uv.x, uv.y, rawDepth, 1.0f), InvViewProjectionMatrix);
return pos.xyz / pos.w; return pos.xyz / pos.w;
} }
@@ -158,7 +158,7 @@ void SpawnParticle(Context context)
@4} @4}
// Main entry point for the particles simulation and spawning // Main entry point for the particles simulation and spawning
META_CS(true, AUTO) META_CS(true, FEATURE_LEVEL_SM5)
[numthreads(THREAD_GROUP_SIZE, 1, 1)] [numthreads(THREAD_GROUP_SIZE, 1, 1)]
void CS_Main(uint3 dispatchThreadId : SV_DispatchThreadID) void CS_Main(uint3 dispatchThreadId : SV_DispatchThreadID)
{ {

View File

@@ -38,7 +38,6 @@ struct VertexOutput
#endif #endif
float4 ClipExtents : TEXCOORD3; float4 ClipExtents : TEXCOORD3;
float2 ClipOrigin : TEXCOORD4; float2 ClipOrigin : TEXCOORD4;
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
#if USE_CUSTOM_VERTEX_INTERPOLATORS #if USE_CUSTOM_VERTEX_INTERPOLATORS
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
#endif #endif
@@ -56,7 +55,6 @@ struct PixelInput
#endif #endif
float4 ClipExtents : TEXCOORD3; float4 ClipExtents : TEXCOORD3;
float2 ClipOrigin : TEXCOORD4; float2 ClipOrigin : TEXCOORD4;
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
#if USE_CUSTOM_VERTEX_INTERPOLATORS #if USE_CUSTOM_VERTEX_INTERPOLATORS
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
#endif #endif
@@ -69,7 +67,6 @@ struct MaterialInput
float3 WorldPosition; float3 WorldPosition;
float TwoSidedSign; float TwoSidedSign;
float2 TexCoord; float2 TexCoord;
float2 CustomData; // x-per-geometry type, y-features mask
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
half4 VertexColor; half4 VertexColor;
#endif #endif
@@ -87,7 +84,6 @@ MaterialInput GetMaterialInput(Render2DVertex input, VertexOutput output)
MaterialInput result; MaterialInput result;
result.WorldPosition = output.WorldPosition; result.WorldPosition = output.WorldPosition;
result.TexCoord = output.TexCoord; result.TexCoord = output.TexCoord;
result.CustomData = input.CustomDataAndClipOrigin.xy;
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
result.VertexColor = output.VertexColor; result.VertexColor = output.VertexColor;
#endif #endif
@@ -107,7 +103,6 @@ MaterialInput GetMaterialInput(PixelInput input)
MaterialInput result; MaterialInput result;
result.WorldPosition = input.WorldPosition; result.WorldPosition = input.WorldPosition;
result.TexCoord = input.TexCoord; result.TexCoord = input.TexCoord;
result.CustomData = input.CustomData;
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
result.VertexColor = input.VertexColor; result.VertexColor = input.VertexColor;
#endif #endif
@@ -227,14 +222,13 @@ VertexOutput VS_GUI(Render2DVertex input)
if ((int)input.CustomDataAndClipOrigin.y & 1) if ((int)input.CustomDataAndClipOrigin.y & 1)
input.Position = (int2)input.Position; input.Position = (int2)input.Position;
output.Position = PROJECT_POINT(float4(input.Position, 0, 1), ViewProjectionMatrix); output.Position = mul(float4(input.Position, 0, 1), ViewProjectionMatrix);
output.WorldPosition = mul(float4(input.Position, 0, 1), WorldMatrix).xyz; output.WorldPosition = mul(float4(input.Position, 0, 1), WorldMatrix).xyz;
output.TexCoord = input.TexCoord; output.TexCoord = input.TexCoord;
output.WindowPos = input.Position; output.WindowPos = input.Position;
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
output.VertexColor = input.Color; output.VertexColor = input.Color;
#endif #endif
output.CustomData = input.CustomDataAndClipOrigin.xy;
output.ClipOrigin = input.CustomDataAndClipOrigin.zw; output.ClipOrigin = input.CustomDataAndClipOrigin.zw;
output.ClipExtents = input.ClipExtents; output.ClipExtents = input.ClipExtents;

View File

@@ -393,7 +393,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
output.WorldPosition = position + spriteVertexPosition; output.WorldPosition = position + spriteVertexPosition;
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.TexCoord = input.TexCoord; output.TexCoord = input.TexCoord;
@@ -431,7 +431,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
// Apply world position offset per-vertex // Apply world position offset per-vertex
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset; output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif #endif
// Copy interpolants for other shader stages // Copy interpolants for other shader stages
@@ -511,7 +511,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
output.WorldPosition = mul(float4(input.Position, 1), world).xyz; output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.TexCoord = input.TexCoord0; output.TexCoord = input.TexCoord0;
@@ -549,7 +549,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
// Apply world position offset per-vertex // Apply world position offset per-vertex
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset; output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif #endif
// Copy interpolants for other shader stages // Copy interpolants for other shader stages
@@ -617,7 +617,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
output.WorldPosition = position + tangentRight * vertexSign * (ribbonWidth.xxx * 0.5f); output.WorldPosition = position + tangentRight * vertexSign * (ribbonWidth.xxx * 0.5f);
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.ParticleIndex = particleIndex; output.ParticleIndex = particleIndex;
@@ -655,7 +655,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
// Apply world position offset per-vertex // Apply world position offset per-vertex
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset; output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif #endif
// Copy interpolants for other shader stages // Copy interpolants for other shader stages

View File

@@ -342,7 +342,7 @@ VertexOutput VS(ModelInput input)
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), object.PrevWorldMatrix).xyz; output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), object.PrevWorldMatrix).xyz;
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1); output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
@@ -378,7 +378,7 @@ VertexOutput VS(ModelInput input)
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset; output.Geometry.WorldPosition += material.PositionOffset;
output.Geometry.PrevWorldPosition += material.PositionOffset; output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif #endif
// Get tessalation multiplier (per vertex) // Get tessalation multiplier (per vertex)
@@ -412,7 +412,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
// Transform vertex position into the screen // Transform vertex position into the screen
float3 worldPosition = mul(float4(input.Position.xyz, 1), object.WorldMatrix).xyz; float3 worldPosition = mul(float4(input.Position.xyz, 1), object.WorldMatrix).xyz;
float4 position = PROJECT_POINT(float4(worldPosition, 1), ViewProjectionMatrix); float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
return position; return position;
} }
@@ -518,7 +518,7 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
#endif #endif
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1); output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
@@ -549,7 +549,7 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset; output.Geometry.WorldPosition += material.PositionOffset;
output.Geometry.PrevWorldPosition += material.PositionOffset; output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif #endif
// Get tessalation multiplier (per vertex) // Get tessalation multiplier (per vertex)

View File

@@ -388,7 +388,7 @@ VertexOutput VS(TerrainVertexInput input)
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz; output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
// Compute clip space position // Compute clip space position
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes // Pass vertex attributes
#if USE_SMOOTH_LOD_TRANSITION #if USE_SMOOTH_LOD_TRANSITION
@@ -436,7 +436,7 @@ VertexOutput VS(TerrainVertexInput input)
// Apply world position offset per-vertex // Apply world position offset per-vertex
#if USE_POSITION_OFFSET #if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset; output.Geometry.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif #endif
// Get tessalation multiplier (per vertex) // Get tessalation multiplier (per vertex)

View File

@@ -8,7 +8,6 @@
#include "./Flax/Common.hlsl" #include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl" #include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.hlsl" #include "./Flax/GBufferCommon.hlsl"
#include "./Flax/VolumetricFog.hlsl"
@7 @7
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
@@ -22,7 +21,6 @@ float Dummy0;
float VolumetricFogMaxDistance; float VolumetricFogMaxDistance;
int ParticleStride; int ParticleStride;
int ParticleIndex; int ParticleIndex;
float4 GridSliceParameters;
@1META_CB_END @1META_CB_END
// Particles attributes buffer // Particles attributes buffer
@@ -204,19 +202,19 @@ Material GetMaterialPS(MaterialInput input)
META_PS(true, FEATURE_LEVEL_SM5) META_PS(true, FEATURE_LEVEL_SM5)
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1) void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
{ {
// Reproject grid position back to the screen and world space
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex); uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
float3 cellOffset = 0.5f; float3 cellOffset = 0.5f;
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy; float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
float sceneDepth = GetDepthFromSlice(GridSliceParameters, gridCoordinate.z + cellOffset.z) / ViewFar; float zSlice = gridCoordinate.z + cellOffset.z;
float sceneDepth = (zSlice / GridSize.z) * VolumetricFogMaxDistance / ViewFar;
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z; float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0); float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix); float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
wsPos.xyz /= wsPos.w; float3 positionWS = wsPos.xyz / wsPos.w;
// Get material parameters // Get material parameters
MaterialInput materialInput = (MaterialInput)0; MaterialInput materialInput = (MaterialInput)0;
materialInput.WorldPosition = wsPos.xyz; materialInput.WorldPosition = positionWS;
materialInput.TexCoord = input.Vertex.TexCoord; materialInput.TexCoord = input.Vertex.TexCoord;
materialInput.ParticleIndex = ParticleIndex; materialInput.ParticleIndex = ParticleIndex;
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
@@ -227,10 +225,9 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
Material material = GetMaterialPS(materialInput); Material material = GetMaterialPS(materialInput);
// Compute fog properties // Compute fog properties
material.Opacity *= material.Mask;
float3 albedo = material.Color; float3 albedo = material.Color;
float extinction = material.Opacity * 0.001f; float extinction = material.Opacity * material.Mask * 0.001f;
float3 emission = material.Emissive * material.Opacity; float3 emission = material.Emissive;
float3 scattering = albedo * extinction; float3 scattering = albedo * extinction;
float absorption = max(0.0f, extinction - Luminance(scattering)); float absorption = max(0.0f, extinction - Luminance(scattering));

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:615dff65b01507be6c4de722e126324aba20fc197f8e12dafaa94a05e46cba6e oid sha256:0f34bf867df5f4296ca66ac691c2bca4efa168fb9e21ca4e613e8086669575cf
size 13222 size 13296

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:706adde844360c2b0e65ecabaf1d2e2cc4eb4ac7ca9d483d0dd04ec8163b3d97 oid sha256:872ac3560279bfd0aeb989ebac1b49750dd142b985bc40058888dfd2b63fe9b2
size 13081 size 13214

View File

@@ -2,12 +2,12 @@
"Name": "Flax", "Name": "Flax",
"Version": { "Version": {
"Major": 1, "Major": 1,
"Minor": 12, "Minor": 11,
"Revision": 0, "Revision": 0,
"Build": 6908 "Build": 6805
}, },
"Company": "Flax", "Company": "Flax",
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.", "Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
"GameTarget": "FlaxGame", "GameTarget": "FlaxGame",
"EditorTarget": "FlaxEditor", "EditorTarget": "FlaxEditor",
"Configuration": { "Configuration": {

View File

@@ -188,7 +188,7 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String> <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String> <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>

View File

@@ -15,7 +15,7 @@ if errorlevel 1 goto BuildToolFailed
:: Build bindings for all editor configurations :: Build bindings for all editor configurations
echo Building C# bindings... echo Building C# bindings...
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor,FlaxGame
popd popd
echo Done! echo Done!

View File

@@ -187,11 +187,6 @@ namespace FlaxEditor.Content.Import
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular // Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
_settings.Settings.Type = TextureFormatType.GrayScale; _settings.Settings.Type = TextureFormatType.GrayScale;
} }
else if (_settings.Settings.Type == TextureFormatType.ColorRGB)
{
// Blind guess that common color texture is sRGB
_settings.Settings.sRGB = true;
}
// Try to restore target asset texture import options (useful for fast reimport) // Try to restore target asset texture import options (useful for fast reimport)
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl); Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);

View File

@@ -749,7 +749,7 @@ namespace FlaxEditor.Content
} }
// Draw short name // Draw short name
Render2D.PushClip(ref textRect); Render2D.PushClip(textRect);
var scale = 0.95f * view.ViewScale; var scale = 0.95f * view.ViewScale;
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale); Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale);
Render2D.PopClip(); Render2D.PopClip();

View File

@@ -45,8 +45,6 @@ namespace FlaxEditor.Content.Thumbnails
{ {
if (item == null) if (item == null)
throw new ArgumentNullException(); throw new ArgumentNullException();
if (_task == null)
return;
// Check if use default icon // Check if use default icon
var defaultThumbnail = item.DefaultThumbnail; var defaultThumbnail = item.DefaultThumbnail;
@@ -225,12 +223,11 @@ namespace FlaxEditor.Content.Thumbnails
/// <inheritdoc /> /// <inheritdoc />
public override void OnInit() public override void OnInit()
{ {
if (Editor.IsHeadlessMode || (GPUDevice.Instance != null && GPUDevice.Instance.RendererType == RendererType.Null))
return;
// Create cache folder // Create cache folder
if (!Directory.Exists(_cacheFolder)) if (!Directory.Exists(_cacheFolder))
{
Directory.CreateDirectory(_cacheFolder); Directory.CreateDirectory(_cacheFolder);
}
// Find atlases in a Editor cache directory // Find atlases in a Editor cache directory
var files = Directory.GetFiles(_cacheFolder, "cache_*.flax", SearchOption.TopDirectoryOnly); var files = Directory.GetFiles(_cacheFolder, "cache_*.flax", SearchOption.TopDirectoryOnly);
@@ -266,7 +263,7 @@ namespace FlaxEditor.Content.Thumbnails
// Create render task but disabled for now // Create render task but disabled for now
_output = GPUDevice.Instance.CreateTexture("ThumbnailsOutput"); _output = GPUDevice.Instance.CreateTexture("ThumbnailsOutput");
var desc = GPUTextureDescription.New2D(PreviewsCache.AssetIconSize, PreviewsCache.AssetIconSize, PreviewsCache.AssetIconsAtlasFormat); var desc = GPUTextureDescription.New2D(PreviewsCache.AssetIconSize, PreviewsCache.AssetIconSize, PreviewsCache.AssetIconsAtlasFormat);
_output.Init(ref desc); _output.Init(desc);
_task = Object.New<RenderTask>(); _task = Object.New<RenderTask>();
_task.Order = 50; // Render this task later _task.Order = 50; // Render this task later
_task.Enabled = false; _task.Enabled = false;
@@ -485,7 +482,7 @@ namespace FlaxEditor.Content.Thumbnails
public override void OnUpdate() public override void OnUpdate()
{ {
// Wait some frames before start generating previews (late init feature) // Wait some frames before start generating previews (late init feature)
if (Time.TimeSinceStartup < 1.0f || HasAllAtlasesLoaded() == false || _task == null) if (Time.TimeSinceStartup < 1.0f || HasAllAtlasesLoaded() == false)
return; return;
lock (_requests) lock (_requests)

View File

@@ -141,11 +141,6 @@ API_ENUM() enum class BuildPlatform
/// </summary> /// </summary>
API_ENUM(Attributes="EditorDisplay(null, \"Windows ARM64\")") API_ENUM(Attributes="EditorDisplay(null, \"Windows ARM64\")")
WindowsARM64 = 15, WindowsARM64 = 15,
/// <summary>
/// Web
/// </summary>
Web = 16,
}; };
/// <summary> /// <summary>
@@ -193,11 +188,6 @@ enum class DotNetAOTModes
/// Use Mono AOT to cross-compile all used C# assemblies into native platform static libraries which can be linked into a single shared library. /// Use Mono AOT to cross-compile all used C# assemblies into native platform static libraries which can be linked into a single shared library.
/// </summary> /// </summary>
MonoAOTStatic, MonoAOTStatic,
/// <summary>
/// Target platform doesn't support .NET or it has been disabled.
/// </summary>
NoDotnet,
}; };
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform); extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);

View File

@@ -69,10 +69,6 @@
#include "Platform/iOS/iOSPlatformTools.h" #include "Platform/iOS/iOSPlatformTools.h"
#include "Engine/Platform/iOS/iOSPlatformSettings.h" #include "Engine/Platform/iOS/iOSPlatformSettings.h"
#endif #endif
#if PLATFORM_TOOLS_WEB
#include "Platform/Web/WebPlatformTools.h"
#include "Engine/Platform/Web/WebPlatformSettings.h"
#endif
namespace GameCookerImpl namespace GameCookerImpl
{ {
@@ -155,8 +151,6 @@ const Char* ToString(const BuildPlatform platform)
return TEXT("iOS ARM64"); return TEXT("iOS ARM64");
case BuildPlatform::WindowsARM64: case BuildPlatform::WindowsARM64:
return TEXT("Windows ARM64"); return TEXT("Windows ARM64");
case BuildPlatform::Web:
return TEXT("Web");
default: default:
return TEXT(""); return TEXT("");
} }
@@ -189,8 +183,6 @@ const Char* ToString(const DotNetAOTModes mode)
return TEXT("MonoAOTDynamic"); return TEXT("MonoAOTDynamic");
case DotNetAOTModes::MonoAOTStatic: case DotNetAOTModes::MonoAOTStatic:
return TEXT("MonoAOTStatic"); return TEXT("MonoAOTStatic");
case DotNetAOTModes::NoDotnet:
return TEXT("NoDotnet");
default: default:
return TEXT(""); return TEXT("");
} }
@@ -315,10 +307,6 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
platform = TEXT("Windows"); platform = TEXT("Windows");
architecture = TEXT("ARM64"); architecture = TEXT("ARM64");
break; break;
case BuildPlatform::Web:
platform = TEXT("Web");
architecture = TEXT("x86");
break;
default: default:
LOG(Fatal, "Unknown or unsupported build platform."); LOG(Fatal, "Unknown or unsupported build platform.");
} }
@@ -473,11 +461,6 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
case BuildPlatform::iOSARM64: case BuildPlatform::iOSARM64:
result = New<iOSPlatformTools>(); result = New<iOSPlatformTools>();
break; break;
#endif
#if PLATFORM_TOOLS_WEB
case BuildPlatform::Web:
result = New<WebPlatformTools>();
break;
#endif #endif
} }
Tools.Add(platform, result); Tools.Add(platform, result);
@@ -621,9 +604,6 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
case PlatformType::iOS: case PlatformType::iOS:
buildPlatform = BuildPlatform::iOSARM64; buildPlatform = BuildPlatform::iOSARM64;
break; break;
case PlatformType::Web:
buildPlatform = BuildPlatform::Web;
break;
default: ; default: ;
} }
} }

View File

@@ -106,7 +106,6 @@ namespace FlaxEditor
case BuildPlatform.MacOSARM64: case BuildPlatform.MacOSARM64:
case BuildPlatform.MacOSx64: return PlatformType.Mac; case BuildPlatform.MacOSx64: return PlatformType.Mac;
case BuildPlatform.iOSARM64: return PlatformType.iOS; case BuildPlatform.iOSARM64: return PlatformType.iOS;
case BuildPlatform.Web: return PlatformType.Web;
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null); default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
} }
} }

View File

@@ -138,7 +138,6 @@ Array<byte> AndroidPlatformTools::SaveCache(CookingData& data, IBuildCache* cach
result.Add((const byte*)&platformCache, sizeof(platformCache)); result.Add((const byte*)&platformCache, sizeof(platformCache));
return result; return result;
} }
void AndroidPlatformTools::OnBuildStarted(CookingData& data) void AndroidPlatformTools::OnBuildStarted(CookingData& data)
{ {
// Adjust the cooking output folder to be located inside the Gradle assets directory // Adjust the cooking output folder to be located inside the Gradle assets directory
@@ -413,6 +412,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
} }
LOG(Info, "Output Android APK application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024); LOG(Info, "Output Android APK application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
return false; return false;
} }

View File

@@ -1,271 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
#if PLATFORM_TOOLS_WEB
#include "WebPlatformTools.h"
#include "Engine/Platform/File.h"
#include "Engine/Platform/FileSystem.h"
#include "Engine/Platform/CreateProcessSettings.h"
#include "Engine/Platform/Web/WebPlatformSettings.h"
#include "Engine/Core/Types/Span.h"
#include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Config/GameSettings.h"
#include "Engine/Core/Config/BuildSettings.h"
#include "Engine/Content/Content.h"
#include "Engine/Content/JsonAsset.h"
#include "Engine/Graphics/PixelFormatExtensions.h"
#include "Engine/Graphics/Textures/TextureBase.h"
#include "Editor/Cooker/GameCooker.h"
IMPLEMENT_SETTINGS_GETTER(WebPlatformSettings, WebPlatform);
namespace
{
struct WebPlatformCache
{
WebPlatformSettings::TextureCompression TexturesCompression;
};
}
const Char* WebPlatformTools::GetDisplayName() const
{
return TEXT("Web");
}
const Char* WebPlatformTools::GetName() const
{
return TEXT("Web");
}
PlatformType WebPlatformTools::GetPlatform() const
{
return PlatformType::Web;
}
ArchitectureType WebPlatformTools::GetArchitecture() const
{
return ArchitectureType::x86;
}
DotNetAOTModes WebPlatformTools::UseAOT() const
{
return DotNetAOTModes::MonoAOTDynamic;//MonoAOTStatic;// DotNetAOTModes::None;//DotNetAOTModes::MonoAOTStatic;//DotNetAOTModes::NoDotnet;
}
PixelFormat WebPlatformTools::GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format)
{
const auto platformSettings = WebPlatformSettings::Get();
const auto uncompressed = PixelFormatExtensions::FindUncompressedFormat(format);
switch (platformSettings->TexturesCompression)
{
case WebPlatformSettings::TextureCompression::Uncompressed:
return uncompressed;
case WebPlatformSettings::TextureCompression::BC:
return format;
case WebPlatformSettings::TextureCompression::ASTC:
switch (format)
{
case PixelFormat::BC4_SNorm:
return PixelFormat::R8_SNorm;
case PixelFormat::BC5_SNorm:
return PixelFormat::R16G16_SNorm;
case PixelFormat::BC6H_Typeless:
case PixelFormat::BC6H_Uf16:
case PixelFormat::BC6H_Sf16:
case PixelFormat::BC7_Typeless:
case PixelFormat::BC7_UNorm:
case PixelFormat::BC7_UNorm_sRGB:
return PixelFormat::R16G16B16A16_Float; // TODO: ASTC HDR
default:
return PixelFormatExtensions::IsSRGB(format) ? PixelFormat::ASTC_6x6_UNorm_sRGB : PixelFormat::ASTC_6x6_UNorm;
}
case WebPlatformSettings::TextureCompression::Basis:
switch (format)
{
case PixelFormat::BC7_Typeless:
case PixelFormat::BC7_UNorm:
case PixelFormat::BC7_UNorm_sRGB:
return PixelFormat::R16G16B16A16_Float; // Basic Universal doesn't support alpha in BC7 (and it can be loaded only from LDR formats)
default:
if (uncompressed != format && texture->Size().MinValue() >= 16)
return PixelFormat::Basis;
return uncompressed;
}
default:
return format;
}
}
void WebPlatformTools::LoadCache(CookingData& data, IBuildCache* cache, const Span<byte>& bytes)
{
const auto platformSettings = WebPlatformSettings::Get();
bool invalidTextures = true;
if (bytes.Length() == sizeof(WebPlatformCache))
{
auto* platformCache = (WebPlatformCache*)bytes.Get();
invalidTextures = platformCache->TexturesCompression != platformSettings->TexturesCompression;
}
if (invalidTextures)
{
LOG(Info, "{0} option has been modified.", TEXT("TexturesQuality"));
cache->InvalidateCacheTextures();
}
}
Array<byte> WebPlatformTools::SaveCache(CookingData& data, IBuildCache* cache)
{
const auto platformSettings = WebPlatformSettings::Get();
WebPlatformCache platformCache;
platformCache.TexturesCompression = platformSettings->TexturesCompression;
Array<byte> result;
result.Add((const byte*)&platformCache, sizeof(platformCache));
return result;
}
bool WebPlatformTools::IsNativeCodeFile(CookingData& data, const String& file)
{
String extension = FileSystem::GetExtension(file);
return extension.IsEmpty() || extension == TEXT("html") || extension == TEXT("js") || extension == TEXT("wasm");
}
void WebPlatformTools::OnBuildStarted(CookingData& data)
{
// Adjust the cooking output folder for the data files so file_packager tool can compress and output final data inside the cooker output folder
data.DataOutputPath = data.CacheDirectory / TEXT("Files");
}
bool WebPlatformTools::OnPostProcess(CookingData& data)
{
const auto gameSettings = GameSettings::Get();
const auto platformSettings = WebPlatformSettings::Get();
const auto platformDataPath = data.GetPlatformBinariesRoot();
// Get name of the output binary (JavaScript and WebAssembly files match)
String gameJs;
{
Array<String> files;
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*"), DirectorySearchOption::TopDirectoryOnly);
for (const String& file : files)
{
if (file.EndsWith(TEXT(".js")))
{
String outputWasm = String(StringUtils::GetPathWithoutExtension(file)) + TEXT(".wasm");
if (files.Contains(outputWasm))
{
gameJs = file;
break;
}
}
}
}
if (gameJs.IsEmpty())
{
data.Error(TEXT("Failed to find the main JavaScript for the output game"));
return true;
}
// Move .wasm assemblies into the data files in order for dlopen to work (blocking)
{
Array<String> files, files2;
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.wasm"), DirectorySearchOption::AllDirectories);
FileSystem::DirectoryGetFiles(files, data.OriginalOutputPath, TEXT("*.so"), DirectorySearchOption::AllDirectories);
StringView gameWasm = StringUtils::GetFileNameWithoutExtension(gameJs);
for (const String& file : files)
{
if (StringUtils::GetFileNameWithoutExtension(file) == gameWasm)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
for (const String& file : files2)
{
if (StringUtils::GetFileNameWithoutExtension(file) == gameWasm)
continue; // Skip the main game module
FileSystem::MoveFile(data.DataOutputPath / StringUtils::GetFileName(file), file, true);
}
}
// Pack data files into a single file using Emscripten's file_packager tool
{
CreateProcessSettings procSettings;
String emscriptenSdk = TEXT("EMSDK");
Platform::GetEnvironmentVariable(emscriptenSdk, emscriptenSdk);
procSettings.FileName = emscriptenSdk / TEXT("upstream/emscripten/tools/file_packager");
#if PLATFORM_WIN32
procSettings.FileName += TEXT(".bat");
#endif
procSettings.Arguments = String::Format(TEXT("files.data --preload \"{}@/\" --lz4 --js-output=files.js"), data.DataOutputPath);
procSettings.WorkingDirectory = data.OriginalOutputPath;
const int32 result = Platform::CreateProcess(procSettings);
if (result != 0)
{
if (!FileSystem::FileExists(procSettings.FileName))
data.Error(TEXT("Missing file_packager.bat. Ensure Emscripten SDK installation is valid and 'EMSDK' environment variable points to it."));
data.Error(String::Format(TEXT("Failed to package project files (result code: {0}). See log for more info."), result));
return true;
}
}
// Copy icon file
{
String dstIcon = data.OriginalOutputPath / TEXT("favicon.ico");
if (!FileSystem::FileExists(dstIcon))
FileSystem::CopyFile(dstIcon, platformDataPath / TEXT("favicon.ico"));
}
// TODO: customizable HTML templates
// Insert packaged file system with game data
{
String gameJsText;
if (File::ReadAllText(gameJs, gameJsText))
{
data.Error(String::Format(TEXT("Failed to load file '{}'"), gameJs));
return true;
}
const String filesIncludeBegin = TEXT("// include: files.js");
const String filesIncludeEnd = TEXT("// end include: files.js");
String fileJs = data.OriginalOutputPath / TEXT("files.js");
if (!gameJsText.Contains(filesIncludeBegin))
{
// Insert generated files.js into the main game file after the minimum_runtime_check.js include
String fileJsText;
if (File::ReadAllText(fileJs, fileJsText))
{
data.Error(String::Format(TEXT("Failed to load file '{}'"), fileJs));
return true;
}
const String insertPrefixLocation = TEXT("// end include: minimum_runtime_check.js");
int32 location = gameJsText.Find(insertPrefixLocation);
if (location != -1)
{
location += insertPrefixLocation.Length() + 1;
fileJsText = filesIncludeBegin + TEXT("\n") + fileJsText + TEXT("\n") + filesIncludeEnd + TEXT("\n");
gameJsText.Insert(location, fileJsText);
}
else
{
// Comments are missing in Release when JS/HTML are minified
fileJsText.Insert(0, filesIncludeBegin);
fileJsText.Insert(0, TEXT("\n"));
gameJsText.Insert(0, fileJsText);
}
File::WriteAllText(gameJs, gameJsText, Encoding::UTF8);
}
// Remove the generated files.js as it's now included in the main game JS file
FileSystem::DeleteFile(fileJs);
}
const auto buildSettings = BuildSettings::Get();
if (buildSettings->SkipPackaging)
return false;
GameCooker::PackageFiles();
// TODO: minify/compress output JS files (in Release builds)
LOG(Info, "Output website size: {0} MB", FileSystem::GetDirectorySize(data.OriginalOutputPath) / 1024 / 1024);
return false;
}
#endif

View File

@@ -1,29 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#if PLATFORM_TOOLS_WEB
#include "../../PlatformTools.h"
/// <summary>
/// The Web platform support tools.
/// </summary>
class WebPlatformTools : public PlatformTools
{
public:
// [PlatformTools]
const Char* GetDisplayName() const override;
const Char* GetName() const override;
PlatformType GetPlatform() const override;
ArchitectureType GetArchitecture() const override;
DotNetAOTModes UseAOT() const override;
PixelFormat GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format) override;
void LoadCache(CookingData& data, IBuildCache* cache, const Span<byte>& bytes) override;
Array<byte> SaveCache(CookingData& data, IBuildCache* cache) override;
bool IsNativeCodeFile(CookingData& data, const String& file) override;
void OnBuildStarted(CookingData& data) override;
bool OnPostProcess(CookingData& data) override;
};
#endif

View File

@@ -572,14 +572,6 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE); COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
break; break;
} }
#endif
#if PLATFORM_TOOLS_WEB
case BuildPlatform::Web:
{
const char* platformDefineName = "PLATFORM_WEB";
COMPILE_PROFILE(WebGPU, SHADER_FILE_CHUNK_INTERNAL_GENERIC_CACHE);
break;
}
#endif #endif
default: default:
{ {
@@ -742,8 +734,37 @@ bool ProcessTextureBase(CookAssetsStep::AssetCookData& data)
{ {
auto chunk = New<FlaxChunk>(); auto chunk = New<FlaxChunk>();
data.InitData.Header.Chunks[mipIndex] = chunk; data.InitData.Header.Chunks[mipIndex] = chunk;
if (TextureTool::WriteTextureData(chunk->Data, *textureData, mipIndex))
return true; // Calculate the texture data storage layout
uint32 rowPitch, slicePitch;
const int32 mipWidth = Math::Max(1, textureData->Width >> mipIndex);
const int32 mipHeight = Math::Max(1, textureData->Height >> mipIndex);
RenderTools::ComputePitch(textureData->Format, mipWidth, mipHeight, rowPitch, slicePitch);
chunk->Data.Allocate(slicePitch * textureData->GetArraySize());
// Copy array slices into mip data (sequential)
for (int32 arrayIndex = 0; arrayIndex < textureData->Items.Count(); arrayIndex++)
{
auto& mipData = textureData->Items[arrayIndex].Mips[mipIndex];
byte* src = mipData.Data.Get();
byte* dst = chunk->Data.Get() + (slicePitch * arrayIndex);
// Faster path if source and destination data layout matches
if (rowPitch == mipData.RowPitch && slicePitch == mipData.DepthPitch)
{
Platform::MemoryCopy(dst, src, slicePitch);
}
else
{
const auto copyRowSize = Math::Min(mipData.RowPitch, rowPitch);
for (uint32 line = 0; line < mipData.Lines; line++)
{
Platform::MemoryCopy(dst, src, copyRowSize);
src += mipData.RowPitch;
dst += rowPitch;
}
}
}
} }
// Clone any custom asset chunks (eg. sprite atlas data, mips are in 0-13 chunks) // Clone any custom asset chunks (eg. sprite atlas data, mips are in 0-13 chunks)

View File

@@ -39,23 +39,17 @@ bool DeployDataStep::Perform(CookingData& data)
} }
String dstDotnet = data.DataOutputPath / TEXT("Dotnet"); String dstDotnet = data.DataOutputPath / TEXT("Dotnet");
const DotNetAOTModes aotMode = data.Tools->UseAOT(); const DotNetAOTModes aotMode = data.Tools->UseAOT();
const bool usAOT = aotMode != DotNetAOTModes::None && aotMode != DotNetAOTModes::NoDotnet; const bool usAOT = aotMode != DotNetAOTModes::None;
if (usAOT) if (usAOT)
{ {
// Deploy Dotnet files into intermediate cooking directory for AOT // Deploy Dotnet files into intermediate cooking directory for AOT
FileSystem::DeleteDirectory(dstDotnet); FileSystem::DeleteDirectory(dstDotnet);
dstDotnet = data.ManagedCodeOutputPath; dstDotnet = data.ManagedCodeOutputPath;
} }
if (aotMode == DotNetAOTModes::NoDotnet) if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet())
{
// No .NET
FileSystem::DeleteDirectory(dstDotnet);
}
else if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet())
{ {
// Use system-installed .NET Runtime // Use system-installed .NET Runtime
FileSystem::DeleteDirectory(dstDotnet); FileSystem::DeleteDirectory(dstDotnet);
LOG(Info, "Not using .NET Runtime");
} }
else else
{ {

View File

@@ -12,9 +12,7 @@
void PrecompileAssembliesStep::OnBuildStarted(CookingData& data) void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
{ {
const DotNetAOTModes aotMode = data.Tools->UseAOT(); const DotNetAOTModes aotMode = data.Tools->UseAOT();
if (aotMode == DotNetAOTModes::None || if (aotMode == DotNetAOTModes::None || EnumHasAllFlags(data.Options, BuildOptions::NoCook))
aotMode == DotNetAOTModes::NoDotnet ||
EnumHasAllFlags(data.Options, BuildOptions::NoCook))
return; return;
const auto& buildSettings = *BuildSettings::Get(); const auto& buildSettings = *BuildSettings::Get();
@@ -37,8 +35,8 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
if (cachedData != aotModeCacheValue) if (cachedData != aotModeCacheValue)
{ {
LOG(Info, "AOT cache invalidation"); LOG(Info, "AOT cache invalidation");
//FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache FileSystem::DeleteDirectory(data.ManagedCodeOutputPath); // Remove AOT cache
//FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build) FileSystem::DeleteDirectory(data.DataOutputPath / TEXT("Dotnet")); // Remove deployed Dotnet libs (be sure to remove any leftovers from previous build)
} }
} }
if (!FileSystem::DirectoryExists(data.ManagedCodeOutputPath)) if (!FileSystem::DirectoryExists(data.ManagedCodeOutputPath))
@@ -51,8 +49,7 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
bool PrecompileAssembliesStep::Perform(CookingData& data) bool PrecompileAssembliesStep::Perform(CookingData& data)
{ {
const DotNetAOTModes aotMode = data.Tools->UseAOT(); const DotNetAOTModes aotMode = data.Tools->UseAOT();
if (aotMode == DotNetAOTModes::None || if (aotMode == DotNetAOTModes::None)
aotMode == DotNetAOTModes::NoDotnet)
return false; return false;
const auto& buildSettings = *BuildSettings::Get(); const auto& buildSettings = *BuildSettings::Get();
if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet()) if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet())

View File

@@ -139,7 +139,7 @@ namespace FlaxEditor.CustomEditors
return new GenericEditor(); return new GenericEditor();
} }
[LibraryImport("FlaxEngine", EntryPoint = "CustomEditorsUtilInternal_GetCustomEditor", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] [LibraryImport("FlaxEngine", EntryPoint = "CustomEditorsUtilInternal_GetCustomEditor", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.Interop.StringMarshaller))]
[return: MarshalUsing(typeof(SystemTypeMarshaller))] [return: MarshalUsing(typeof(SystemTypeMarshaller))]
internal static partial Type Internal_GetCustomEditor([MarshalUsing(typeof(SystemTypeMarshaller))] Type targetType); internal static partial Type Internal_GetCustomEditor([MarshalUsing(typeof(SystemTypeMarshaller))] Type targetType);
} }

View File

@@ -60,14 +60,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (prefab && !prefab.WaitForLoaded()) if (prefab && !prefab.WaitForLoaded())
{ {
var prefabObjectId = actor.PrefabObjectID; var prefabObjectId = actor.PrefabObjectID;
var prefabInstance = prefab.GetDefaultInstance(ref prefabObjectId); var prefabInstance = prefab.GetDefaultInstance(prefabObjectId);
if (prefabInstance != null) if (prefabInstance != null)
{ {
// Use default prefab instance as a reference for the editor // Use default prefab instance as a reference for the editor
Values.SetReferenceValue(prefabInstance); Values.SetReferenceValue(prefabInstance);
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs) // Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId); prefab.GetNestedObject(prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId); var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
var panel = layout.UniformGrid(); var panel = layout.UniformGrid();
panel.CustomControl.Height = 20.0f; panel.CustomControl.Height = 20.0f;
@@ -207,7 +207,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{ {
var actor = (Actor)Values[0]; var actor = (Actor)Values[0];
var prefabObjectId = actor.PrefabObjectID; var prefabObjectId = actor.PrefabObjectID;
var prefabInstance = prefab.GetDefaultInstance(ref prefabObjectId); var prefabInstance = prefab.GetDefaultInstance(prefabObjectId);
if (prefabInstance != null) if (prefabInstance != null)
{ {
Values.SetReferenceValue(prefabInstance); Values.SetReferenceValue(prefabInstance);
@@ -525,7 +525,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var restored = actor.AddScript(removed.PrefabObject.GetType()); var restored = actor.AddScript(removed.PrefabObject.GetType());
var prefabId = actor.PrefabID; var prefabId = actor.PrefabID;
var prefabObjectId = restored.PrefabObjectID; var prefabObjectId = restored.PrefabObjectID;
Script.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId); Script.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), prefabId, prefabObjectId);
string data = JsonSerializer.Serialize(removed.PrefabObject); string data = JsonSerializer.Serialize(removed.PrefabObject);
JsonSerializer.Deserialize(restored, data); JsonSerializer.Deserialize(restored, data);
@@ -547,7 +547,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
string data = JsonSerializer.Serialize(removedActor.PrefabObject); string data = JsonSerializer.Serialize(removedActor.PrefabObject);
JsonSerializer.Deserialize(restored, data); JsonSerializer.Deserialize(restored, data);
Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent); Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent);
Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId); Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), prefabId, prefabObjectId);
return; return;
} }

View File

@@ -21,12 +21,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (Values.HasDifferentTypes == false) if (Values.HasDifferentTypes == false)
{ {
var group = layout.Group("Probe"); var group = layout.Group("Bake");
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2); group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
_bake = group.Button("Bake").Button; _bake = group.Button("Bake").Button;
_bake.Clicked += BakeButtonClicked; _bake.Clicked += BakeButtonClicked;
var view = group.Button("View", "Opens the probe texture viewer");
view.Button.Clicked += OnViewButtonClicked;
} }
} }
@@ -52,14 +50,5 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
} }
} }
private void OnViewButtonClicked()
{
foreach (var value in Values)
{
if (value is EnvironmentProbe probe && probe.ProbeAsset)
Editor.Instance.ContentEditing.Open(probe.ProbeAsset);
}
}
} }
} }

View File

@@ -195,7 +195,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
filesCount += files.Length; filesCount += files.Length;
foreach (var file in files) foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys); FindNewKeysCpp(file, newKeys, allKeys);
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray(); files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray();;
filesCount += files.Length; filesCount += files.Length;
foreach (var file in files) foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys); FindNewKeysCpp(file, newKeys, allKeys);

View File

@@ -164,11 +164,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14); var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14);
// Deselect // Deselect
if (isSelected && button1Rect.Contains(ref location)) if (isSelected && button1Rect.Contains(location))
Value = new ModelInstanceActor.MeshReference { Actor = null, LODIndex = -1, MeshIndex = -1 }; Value = new ModelInstanceActor.MeshReference { Actor = null, LODIndex = -1, MeshIndex = -1 };
// Picker dropdown menu // Picker dropdown menu
if ((isSelected ? button2Rect : button1Rect).Contains(ref location)) if ((isSelected ? button2Rect : button1Rect).Contains(location))
ShowDropDownMenu(); ShowDropDownMenu();
return base.OnMouseUp(location, button); return base.OnMouseUp(location, button);

View File

@@ -40,7 +40,7 @@ public class ModelPrefabEditor : GenericEditor
if (prefab) if (prefab)
{ {
var prefabObjectId = modelPrefab.PrefabObjectID; var prefabObjectId = modelPrefab.PrefabObjectID;
var prefabObject = prefab.GetDefaultInstance(ref prefabObjectId); var prefabObject = prefab.GetDefaultInstance(prefabObjectId);
if (prefabObject.PrefabID == _prefabId) if (prefabObject.PrefabID == _prefabId)
break; break;
_prefabId = prefabObject.PrefabID; _prefabId = prefabObject.PrefabID;

View File

@@ -1,38 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEngine;
namespace FlaxEditor.CustomEditors.Dedicated
{
/// <summary>
/// Custom editor for <see cref="NavMeshBoundsVolume"/>.
/// </summary>
/// <seealso cref="ActorEditor" />
[CustomEditor(typeof(NavMeshBoundsVolume)), DefaultEditor]
internal class NavMeshBoundsVolumeEditor : ActorEditor
{
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
base.Initialize(layout);
if (Values.HasDifferentTypes == false)
{
var button = layout.Button("Build");
button.Button.Clicked += OnBuildClicked;
}
}
private void OnBuildClicked()
{
foreach (var value in Values)
{
if (value is NavMeshBoundsVolume volume)
{
Navigation.BuildNavMesh(volume.Box, volume.Scene);
Editor.Instance.Scene.MarkSceneEdited(volume.Scene);
}
}
}
}
}

View File

@@ -1,6 +1,7 @@
// Copyright (c) Wojciech Figat. All rights reserved. // Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Emit;
using FlaxEditor.CustomEditors.GUI; using FlaxEditor.CustomEditors.GUI;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;

View File

@@ -103,12 +103,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
var actors = ScriptsEditor.ParentEditor.Values; var actors = ScriptsEditor.ParentEditor.Values;
foreach (var a in actors) foreach (var a in actors)
{ {
if (a.GetType() == requireActor.RequiredType) if (a.GetType() != requireActor.RequiredType)
continue; {
if (requireActor.IncludeInheritedTypes && a.GetType().IsSubclassOf(requireActor.RequiredType)) item.Enabled = false;
continue; break;
item.Enabled = false; }
break;
} }
} }
cm.AddItem(item); cm.AddItem(item);
@@ -740,8 +739,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc /> /// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout) public override void Initialize(LayoutElementsContainer layout)
{ {
var style = FlaxEngine.GUI.Style.Current;
// Area for drag&drop scripts // Area for drag&drop scripts
var dragArea = layout.CustomContainer<DragAreaControl>(); var dragArea = layout.CustomContainer<DragAreaControl>();
dragArea.CustomControl.ScriptsEditor = this; dragArea.CustomControl.ScriptsEditor = this;
@@ -803,10 +800,17 @@ namespace FlaxEditor.CustomEditors.Dedicated
bool hasAllRequirements = true; bool hasAllRequirements = true;
if (scriptType.HasAttribute(typeof(RequireScriptAttribute), false)) if (scriptType.HasAttribute(typeof(RequireScriptAttribute), false))
{ {
var attribute = (RequireScriptAttribute)scriptType.GetAttributes(false).FirstOrDefault(x => x is RequireScriptAttribute); RequireScriptAttribute scriptAttribute = null;
if (attribute != null) foreach (var e in scriptType.GetAttributes(false))
{ {
foreach (var type in attribute.RequiredTypes) if (e is not RequireScriptAttribute requireScriptAttribute)
continue;
scriptAttribute = requireScriptAttribute;
}
if (scriptAttribute != null)
{
foreach (var type in scriptAttribute.RequiredTypes)
{ {
if (!type.IsSubclassOf(typeof(Script))) if (!type.IsSubclassOf(typeof(Script)))
continue; continue;
@@ -821,11 +825,19 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
if (scriptType.HasAttribute(typeof(RequireActorAttribute), false)) if (scriptType.HasAttribute(typeof(RequireActorAttribute), false))
{ {
var attribute = (RequireActorAttribute)scriptType.GetAttributes(false).FirstOrDefault(x => x is RequireActorAttribute); RequireActorAttribute attribute = null;
foreach (var e in scriptType.GetAttributes(false))
{
if (e is not RequireActorAttribute requireActorAttribute)
continue;
attribute = requireActorAttribute;
break;
}
if (attribute != null) if (attribute != null)
{ {
var actor = script.Actor; var actor = script.Actor;
if (actor.GetType() != attribute.RequiredType && (attribute.IncludeInheritedTypes && !actor.GetType().IsSubclassOf(attribute.RequiredType))) if (actor.GetType() != attribute.RequiredType && !actor.GetType().IsSubclassOf(attribute.RequiredType))
{ {
Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(scriptType.Name)}` on `{script.Actor}` is missing a required Actor of type `{attribute.RequiredType}`."); Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(scriptType.Name)}` on `{script.Actor}` is missing a required Actor of type `{attribute.RequiredType}`.");
hasAllRequirements = false; hasAllRequirements = false;
@@ -838,7 +850,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var title = Utilities.Utils.GetPropertyNameUI(scriptType.Name); var title = Utilities.Utils.GetPropertyNameUI(scriptType.Name);
var group = layout.Group(title, editor); var group = layout.Group(title, editor);
if (!hasAllRequirements) if (!hasAllRequirements)
group.Panel.HeaderTextColor = style.Statusbar.Failed; group.Panel.HeaderTextColor = FlaxEngine.GUI.Style.Current.Statusbar.Failed;
if ((Presenter.Features & FeatureFlags.CacheExpandedGroups) != 0) if ((Presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{ {
if (Editor.Instance.ProjectCache.IsGroupToggled(title)) if (Editor.Instance.ProjectCache.IsGroupToggled(title))
@@ -851,10 +863,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
group.Panel.Open(); group.Panel.Open();
// Customize // Customize
float totalHeaderButtonsOffset = 0f;
group.Panel.TooltipText = Editor.Instance.CodeDocs.GetTooltip(scriptType); group.Panel.TooltipText = Editor.Instance.CodeDocs.GetTooltip(scriptType);
if (script.HasPrefabLink) if (script.HasPrefabLink)
group.Panel.HeaderTextColor = style.ProgressNormal; group.Panel.HeaderTextColor = FlaxEngine.GUI.Style.Current.ProgressNormal;
// Add toggle button to the group // Add toggle button to the group
var headerHeight = group.Panel.HeaderHeight; var headerHeight = group.Panel.HeaderHeight;
@@ -878,7 +889,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
TooltipText = "Script reference.", TooltipText = "Script reference.",
AutoFocus = true, AutoFocus = true,
IsScrollable = false, IsScrollable = false,
Color = style.ForegroundGrey, Color = FlaxEngine.GUI.Style.Current.ForegroundGrey,
Parent = group.Panel, Parent = group.Panel,
Bounds = new Rectangle(scriptToggle.Right, 0.5f, headerHeight, headerHeight), Bounds = new Rectangle(scriptToggle.Right, 0.5f, headerHeight, headerHeight),
Margin = new Margin(1), Margin = new Margin(1),
@@ -897,35 +908,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
var settingsButton = group.AddSettingsButton(); var settingsButton = group.AddSettingsButton();
settingsButton.Tag = script; settingsButton.Tag = script;
settingsButton.Clicked += OnSettingsButtonClicked; settingsButton.Clicked += OnSettingsButtonClicked;
totalHeaderButtonsOffset += settingsButton.Width + FlaxEditor.Utilities.Constants.UIMargin;
// Add script obsolete icon to the group group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2);
if (scriptType.HasAttribute(typeof(ObsoleteAttribute), false))
{
var attribute = (ObsoleteAttribute)scriptType.GetAttributes(false).First(x => x is ObsoleteAttribute);
var tooltip = "Script marked as obsolete." +
(string.IsNullOrEmpty(attribute.Message) ? "" : $"\n{attribute.Message}") +
(string.IsNullOrEmpty(attribute.DiagnosticId) ? "" : $"\n{attribute.DiagnosticId}");
var obsoleteButton = group.AddHeaderButton(tooltip, totalHeaderButtonsOffset, Editor.Instance.Icons.Info32);
obsoleteButton.Color = Color.Orange;
obsoleteButton.MouseOverColor = Color.DarkOrange;
totalHeaderButtonsOffset += obsoleteButton.Width;
}
// Show visual indicator if script only exists in prefab instance and is not part of the prefab
bool isPrefabActor = scripts.Any(s => s.Actor.HasPrefabLink);
if (isPrefabActor && script.PrefabID == Guid.Empty)
{
var prefabInstanceButton = group.AddHeaderButton("Script only exists in this prefab instance.", totalHeaderButtonsOffset, Editor.Instance.Icons.Add32);
prefabInstanceButton.Color = style.ProgressNormal;
prefabInstanceButton.MouseOverColor = style.ProgressNormal * 0.9f;
totalHeaderButtonsOffset += prefabInstanceButton.Width;
}
// Adjust margin to not overlap with other ui elements in the header
group.Panel.HeaderTextMargin = group.Panel.HeaderTextMargin with { Left = scriptDrag.Right - 12, Right = settingsButton.Width + Utilities.Constants.UIMargin };
group.Object(values, editor); group.Object(values, editor);
// Remove drop down arrows and containment lines if no objects in the group // Remove drop down arrows and containment lines if no objects in the group
if (group.Children.Count == 0) if (group.Children.Count == 0)
{ {

View File

@@ -18,7 +18,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
public class SplineEditor : ActorEditor public class SplineEditor : ActorEditor
{ {
/// <summary> /// <summary>
/// Stores undo spline data. /// Storage undo spline data
/// </summary> /// </summary>
private struct UndoData private struct UndoData
{ {
@@ -83,7 +83,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
/// <summary> /// <summary>
/// Edit curve options manipulate the curve as free mode. /// Edit curve options manipulate the curve as free mode
/// </summary> /// </summary>
private sealed class FreeTangentMode : EditTangentOptionBase private sealed class FreeTangentMode : EditTangentOptionBase
{ {
@@ -98,7 +98,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
/// <summary> /// <summary>
/// Edit curve options to set tangents to linear. /// Edit curve options to set tangents to linear
/// </summary> /// </summary>
private sealed class LinearTangentMode : EditTangentOptionBase private sealed class LinearTangentMode : EditTangentOptionBase
{ {
@@ -107,13 +107,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
{ {
SetKeyframeLinear(spline, index); SetKeyframeLinear(spline, index);
// Change the selection to tangent parent (a spline point / keyframe) // change the selection to tangent parent (a spline point / keyframe)
Editor.SetSelectSplinePointNode(spline, index); Editor.SetSelectSplinePointNode(spline, index);
} }
} }
/// <summary> /// <summary>
/// Edit curve options to align tangents of selected spline. /// Edit curve options to align tangents of selected spline
/// </summary> /// </summary>
private sealed class AlignedTangentMode : EditTangentOptionBase private sealed class AlignedTangentMode : EditTangentOptionBase
{ {
@@ -168,7 +168,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
/// <summary> /// <summary>
/// Edit curve options manipulate the curve setting selected point tangent in as smoothed but tangent out as linear. /// Edit curve options manipulate the curve setting selected point
/// tangent in as smoothed but tangent out as linear
/// </summary> /// </summary>
private sealed class SmoothInTangentMode : EditTangentOptionBase private sealed class SmoothInTangentMode : EditTangentOptionBase
{ {
@@ -181,7 +182,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
} }
/// <summary> /// <summary>
/// Edit curve options manipulate the curve setting selected point tangent in as linear but tangent out as smoothed. /// Edit curve options manipulate the curve setting selected point
/// tangent in as linear but tangent out as smoothed
/// </summary> /// </summary>
private sealed class SmoothOutTangentMode : EditTangentOptionBase private sealed class SmoothOutTangentMode : EditTangentOptionBase
{ {
@@ -217,8 +219,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var enabled = EnabledInHierarchy && tab.EnabledInHierarchy; var enabled = EnabledInHierarchy && tab.EnabledInHierarchy;
var style = FlaxEngine.GUI.Style.Current; var style = FlaxEngine.GUI.Style.Current;
var size = Size; var size = Size;
var textHeight = 30.0f; var textHeight = 16.0f;
// Make icons smaller when tabs get thinner
var iconSize = size.Y - textHeight; var iconSize = size.Y - textHeight;
var iconRect = new Rectangle((Width - iconSize) / 2, 0, iconSize, iconSize); var iconRect = new Rectangle((Width - iconSize) / 2, 0, iconSize, iconSize);
if (tab._mirrorIcon) if (tab._mirrorIcon)
@@ -229,11 +230,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
var color = style.Foreground; var color = style.Foreground;
if (!enabled) if (!enabled)
color *= 0.6f; color *= 0.6f;
var textRect = new Rectangle(0, size.Y - textHeight, size.X, textHeight);
Render2D.PushClip(new Rectangle(Float2.Zero, Size));
Render2D.DrawSprite(tab._customIcon, iconRect, color); Render2D.DrawSprite(tab._customIcon, iconRect, color);
Render2D.DrawText(style.FontMedium, tab._customText, textRect, color, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords, 0.65f); Render2D.DrawText(style.FontMedium, tab._customText, new Rectangle(0, iconSize, size.X, textHeight), color, TextAlignment.Center, TextAlignment.Center);
Render2D.PopClip();
} }
} }
@@ -293,21 +291,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
return; return;
_selectedSpline = spline; _selectedSpline = spline;
//var tabSize = 46; layout.Space(10);
var tabSize = 60; var tabSize = 46;
var icons = Editor.Instance.Icons; var icons = Editor.Instance.Icons;
var group = layout.Group("Selected Point"); layout.Header("Selected spline point");
_selectedPointsTabs = new Tabs _selectedPointsTabs = new Tabs
{ {
Height = tabSize, Height = tabSize,
TabsSize = new Float2(tabSize), TabsSize = new Float2(tabSize),
AutoTabsSize = true, AutoTabsSize = true,
Parent = group.ContainerControl, Parent = layout.ContainerControl,
}; };
// Move the group above the group containing spline points
group.Control.IndexInParent = 3;
_linearTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedLinear, "Linear", icons.SplineLinear64)); _linearTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedLinear, "Linear", icons.SplineLinear64));
_freeTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedFree, "Free", icons.SplineFree64)); _freeTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedFree, "Free", icons.SplineFree64));
_alignedTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedAligned, "Aligned", icons.SplineAligned64)); _alignedTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedAligned, "Aligned", icons.SplineAligned64));
@@ -315,13 +310,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
_smoothOutTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedSmoothOut, "Smooth Out", icons.SplineSmoothIn64, true)); _smoothOutTangentTab = _selectedPointsTabs.AddTab(new IconTab(OnSetSelectedSmoothOut, "Smooth Out", icons.SplineSmoothIn64, true));
_selectedPointsTabs.SelectedTabIndex = -1; _selectedPointsTabs.SelectedTabIndex = -1;
group = layout.Group("All Points"); layout.Header("All spline points");
_allPointsTabs = new Tabs _allPointsTabs = new Tabs
{ {
Height = tabSize, Height = tabSize,
TabsSize = new Float2(tabSize), TabsSize = new Float2(tabSize),
AutoTabsSize = true, AutoTabsSize = true,
Parent = group.ContainerControl, Parent = layout.ContainerControl,
}; };
_setLinearAllTangentsTab = _allPointsTabs.AddTab(new IconTab(OnSetTangentsLinear, "Set Linear Tangents", icons.SplineLinear64)); _setLinearAllTangentsTab = _allPointsTabs.AddTab(new IconTab(OnSetTangentsLinear, "Set Linear Tangents", icons.SplineLinear64));
_setSmoothAllTangentsTab = _allPointsTabs.AddTab(new IconTab(OnSetTangentsSmooth, "Set Smooth Tangents", icons.SplineAligned64)); _setSmoothAllTangentsTab = _allPointsTabs.AddTab(new IconTab(OnSetTangentsSmooth, "Set Smooth Tangents", icons.SplineAligned64));

Some files were not shown because too many files have changed in this diff Show More