18 Commits

Author SHA1 Message Date
0f881fbc7a Enforce pointer alignment for InlinedAllocation
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
AssetReferences stored in inlined allocation needs to be aligned to
pointer sized boundary due to atomic operations having strict
requirements for such. Unaligned access seems to only crash on
Windows on ARM systems when trying to allocate TextRender draw chunks.
2025-10-19 22:13:40 +03:00
0898f3d020 Fix wrong build configuration used in ogg and vorbis for Windows
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-10-19 17:24:10 +03:00
c63e79efa4 Add dependency build script for Visual Studio EnvDTE 2025-10-19 13:47:58 +03:00
d0eb85c04f Add dependency build script for WinPixEventRuntime
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-10-18 04:20:58 +03:00
a7749abdcc Fix compiler error and wrong CPU architecture warnings on WoA 2025-10-18 04:20:58 +03:00
242d24d1a6 Fix building vorbis on Windows 2025-10-18 04:20:58 +03:00
853a7510f6 Check VS2026 toolset before trying to compile PhysX 2025-10-18 04:20:58 +03:00
88bd636cbe Fix building ogg+vorbis on macOS 2025-10-18 04:20:57 +03:00
65df32f5d7 Fix NvCloth compilation on Linux and macOS 2025-10-18 04:20:57 +03:00
4baa7fb7b8 Fix PhysX compilation on Linux and macOS 2025-10-18 04:20:57 +03:00
1644c9c5e0 Fix python tool call on macOS for glslang 2025-10-18 04:20:57 +03:00
e130ac7d80 Fix building PhysX on Linux and macOS 2025-10-18 04:20:56 +03:00
45e1d28ba2 Support building OpenAL from Git repository in other platforms 2025-10-18 04:20:56 +03:00
12f686262c Fix building curl on Linux 2025-10-18 02:33:54 +03:00
c76b9f206f Fix building Assimp on Linux
Versioned clang++ symlinks are not available on Arch
2025-10-18 02:33:44 +03:00
078485892f Add support for building dependencies with specific architecture 2025-10-18 02:33:22 +03:00
44b2db5d5d Fix CMake compatibility errors with dependencies 2025-10-18 02:19:57 +03:00
cc401f0316 Support Visual Studio 2026 as a generator for CMake dependencies 2025-10-18 02:19:57 +03:00
1314 changed files with 14257 additions and 152883 deletions

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please attach a minimal reproduction project if available!
Thanks for taking the time to fill out this bug report! Please attach any minimal reproduction projects!
- type: textarea
id: description-area
attributes:
@@ -17,21 +17,21 @@ body:
id: steps-area
attributes:
label: Steps to reproduce
description: Please provide reproduction steps if available.
description: Please provide reproduction steps if possible.
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
description: What version of Flax did you experience the bug in?
description: What version of Flax are you running?
options:
- '1.8'
- '1.9'
- '1.10'
- '1.11'
- '1.12'
- master branch
default: 3
default: 2
validations:
required: true
- type: textarea

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thank you for taking the time to submit this feature request!
Thanks for taking the time to fill out a feature request!
- type: textarea
id: description-area
attributes:
@@ -17,6 +17,6 @@ body:
id: benefits-area
attributes:
label: Benefits
description: Please list what benefits this feature would provide to the engine!
description: Please provide what benefits this feature would provide to the engine!
validations:
required: true

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

@@ -1,18 +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 'handle SIG34 nostop pass' \
-ex 'set print thread-events off' \
-return-child-result \
-ex 'run' \
-ex 'thread apply all bt' \
--tty=/dev/stdout \
--args $*

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -20,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Setup .NET Workload
run: |
dotnet workload install android
@@ -34,7 +33,4 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame

View File

@@ -16,8 +16,7 @@ jobs:
uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update
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
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
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -45,8 +44,7 @@ jobs:
uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update
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
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev libwayland-dev
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -20,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -31,9 +30,6 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
# Game
@@ -48,7 +44,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -59,7 +55,4 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame

View File

@@ -7,7 +7,6 @@ on:
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=1 -c lfs.transfer.maxretries=2 -c http.version="HTTP/1.1" -c lfs.activitytimeout=60'
jobs:
@@ -28,16 +27,13 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
dotnet workload --info
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output -dotnet=8
- name: Upload
uses: actions/upload-artifact@v4
@@ -64,16 +60,13 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
dotnet workload --info
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output -dotnet=8
- name: Upload
uses: actions/upload-artifact@v4
@@ -94,8 +87,7 @@ jobs:
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
- name: Install dependencies
run: |
sudo apt-get update
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
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -126,8 +118,7 @@ jobs:
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
- name: Install dependencies
run: |
sudo apt-get update
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
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
DOTNET_ROLL_FORWARD: 'minor'
jobs:
@@ -29,23 +28,25 @@ jobs:
git lfs pull
- name: Install dependencies
run: |
sudo apt-get update
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
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
- name: Build
run: |
./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
- name: Test
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
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/Newtonsoft.Json.dll Binaries/Tests
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-windows:
@@ -57,7 +58,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.419
dotnet-version: 8.0.x
- name: Print .NET info
run: |
dotnet --info
@@ -68,9 +69,6 @@ jobs:
git lfs pull
- name: Build
run: |
PowerShell "(Get-Content global.json).Replace('latestMajor', 'minor') | Set-Content global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/global.json).Replace('latestMajor', 'minor') | Set-Content Source/Tools/Flax.Build/global.json"
PowerShell "(Get-Content Source/Tools/Flax.Build/Flax.Build.csproj).Replace('LatestMajor', 'Minor') | Set-Content Source/Tools/Flax.Build/Flax.Build.csproj"
.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs -dotnet=8
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=8 -arch=x64 -platform=Windows -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
@@ -78,7 +76,7 @@ jobs:
shell: pwsh
run: |
$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 }
dotnet test -f net8.0 Binaries\Tests\Flax.Build.Tests.dll
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests

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

@@ -42,10 +42,10 @@ struct MaterialInput
float2 SvPositionToDecalUV(float4 svPosition)
{
float2 screenUV = svPosition.xy * ScreenSize.zw;
svPosition.z = SAMPLE_RT_DEPTH(DepthBuffer, screenUV);
float4 positionHS = PROJECT_POINT(float4(svPosition.xyz, 1), SvPositionToWorld);
svPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = mul(float4(svPosition.xyz, 1), SvPositionToWorld);
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;
}
@@ -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)
{
// 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
SvPosition = PROJECT_POINT(float4(worldPosition.xyz, 1), ViewProjectionMatrix);
SvPosition = mul(float4(worldPosition.xyz, 1), ViewProjectionMatrix);
}
// Pixel Shader function for decals rendering
@@ -213,11 +213,11 @@ void PS_Decal(
}
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 positionOS = PROJECT_POINT(float4(positionWS, 1), InvWorld).xyz;
float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
clip(0.5 - abs(positionOS.xyz));
float2 decalUVs = positionOS.xz + 0.5f;

View File

@@ -308,7 +308,7 @@ VertexOutput VS_SplineModel(ModelInput input)
world = mul(world, WorldMatrix);
// 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
output.Geometry.TexCoord = input.TexCoord0;
@@ -337,7 +337,8 @@ VertexOutput VS_SplineModel(ModelInput input)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif
// Get tessalation multiplier (per vertex)

View File

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

View File

@@ -67,7 +67,7 @@ float Rand(inout uint seed)
float3 ReprojectPosition(float2 uv, float rawDepth)
{
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;
}
@@ -158,7 +158,7 @@ void SpawnParticle(Context context)
@4}
// 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)]
void CS_Main(uint3 dispatchThreadId : SV_DispatchThreadID)
{

View File

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

View File

@@ -393,7 +393,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
output.WorldPosition = position + spriteVertexPosition;
// 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
output.TexCoord = input.TexCoord;
@@ -431,7 +431,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif
// 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;
// Compute clip space position
output.Position = PROJECT_POINT(float4(output.WorldPosition, 1), ViewProjectionMatrix);
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes
output.TexCoord = input.TexCoord0;
@@ -549,7 +549,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif
// 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);
// 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
output.ParticleIndex = particleIndex;
@@ -655,7 +655,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.WorldPosition += material.PositionOffset;
output.Position = PROJECT_POINT(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
#endif
// 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;
// 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
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
@@ -378,7 +378,7 @@ VertexOutput VS(ModelInput input)
#if USE_POSITION_OFFSET
output.Geometry.WorldPosition += 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
// Get tessalation multiplier (per vertex)
@@ -412,7 +412,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
// Transform vertex position into the screen
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;
}
@@ -518,7 +518,7 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
#endif
// 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
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
@@ -549,7 +549,7 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
#if USE_POSITION_OFFSET
output.Geometry.WorldPosition += 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
// Get tessalation multiplier (per vertex)

View File

@@ -388,7 +388,7 @@ VertexOutput VS(TerrainVertexInput input)
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
// 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
#if USE_SMOOTH_LOD_TRANSITION
@@ -436,7 +436,7 @@ VertexOutput VS(TerrainVertexInput input)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
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
// Get tessalation multiplier (per vertex)

View File

@@ -8,7 +8,6 @@
#include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.hlsl"
#include "./Flax/VolumetricFog.hlsl"
@7
// Primary constant buffer (with additional material parameters)
@@ -22,7 +21,6 @@ float Dummy0;
float VolumetricFogMaxDistance;
int ParticleStride;
int ParticleIndex;
float4 GridSliceParameters;
@1META_CB_END
// Particles attributes buffer
@@ -204,19 +202,19 @@ Material GetMaterialPS(MaterialInput input)
META_PS(true, FEATURE_LEVEL_SM5)
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);
float3 cellOffset = 0.5f;
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;
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
wsPos.xyz /= wsPos.w;
float3 positionWS = wsPos.xyz / wsPos.w;
// Get material parameters
MaterialInput materialInput = (MaterialInput)0;
materialInput.WorldPosition = wsPos.xyz;
materialInput.WorldPosition = positionWS;
materialInput.TexCoord = input.Vertex.TexCoord;
materialInput.ParticleIndex = ParticleIndex;
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);
// Compute fog properties
material.Opacity *= material.Mask;
float3 albedo = material.Color;
float extinction = material.Opacity * 0.001f;
float3 emission = material.Emissive * material.Opacity;
float extinction = material.Opacity * material.Mask * 0.001f;
float3 emission = material.Emissive;
float3 scattering = albedo * extinction;
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.

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.

Binary file not shown.

Binary file not shown.

View File

@@ -2,26 +2,18 @@
"Name": "Flax",
"Version": {
"Major": 1,
"Minor": 12,
"Minor": 11,
"Revision": 0,
"Build": 6910
"Build": 6801
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
"GameTarget": "FlaxGame",
"EditorTarget": "FlaxEditor",
"Configuration": {
"UseCSharp": true,
"UseLargeWorlds": false,
"UseDotNet": true,
"Windows": {
"UseSDL": false,
},
"Mac": {
"UseSDL": false,
},
"Linux": {
"UseSDL": true,
},
"UseSDL": true
}
}
}

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: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: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/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>

View File

@@ -49,7 +49,7 @@ Follow the instructions below to compile and run the engine from source.
* Fedora: `sudo dnf install dotnet-sdk-8.0`
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
* Ubuntu: `sudo apt install vulkan-sdk` (deprecated, follow official docs)
* Ubuntu: `sudo apt install vulkan-sdk`
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
* Install Git with LFS
@@ -60,7 +60,7 @@ Follow the instructions below to compile and run the engine from source.
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
* Install Clang compiler (version 14 or later):
* Install Clang compiler (version 6 or later):
* Ubuntu: `sudo apt-get install clang lldb lld`
* Fedora: `sudo dnf install clang llvm lldb lld`
* Arch: `sudo pacman -S clang lldb lld`

View File

@@ -19,7 +19,7 @@ namespace FlaxEditor.Content.GUI
/// <summary>
/// Gets the target node.
/// </summary>
public ContentFolderTreeNode TargetNode { get; }
public ContentTreeNode TargetNode { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ContentNavigationButton"/> class.
@@ -28,7 +28,7 @@ namespace FlaxEditor.Content.GUI
/// <param name="x">The x position.</param>
/// <param name="y">The y position.</param>
/// <param name="height">The height.</param>
public ContentNavigationButton(ContentFolderTreeNode targetNode, float x, float y, float height)
public ContentNavigationButton(ContentTreeNode targetNode, float x, float y, float height)
: base(x, y, height)
{
TargetNode = targetNode;
@@ -147,7 +147,7 @@ namespace FlaxEditor.Content.GUI
ClearItems();
foreach (var child in Target.TargetNode.Children)
{
if (child is ContentFolderTreeNode node)
if (child is ContentTreeNode node)
{
if (node.Folder.VisibleInHierarchy) // Respect the filter set by ContentFilterConfig.Filter(...)
AddItem(node.Folder.ShortName);
@@ -180,7 +180,7 @@ namespace FlaxEditor.Content.GUI
var item = _items[index];
foreach (var child in Target.TargetNode.Children)
{
if (child is ContentFolderTreeNode node && node.Folder.ShortName == item)
if (child is ContentTreeNode node && node.Folder.ShortName == item)
{
Editor.Instance.Windows.ContentWin.Navigate(node);
return;

View File

@@ -187,11 +187,6 @@ namespace FlaxEditor.Content.Import
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
_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)
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);

View File

@@ -59,7 +59,7 @@ namespace FlaxEditor.Content
/// <summary>
/// Gets the content node.
/// </summary>
public ContentFolderTreeNode Node { get; }
public ContentTreeNode Node { get; }
/// <summary>
/// The subitems of this folder.
@@ -72,7 +72,7 @@ namespace FlaxEditor.Content
/// <param name="type">The folder type.</param>
/// <param name="path">The path to the item.</param>
/// <param name="node">The folder parent node.</param>
internal ContentFolder(ContentFolderType type, string path, ContentFolderTreeNode node)
internal ContentFolder(ContentFolderType type, string path, ContentTreeNode node)
: base(path)
{
FolderType = type;
@@ -118,7 +118,7 @@ namespace FlaxEditor.Content
get
{
var hasParentFolder = ParentFolder != null;
var isContentFolder = Node is MainContentFolderTreeNode;
var isContentFolder = Node is MainContentTreeNode;
return hasParentFolder && !isContentFolder;
}
}

View File

@@ -281,13 +281,6 @@ namespace FlaxEditor.Content
private void CacheData()
{
if (!_asset)
{
_parameters = Utils.GetEmptyArray<ScriptMemberInfo>();
_methods = Utils.GetEmptyArray<ScriptMemberInfo>();
_attributes = Utils.GetEmptyArray<Attribute>();
return;
}
if (_parameters != null)
return;
if (_asset.WaitForLoaded())
@@ -351,13 +344,13 @@ namespace FlaxEditor.Content
}
/// <inheritdoc />
public string Name => _asset ? Path.GetFileNameWithoutExtension(_asset.Path) : null;
public string Name => Path.GetFileNameWithoutExtension(_asset.Path);
/// <inheritdoc />
public string Namespace => string.Empty;
/// <inheritdoc />
public string TypeName => _asset ? JsonSerializer.GetStringID(_asset.ID) : null;
public string TypeName => JsonSerializer.GetStringID(_asset.ID);
/// <inheritdoc />
public bool IsPublic => true;

View File

@@ -130,11 +130,6 @@ namespace FlaxEditor.Content
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
var antiAliasing = preview.PostFxVolume.AntiAliasing;
antiAliasing.Mode = AntialiasingMode.FastApproximateAntialiasing;
antiAliasing.OverrideFlags |= AntiAliasingSettingsOverride.Mode;
preview.PostFxVolume.AntiAliasing = antiAliasing;
}
}
}

View File

@@ -45,8 +45,6 @@ namespace FlaxEditor.Content.Thumbnails
{
if (item == null)
throw new ArgumentNullException();
if (_task == null)
return;
// Check if use default icon
var defaultThumbnail = item.DefaultThumbnail;
@@ -225,12 +223,11 @@ namespace FlaxEditor.Content.Thumbnails
/// <inheritdoc />
public override void OnInit()
{
if (Editor.IsHeadlessMode || (GPUDevice.Instance != null && GPUDevice.Instance.RendererType == RendererType.Null))
return;
// Create cache folder
if (!Directory.Exists(_cacheFolder))
{
Directory.CreateDirectory(_cacheFolder);
}
// Find atlases in a Editor cache directory
var files = Directory.GetFiles(_cacheFolder, "cache_*.flax", SearchOption.TopDirectoryOnly);
@@ -485,7 +482,7 @@ namespace FlaxEditor.Content.Thumbnails
public override void OnUpdate()
{
// 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;
lock (_requests)

View File

@@ -1,433 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.SceneGraph;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content;
/// <summary>
/// Content folder tree node.
/// </summary>
/// <seealso cref="TreeNode" />
public class ContentFolderTreeNode : TreeNode
{
private DragItems _dragOverItems;
private DragActors _dragActors;
private List<Rectangle> _highlights;
/// <summary>
/// The folder.
/// </summary>
protected ContentFolder _folder;
/// <summary>
/// Whether this node can be deleted.
/// </summary>
public virtual bool CanDelete => true;
/// <summary>
/// Whether this node can be duplicated.
/// </summary>
public virtual bool CanDuplicate => true;
/// <summary>
/// Gets the content folder item.
/// </summary>
public ContentFolder Folder => _folder;
/// <summary>
/// Gets the type of the folder.
/// </summary>
public ContentFolderType FolderType => _folder.FolderType;
/// <summary>
/// Returns true if that folder can import/manage scripts.
/// </summary>
public bool CanHaveScripts => _folder.CanHaveScripts;
/// <summary>
/// Returns true if that folder can import/manage assets.
/// </summary>
/// <returns>True if can contain assets for project, otherwise false</returns>
public bool CanHaveAssets => _folder.CanHaveAssets;
/// <summary>
/// Gets the parent node.
/// </summary>
public ContentFolderTreeNode ParentNode => Parent as ContentFolderTreeNode;
/// <summary>
/// Gets the folder path.
/// </summary>
public string Path => _folder.Path;
/// <summary>
/// Gets the navigation button label.
/// </summary>
public virtual string NavButtonLabel => _folder.ShortName;
/// <summary>
/// Initializes a new instance of the <see cref="ContentFolderTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="path">The folder path.</param>
public ContentFolderTreeNode(ContentFolderTreeNode parent, string path)
: this(parent, parent?.FolderType ?? ContentFolderType.Other, path)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentFolderTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
protected ContentFolderTreeNode(ContentFolderTreeNode parent, ContentFolderType type, string path)
: base(false, Editor.Instance.Icons.FolderClosed32, Editor.Instance.Icons.FolderOpen32)
{
_folder = new ContentFolder(type, path, this);
Text = _folder.ShortName;
if (parent != null)
{
Folder.ParentFolder = parent.Folder;
Parent = parent;
}
IconColor = Color.Transparent; // Hide default icon, we draw scaled icon manually
UpdateCustomArrowRect();
Editor.Instance?.Windows?.ContentWin?.TryAutoExpandContentNode(this);
}
/// <summary>
/// Updates the custom arrow rectangle so it stays aligned with the current layout.
/// </summary>
private void UpdateCustomArrowRect()
{
var contentWindow = Editor.Instance?.Windows?.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var arrowSize = Mathf.Clamp(12.0f * scale, 10.0f, 20.0f);
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
// Use the current text layout, not just cached values.
var textRect = TextRect;
var iconLeft = textRect.Left - iconSize - 2.0f;
var x = Mathf.Max(iconLeft - arrowSize - 2.0f, 0.0f);
var y = Mathf.Max((HeaderHeight - arrowSize) * 0.5f, 0.0f);
CustomArrowRect = new Rectangle(x, y, arrowSize, arrowSize);
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
base.PerformLayout(force);
UpdateCustomArrowRect();
}
/// <summary>
/// Shows the rename popup for the item.
/// </summary>
public void StartRenaming()
{
if (!_folder.CanRename)
return;
// Start renaming the folder
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(false);
var dialog = RenamePopup.Show(this, TextRect, _folder.ShortName, false);
dialog.Tag = _folder;
dialog.Renamed += popup =>
{
Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text);
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true);
};
dialog.Closed += popup => { Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); };
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
// Update itself
bool isThisVisible;
if (noFilter)
{
// Clear filter
_highlights?.Clear();
isThisVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
}
else
{
// Hide
_highlights?.Clear();
isThisVisible = false;
}
}
// Update children
bool isAnyChildVisible = false;
for (int i = 0; i < _children.Count; i++)
{
if (_children[i] is ContentFolderTreeNode child)
{
child.UpdateFilter(filterText);
isAnyChildVisible |= child.Visible;
}
else if (_children[i] is ContentItemTreeNode itemNode)
{
itemNode.UpdateFilter(filterText);
isAnyChildVisible |= itemNode.Visible;
}
}
if (!noFilter)
{
bool isExpanded = isAnyChildVisible;
if (isExpanded)
Expand(true);
else
Collapse(true);
}
Visible = isThisVisible | isAnyChildVisible;
}
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ContentItemTreeNode)
return -1;
if (other is ContentFolderTreeNode otherNode)
return string.Compare(Text, otherNode.Text, StringComparison.Ordinal);
return base.Compare(other);
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
// Draw all highlights
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
var contentWindow = Editor.Instance.Windows.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var icon = IsExpanded ? Editor.Instance.Icons.FolderOpen32 : Editor.Instance.Icons.FolderClosed32;
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
var iconRect = new Rectangle(TextRect.Left - iconSize - 2.0f, (HeaderHeight - iconSize) * 0.5f, iconSize, iconSize);
Render2D.DrawSprite(icon, iconRect);
}
/// <inheritdoc />
public override void OnDestroy()
{
// Delete folder item
_folder.Dispose();
base.OnDestroy();
}
/// <inheritdoc />
protected override void OnExpandedChanged()
{
base.OnExpandedChanged();
Editor.Instance?.Windows?.ContentWin?.OnContentTreeNodeExpandedChanged(this, IsExpanded);
}
private DragDropEffect GetDragEffect(DragData data)
{
if (_dragActors != null && _dragActors.HasValidDrag)
return DragDropEffect.Move;
if (data is DragDataFiles)
{
if (_folder.CanHaveAssets)
return DragDropEffect.Copy;
}
else
{
if (_dragOverItems != null && _dragOverItems.HasValidDrag)
return DragDropEffect.Move;
}
return DragDropEffect.None;
}
private bool ValidateDragItem(ContentItem item)
{
// Reject itself and any parent
return item != _folder && !item.Find(_folder);
}
private bool ValidateDragActors(ActorNode actor)
{
return actor.CanCreatePrefab && _folder.CanHaveAssets;
}
private void ImportActors(DragActors actors)
{
Select();
foreach (var actorNode in actors.Objects)
{
var actor = actorNode.Actor;
if (actors.Objects.Contains(actorNode.ParentNode as ActorNode))
continue;
Editor.Instance.Prefabs.CreatePrefab(actor, false);
}
Editor.Instance.Windows.ContentWin.RefreshView();
}
/// <inheritdoc />
protected override DragDropEffect OnDragEnterHeader(DragData data)
{
if (data is DragDataFiles)
return _folder.CanHaveAssets ? DragDropEffect.Copy : DragDropEffect.None;
if (_dragActors == null)
_dragActors = new DragActors(ValidateDragActors);
if (_dragActors.OnDragEnter(data))
return DragDropEffect.Move;
if (_dragOverItems == null)
_dragOverItems = new DragItems(ValidateDragItem);
_dragOverItems.OnDragEnter(data);
return GetDragEffect(data);
}
/// <inheritdoc />
protected override DragDropEffect OnDragMoveHeader(DragData data)
{
if (data is DragDataFiles)
return _folder.CanHaveAssets ? DragDropEffect.Copy : DragDropEffect.None;
if (_dragActors != null && _dragActors.HasValidDrag)
return DragDropEffect.Move;
return GetDragEffect(data);
}
/// <inheritdoc />
protected override void OnDragLeaveHeader()
{
_dragOverItems?.OnDragLeave();
_dragActors?.OnDragLeave();
base.OnDragLeaveHeader();
}
/// <inheritdoc />
protected override DragDropEffect OnDragDropHeader(DragData data)
{
var result = DragDropEffect.None;
// Check if drop element or files
if (data is DragDataFiles files)
{
// Import files
Editor.Instance.ContentImporting.Import(files.Files, _folder);
result = DragDropEffect.Copy;
Expand();
}
else if (_dragActors != null && _dragActors.HasValidDrag)
{
ImportActors(_dragActors);
_dragActors.OnDragDrop();
result = DragDropEffect.Move;
Expand();
}
else if (_dragOverItems != null && _dragOverItems.HasValidDrag)
{
// Move items
Editor.Instance.ContentDatabase.Move(_dragOverItems.Objects, _folder);
result = DragDropEffect.Move;
Expand();
}
_dragOverItems?.OnDragDrop();
return result;
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(_folder));
}
/// <inheritdoc />
protected override void OnLongPress()
{
Select();
StartRenaming();
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.F2:
StartRenaming();
return true;
case KeyboardKeys.Delete:
if (Folder.Exists && CanDelete)
Editor.Instance.Windows.ContentWin.Delete(Folder);
return true;
}
if (RootWindow.GetKey(KeyboardKeys.Control))
{
switch (key)
{
case KeyboardKeys.D:
if (Folder.Exists && CanDuplicate)
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
return true;
}
}
}
return base.OnKeyDown(key);
}
}

View File

@@ -1,224 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content;
/// <summary>
/// Tree node for non-folder content items.
/// </summary>
public sealed class ContentItemTreeNode : TreeNode, IContentItemOwner
{
private List<Rectangle> _highlights;
/// <summary>
/// The content item.
/// </summary>
public ContentItem Item { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ContentItemTreeNode"/> class.
/// </summary>
/// <param name="item">The content item.</param>
public ContentItemTreeNode(ContentItem item)
: base(false, Editor.Instance.Icons.Document128, Editor.Instance.Icons.Document128)
{
Item = item ?? throw new ArgumentNullException(nameof(item));
UpdateDisplayedName();
IconColor = Color.Transparent; // Reserve icon space but draw custom thumbnail.
Item.AddReference(this);
}
private static SpriteHandle GetIcon(ContentItem item)
{
if (item == null)
return SpriteHandle.Invalid;
var icon = item.Thumbnail;
if (!icon.IsValid)
icon = item.DefaultThumbnail;
if (!icon.IsValid)
icon = Editor.Instance.Icons.Document128;
return icon;
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
bool isVisible;
if (noFilter)
{
_highlights?.Clear();
isVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isVisible = true;
}
else
{
_highlights?.Clear();
isVisible = false;
}
}
Visible = isVisible;
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
var icon = GetIcon(Item);
if (icon.IsValid)
{
var contentWindow = Editor.Instance.Windows.ContentWin;
var scale = contentWindow != null && contentWindow.IsTreeOnlyMode ? contentWindow.View.ViewScale : 1.0f;
var iconSize = Mathf.Clamp(16.0f * scale, 12.0f, 28.0f);
var textRect = TextRect;
var iconRect = new Rectangle(textRect.Left - iconSize - 2.0f, (HeaderHeight - iconSize) * 0.5f, iconSize, iconSize);
Render2D.DrawSprite(icon, iconRect);
}
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
}
/// <inheritdoc />
protected override bool OnMouseDoubleClickHeader(ref Float2 location, MouseButton button)
{
if (button == MouseButton.Left)
{
Editor.Instance.Windows.ContentWin.Open(Item);
return true;
}
return base.OnMouseDoubleClickHeader(ref location, button);
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.Return:
Editor.Instance.Windows.ContentWin.Open(Item);
return true;
case KeyboardKeys.F2:
Editor.Instance.Windows.ContentWin.Rename(Item);
return true;
case KeyboardKeys.Delete:
Editor.Instance.Windows.ContentWin.Delete(Item);
return true;
}
}
return base.OnKeyDown(key);
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(Item));
}
/// <inheritdoc />
public override bool OnShowTooltip(out string text, out Float2 location, out Rectangle area)
{
Item.UpdateTooltipText();
TooltipText = Item.TooltipText;
return base.OnShowTooltip(out text, out location, out area);
}
/// <inheritdoc />
void IContentItemOwner.OnItemDeleted(ContentItem item)
{
}
/// <inheritdoc />
void IContentItemOwner.OnItemRenamed(ContentItem item)
{
UpdateDisplayedName();
}
/// <inheritdoc />
void IContentItemOwner.OnItemReimported(ContentItem item)
{
}
/// <inheritdoc />
void IContentItemOwner.OnItemDispose(ContentItem item)
{
}
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ContentFolderTreeNode)
return 1;
if (other is ContentItemTreeNode otherItem)
return ApplySortOrder(string.Compare(Text, otherItem.Text, StringComparison.InvariantCulture));
return base.Compare(other);
}
/// <inheritdoc />
public override void OnDestroy()
{
Item.RemoveReference(this);
base.OnDestroy();
}
/// <summary>
/// Updates the text of the node.
/// </summary>
public void UpdateDisplayedName()
{
var contentWindow = Editor.Instance?.Windows?.ContentWin;
var showExtensions = contentWindow?.View?.ShowFileExtensions ?? true;
Text = Item.ShowFileExtension || showExtensions ? Item.FileName : Item.ShortName;
}
private static SortType GetSortType()
{
return Editor.Instance?.Windows?.ContentWin?.CurrentSortType ?? SortType.AlphabeticOrder;
}
private static int ApplySortOrder(int result)
{
return GetSortType() == SortType.AlphabeticReverse ? -result : result;
}
}

View File

@@ -0,0 +1,333 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// Content folder tree node.
/// </summary>
/// <seealso cref="TreeNode" />
public class ContentTreeNode : TreeNode
{
private DragItems _dragOverItems;
private List<Rectangle> _highlights;
/// <summary>
/// The folder.
/// </summary>
protected ContentFolder _folder;
/// <summary>
/// Whether this node can be deleted.
/// </summary>
public virtual bool CanDelete => true;
/// <summary>
/// Whether this node can be duplicated.
/// </summary>
public virtual bool CanDuplicate => true;
/// <summary>
/// Gets the content folder item.
/// </summary>
public ContentFolder Folder => _folder;
/// <summary>
/// Gets the type of the folder.
/// </summary>
public ContentFolderType FolderType => _folder.FolderType;
/// <summary>
/// Returns true if that folder can import/manage scripts.
/// </summary>
public bool CanHaveScripts => _folder.CanHaveScripts;
/// <summary>
/// Returns true if that folder can import/manage assets.
/// </summary>
/// <returns>True if can contain assets for project, otherwise false</returns>
public bool CanHaveAssets => _folder.CanHaveAssets;
/// <summary>
/// Gets the parent node.
/// </summary>
public ContentTreeNode ParentNode => Parent as ContentTreeNode;
/// <summary>
/// Gets the folder path.
/// </summary>
public string Path => _folder.Path;
/// <summary>
/// Gets the navigation button label.
/// </summary>
public virtual string NavButtonLabel => _folder.ShortName;
/// <summary>
/// Initializes a new instance of the <see cref="ContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="path">The folder path.</param>
public ContentTreeNode(ContentTreeNode parent, string path)
: this(parent, parent?.FolderType ?? ContentFolderType.Other, path)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent node.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
protected ContentTreeNode(ContentTreeNode parent, ContentFolderType type, string path)
: base(false, Editor.Instance.Icons.FolderClosed32, Editor.Instance.Icons.FolderOpen32)
{
_folder = new ContentFolder(type, path, this);
Text = _folder.ShortName;
if (parent != null)
{
Folder.ParentFolder = parent.Folder;
Parent = parent;
}
IconColor = Style.Current.Foreground;
}
/// <summary>
/// Shows the rename popup for the item.
/// </summary>
public void StartRenaming()
{
if (!_folder.CanRename)
return;
// Start renaming the folder
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(false);
var dialog = RenamePopup.Show(this, TextRect, _folder.ShortName, false);
dialog.Tag = _folder;
dialog.Renamed += popup =>
{
Editor.Instance.Windows.ContentWin.Rename((ContentFolder)popup.Tag, popup.Text);
Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true);
};
dialog.Closed += popup => { Editor.Instance.Windows.ContentWin.ScrollingOnTreeView(true); };
}
/// <summary>
/// Updates the query search filter.
/// </summary>
/// <param name="filterText">The filter text.</param>
public void UpdateFilter(string filterText)
{
bool noFilter = string.IsNullOrWhiteSpace(filterText);
// Update itself
bool isThisVisible;
if (noFilter)
{
// Clear filter
_highlights?.Clear();
isThisVisible = true;
}
else
{
var text = Text;
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
var start = font.GetCharPosition(text, ranges[i].StartIndex);
var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
}
else
{
// Hide
_highlights?.Clear();
isThisVisible = false;
}
}
// Update children
bool isAnyChildVisible = false;
for (int i = 0; i < _children.Count; i++)
{
if (_children[i] is ContentTreeNode child)
{
child.UpdateFilter(filterText);
isAnyChildVisible |= child.Visible;
}
}
bool isExpanded = isAnyChildVisible;
if (isExpanded)
{
Expand(true);
}
else
{
Collapse(true);
}
Visible = isThisVisible | isAnyChildVisible;
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
// Draw all highlights
if (_highlights != null)
{
var style = Style.Current;
var color = style.ProgressNormal * 0.6f;
for (int i = 0; i < _highlights.Count; i++)
Render2D.FillRectangle(_highlights[i], color);
}
}
/// <inheritdoc />
public override void OnDestroy()
{
// Delete folder item
_folder.Dispose();
base.OnDestroy();
}
private DragDropEffect GetDragEffect(DragData data)
{
if (data is DragDataFiles)
{
if (_folder.CanHaveAssets)
return DragDropEffect.Copy;
}
else
{
if (_dragOverItems.HasValidDrag)
return DragDropEffect.Move;
}
return DragDropEffect.None;
}
private bool ValidateDragItem(ContentItem item)
{
// Reject itself and any parent
return item != _folder && !item.Find(_folder);
}
/// <inheritdoc />
protected override DragDropEffect OnDragEnterHeader(DragData data)
{
if (_dragOverItems == null)
_dragOverItems = new DragItems(ValidateDragItem);
_dragOverItems.OnDragEnter(data);
return GetDragEffect(data);
}
/// <inheritdoc />
protected override DragDropEffect OnDragMoveHeader(DragData data)
{
return GetDragEffect(data);
}
/// <inheritdoc />
protected override void OnDragLeaveHeader()
{
_dragOverItems.OnDragLeave();
base.OnDragLeaveHeader();
}
/// <inheritdoc />
protected override DragDropEffect OnDragDropHeader(DragData data)
{
var result = DragDropEffect.None;
// Check if drop element or files
if (data is DragDataFiles files)
{
// Import files
Editor.Instance.ContentImporting.Import(files.Files, _folder);
result = DragDropEffect.Copy;
Expand();
}
else if (_dragOverItems.HasValidDrag)
{
// Move items
Editor.Instance.ContentDatabase.Move(_dragOverItems.Objects, _folder);
result = DragDropEffect.Move;
Expand();
}
_dragOverItems.OnDragDrop();
return result;
}
/// <inheritdoc />
protected override void DoDragDrop()
{
DoDragDrop(DragItems.GetDragData(_folder));
}
/// <inheritdoc />
protected override void OnLongPress()
{
Select();
StartRenaming();
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (IsFocused)
{
switch (key)
{
case KeyboardKeys.F2:
StartRenaming();
return true;
case KeyboardKeys.Delete:
if (Folder.Exists && CanDelete)
Editor.Instance.Windows.ContentWin.Delete(Folder);
return true;
}
if (RootWindow.GetKey(KeyboardKeys.Control))
{
switch (key)
{
case KeyboardKeys.D:
if (Folder.Exists && CanDuplicate)
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
return true;
}
}
}
return base.OnKeyDown(key);
}
}
}

View File

@@ -7,8 +7,8 @@ namespace FlaxEditor.Content
/// <summary>
/// Content tree node used for main directories.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public class MainContentFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public class MainContentTreeNode : ContentTreeNode
{
private FileSystemWatcher _watcher;
@@ -19,12 +19,12 @@ namespace FlaxEditor.Content
public override bool CanDuplicate => false;
/// <summary>
/// Initializes a new instance of the <see cref="MainContentFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="MainContentTreeNode"/> class.
/// </summary>
/// <param name="parent">The parent project.</param>
/// <param name="type">The folder type.</param>
/// <param name="path">The folder path.</param>
public MainContentFolderTreeNode(ProjectFolderTreeNode parent, ContentFolderType type, string path)
public MainContentTreeNode(ProjectTreeNode parent, ContentFolderType type, string path)
: base(parent, type, path)
{
_watcher = new FileSystemWatcher(path)

View File

@@ -1,6 +1,5 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
@@ -8,8 +7,8 @@ namespace FlaxEditor.Content
/// <summary>
/// Root tree node for the project workspace.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public sealed class ProjectFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public sealed class ProjectTreeNode : ContentTreeNode
{
/// <summary>
/// The project/
@@ -19,18 +18,18 @@ namespace FlaxEditor.Content
/// <summary>
/// The project content directory.
/// </summary>
public MainContentFolderTreeNode Content;
public MainContentTreeNode Content;
/// <summary>
/// The project source code directory.
/// </summary>
public MainContentFolderTreeNode Source;
public MainContentTreeNode Source;
/// <summary>
/// Initializes a new instance of the <see cref="ProjectFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="ProjectTreeNode"/> class.
/// </summary>
/// <param name="project">The project.</param>
public ProjectFolderTreeNode(ProjectInfo project)
public ProjectTreeNode(ProjectInfo project)
: base(null, project.ProjectFolderPath)
{
Project = project;
@@ -49,29 +48,9 @@ namespace FlaxEditor.Content
/// <inheritdoc />
public override int Compare(Control other)
{
if (other is ProjectFolderTreeNode otherProject)
{
var gameProject = Editor.Instance.GameProject;
var engineProject = Editor.Instance.EngineProject;
bool isGame = Project == gameProject;
bool isEngine = Project == engineProject;
bool otherIsGame = otherProject.Project == gameProject;
bool otherIsEngine = otherProject.Project == engineProject;
// Main game project at the top
if (isGame && !otherIsGame)
return -1;
if (!isGame && otherIsGame)
return 1;
// Engine project at the bottom (when distinct)
if (isEngine && !otherIsEngine)
return 1;
if (!isEngine && otherIsEngine)
return -1;
return string.CompareOrdinal(Project.Name, otherProject.Project.Name);
}
// Move the main game project to the top
if (Project.Name == Editor.Instance.GameProject.Name)
return -1;
return base.Compare(other);
}
}

View File

@@ -5,13 +5,13 @@ namespace FlaxEditor.Content
/// <summary>
/// Root tree node for the content workspace.
/// </summary>
/// <seealso cref="ContentFolderTreeNode" />
public sealed class RootContentFolderTreeNode : ContentFolderTreeNode
/// <seealso cref="FlaxEditor.Content.ContentTreeNode" />
public sealed class RootContentTreeNode : ContentTreeNode
{
/// <summary>
/// Initializes a new instance of the <see cref="RootContentFolderTreeNode"/> class.
/// Initializes a new instance of the <see cref="RootContentTreeNode"/> class.
/// </summary>
public RootContentFolderTreeNode()
public RootContentTreeNode()
: base(null, string.Empty)
{
}

View File

@@ -141,11 +141,6 @@ API_ENUM() enum class BuildPlatform
/// </summary>
API_ENUM(Attributes="EditorDisplay(null, \"Windows ARM64\")")
WindowsARM64 = 15,
/// <summary>
/// Web
/// </summary>
Web = 16,
};
/// <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.
/// </summary>
MonoAOTStatic,
/// <summary>
/// Target platform doesn't support .NET or it has been disabled.
/// </summary>
NoDotnet,
};
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);

View File

@@ -69,10 +69,6 @@
#include "Platform/iOS/iOSPlatformTools.h"
#include "Engine/Platform/iOS/iOSPlatformSettings.h"
#endif
#if PLATFORM_TOOLS_WEB
#include "Platform/Web/WebPlatformTools.h"
#include "Engine/Platform/Web/WebPlatformSettings.h"
#endif
namespace GameCookerImpl
{
@@ -155,8 +151,6 @@ const Char* ToString(const BuildPlatform platform)
return TEXT("iOS ARM64");
case BuildPlatform::WindowsARM64:
return TEXT("Windows ARM64");
case BuildPlatform::Web:
return TEXT("Web");
default:
return TEXT("");
}
@@ -189,8 +183,6 @@ const Char* ToString(const DotNetAOTModes mode)
return TEXT("MonoAOTDynamic");
case DotNetAOTModes::MonoAOTStatic:
return TEXT("MonoAOTStatic");
case DotNetAOTModes::NoDotnet:
return TEXT("NoDotnet");
default:
return TEXT("");
}
@@ -315,10 +307,6 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
platform = TEXT("Windows");
architecture = TEXT("ARM64");
break;
case BuildPlatform::Web:
platform = TEXT("Web");
architecture = TEXT("x86");
break;
default:
LOG(Fatal, "Unknown or unsupported build platform.");
}
@@ -473,11 +461,6 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
case BuildPlatform::iOSARM64:
result = New<iOSPlatformTools>();
break;
#endif
#if PLATFORM_TOOLS_WEB
case BuildPlatform::Web:
result = New<WebPlatformTools>();
break;
#endif
}
Tools.Add(platform, result);
@@ -535,8 +518,7 @@ bool GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
{
Function<int32()> f;
f.Bind(ThreadFunction);
uint32 stackSize = 4 * 1024 * 1024; // Larger stack
const auto thread = ThreadSpawner::Start(f, GameCookerServiceInstance.Name, ThreadPriority::Highest, stackSize);
const auto thread = ThreadSpawner::Start(f, GameCookerServiceInstance.Name, ThreadPriority::Highest);
if (thread == nullptr)
{
GameCookerImpl::IsRunning = false;
@@ -622,9 +604,6 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
case PlatformType::iOS:
buildPlatform = BuildPlatform::iOSARM64;
break;
case PlatformType::Web:
buildPlatform = BuildPlatform::Web;
break;
default: ;
}
}

View File

@@ -106,7 +106,6 @@ namespace FlaxEditor
case BuildPlatform.MacOSARM64:
case BuildPlatform.MacOSx64: return PlatformType.Mac;
case BuildPlatform.iOSARM64: return PlatformType.iOS;
case BuildPlatform.Web: return PlatformType.Web;
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));
return result;
}
void AndroidPlatformTools::OnBuildStarted(CookingData& data)
{
// Adjust the cooking output folder to be located inside the Gradle assets directory
@@ -412,6 +411,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
return true;
}
LOG(Info, "Output Android APK application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
return false;
}

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