60 Commits

Author SHA1 Message Date
3554747a67 Fix window dragging when not supported by Wayland compositor
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-02-02 18:36:03 +02:00
62968dd437 Show current display server in Editor window tooltip 2025-02-02 18:34:47 +02:00
c660fac524 Properly mark floating windows with transparency support 2025-02-02 13:38:15 +02:00
431a69e357 Enable transparency support in Vulkan swapchains 2025-02-01 22:31:50 +02:00
f4fcc07288 Fix compilation for game builds
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-01-29 16:17:27 +02:00
a38cc4d5cb Fix cloning SDL repository
Some checks are pending
Build Android / Game (Android, Release ARM64) (push) Waiting to run
Build iOS / Game (iOS, Release ARM64) (push) Waiting to run
Build Linux / Editor (Linux, Development x64) (push) Waiting to run
Build Linux / Game (Linux, Release x64) (push) Waiting to run
Build macOS / Editor (Mac, Development ARM64) (push) Waiting to run
Build macOS / Game (Mac, Release ARM64) (push) Waiting to run
Build Windows / Editor (Windows, Development x64) (push) Waiting to run
Build Windows / Game (Windows, Release x64) (push) Waiting to run
Cooker / Cook (Mac) (push) Waiting to run
Tests / Tests (Linux) (push) Waiting to run
Tests / Tests (Windows) (push) Waiting to run
2025-01-28 22:41:45 +02:00
1528d458d9 Fix text input not working on X11 2025-01-28 22:08:17 +02:00
9e937776ac Apply patches to rapidjson 2025-01-28 22:08:16 +02:00
a8aebdd01f Update rapidjson to latest version
Commit d621dc9e9c77f81e5c8a35b8dcc16dcd63351321 in Tencent/rapidjson
2025-01-28 22:08:16 +02:00
998ed87029 Fix button latching on Windows after drag and drop operation 2025-01-28 22:08:16 +02:00
279b3f8d9a Implement new window dragging system 2025-01-28 22:08:15 +02:00
738a506b6d Fix mouse resetting issues after ending relative mode 2025-01-28 22:08:15 +02:00
0ddecdda1f Fix frame stutter when window is focused 2025-01-28 22:08:14 +02:00
94a22907e2 Fix error when docking to sides of tabbed panel 2025-01-28 22:08:14 +02:00
d22a0aad0c Cleanup Linux SDL implementation 2025-01-28 22:08:14 +02:00
9e035f3818 Support compiling third party library C files as C code 2025-01-28 22:08:13 +02:00
99a810458a Implement Wayland protocols module and file generation 2025-01-28 22:08:13 +02:00
2806578126 Fix mouse warping after ending relative mode 2025-01-28 22:08:13 +02:00
882e9a6623 Add git fetch method for dependencies 2025-01-28 22:08:12 +02:00
14c156e351 Fix window ShowInTaskbar setting 2025-01-28 22:08:12 +02:00
cd2151332e Fix various issues with child window positioning 2025-01-28 22:08:12 +02:00
53bbca3779 Add Window.IsAlwaysOnTop property 2025-01-28 22:08:11 +02:00
51f4ac467e Use SDL locale 2025-01-28 22:08:11 +02:00
81427a7f9e Allow window with single tab to be dragged from tab area 2025-01-28 22:08:10 +02:00
faadfb28b3 Fix ValueBox mouse position resetting after releasing the button 2025-01-28 22:08:10 +02:00
6bfe0bed35 Fix SDL build process on Linux 2025-01-28 22:08:10 +02:00
6e4d5b853f Update SDL to 3.2.0 2025-01-28 22:08:09 +02:00
0ebe23b482 _sdl binary 2025-01-28 22:08:09 +02:00
abbde5861a Update SDL3 binaries 2025-01-28 22:08:08 +02:00
b78d4349a7 _lfsconfig 2025-01-28 22:08:08 +02:00
3c1d3234b8 Force cursor to center of Game Window when tab handle is clicked 2025-01-28 22:08:07 +02:00
Chandler Cox
79baaae8e7 Fix rotation using SDL 2025-01-28 22:08:07 +02:00
79289662ed Fix Linux compilation without SDL 2025-01-28 22:08:07 +02:00
89a2985ad8 Fix compilation 2025-01-28 22:08:06 +02:00
1f0a521a87 Update SDL3 2025-01-28 22:08:06 +02:00
8a0e43c38c Fix compilation issues 2025-01-28 22:08:06 +02:00
ac9022f585 Fix windows not being hidden initially 2025-01-28 22:08:05 +02:00
314dbbbeaf Fix parent window position handling with popup/tooltip windows 2025-01-28 22:08:05 +02:00
f13e09910d Fix compilation errors in other platforms 2025-01-28 22:08:04 +02:00
67b9511afe Fix CI for Linux 2025-01-28 22:08:04 +02:00
510c477468 Prevent building with SDL in unsupported platforms 2025-01-28 22:08:04 +02:00
697fcc18ab Fallback to X11 message box implementation when SDL fails 2025-01-28 22:08:03 +02:00
89ff08b3f2 Fix popup and context menus not working on Wayland 2025-01-28 22:08:03 +02:00
9417585cd9 Hide warnings for unsupported SDL operations on Wayland 2025-01-28 22:08:03 +02:00
f794bb5455 Log a warning for not implemented Wayland functionality 2025-01-28 22:08:02 +02:00
bb7a5326cd Fix compilation in Linux 2025-01-28 22:08:02 +02:00
a998b2a44e Enable warning sound in question dialogs 2025-01-28 22:08:02 +02:00
a69eb4296f Enable modern Windows dialog boxes 2025-01-28 22:08:01 +02:00
727af5a5b9 Implement relative mouse mode (raw input) for SDL platform 2025-01-28 22:08:01 +02:00
d545dd8219 Add flag for Window types 2025-01-28 22:08:00 +02:00
29e385ab4b Enable native windowing system settings with SDL platform 2025-01-28 22:08:00 +02:00
5c63e30b84 Add command-line switches to force X11 and Wayland SDL drivers 2025-01-28 22:08:00 +02:00
5187c677f1 Implement SDL platform, windowing and input handling 2025-01-28 22:07:59 +02:00
1d43314efd Refactor application window class name 2025-01-28 22:07:59 +02:00
91ef8c69db Move Window related enums to separate header file 2025-01-28 22:07:59 +02:00
f24251af82 Refactor Windows drag and drop implementation 2025-01-28 22:07:58 +02:00
ed6e0138e6 Refactor ScreenUtilities 2025-01-28 22:07:58 +02:00
4362cdb396 Add more helper methods for managing Git repos 2025-01-28 22:07:57 +02:00
8146680b53 Fix centered window location on X11 2025-01-28 22:07:57 +02:00
27aa2cfa1f Fix initial position of Tooltips 2025-01-28 22:07:57 +02:00
791 changed files with 17313 additions and 24803 deletions

View File

@@ -1,13 +1,13 @@
name: Continuous Deployment
on:
schedule:
- cron: '15 6 * * *'
- cron: '15 4 * * *'
workflow_dispatch:
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=1 -c lfs.transfer.maxretries=2 -c http.version="HTTP/1.1" -c lfs.activitytimeout=60'
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=10 -c lfs.transfer.maxretries=2'
jobs:
@@ -84,7 +84,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
- name: Install dependencies
run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev

View File

@@ -73,11 +73,8 @@ jobs:
.\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
- name: Test
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
.\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
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.runtimeconfig.json Binaries\Tests

View File

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

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Camera/O_Camera.flax (Stored with Git LFS)

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.

BIN
Content/Editor/DefaultFontMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/RotationAxis.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/ScaleAxis.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/TranslationAxis.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/WireBox.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/AudioListener.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/AudioSource.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/Decal.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/DirectionalLight.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/EnvironmentProbe.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/ParticleEffect.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/PointLight.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Icons/SkyLight.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/Skybox.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@@ -83,12 +83,6 @@ float3 GetObjectSize(MaterialInput input)
return float3(1, 1, 1);
}
// Gets the current object scale (supports instancing)
float3 GetObjectScale(MaterialInput input)
{
return float3(1, 1, 1);
}
// Get the current object random value supports instancing)
float GetPerInstanceRandom(MaterialInput input)
{

View File

@@ -207,20 +207,6 @@ float3 GetObjectSize(MaterialInput input)
return GeometrySize * float3(world._m00, world._m11, world._m22);
}
// Gets the current object scale (supports instancing)
float3 GetObjectScale(MaterialInput input)
{
float4x4 world = WorldMatrix;
// Extract scale from the world matrix
float3 scale;
scale.x = length(float3(world._11, world._12, world._13));
scale.y = length(float3(world._21, world._22, world._23));
scale.z = length(float3(world._31, world._32, world._33));
return scale;
}
// Get the current object random value
float GetPerInstanceRandom(MaterialInput input)
{
@@ -311,7 +297,7 @@ VertexOutput VS_SplineModel(ModelInput input)
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes
output.Geometry.TexCoord = input.TexCoord0;
output.Geometry.TexCoord = input.TexCoord;
#if USE_VERTEX_COLOR
output.Geometry.VertexColor = input.Color;
#endif

View File

@@ -140,7 +140,7 @@ void SetParticleVec4(uint particleIndex, int offset, float4 value)
bool AddParticle(out uint dstIndex)
{
// Acquire the particle index in the destination buffer
DstParticlesData.InterlockedAdd(ParticleCounterOffset, 1u, dstIndex);
DstParticlesData.InterlockedAdd(ParticleCounterOffset, 1, dstIndex);
// Prevent overflow
return dstIndex >= PARTICLE_CAPACITY;

View File

@@ -163,12 +163,6 @@ float3 GetObjectSize(MaterialInput input)
return float3(1, 1, 1);
}
// Gets the current object scale (supports instancing)
float3 GetObjectScale(MaterialInput input)
{
return float3(1, 1, 1);
}
// Get the current object random value supports instancing)
float GetPerInstanceRandom(MaterialInput input)
{

View File

@@ -299,22 +299,24 @@ half3x3 CalcTangentToLocal(ModelInput input)
float3 normal = input.Normal.xyz * 2.0 - 1.0;
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
float3 bitangent = cross(normal, tangent) * bitangentSign;
return (half3x3)float3x3(tangent, bitangent, normal);
return float3x3(tangent, bitangent, normal);
}
half3x3 CalcTangentToWorld(in float4x4 world, in half3x3 tangentToLocal)
{
half3x3 localToWorld = (half3x3)RemoveScaleFromLocalToWorld((float3x3)world);
half3x3 localToWorld = RemoveScaleFromLocalToWorld((float3x3)world);
return mul(tangentToLocal, localToWorld);
}
float3 GetParticlePosition(uint particleIndex)
float3 GetParticlePosition(uint ParticleIndex)
{
return TransformParticlePosition(GetParticleVec3(particleIndex, PositionOffset));
return TransformParticlePosition(GetParticleVec3(ParticleIndex, PositionOffset));
}
// Vertex Shader function for Sprite Rendering
META_VS(true, FEATURE_LEVEL_ES2)
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, 0, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
{
VertexOutput output;
@@ -405,7 +407,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = half3x3(axisX, axisY, axisZ);
half3x3 tangentToLocal = float3x3(axisX, axisY, axisZ);
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
output.TBN = tangentToWorld;
@@ -514,7 +516,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes
output.TexCoord = input.TexCoord0;
output.TexCoord = input.TexCoord;
output.ParticleIndex = particleIndex;
#if USE_VERTEX_COLOR
output.VertexColor = input.Color;
@@ -610,7 +612,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
{
output.TexCoord.x = (float)input.Order / (float)RibbonSegmentCount;
}
output.TexCoord.y = (float)((vertexIndex + 1) & 0x1);
output.TexCoord.y = (vertexIndex + 1) & 0x1;
output.TexCoord = output.TexCoord * RibbonUVScale + RibbonUVOffset;
// Compute world space vertex position
@@ -629,7 +631,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = half3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
output.TBN = tangentToWorld;

View File

@@ -2,7 +2,6 @@
// Version: @0
#define MATERIAL 1
#define MATERIAL_TEXCOORDS 4
#define USE_PER_VIEW_CONSTANTS 1
#define USE_PER_DRAW_CONSTANTS 1
@3
@@ -25,29 +24,21 @@ Buffer<float4> BoneMatrices : register(t1);
Buffer<float4> PrevBoneMatrices : register(t2);
#endif
#endif
// Geometry data passed though the graphics rendering stages up to the pixel shader
struct GeometryData
{
float3 WorldPosition : TEXCOORD0;
float4 TexCoords01 : TEXCOORD1;
float4 TexCoords23 : TEXCOORD2;
float2 LightmapUV : TEXCOORD3;
float2 TexCoord : TEXCOORD1;
float2 LightmapUV : TEXCOORD2;
#if USE_VERTEX_COLOR
half4 VertexColor : COLOR;
#endif
float3 WorldNormal : TEXCOORD4;
float4 WorldTangent : TEXCOORD5;
float3 WorldNormal : TEXCOORD3;
float4 WorldTangent : TEXCOORD4;
float3 PrevWorldPosition : TEXCOORD7;
nointerpolation uint ObjectIndex : TEXCOORD8;
};
float3 DecodeNormal(float4 normalMap)
{
float2 xy = normalMap.rg * 2.0 - 1.0;
return float3(xy, sqrt(1.0 - saturate(dot(xy, xy))));
}
// Interpolants passed from the vertex shader
struct VertexOutput
{
@@ -77,7 +68,7 @@ struct MaterialInput
{
float3 WorldPosition;
float TwoSidedSign;
float2 TexCoords[MATERIAL_TEXCOORDS];
float2 TexCoord;
#if USE_LIGHTMAP
float2 LightmapUV;
#endif
@@ -95,18 +86,12 @@ struct MaterialInput
#endif
};
// Map access to the main texure coordinate channel as UV0
#define TexCoord TexCoords[0]
// Extracts geometry data to the material input
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
{
MaterialInput output = (MaterialInput)0;
output.WorldPosition = geometry.WorldPosition;
output.TexCoords[0] = geometry.TexCoords01.xy;
output.TexCoords[1] = geometry.TexCoords01.zw;
output.TexCoords[2] = geometry.TexCoords23.xy;
output.TexCoords[3] = geometry.TexCoords23.zw;
output.TexCoord = geometry.TexCoord;
#if USE_LIGHTMAP
output.LightmapUV = geometry.LightmapUV;
#endif
@@ -141,8 +126,8 @@ MaterialInput GetGeometryMaterialInput(GeometryData geometry)
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
{
GeometryData output = (GeometryData)0;
output.TexCoords01 = p0.TexCoords01 * w0 + p1.TexCoords01 * w1 + p2.TexCoords01 * w2;
output.TexCoords23 = p0.TexCoords23 * w0 + p1.TexCoords23 * w1 + p2.TexCoords23 * w2;
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2;
#if USE_VERTEX_COLOR
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
#endif
@@ -238,24 +223,6 @@ float3 GetObjectSize(MaterialInput input)
return input.Object.GeometrySize * float3(world._m00, world._m11, world._m22);
}
// Gets the current object scale (supports instancing)
float3 GetObjectScale(MaterialInput input)
{
float4x4 world = input.Object.WorldMatrix;
// Get the squares of the scale factors
float scaleXSquared = dot(world[0].xyz, world[0].xyz);
float scaleYSquared = dot(world[1].xyz, world[1].xyz);
float scaleZSquared = dot(world[2].xyz, world[2].xyz);
// Take square root to get actual scales
return float3(
sqrt(scaleXSquared),
sqrt(scaleYSquared),
sqrt(scaleZSquared)
);
}
// Get the current object random value (supports instancing)
float GetPerInstanceRandom(MaterialInput input)
{
@@ -345,15 +312,14 @@ VertexOutput VS(ModelInput input)
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
output.Geometry.TexCoords23 = float4(input.TexCoord2, input.TexCoord3);
output.Geometry.TexCoord = input.TexCoord;
#if USE_VERTEX_COLOR
output.Geometry.VertexColor = input.Color;
#endif
#if CAN_USE_LIGHTMAP
output.Geometry.LightmapUV = input.LightmapUV * object.LightmapArea.zw + object.LightmapArea.xy;
#else
output.Geometry.LightmapUV = float2(0, 0);
output.Geometry.LightmapUV = input.LightmapUV;
#endif
// Calculate tanget space to world space transformation matrix for unit vectors
@@ -493,7 +459,7 @@ META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0,
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(BLENDINDICES, 0, R8G8B8A8_UINT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(BLENDWEIGHTS, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(BLENDWEIGHT, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0, true)
VertexOutput VS_Skinned(ModelInput_Skinned input)
{
VertexOutput output;
@@ -520,10 +486,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
// Pass vertex attributes
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
output.Geometry.TexCoords23 = float4(input.TexCoord2, input.TexCoord3);
output.Geometry.TexCoord = input.TexCoord;
#if USE_VERTEX_COLOR
output.Geometry.VertexColor = input.Color;
output.Geometry.VertexColor = float4(0, 0, 0, 1);
#endif
output.Geometry.LightmapUV = float2(0, 0);

View File

@@ -236,12 +236,6 @@ float3 GetObjectSize(MaterialInput input)
return float3(1, 1, 1);
}
// Gets the current object scale (supports instancing)
float3 GetObjectScale(MaterialInput input)
{
return float3(1, 1, 1);
}
// Get the current object random value
float GetPerInstanceRandom(MaterialInput input)
{
@@ -325,6 +319,8 @@ struct TerrainVertexInput
// Vertex Shader function for terrain rendering
META_VS(true, FEATURE_LEVEL_ES2)
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 1, R8G8B8A8_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
VertexOutput VS(TerrainVertexInput input)
{
VertexOutput output;

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Primitives/Capsule.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Primitives/Cone.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Primitives/Cube.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Primitives/Cylinder.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Primitives/Plane.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Primitives/Sphere.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/SpriteMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/TexturePreviewMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultRadialMenu.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/Models/Box.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/Models/Quad.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/Models/SimpleBox.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/Models/Sphere.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/Models/SphereLowPoly.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/WhiteMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/BakeLightmap.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/Editor/Grid.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/PostProcessing.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/Quad.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/Shadows.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -2,9 +2,9 @@
"Name": "Flax",
"Version": {
"Major": 1,
"Minor": 10,
"Minor": 9,
"Revision": 0,
"Build": 6702
"Build": 6606
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",

View File

@@ -237,7 +237,6 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=Try_0020to_0020scripting/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/GrammarAndSpelling/GrammarChecking/RulesStates/=LanguageTool_002EEN_002EE_005FG/@EntryIndexedValue">DisabledByUser</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/Color/@EntryValue">Blue</s:String>

View File

@@ -1,11 +1,9 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Linq;
using FlaxEditor.Content.Create;
using FlaxEditor.CustomEditors;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
@@ -86,67 +84,18 @@ namespace FlaxEditor.Content
if (_element != null)
{
_element.CustomControl.CheckValid += OnCheckValidJsonAssetType;
// Define the rule for the types that can be used to create a json data asset
_element.CustomControl.CheckValid += type =>
type.Type != null &&
type.IsClass &&
type.Type.IsVisible &&
!type.IsAbstract &&
!type.IsGenericType &&
type.Type.GetConstructor(Type.EmptyTypes) != null &&
!typeof(FlaxEngine.GUI.Control).IsAssignableFrom(type.Type) &&
!typeof(FlaxEngine.Object).IsAssignableFrom(type.Type);
}
}
private static Type[] BlacklistedClasses =
[
typeof(System.Attribute),
typeof(FlaxEngine.Object),
typeof(FlaxEngine.GUI.Control),
];
private static Type[] BlacklistedStructs =
[
typeof(Float2),
typeof(Float3),
typeof(Float4),
typeof(Double2),
typeof(Double3),
typeof(Double4),
typeof(Vector2),
typeof(Vector3),
typeof(Vector4),
typeof(Half2),
typeof(Half3),
typeof(Half4),
typeof(Int2),
typeof(Int3),
typeof(Int4),
typeof(Transform),
typeof(Quaternion),
typeof(BoundingBox),
typeof(BoundingSphere),
typeof(BoundingFrustum),
typeof(Ray),
typeof(Plane),
typeof(Matrix),
typeof(Color),
typeof(Color32),
typeof(FloatR11G11B10),
typeof(FloatR10G10B10A2),
typeof(FlaxEngine.Half),
];
private static bool OnCheckValidJsonAssetType(ScriptType type)
{
// Define the rule for the types that can be used to create a json data asset
var mType = type.Type;
if (mType == null ||
type.IsAbstract ||
type.IsStatic ||
type.IsGenericType ||
!mType.IsVisible)
return false;
if (type.IsClass)
return mType.GetConstructor(Type.EmptyTypes) != null && BlacklistedClasses.FirstOrDefault(x => x.IsAssignableFrom(mType)) == null;
if (type.IsStructure)
return !type.IsPrimitive &&
!type.IsVoid &&
!BlacklistedStructs.Contains(mType);
return false;
}
}
}
@@ -226,7 +175,7 @@ namespace FlaxEditor.Content
{
_thumbnail = SpriteHandle.Invalid;
}
/// <summary>
/// Constructor with overriden thumbnail.
/// </summary>
@@ -247,7 +196,7 @@ namespace FlaxEditor.Content
{
Editor.SaveJsonAsset(outputPath, new T());
}
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{

View File

@@ -496,7 +496,7 @@ namespace FlaxEditor.Content.Thumbnails
// Prepare requests
bool isAnyReady = false;
int checks = Mathf.Min(10, _requests.Count);
for (int i = 0; i < checks && i < _requests.Count; i++)
for (int i = 0; i < checks; i++)
{
var request = _requests[i];
try

View File

@@ -8,7 +8,6 @@
#include "Engine/Core/Math/Color32.h"
#include "Engine/Core/Config/GameSettings.h"
#include "Editor/Utilities/EditorUtilities.h"
#include "Engine/Graphics/PixelFormatSampler.h"
#include "Engine/Graphics/Textures/TextureData.h"
#include "Engine/Tools/TextureTool/TextureTool.h"
#include "Engine/Content/Content.h"
@@ -241,7 +240,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
const TextureMipData* srcPixels = icon->GetData(0, srcPixelsMip);
const Color32* srcPixelsData = (Color32*)srcPixels->Data.Get();
const Int2 srcPixelsSize(Math::Max(1, icon->Width >> srcPixelsMip), Math::Max(1, icon->Height >> srcPixelsMip));
const auto sampler = PixelFormatSampler::Get(icon->Format);
const auto sampler = TextureTool::GetSampler(icon->Format);
ASSERT_LOW_LAYER(sampler);
// Write colors
@@ -253,7 +252,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
for (uint32 x = 0; x < width; x++)
{
float u = (float)x / width;
const Color c = sampler->SampleLinear(srcPixelsData, Float2(u, v), srcPixelsSize, srcPixels->RowPitch);
const Color c = TextureTool::SampleLinear(sampler, Float2(u, v), srcPixelsData, srcPixelsSize, srcPixels->RowPitch);
colorData[idx++] = Color32(c).GetAsBGRA();
}
}
@@ -272,7 +271,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
{
uint32 x = packedX * 8 + pixelIdx;
float u = (float)x / width;
const Color c = sampler->SampleLinear(srcPixelsData, Float2(u, v), srcPixelsSize, srcPixels->RowPitch);
const Color c = TextureTool::SampleLinear(sampler, Float2(u, v), srcPixelsData, srcPixelsSize, srcPixels->RowPitch);
if (c.A < 0.25f)
mask |= 1 << (7 - pixelIdx);
}
@@ -323,7 +322,7 @@ bool UpdateExeIcon(const String& path, const TextureData& icon)
const TextureData* iconRGBA8 = &icon;
TextureData tmpData1;
//if (icon.Format != PixelFormat::R8G8B8A8_UNorm)
if (PixelFormatSampler::Get(icon.Format) == nullptr)
if (TextureTool::GetSampler(icon.Format) == nullptr)
{
if (TextureTool::Convert(tmpData1, *iconRGBA8, PixelFormat::R8G8B8A8_UNorm))
{

View File

@@ -137,7 +137,10 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
if (!FileSystem::DirectoryExists(CacheFolder))
FileSystem::CreateDirectory(CacheFolder);
if (!FileSystem::FileExists(HeaderFilePath))
{
LOG(Warning, "Missing incremental build cooking assets cache.");
return;
}
auto file = FileReadStream::Open(HeaderFilePath);
if (file == nullptr)
@@ -155,7 +158,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
LOG(Info, "Loading incremental build cooking cache (entries count: {0})", entriesCount);
file->ReadBytes(&Settings, sizeof(Settings));
Entries.EnsureCapacity(entriesCount);
Entries.EnsureCapacity(Math::RoundUpToPowerOf2(static_cast<int32>(entriesCount * 3.0f)));
Array<Pair<String, DateTime>> fileDependencies;
for (int32 i = 0; i < entriesCount; i++)
@@ -163,7 +166,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
Guid id;
file->Read(id);
String typeName;
file->Read(typeName);
file->ReadString(&typeName);
DateTime fileModified;
file->Read(fileModified);
int32 fileDependenciesCount;
@@ -173,7 +176,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
for (int32 j = 0; j < fileDependenciesCount; j++)
{
Pair<String, DateTime>& f = fileDependencies[j];
file->Read(f.First, 10);
file->ReadString(&f.First, 10);
file->Read(f.Second);
}
@@ -308,9 +311,9 @@ void CookAssetsStep::CacheData::Save(CookingData& data)
{
auto& e = i->Value;
file->Write(e.ID);
file->Write(e.TypeName);
file->WriteString(e.TypeName);
file->Write(e.FileModified);
file->Write(e.FileDependencies.Count());
file->WriteInt32(e.FileDependencies.Count());
for (auto& f : e.FileDependencies)
{
file->Write(f.First, 10);
@@ -362,27 +365,17 @@ bool CookAssetsStep::ProcessDefaultAsset(AssetCookData& options)
bool CookAssetsStep::Process(CookingData& data, CacheData& cache, Asset* asset)
{
PROFILE_CPU_ASSET(asset);
// Validate asset
if (asset->IsVirtual())
{
// Virtual assets are not included into the build
return false;
}
const bool wasLoaded = asset->IsLoaded();
if (asset->WaitForLoaded())
{
LOG(Error, "Failed to load asset \'{0}\'", asset->ToString());
return true;
}
if (!wasLoaded)
{
// HACK: give some time to resave any old assets in Asset::onLoad after it's loaded
// This assumes that if Load Thread enters Asset::Save then it will get asset lock and hold it until asset is saved
// So we can take the same lock to wait for save end but first we need to wait for it to get that lock
// (in future try to handle it in a better way)
Platform::Sleep(5);
}
ScopeLock lock(asset->Locker);
// Switch based on an asset type
const auto asBinaryAsset = dynamic_cast<BinaryAsset*>(asset);
@@ -800,10 +793,7 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, BinaryAsset* a
// Prepare asset data
AssetInitData initData;
if (asset->Storage->LoadAssetHeader(asset->GetID(), initData))
{
LOG(Warning, "Failed to load asset {} header from storage '{}'", asset->GetID(), asset->Storage->GetPath());
return true;
}
initData.Header.UnlinkChunks();
initData.Metadata.Release();
for (auto& e : initData.Dependencies)
@@ -1175,7 +1165,7 @@ bool CookAssetsStep::Perform(CookingData& data)
assetRef = Content::LoadAsync<Asset>(assetId);
if (assetRef == nullptr)
{
LOG(Error, "Failed to load asset {} included in build", assetId);
data.Error(TEXT("Failed to load asset included in build."));
return true;
}
e.Info.TypeName = assetRef->GetTypeName();
@@ -1183,7 +1173,6 @@ bool CookAssetsStep::Perform(CookingData& data)
// Cook asset
if (Process(data, cache, assetRef.Get()))
{
LOG(Error, "Failed to process asset {}", assetRef->ToString());
cache.Save(data);
return true;
}
@@ -1216,17 +1205,10 @@ bool CookAssetsStep::Perform(CookingData& data)
// Copy file
if (!FileSystem::FileExists(cookedPath) || FileSystem::GetFileLastEditTime(cookedPath) >= FileSystem::GetFileLastEditTime(filePath))
{
const String cookedFolder = StringUtils::GetDirectoryName(cookedPath);
if (FileSystem::CreateDirectory(cookedFolder))
{
LOG(Error, "Failed to create directory '{}'", cookedFolder);
if (FileSystem::CreateDirectory(StringUtils::GetDirectoryName(cookedPath)))
return true;
}
if (FileSystem::CopyFile(cookedPath, filePath))
{
LOG(Error, "Failed to copy file from '{}' to '{}'", filePath, cookedPath);
return true;
}
}
// Count stats of file extension
@@ -1267,7 +1249,7 @@ bool CookAssetsStep::Perform(CookingData& data)
*(int32*)(bytes.Get() + 804) = contentKey;
*(Guid*)(bytes.Get() + 808) = gameSettings->SplashScreen;
Encryption::EncryptBytes(bytes.Get(), bytes.Count());
stream->Write(bytes);
stream->WriteArray(bytes);
Delete(stream);
}

View File

@@ -213,59 +213,38 @@ bool DeployDataStep::Perform(CookingData& data)
}
FileSystem::NormalizePath(srcDotnet);
LOG(Info, "Using .NET Runtime {} at {}", TEXT("Host"), srcDotnet);
const bool srcDotnetFromEngine = srcDotnet.Contains(TEXT("Source/Platforms"));
String packFolder = srcDotnet / TEXT("../../../");
// Get .NET runtime version
// Get major Version
Array<String> pathParts;
srcDotnet.Split('/', pathParts);
String version;
for (int i = 0; i < pathParts.Count(); i++)
{
// Detect from path provided by build tool
Array<String> pathParts;
srcDotnet.Split('/', pathParts);
for (int32 i = 1; i < pathParts.Count(); i++)
if (pathParts[i] == TEXT("runtimes"))
{
if (pathParts[i] == TEXT("runtimes"))
Array<String> versionParts;
pathParts[i - 1].Split('.', versionParts);
if (!versionParts.IsEmpty())
{
Array<String> versionParts;
pathParts[i - 1].Split('.', versionParts);
if (!versionParts.IsEmpty())
{
const String majorVersion = versionParts[0].TrimTrailing();
int32 versionNum;
StringUtils::Parse(*majorVersion, majorVersion.Length(), &versionNum);
if (Math::IsInRange(versionNum, GAME_BUILD_DOTNET_RUNTIME_MIN_VER, GAME_BUILD_DOTNET_RUNTIME_MAX_VER)) // Check for major part
version = majorVersion;
}
}
}
if (version.IsEmpty())
{
if (srcDotnetFromEngine)
{
// Detect version from runtime files inside Engine Platform folder
for (int32 i = GAME_BUILD_DOTNET_RUNTIME_MAX_VER; i >= GAME_BUILD_DOTNET_RUNTIME_MIN_VER; i--)
{
// Check runtime files inside Engine Platform folder
String testPath1 = srcDotnet / String::Format(TEXT("lib/net{}.0"), i);
String testPath2 = packFolder / String::Format(TEXT("Dotnet/lib/net{}.0"), i);
if ((FileSystem::DirectoryExists(testPath1) && FileSystem::GetDirectorySize(testPath1) > 0) ||
(FileSystem::DirectoryExists(testPath2) && FileSystem::GetDirectorySize(testPath2) > 0))
{
version = StringUtils::ToString(i);
break;
}
}
}
if (version.IsEmpty())
{
data.Error(TEXT("Failed to find supported .NET version for the current host platform."));
return true;
const String majorVersion = versionParts[0].TrimTrailing();
int32 versionNum;
StringUtils::Parse(*majorVersion, majorVersion.Length(), &versionNum);
if (Math::IsInRange(versionNum, GAME_BUILD_DOTNET_RUNTIME_MIN_VER, GAME_BUILD_DOTNET_RUNTIME_MAX_VER)) // Check for major part
version = majorVersion;
}
}
}
if (version.IsEmpty())
{
data.Error(TEXT("Failed to find supported .NET version for the current host platform."));
return true;
}
// Deploy runtime files
const Char* corlibPrivateName = TEXT("System.Private.CoreLib.dll");
const bool srcDotnetFromEngine = srcDotnet.Contains(TEXT("Source/Platforms"));
String packFolder = srcDotnet / TEXT("../../../");
String dstDotnetLibs = dstDotnet, srcDotnetLibs = srcDotnet;
StringUtils::PathRemoveRelativeParts(packFolder);
if (usAOT)

View File

@@ -39,9 +39,14 @@ CustomEditorsUtilService CustomEditorsUtilServiceInstance;
struct Entry
{
MClass* DefaultEditor = nullptr;
MClass* CustomEditor = nullptr;
MType* CustomEditorType = nullptr;
MClass* DefaultEditor;
MClass* CustomEditor;
Entry()
{
DefaultEditor = nullptr;
CustomEditor = nullptr;
}
};
Dictionary<MType*, Entry> Cache(512);
@@ -58,11 +63,11 @@ MTypeObject* CustomEditorsUtil::GetCustomEditor(MTypeObject* refType)
Entry result;
if (Cache.TryGet(type, result))
{
if (result.CustomEditorType)
return INTERNAL_TYPE_GET_OBJECT(result.CustomEditorType);
MClass* editor = result.CustomEditor ? result.CustomEditor : result.DefaultEditor;
if (editor)
{
return MUtils::GetType(editor);
}
}
return nullptr;
}
@@ -152,7 +157,7 @@ void OnAssemblyLoaded(MAssembly* assembly)
else if (typeClass)
{
auto& entry = Cache[mclass->GetType()];
entry.CustomEditorType = type;
entry.CustomEditor = typeClass;
//LOG(Info, "Custom Editor {0} for type {1}", String(typeClass->GetFullName()), String(mclass->GetFullName()));
}

View File

@@ -68,15 +68,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Use default prefab instance as a reference for the editor
Values.SetReferenceValue(prefabInstance);
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
var panel = layout.CustomContainer<UniformGridPanel>();
panel.CustomControl.Height = 20.0f;
panel.CustomControl.SlotsVertically = 1;
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter || nestedPrefab)
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter)
{
var targetPrefab = nestedPrefab ?? prefab;
// Add some UI
var panel = layout.CustomContainer<UniformGridPanel>();
panel.CustomControl.Height = 20.0f;
panel.CustomControl.SlotsVertically = 1;
panel.CustomControl.SlotsHorizontally = 3;
// Selecting actor prefab asset
@@ -84,21 +81,17 @@ namespace FlaxEditor.CustomEditors.Dedicated
selectPrefab.Button.Clicked += () =>
{
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
Editor.Instance.Windows.ContentWin.Select(targetPrefab);
Editor.Instance.Windows.ContentWin.Select(prefab);
};
// Edit selected prefab asset
var editPrefab = panel.Button("Edit Prefab");
editPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Open(Editor.Instance.ContentDatabase.FindAsset(targetPrefab.ID));
}
else
{
panel.CustomControl.SlotsHorizontally = 1;
}
editPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Open(Editor.Instance.ContentDatabase.FindAsset(prefab.ID));
// Viewing changes applied to this actor
var viewChanges = panel.Button("View Changes");
viewChanges.Button.Clicked += () => ViewChanges(viewChanges.Button, new Float2(0.0f, 20.0f));
// Viewing changes applied to this actor
var viewChanges = panel.Button("View Changes");
viewChanges.Button.Clicked += () => ViewChanges(viewChanges.Button, new Float2(0.0f, 20.0f));
}
// Link event to update editor on prefab apply
_linkedPrefabId = prefab.ID;

View File

@@ -15,23 +15,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
private int _firstTimeShow;
private BezierCurveEditor<T> _curve;
private Splitter _splitter;
private string _heightCachedPath;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var item = layout.CustomContainer<BezierCurveEditor<T>>();
_curve = item.CustomControl;
var height = 120.0f;
var presenter = Presenter;
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Try to restore curve height
_heightCachedPath = layout.GetLayoutCachePath("Height");
if (Editor.Instance.ProjectCache.TryGetCustomData(_heightCachedPath, out float cachedHeight) && cachedHeight > 10.0f)
height = cachedHeight;
}
_curve.Height = height;
_curve.Height = 120.0f;
_curve.Edited += OnCurveEdited;
_firstTimeShow = 4; // For some weird reason it needs several frames of warmup (probably due to sliders smoothing)
_splitter = new Splitter
@@ -55,11 +45,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void OnSplitterMoved(Float2 location)
{
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
// Cache curve height
if (_heightCachedPath != null)
Editor.Instance.ProjectCache.SetCustomData(_heightCachedPath, _curve.Height);
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
}
/// <inheritdoc />
@@ -147,23 +133,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
private int _firstTimeShow;
private LinearCurveEditor<T> _curve;
private Splitter _splitter;
private string _heightCachedPath;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var item = layout.CustomContainer<LinearCurveEditor<T>>();
_curve = item.CustomControl;
var height = 120.0f;
var presenter = Presenter;
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Try to restore curve height
_heightCachedPath = layout.GetLayoutCachePath("Height");
if (Editor.Instance.ProjectCache.TryGetCustomData(_heightCachedPath, out float cachedHeight) && cachedHeight > 10.0f)
height = cachedHeight;
}
_curve.Height = height;
_curve.Height = 120.0f;
_curve.Edited += OnCurveEdited;
_firstTimeShow = 4; // For some weird reason it needs several frames of warmup (probably due to sliders smoothing)
_splitter = new Splitter
@@ -188,10 +164,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void OnSplitterMoved(Float2 location)
{
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
// Cache curve height
if (_heightCachedPath != null)
Editor.Instance.ProjectCache.SetCustomData(_heightCachedPath, _curve.Height);
}
/// <inheritdoc />

View File

@@ -92,7 +92,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (IsLinearTangentMode(spline, index) || IsSmoothInTangentMode(spline, index) || IsSmoothOutTangentMode(spline, index))
{
SetPointSmooth(Editor, spline, index);
SetPointSmooth(spline, index);
}
}
}
@@ -145,7 +145,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (!IsAlignedTangentMode(spline, index))
{
SetPointSmooth(Editor, spline, index);
SetPointSmooth(spline, index);
}
}
@@ -176,7 +176,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc/>
public override void OnSetMode(Spline spline, int index)
{
SetTangentSmoothIn(Editor, spline, index);
SetTangentSmoothIn(spline, index);
Editor.SetSelectTangentIn(spline, index);
}
}
@@ -190,7 +190,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc/>
public override void OnSetMode(Spline spline, int index)
{
SetTangentSmoothOut(Editor, spline, index);
SetTangentSmoothOut(spline, index);
Editor.SetSelectTangentOut(spline, index);
}
}
@@ -756,15 +756,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline();
}
private static void SetTangentSmoothIn(SplineEditor editor, Spline spline, int index)
private static void SetTangentSmoothIn(Spline spline, int index)
{
var keyframe = spline.GetSplineKeyframe(index);
// Auto smooth tangent if's linear
if (keyframe.TangentIn.Translation.Length == 0)
{
var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f, cameraTransform);
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f);
var previousKeyframe = spline.GetSplineKeyframe(index - 1);
var tangentDirection = keyframe.Value.WorldToLocalVector(previousKeyframe.Value.Translation - keyframe.Value.Translation);
tangentDirection = tangentDirection.Normalized * smoothRange;
@@ -776,15 +775,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline();
}
private static void SetTangentSmoothOut(SplineEditor editor, Spline spline, int index)
private static void SetTangentSmoothOut(Spline spline, int index)
{
var keyframe = spline.GetSplineKeyframe(index);
// Auto smooth tangent if's linear
if (keyframe.TangentOut.Translation.Length == 0)
{
var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f, cameraTransform);
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplineTangent(index, false).Translation, 10f);
var nextKeyframe = spline.GetSplineKeyframe(index + 1);
var tangentDirection = keyframe.Value.WorldToLocalVector(nextKeyframe.Value.Translation - keyframe.Value.Translation);
tangentDirection = tangentDirection.Normalized * smoothRange;
@@ -797,7 +795,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
spline.UpdateSpline();
}
private static void SetPointSmooth(SplineEditor editor, Spline spline, int index)
private static void SetPointSmooth(Spline spline, int index)
{
var keyframe = spline.GetSplineKeyframe(index);
var tangentInSize = keyframe.TangentIn.Translation.Length;
@@ -805,8 +803,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var isLastKeyframe = index >= spline.SplinePointsCount - 1;
var isFirstKeyframe = index <= 0;
var cameraTransform = editor.Presenter.Owner.PresenterViewport.ViewTransform.Translation;
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplinePoint(index), 10f, cameraTransform);
var smoothRange = SplineNode.NodeSizeByDistance(spline.GetSplinePoint(index), 10f);
// Force smooth it's linear point
if (tangentInSize == 0f)

View File

@@ -95,7 +95,7 @@ namespace FlaxEditor.CustomEditors.Editors
if (assetReference != null)
{
if (assetReference.UseSmallPicker)
height = 36;
height = 32;
if (string.IsNullOrEmpty(assetReference.TypeName))
{
}
@@ -123,9 +123,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
var differentValues = HasDifferentValues;
Picker.DifferentValues = differentValues;
if (!differentValues)
if (!HasDifferentValues)
{
_isRefreshing = true;
var value = Values[0];
@@ -377,9 +375,12 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
_isRefreshing = true;
_textBox.Text = HasDifferentValues ? "Multiple Values" : GetPath();
_isRefreshing = false;
if (!HasDifferentValues)
{
_isRefreshing = true;
_textBox.Text = GetPath();
_isRefreshing = false;
}
}
/// <inheritdoc />

View File

@@ -26,8 +26,6 @@ namespace FlaxEditor.CustomEditors.Editors
public override void Initialize(LayoutElementsContainer layout)
{
_label = layout.ClickableLabel(Path).CustomControl;
_label.Margin = new Margin(0, 20.0f, 0, 0);
_label.ClipText = true;
_label.RightClick += ShowPicker;
var button = new Button
{

View File

@@ -1,84 +0,0 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using Object = FlaxEngine.Object;
namespace FlaxEditor.CustomEditors.Editors;
/// <summary>
/// The reference picker control used for UIControls using ControlReference.
/// </summary>
internal class UIControlRefPickerControl : FlaxObjectRefPickerControl
{
/// <summary>
/// Type of the control to pick.
/// </summary>
public Type ControlType;
/// <inheritdoc />
protected override bool IsValid(Object obj)
{
return obj == null || (obj is UIControl control && control.Control.GetType() == ControlType);
}
}
/// <summary>
/// ControlReferenceEditor class.
/// </summary>
[CustomEditor(typeof(ControlReference<>)), DefaultEditor]
internal class ControlReferenceEditor : CustomEditor
{
private CustomElement<UIControlRefPickerControl> _element;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
if (!HasDifferentTypes)
{
_element = layout.Custom<UIControlRefPickerControl>();
if (ValuesTypes == null || ValuesTypes[0] == null)
{
Editor.LogWarning("ControlReference needs to be assigned in code.");
return;
}
Type genType = ValuesTypes[0].GetGenericArguments()[0];
if (typeof(Control).IsAssignableFrom(genType))
{
_element.CustomControl.PresenterContext = Presenter.Owner;
_element.CustomControl.ControlType = genType;
_element.CustomControl.Type = new ScriptType(typeof(UIControl));
}
_element.CustomControl.ValueChanged += () =>
{
Type genericType = ValuesTypes[0].GetGenericArguments()[0];
if (typeof(Control).IsAssignableFrom(genericType))
{
Type t = typeof(ControlReference<>);
Type tw = t.MakeGenericType(new Type[] { genericType });
var instance = Activator.CreateInstance(tw);
((IControlReference)instance).UIControl = (UIControl)_element.CustomControl.Value;
SetValue(instance);
}
};
}
}
/// <inheritdoc />
public override void Refresh()
{
base.Refresh();
if (!HasDifferentValues)
{
if (Values[0] is IControlReference cr)
_element.CustomControl.Value = cr.UIControl;
}
}
}

View File

@@ -9,8 +9,6 @@ using FlaxEditor.GUI.Drag;
using FlaxEditor.SceneGraph;
using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
@@ -43,12 +41,7 @@ namespace FlaxEditor.CustomEditors.Editors
private DragHandlers _dragHandlers;
/// <summary>
/// The presenter using this control.
/// </summary>
public IPresenterOwner PresenterContext;
/// <summary>
/// Gets or sets the allowed objects type (given type and all subclasses). Must be <see cref="Object"/> type of any subclass.
/// Gets or sets the allowed objects type (given type and all sub classes). Must be <see cref="Object"/> type of any subclass.
/// </summary>
public ScriptType Type
{
@@ -61,8 +54,7 @@ namespace FlaxEditor.CustomEditors.Editors
throw new ArgumentException(string.Format("Invalid type for FlaxObjectRefEditor. Input type: {0}", value != ScriptType.Null ? value.TypeName : "null"));
_type = value;
_supportsPickDropDown = new ScriptType(typeof(Actor)).IsAssignableFrom(value) ||
new ScriptType(typeof(Script)).IsAssignableFrom(value);
_supportsPickDropDown = new ScriptType(typeof(Actor)).IsAssignableFrom(value) || new ScriptType(typeof(Script)).IsAssignableFrom(value);
// Deselect value if it's not valid now
if (!IsValid(_value))
@@ -81,7 +73,7 @@ namespace FlaxEditor.CustomEditors.Editors
if (_value == value)
return;
if (!IsValid(value))
value = null;
throw new ArgumentException("Invalid object type.");
// Special case for missing objects (eg. referenced actor in script that is deleted in editor)
if (value != null && (Object.GetUnmanagedPtr(value) == IntPtr.Zero || value.ID == Guid.Empty))
@@ -92,17 +84,27 @@ namespace FlaxEditor.CustomEditors.Editors
// Get name to display
if (_value is Script script)
{
_valueName = script.Actor ? $"{type.Name} ({script.Actor.Name})" : type.Name;
}
else if (_value != null)
{
_valueName = _value.ToString();
}
else
{
_valueName = string.Empty;
}
// Update tooltip
if (_value is SceneObject sceneObject)
{
TooltipText = Utilities.Utils.GetTooltip(sceneObject);
}
else
{
TooltipText = string.Empty;
}
OnValueChanged();
}
@@ -127,11 +129,6 @@ namespace FlaxEditor.CustomEditors.Editors
/// </summary>
public Func<Object, ScriptType, bool> CheckValid;
/// <summary>
/// Utility flag used to indicate that there are different values assigned to this reference editor and user should be informed about it.
/// </summary>
public bool DifferentValues;
/// <summary>
/// Initializes a new instance of the <see cref="FlaxObjectRefPickerControl"/> class.
/// </summary>
@@ -141,12 +138,7 @@ namespace FlaxEditor.CustomEditors.Editors
_type = ScriptType.Object;
}
/// <summary>
/// Object validation check routine.
/// </summary>
/// <param name="obj">Input object to check.</param>
/// <returns>True if it can be assigned, otherwise false.</returns>
protected virtual bool IsValid(Object obj)
private bool IsValid(Object obj)
{
var type = TypeUtils.GetObjectType(obj);
return obj == null || _type.IsAssignableFrom(type) && (CheckValid == null || CheckValid(obj, type));
@@ -162,16 +154,7 @@ namespace FlaxEditor.CustomEditors.Editors
Value = actor;
RootWindow.Focus();
Focus();
}, PresenterContext);
}
else if (new ScriptType(typeof(Control)).IsAssignableFrom(_type))
{
ActorSearchPopup.Show(this, new Float2(0, Height), IsValid, actor =>
{
Value = actor as UIControl;
RootWindow.Focus();
Focus();
}, PresenterContext);
});
}
else
{
@@ -180,7 +163,7 @@ namespace FlaxEditor.CustomEditors.Editors
Value = script;
RootWindow.Focus();
Focus();
}, PresenterContext);
});
}
}
@@ -204,7 +187,7 @@ namespace FlaxEditor.CustomEditors.Editors
var frameRect = new Rectangle(0, 0, Width, 16);
if (isSelected)
frameRect.Width -= 16;
if (_supportsPickDropDown && isEnabled)
if (_supportsPickDropDown)
frameRect.Width -= 16;
var nameRect = new Rectangle(2, 1, frameRect.Width - 4, 14);
var button1Rect = new Rectangle(nameRect.Right + 2, 1, 14, 14);
@@ -214,14 +197,7 @@ namespace FlaxEditor.CustomEditors.Editors
Render2D.DrawRectangle(frameRect, isEnabled && (IsMouseOver || IsNavFocused) ? style.BorderHighlighted : style.BorderNormal);
// Check if has item selected
if (DifferentValues)
{
// Draw info
Render2D.PushClip(nameRect);
Render2D.DrawText(style.FontMedium, Type != null ? $"Multiple Values ({Utilities.Utils.GetPropertyNameUI(Type.ToString())})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
else if (isSelected)
if (isSelected)
{
// Draw name
Render2D.PushClip(nameRect);
@@ -240,7 +216,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
// Draw picker button
if (_supportsPickDropDown && isEnabled)
if (_supportsPickDropDown)
{
var pickerRect = isSelected ? button2Rect : button1Rect;
Render2D.DrawSprite(style.ArrowDown, pickerRect, isEnabled && pickerRect.Contains(_mousePos) ? style.Foreground : style.ForegroundGrey);
@@ -350,19 +326,10 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
if (PresenterContext is PropertiesWindow)
_linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
else if (PresenterContext is PrefabWindow prefabWindow)
_linkedTreeNode = prefabWindow.Graph.Root.Find(actor).TreeNode;
if (_linkedTreeNode != null)
{
_linkedTreeNode.ExpandAllParents();
if (PresenterContext is PropertiesWindow)
Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
else if (PresenterContext is PrefabWindow prefabWindow)
(prefabWindow.Tree.Parent as Panel).ScrollViewTo(_linkedTreeNode, true);
_linkedTreeNode.StartHighlight();
}
_linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
_linkedTreeNode.ExpandAllParents();
Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
_linkedTreeNode.StartHighlight();
}
return true;
}
@@ -405,9 +372,9 @@ namespace FlaxEditor.CustomEditors.Editors
// Select object
if (_value is Actor actor)
Select(actor);
Editor.Instance.SceneEditing.Select(actor);
else if (_value is Script script && script.Actor)
Select(script.Actor);
Editor.Instance.SceneEditing.Select(script.Actor);
else if (_value is Asset asset)
Editor.Instance.Windows.ContentWin.Select(asset);
}
@@ -425,14 +392,6 @@ namespace FlaxEditor.CustomEditors.Editors
ShowDropDownMenu();
}
private void Select(Actor actor)
{
if (PresenterContext is PropertiesWindow)
Editor.Instance.SceneEditing.Select(actor);
else if (PresenterContext is PrefabWindow prefabWindow)
prefabWindow.Select(prefabWindow.Graph.Root.Find(actor));
}
private void DoDrag()
{
// Do the drag drop operation if has selected element
@@ -456,13 +415,13 @@ namespace FlaxEditor.CustomEditors.Editors
// Ensure to have valid drag helpers (uses lazy init)
if (_dragActors == null)
_dragActors = new DragActors(ValidateDragActor);
_dragActors = new DragActors(x => IsValid(x.Actor));
if (_dragActorsWithScript == null)
_dragActorsWithScript = new DragActors(ValidateDragActorWithScript);
if (_dragAssets == null)
_dragAssets = new DragAssets(ValidateDragAsset);
if (_dragScripts == null)
_dragScripts = new DragScripts(ValidateDragScript);
_dragScripts = new DragScripts(IsValid);
if (_dragHandlers == null)
{
_dragHandlers = new DragHandlers
@@ -487,43 +446,6 @@ namespace FlaxEditor.CustomEditors.Editors
return DragEffect;
}
private bool ValidateDragActor(ActorNode a)
{
if (!IsValid(a.Actor))
return false;
if (PresenterContext is PrefabWindow prefabWindow)
{
if (prefabWindow.Tree == a.TreeNode.ParentTree)
return true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (a.ParentScene != null)
return true;
}
return false;
}
private bool ValidateDragScript(Script script)
{
if (!IsValid(script))
return false;
if (PresenterContext is PrefabWindow prefabWindow)
{
var actorNode = prefabWindow.Graph.Root.Find(script.Actor);
if (actorNode != null)
return true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (script.Actor.HasScene)
return true;
}
return false;
}
private bool ValidateDragAsset(AssetItem assetItem)
{
// Check if can accept assets
@@ -542,18 +464,7 @@ namespace FlaxEditor.CustomEditors.Editors
private bool ValidateDragActorWithScript(ActorNode node)
{
bool isCorrectContext = false;
if (PresenterContext is PrefabWindow prefabWindow)
{
if (prefabWindow.Tree == node.TreeNode.ParentTree)
isCorrectContext = true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (node.ParentScene != null)
isCorrectContext = true;
}
return node.Actor.Scripts.Any(IsValid) && isCorrectContext;
return node.Actor.Scripts.Any(IsValid);
}
/// <inheritdoc />
@@ -625,7 +536,6 @@ namespace FlaxEditor.CustomEditors.Editors
if (!HasDifferentTypes)
{
_element = layout.Custom<FlaxObjectRefPickerControl>();
_element.CustomControl.PresenterContext = Presenter.Owner;
_element.CustomControl.Type = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
_element.CustomControl.ValueChanged += () => SetValue(_element.CustomControl.Value);
}
@@ -636,9 +546,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
var differentValues = HasDifferentValues;
_element.CustomControl.DifferentValues = differentValues;
if (!differentValues)
if (!HasDifferentValues)
{
_element.CustomControl.Value = Values[0] as Object;
}

View File

@@ -36,7 +36,7 @@ namespace FlaxEditor.CustomEditors.Editors
float height = 48;
if (assetReference.UseSmallPicker)
height = 36;
height = 32;
if (string.IsNullOrEmpty(assetReference.TypeName))
{

View File

@@ -96,20 +96,6 @@ namespace FlaxEditor.CustomEditors
menu.Show(groupPanel, location);
}
internal string GetLayoutCachePath(string name)
{
// Build group identifier (made of path from group titles)
var expandPath = name;
var container = this;
while (container != null && !(container is CustomEditorPresenter))
{
if (container.ContainerControl is DropPanel dropPanel)
expandPath = dropPanel.HeaderText + "/" + expandPath;
container = container._parent;
}
return expandPath;
}
/// <summary>
/// Adds new group element.
/// </summary>
@@ -126,7 +112,14 @@ namespace FlaxEditor.CustomEditors
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Build group identifier (made of path from group titles)
var expandPath = GetLayoutCachePath(title);
var expandPath = title;
var container = this;
while (container != null && !(container is CustomEditorPresenter))
{
if (container.ContainerControl is DropPanel dropPanel)
expandPath = dropPanel.HeaderText + "/" + expandPath;
container = container._parent;
}
// Caching/restoring expanded groups (non-root groups cache expanded state so invert boolean expression)
if (Editor.Instance.ProjectCache.IsGroupToggled(expandPath) ^ isSubGroup)

View File

@@ -250,7 +250,7 @@ namespace FlaxEditor.CustomEditors
if (objA == null && objB is string objBStr && objBStr.Length == 0)
return true;
return FlaxEngine.Json.JsonSerializer.ValueEquals(objA, objB);
return Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals(objA, objB);
}
/// <summary>

View File

@@ -41,9 +41,6 @@ public class Editor : EditorModule
options.ScriptingAPI.SystemReferences.Add("System.Xml.ReaderWriter");
options.ScriptingAPI.SystemReferences.Add("System.Text.RegularExpressions");
options.ScriptingAPI.SystemReferences.Add("System.IO.Compression.ZipFile");
options.ScriptingAPI.SystemReferences.Add("System.Diagnostics.Process");
if (Profiler.Use(options))
options.ScriptingAPI.Defines.Add("USE_PROFILER");
// Enable optimizations for Editor, disable this for debugging the editor
if (options.Configuration == TargetConfiguration.Development)

View File

@@ -79,6 +79,10 @@ bool Editor::CheckProjectUpgrade()
Delete(file);
}
}
else
{
LOG(Warning, "Missing version cache file");
}
// Check if project is in the old, deprecated layout
if (EditorImpl::IsOldProjectXmlFormat)
@@ -399,7 +403,7 @@ int32 Editor::LoadProduct()
}
// Create new project option
if (CommandLine::Options.NewProject.IsTrue())
if (CommandLine::Options.NewProject)
{
Array<String> projectFiles;
FileSystem::DirectoryGetFiles(projectFiles, projectPath, TEXT("*.flaxproj"), DirectorySearchOption::TopDirectoryOnly);
@@ -424,7 +428,7 @@ int32 Editor::LoadProduct()
}
}
}
if (CommandLine::Options.NewProject.IsTrue())
if (CommandLine::Options.NewProject)
{
if (projectPath.IsEmpty())
projectPath = Platform::GetWorkingDirectory();
@@ -525,7 +529,7 @@ int32 Editor::LoadProduct()
if (projectPath.IsEmpty())
{
#if PLATFORM_HAS_HEADLESS_MODE
if (CommandLine::Options.Headless.IsTrue())
if (CommandLine::Options.Headless)
{
Platform::Fatal(TEXT("Missing project path."));
return -1;
@@ -608,7 +612,7 @@ int32 Editor::LoadProduct()
// Validate project min supported version (older engine may try to load newer project)
// Special check if project specifies only build number, then major/minor fields are set to 0
const auto engineVersion = FLAXENGINE_VERSION;
for (const auto& e : projects)
for (auto e : projects)
{
const auto project = e.Item;
if (project->MinEngineVersion > engineVersion ||
@@ -653,7 +657,7 @@ Window* Editor::CreateMainWindow()
bool Editor::Init()
{
// Scripts project files generation from command line
if (CommandLine::Options.GenProjectFiles.IsTrue())
if (CommandLine::Options.GenProjectFiles)
{
const String customArgs = TEXT("-verbose -log -logfile=\"Cache/Intermediate/ProjectFileLog.txt\"");
const bool failed = ScriptsBuilder::GenerateProject(customArgs);

View File

@@ -1550,9 +1550,9 @@ namespace FlaxEditor
// Handle case when Game window is not selected in tab view
var dockedTo = gameWin.ParentDockPanel;
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
result = dockedTo.SelectedTab.Size;
result = dockedTo.SelectedTab.Size * root.DpiScale;
else
result = gameWin.Viewport.Size;
result = gameWin.Viewport.Size * root.DpiScale;
result = Float2.Round(result);
}
@@ -1686,6 +1686,9 @@ namespace FlaxEditor
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_CanSetToRoot(IntPtr prefab, IntPtr newRoot);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetPrefabNestedObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
internal static partial void Internal_GetPrefabNestedObject(IntPtr prefabId, IntPtr prefabObjectId, IntPtr outPrefabId, IntPtr outPrefabObjectId);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetAnimationTime", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
internal static partial float Internal_GetAnimationTime(IntPtr animatedModel);

View File

@@ -48,11 +48,6 @@ namespace FlaxEditor.GUI
/// </summary>
public bool CanEdit = true;
/// <summary>
/// Utility flag used to indicate that there are different values assigned to this reference editor and user should be informed about it.
/// </summary>
public bool DifferentValues;
/// <summary>
/// Initializes a new instance of the <see cref="AssetPicker"/> class.
/// </summary>
@@ -126,13 +121,7 @@ namespace FlaxEditor.GUI
if (CanEdit)
Render2D.DrawSprite(style.ArrowDown, button1Rect, button1Rect.Contains(_mousePos) ? style.Foreground : style.ForegroundGrey);
if (DifferentValues)
{
// No element selected
Render2D.FillRectangle(iconRect, style.BackgroundNormal);
Render2D.DrawText(style.FontMedium, "Multiple\nValues", iconRect, style.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
}
else if (Validator.SelectedItem != null)
if (Validator.SelectedItem != null)
{
// Draw item preview
Validator.SelectedItem.DrawThumbnail(ref iconRect);

View File

@@ -355,14 +355,14 @@ namespace FlaxEditor.GUI.ContextMenu
}
/// <inheritdoc />
public override void Show(Control parent, Float2 location, ContextMenuDirection? direction = null)
public override void Show(Control parent, Float2 location)
{
// Remove last separator to make context menu look better
int lastIndex = _panel.Children.Count - 1;
if (lastIndex >= 0 && _panel.Children[lastIndex] is ContextMenuSeparator separator)
separator.Dispose();
base.Show(parent, location, direction);
base.Show(parent, location);
}
/// <inheritdoc />

View File

@@ -101,16 +101,6 @@ namespace FlaxEditor.GUI.ContextMenu
/// </summary>
public List<Window> ExternalPopups = new List<Window>();
/// <summary>
/// Optional flag that can disable popup visibility based on window focus and use external control via Hide.
/// </summary>
public bool UseVisibilityControl = true;
/// <summary>
/// Optional flag that can disable popup input capturing. Useful for transparent or visual-only popups.
/// </summary>
public bool UseInput = true;
/// <summary>
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
/// </summary>
@@ -147,26 +137,21 @@ namespace FlaxEditor.GUI.ContextMenu
/// </summary>
/// <param name="parent">Parent control to attach to it.</param>
/// <param name="location">Popup menu origin location in parent control coordinates.</param>
/// <param name="direction">The custom popup direction. Null to use automatic direction.</param>
public virtual void Show(Control parent, Float2 location, ContextMenuDirection? direction = null)
public virtual void Show(Control parent, Float2 location)
{
Assert.IsNotNull(parent);
bool isAlreadyVisible = Visible && _window;
if (!isAlreadyVisible)
Hide();
// Ensure to be closed
Hide();
// Peek parent control window
var parentWin = parent.RootWindow;
if (parentWin == null)
{
Hide();
return;
}
// Check if show menu inside the other menu - then link as a child to prevent closing the calling menu window on lost focus
if (_parentCM == null && parentWin.ChildrenCount == 1 && parentWin.Children[0] is ContextMenuBase parentCM)
{
Hide();
parentCM.ShowChild(this, parentCM.PointFromScreen(parent.PointToScreen(location)), false);
return;
}
@@ -184,7 +169,7 @@ namespace FlaxEditor.GUI.ContextMenu
var monitorBounds = Platform.GetMonitorBounds(locationSS);
var rightBottomLocationSS = locationSS + dpiSize;
bool isUp = false, isLeft = false;
if (UseAutomaticDirectionFix && direction == null)
if (UseAutomaticDirectionFix)
{
var parentMenu = parent as ContextMenu;
if (monitorBounds.Bottom < rightBottomLocationSS.Y)
@@ -211,26 +196,6 @@ namespace FlaxEditor.GUI.ContextMenu
locationSS.X -= dpiSize.X;
}
}
else if (direction.HasValue)
{
switch (direction.Value)
{
case ContextMenuDirection.RightUp:
isUp = true;
break;
case ContextMenuDirection.LeftDown:
isLeft = true;
break;
case ContextMenuDirection.LeftUp:
isLeft = true;
isUp = true;
break;
}
if (isLeft)
locationSS.X -= dpiSize.X;
if (isUp)
locationSS.Y -= dpiSize.Y;
}
// Update direction flag
if (isUp)
@@ -238,62 +203,47 @@ namespace FlaxEditor.GUI.ContextMenu
else
_direction = isLeft ? ContextMenuDirection.LeftDown : ContextMenuDirection.RightDown;
if (isAlreadyVisible)
{
_window.ClientBounds = new Rectangle(locationSS, dpiSize);
}
else
{
// Create window
var desc = CreateWindowSettings.Default;
desc.Position = locationSS;
desc.StartPosition = WindowStartPosition.Manual;
desc.Size = dpiSize;
desc.Fullscreen = false;
desc.HasBorder = false;
desc.SupportsTransparency = false;
desc.ShowInTaskbar = false;
desc.ActivateWhenFirstShown = UseInput;
desc.AllowInput = UseInput;
desc.AllowMinimize = false;
desc.AllowMaximize = false;
desc.AllowDragAndDrop = false;
desc.IsTopmost = true;
desc.Type = WindowType.Popup;
desc.Parent = parentWin.Window;
desc.Title = "ContextMenu";
desc.HasSizingFrame = false;
OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc);
if (UseVisibilityControl)
{
_window.GotFocus += OnWindowGotFocus;
_window.LostFocus += OnWindowLostFocus;
}
// Create window
var desc = CreateWindowSettings.Default;
desc.Position = locationSS;
desc.StartPosition = WindowStartPosition.Manual;
desc.Size = dpiSize;
desc.Fullscreen = false;
desc.HasBorder = false;
desc.SupportsTransparency = false;
desc.ShowInTaskbar = false;
desc.ActivateWhenFirstShown = true;
desc.AllowInput = true;
desc.AllowMinimize = false;
desc.AllowMaximize = false;
desc.AllowDragAndDrop = false;
desc.IsTopmost = true;
desc.Type = WindowType.Popup;
desc.Parent = parentWin.Window;
desc.Title = "ContextMenu";
desc.HasSizingFrame = false;
OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc);
_window.GotFocus += OnWindowGotFocus;
_window.LostFocus += OnWindowLostFocus;
#if USE_IS_FOREGROUND && USE_SDL_WORKAROUNDS
// The focus between popup and parent windows doesn't change, force hide the popup when clicked on parent
parentWin.Window.MouseDown += OnWindowMouseDown;
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
// The focus between popup and parent windows doesn't change, force hide the popup when clicked on parent
parentWin.Window.MouseDown += OnWindowMouseDown;
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
#endif
// Attach to the window
_parentCM = parent as ContextMenuBase;
Parent = _window.GUI;
}
// Attach to the window
_parentCM = parent as ContextMenuBase;
Parent = _window.GUI;
// Show
Visible = true;
if (_window == null)
return;
_window.Show();
PerformLayout();
if (UseVisibilityControl)
{
_previouslyFocused = parentWin.FocusedControl;
Focus();
OnShow();
}
_previouslyFocused = parentWin.FocusedControl;
Focus();
OnShow();
}
/// <summary>
@@ -558,7 +508,7 @@ namespace FlaxEditor.GUI.ContextMenu
base.Update(deltaTime);
// Let root context menu to check if none of the popup windows
if (_parentCM == null && UseVisibilityControl && !IsForeground)
if (_parentCM == null && !IsForeground)
{
#if USE_SDL_WORKAROUNDS
if (!IsMouseOver)

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