Merge remote-tracking branch 'origin/1.10' into sdl_platform
# Conflicts: # Source/Editor/GUI/ContextMenu/ContextMenuBase.cs # Source/Engine/Platform/Linux/LinuxPlatform.cpp
This commit is contained in:
3
.github/workflows/tests.yml
vendored
3
.github/workflows/tests.yml
vendored
@@ -73,8 +73,11 @@ jobs:
|
|||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
|
.\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
|
dotnet msbuild Source\Tools\Flax.Build.Tests\Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||||
- name: Test
|
- name: Test
|
||||||
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
.\Binaries\Editor\Win64\Development\FlaxTests.exe
|
.\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
|
dotnet test -f net8.0 Binaries\Tests\Flax.Build.Tests.dll
|
||||||
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests
|
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests
|
||||||
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.runtimeconfig.json Binaries\Tests
|
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.runtimeconfig.json Binaries\Tests
|
||||||
|
|||||||
BIN
Content/Editor/Camera/M_Camera.flax
(Stored with Git LFS)
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)
BIN
Content/Editor/Camera/O_Camera.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialWireFocus.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialWireFocus.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/RotationAxis.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/RotationAxis.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/ScaleAxis.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/ScaleAxis.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/TranslationAxis.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/TranslationAxis.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/WireBox.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/WireBox.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/AudioListener.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/AudioListener.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/AudioSource.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/AudioSource.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/Decal.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/Decal.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/DirectionalLight.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/DirectionalLight.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/EnvironmentProbe.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/EnvironmentProbe.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/ParticleEffect.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/ParticleEffect.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/PointLight.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/PointLight.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/SceneAnimationPlayer.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/SceneAnimationPlayer.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/SkyLight.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/SkyLight.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/Skybox.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/Skybox.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
@@ -83,6 +83,12 @@ float3 GetObjectSize(MaterialInput input)
|
|||||||
return float3(1, 1, 1);
|
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)
|
// Get the current object random value supports instancing)
|
||||||
float GetPerInstanceRandom(MaterialInput input)
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -207,6 +207,20 @@ float3 GetObjectSize(MaterialInput input)
|
|||||||
return GeometrySize * float3(world._m00, world._m11, world._m22);
|
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
|
// Get the current object random value
|
||||||
float GetPerInstanceRandom(MaterialInput input)
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
{
|
{
|
||||||
@@ -297,7 +311,7 @@ VertexOutput VS_SplineModel(ModelInput input)
|
|||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
// Pass vertex attributes
|
// Pass vertex attributes
|
||||||
output.Geometry.TexCoord = input.TexCoord;
|
output.Geometry.TexCoord = input.TexCoord0;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.Geometry.VertexColor = input.Color;
|
output.Geometry.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -163,6 +163,12 @@ float3 GetObjectSize(MaterialInput input)
|
|||||||
return float3(1, 1, 1);
|
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)
|
// Get the current object random value supports instancing)
|
||||||
float GetPerInstanceRandom(MaterialInput input)
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -299,24 +299,22 @@ half3x3 CalcTangentToLocal(ModelInput input)
|
|||||||
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
||||||
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||||
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
||||||
return float3x3(tangent, bitangent, normal);
|
return (half3x3)float3x3(tangent, bitangent, normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
half3x3 CalcTangentToWorld(in float4x4 world, in half3x3 tangentToLocal)
|
half3x3 CalcTangentToWorld(in float4x4 world, in half3x3 tangentToLocal)
|
||||||
{
|
{
|
||||||
half3x3 localToWorld = RemoveScaleFromLocalToWorld((float3x3)world);
|
half3x3 localToWorld = (half3x3)RemoveScaleFromLocalToWorld((float3x3)world);
|
||||||
return mul(tangentToLocal, localToWorld);
|
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
|
// Vertex Shader function for Sprite Rendering
|
||||||
META_VS(true, FEATURE_LEVEL_ES2)
|
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 VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
|
||||||
{
|
{
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
@@ -407,7 +405,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
|
|||||||
output.InstanceParams = PerInstanceRandom;
|
output.InstanceParams = PerInstanceRandom;
|
||||||
|
|
||||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
half3x3 tangentToLocal = float3x3(axisX, axisY, axisZ);
|
half3x3 tangentToLocal = half3x3(axisX, axisY, axisZ);
|
||||||
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||||
output.TBN = tangentToWorld;
|
output.TBN = tangentToWorld;
|
||||||
|
|
||||||
@@ -516,7 +514,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
|||||||
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
// Pass vertex attributes
|
// Pass vertex attributes
|
||||||
output.TexCoord = input.TexCoord;
|
output.TexCoord = input.TexCoord0;
|
||||||
output.ParticleIndex = particleIndex;
|
output.ParticleIndex = particleIndex;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = input.Color;
|
output.VertexColor = input.Color;
|
||||||
@@ -612,7 +610,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
|
|||||||
{
|
{
|
||||||
output.TexCoord.x = (float)input.Order / (float)RibbonSegmentCount;
|
output.TexCoord.x = (float)input.Order / (float)RibbonSegmentCount;
|
||||||
}
|
}
|
||||||
output.TexCoord.y = (vertexIndex + 1) & 0x1;
|
output.TexCoord.y = (float)((vertexIndex + 1) & 0x1);
|
||||||
output.TexCoord = output.TexCoord * RibbonUVScale + RibbonUVOffset;
|
output.TexCoord = output.TexCoord * RibbonUVScale + RibbonUVOffset;
|
||||||
|
|
||||||
// Compute world space vertex position
|
// Compute world space vertex position
|
||||||
@@ -631,7 +629,7 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
|
|||||||
output.InstanceParams = PerInstanceRandom;
|
output.InstanceParams = PerInstanceRandom;
|
||||||
|
|
||||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
|
half3x3 tangentToLocal = half3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
|
||||||
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||||
output.TBN = tangentToWorld;
|
output.TBN = tangentToWorld;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Version: @0
|
// Version: @0
|
||||||
|
|
||||||
#define MATERIAL 1
|
#define MATERIAL 1
|
||||||
|
#define MATERIAL_TEXCOORDS 4
|
||||||
#define USE_PER_VIEW_CONSTANTS 1
|
#define USE_PER_VIEW_CONSTANTS 1
|
||||||
#define USE_PER_DRAW_CONSTANTS 1
|
#define USE_PER_DRAW_CONSTANTS 1
|
||||||
@3
|
@3
|
||||||
@@ -24,21 +25,29 @@ Buffer<float4> BoneMatrices : register(t1);
|
|||||||
Buffer<float4> PrevBoneMatrices : register(t2);
|
Buffer<float4> PrevBoneMatrices : register(t2);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||||
struct GeometryData
|
struct GeometryData
|
||||||
{
|
{
|
||||||
float3 WorldPosition : TEXCOORD0;
|
float3 WorldPosition : TEXCOORD0;
|
||||||
float2 TexCoord : TEXCOORD1;
|
float4 TexCoords01 : TEXCOORD1;
|
||||||
float2 LightmapUV : TEXCOORD2;
|
float4 TexCoords23 : TEXCOORD2;
|
||||||
|
float2 LightmapUV : TEXCOORD3;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
half4 VertexColor : COLOR;
|
half4 VertexColor : COLOR;
|
||||||
#endif
|
#endif
|
||||||
float3 WorldNormal : TEXCOORD3;
|
float3 WorldNormal : TEXCOORD4;
|
||||||
float4 WorldTangent : TEXCOORD4;
|
float4 WorldTangent : TEXCOORD5;
|
||||||
float3 PrevWorldPosition : TEXCOORD7;
|
float3 PrevWorldPosition : TEXCOORD7;
|
||||||
nointerpolation uint ObjectIndex : TEXCOORD8;
|
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
|
// Interpolants passed from the vertex shader
|
||||||
struct VertexOutput
|
struct VertexOutput
|
||||||
{
|
{
|
||||||
@@ -68,7 +77,7 @@ struct MaterialInput
|
|||||||
{
|
{
|
||||||
float3 WorldPosition;
|
float3 WorldPosition;
|
||||||
float TwoSidedSign;
|
float TwoSidedSign;
|
||||||
float2 TexCoord;
|
float2 TexCoords[MATERIAL_TEXCOORDS];
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
float2 LightmapUV;
|
float2 LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
@@ -86,12 +95,18 @@ struct MaterialInput
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Map access to the main texure coordinate channel as UV0
|
||||||
|
#define TexCoord TexCoords[0]
|
||||||
|
|
||||||
// Extracts geometry data to the material input
|
// Extracts geometry data to the material input
|
||||||
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||||
{
|
{
|
||||||
MaterialInput output = (MaterialInput)0;
|
MaterialInput output = (MaterialInput)0;
|
||||||
output.WorldPosition = geometry.WorldPosition;
|
output.WorldPosition = geometry.WorldPosition;
|
||||||
output.TexCoord = geometry.TexCoord;
|
output.TexCoords[0] = geometry.TexCoords01.xy;
|
||||||
|
output.TexCoords[1] = geometry.TexCoords01.zw;
|
||||||
|
output.TexCoords[2] = geometry.TexCoords23.xy;
|
||||||
|
output.TexCoords[3] = geometry.TexCoords23.zw;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
output.LightmapUV = geometry.LightmapUV;
|
output.LightmapUV = geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
@@ -126,8 +141,8 @@ MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
|||||||
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
||||||
{
|
{
|
||||||
GeometryData output = (GeometryData)0;
|
GeometryData output = (GeometryData)0;
|
||||||
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
|
output.TexCoords01 = p0.TexCoords01 * w0 + p1.TexCoords01 * w1 + p2.TexCoords01 * w2;
|
||||||
output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2;
|
output.TexCoords23 = p0.TexCoords23 * w0 + p1.TexCoords23 * w1 + p2.TexCoords23 * w2;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
|
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
|
||||||
#endif
|
#endif
|
||||||
@@ -223,6 +238,24 @@ float3 GetObjectSize(MaterialInput input)
|
|||||||
return input.Object.GeometrySize * float3(world._m00, world._m11, world._m22);
|
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)
|
// Get the current object random value (supports instancing)
|
||||||
float GetPerInstanceRandom(MaterialInput input)
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
{
|
{
|
||||||
@@ -312,14 +345,15 @@ VertexOutput VS(ModelInput input)
|
|||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
// Pass vertex attributes
|
// Pass vertex attributes
|
||||||
output.Geometry.TexCoord = input.TexCoord;
|
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
|
||||||
|
output.Geometry.TexCoords23 = float4(input.TexCoord2, input.TexCoord3);
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.Geometry.VertexColor = input.Color;
|
output.Geometry.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
#if CAN_USE_LIGHTMAP
|
#if CAN_USE_LIGHTMAP
|
||||||
output.Geometry.LightmapUV = input.LightmapUV * object.LightmapArea.zw + object.LightmapArea.xy;
|
output.Geometry.LightmapUV = input.LightmapUV * object.LightmapArea.zw + object.LightmapArea.xy;
|
||||||
#else
|
#else
|
||||||
output.Geometry.LightmapUV = input.LightmapUV;
|
output.Geometry.LightmapUV = float2(0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
@@ -459,7 +493,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(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(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(BLENDINDICES, 0, R8G8B8A8_UINT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||||
META_VS_IN_ELEMENT(BLENDWEIGHT, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0, true)
|
META_VS_IN_ELEMENT(BLENDWEIGHTS, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0, true)
|
||||||
VertexOutput VS_Skinned(ModelInput_Skinned input)
|
VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||||
{
|
{
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
@@ -486,9 +520,10 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
|||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
// Pass vertex attributes
|
// Pass vertex attributes
|
||||||
output.Geometry.TexCoord = input.TexCoord;
|
output.Geometry.TexCoords01 = float4(input.TexCoord0, input.TexCoord1);
|
||||||
|
output.Geometry.TexCoords23 = float4(input.TexCoord2, input.TexCoord3);
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.Geometry.VertexColor = float4(0, 0, 0, 1);
|
output.Geometry.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
output.Geometry.LightmapUV = float2(0, 0);
|
output.Geometry.LightmapUV = float2(0, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -236,6 +236,12 @@ float3 GetObjectSize(MaterialInput input)
|
|||||||
return float3(1, 1, 1);
|
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
|
// Get the current object random value
|
||||||
float GetPerInstanceRandom(MaterialInput input)
|
float GetPerInstanceRandom(MaterialInput input)
|
||||||
{
|
{
|
||||||
@@ -319,8 +325,6 @@ struct TerrainVertexInput
|
|||||||
|
|
||||||
// Vertex Shader function for terrain rendering
|
// Vertex Shader function for terrain rendering
|
||||||
META_VS(true, FEATURE_LEVEL_ES2)
|
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 VS(TerrainVertexInput input)
|
||||||
{
|
{
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
|
|||||||
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Particle Material Preview.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Particle Material Preview.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Capsule.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Capsule.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Cone.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cone.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Cylinder.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cylinder.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Plane.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Plane.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Sphere.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Sphere.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Models/Box.flax
(Stored with Git LFS)
BIN
Content/Engine/Models/Box.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Models/Quad.flax
(Stored with Git LFS)
BIN
Content/Engine/Models/Quad.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Models/SimpleBox.flax
(Stored with Git LFS)
BIN
Content/Engine/Models/SimpleBox.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Models/Sphere.flax
(Stored with Git LFS)
BIN
Content/Engine/Models/Sphere.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Models/SphereLowPoly.flax
(Stored with Git LFS)
BIN
Content/Engine/Models/SphereLowPoly.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/WhiteMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/WhiteMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/BakeLightmap.flax
(Stored with Git LFS)
BIN
Content/Shaders/BakeLightmap.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Editor/LightmapUVsDensity.flax
(Stored with Git LFS)
BIN
Content/Shaders/Editor/LightmapUVsDensity.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Shadows.flax
(Stored with Git LFS)
BIN
Content/Shaders/Shadows.flax
(Stored with Git LFS)
Binary file not shown.
@@ -2,9 +2,9 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 9,
|
"Minor": 10,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6606
|
"Build": 6702
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
||||||
|
|||||||
@@ -237,6 +237,7 @@
|
|||||||
<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_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_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/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: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: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>
|
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/Color/@EntryValue">Blue</s:String>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "Engine/Core/Math/Color32.h"
|
#include "Engine/Core/Math/Color32.h"
|
||||||
#include "Engine/Core/Config/GameSettings.h"
|
#include "Engine/Core/Config/GameSettings.h"
|
||||||
#include "Editor/Utilities/EditorUtilities.h"
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
|
#include "Engine/Graphics/PixelFormatSampler.h"
|
||||||
#include "Engine/Graphics/Textures/TextureData.h"
|
#include "Engine/Graphics/Textures/TextureData.h"
|
||||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
@@ -240,7 +241,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
|
|||||||
const TextureMipData* srcPixels = icon->GetData(0, srcPixelsMip);
|
const TextureMipData* srcPixels = icon->GetData(0, srcPixelsMip);
|
||||||
const Color32* srcPixelsData = (Color32*)srcPixels->Data.Get();
|
const Color32* srcPixelsData = (Color32*)srcPixels->Data.Get();
|
||||||
const Int2 srcPixelsSize(Math::Max(1, icon->Width >> srcPixelsMip), Math::Max(1, icon->Height >> srcPixelsMip));
|
const Int2 srcPixelsSize(Math::Max(1, icon->Width >> srcPixelsMip), Math::Max(1, icon->Height >> srcPixelsMip));
|
||||||
const auto sampler = TextureTool::GetSampler(icon->Format);
|
const auto sampler = PixelFormatSampler::Get(icon->Format);
|
||||||
ASSERT_LOW_LAYER(sampler);
|
ASSERT_LOW_LAYER(sampler);
|
||||||
|
|
||||||
// Write colors
|
// Write colors
|
||||||
@@ -252,7 +253,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
|
|||||||
for (uint32 x = 0; x < width; x++)
|
for (uint32 x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
float u = (float)x / width;
|
float u = (float)x / width;
|
||||||
const Color c = TextureTool::SampleLinear(sampler, Float2(u, v), srcPixelsData, srcPixelsSize, srcPixels->RowPitch);
|
const Color c = sampler->SampleLinear(srcPixelsData, Float2(u, v), srcPixelsSize, srcPixels->RowPitch);
|
||||||
colorData[idx++] = Color32(c).GetAsBGRA();
|
colorData[idx++] = Color32(c).GetAsBGRA();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,7 +272,7 @@ void UpdateIconData(uint8* iconData, const TextureData* icon)
|
|||||||
{
|
{
|
||||||
uint32 x = packedX * 8 + pixelIdx;
|
uint32 x = packedX * 8 + pixelIdx;
|
||||||
float u = (float)x / width;
|
float u = (float)x / width;
|
||||||
const Color c = TextureTool::SampleLinear(sampler, Float2(u, v), srcPixelsData, srcPixelsSize, srcPixels->RowPitch);
|
const Color c = sampler->SampleLinear(srcPixelsData, Float2(u, v), srcPixelsSize, srcPixels->RowPitch);
|
||||||
if (c.A < 0.25f)
|
if (c.A < 0.25f)
|
||||||
mask |= 1 << (7 - pixelIdx);
|
mask |= 1 << (7 - pixelIdx);
|
||||||
}
|
}
|
||||||
@@ -322,7 +323,7 @@ bool UpdateExeIcon(const String& path, const TextureData& icon)
|
|||||||
const TextureData* iconRGBA8 = &icon;
|
const TextureData* iconRGBA8 = &icon;
|
||||||
TextureData tmpData1;
|
TextureData tmpData1;
|
||||||
//if (icon.Format != PixelFormat::R8G8B8A8_UNorm)
|
//if (icon.Format != PixelFormat::R8G8B8A8_UNorm)
|
||||||
if (TextureTool::GetSampler(icon.Format) == nullptr)
|
if (PixelFormatSampler::Get(icon.Format) == nullptr)
|
||||||
{
|
{
|
||||||
if (TextureTool::Convert(tmpData1, *iconRGBA8, PixelFormat::R8G8B8A8_UNorm))
|
if (TextureTool::Convert(tmpData1, *iconRGBA8, PixelFormat::R8G8B8A8_UNorm))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -137,10 +137,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
|||||||
if (!FileSystem::DirectoryExists(CacheFolder))
|
if (!FileSystem::DirectoryExists(CacheFolder))
|
||||||
FileSystem::CreateDirectory(CacheFolder);
|
FileSystem::CreateDirectory(CacheFolder);
|
||||||
if (!FileSystem::FileExists(HeaderFilePath))
|
if (!FileSystem::FileExists(HeaderFilePath))
|
||||||
{
|
|
||||||
LOG(Warning, "Missing incremental build cooking assets cache.");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
auto file = FileReadStream::Open(HeaderFilePath);
|
auto file = FileReadStream::Open(HeaderFilePath);
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
@@ -158,7 +155,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
|||||||
|
|
||||||
LOG(Info, "Loading incremental build cooking cache (entries count: {0})", entriesCount);
|
LOG(Info, "Loading incremental build cooking cache (entries count: {0})", entriesCount);
|
||||||
file->ReadBytes(&Settings, sizeof(Settings));
|
file->ReadBytes(&Settings, sizeof(Settings));
|
||||||
Entries.EnsureCapacity(Math::RoundUpToPowerOf2(static_cast<int32>(entriesCount * 3.0f)));
|
Entries.EnsureCapacity(entriesCount);
|
||||||
|
|
||||||
Array<Pair<String, DateTime>> fileDependencies;
|
Array<Pair<String, DateTime>> fileDependencies;
|
||||||
for (int32 i = 0; i < entriesCount; i++)
|
for (int32 i = 0; i < entriesCount; i++)
|
||||||
@@ -166,7 +163,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
|||||||
Guid id;
|
Guid id;
|
||||||
file->Read(id);
|
file->Read(id);
|
||||||
String typeName;
|
String typeName;
|
||||||
file->ReadString(&typeName);
|
file->Read(typeName);
|
||||||
DateTime fileModified;
|
DateTime fileModified;
|
||||||
file->Read(fileModified);
|
file->Read(fileModified);
|
||||||
int32 fileDependenciesCount;
|
int32 fileDependenciesCount;
|
||||||
@@ -176,7 +173,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
|||||||
for (int32 j = 0; j < fileDependenciesCount; j++)
|
for (int32 j = 0; j < fileDependenciesCount; j++)
|
||||||
{
|
{
|
||||||
Pair<String, DateTime>& f = fileDependencies[j];
|
Pair<String, DateTime>& f = fileDependencies[j];
|
||||||
file->ReadString(&f.First, 10);
|
file->Read(f.First, 10);
|
||||||
file->Read(f.Second);
|
file->Read(f.Second);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,9 +308,9 @@ void CookAssetsStep::CacheData::Save(CookingData& data)
|
|||||||
{
|
{
|
||||||
auto& e = i->Value;
|
auto& e = i->Value;
|
||||||
file->Write(e.ID);
|
file->Write(e.ID);
|
||||||
file->WriteString(e.TypeName);
|
file->Write(e.TypeName);
|
||||||
file->Write(e.FileModified);
|
file->Write(e.FileModified);
|
||||||
file->WriteInt32(e.FileDependencies.Count());
|
file->Write(e.FileDependencies.Count());
|
||||||
for (auto& f : e.FileDependencies)
|
for (auto& f : e.FileDependencies)
|
||||||
{
|
{
|
||||||
file->Write(f.First, 10);
|
file->Write(f.First, 10);
|
||||||
@@ -365,17 +362,27 @@ bool CookAssetsStep::ProcessDefaultAsset(AssetCookData& options)
|
|||||||
|
|
||||||
bool CookAssetsStep::Process(CookingData& data, CacheData& cache, Asset* asset)
|
bool CookAssetsStep::Process(CookingData& data, CacheData& cache, Asset* asset)
|
||||||
{
|
{
|
||||||
// Validate asset
|
PROFILE_CPU_ASSET(asset);
|
||||||
if (asset->IsVirtual())
|
if (asset->IsVirtual())
|
||||||
{
|
{
|
||||||
// Virtual assets are not included into the build
|
// Virtual assets are not included into the build
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const bool wasLoaded = asset->IsLoaded();
|
||||||
if (asset->WaitForLoaded())
|
if (asset->WaitForLoaded())
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to load asset \'{0}\'", asset->ToString());
|
LOG(Error, "Failed to load asset \'{0}\'", asset->ToString());
|
||||||
return true;
|
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
|
// Switch based on an asset type
|
||||||
const auto asBinaryAsset = dynamic_cast<BinaryAsset*>(asset);
|
const auto asBinaryAsset = dynamic_cast<BinaryAsset*>(asset);
|
||||||
@@ -793,7 +800,10 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, BinaryAsset* a
|
|||||||
// Prepare asset data
|
// Prepare asset data
|
||||||
AssetInitData initData;
|
AssetInitData initData;
|
||||||
if (asset->Storage->LoadAssetHeader(asset->GetID(), initData))
|
if (asset->Storage->LoadAssetHeader(asset->GetID(), initData))
|
||||||
|
{
|
||||||
|
LOG(Warning, "Failed to load asset {} header from storage '{}'", asset->GetID(), asset->Storage->GetPath());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
initData.Header.UnlinkChunks();
|
initData.Header.UnlinkChunks();
|
||||||
initData.Metadata.Release();
|
initData.Metadata.Release();
|
||||||
for (auto& e : initData.Dependencies)
|
for (auto& e : initData.Dependencies)
|
||||||
@@ -1165,7 +1175,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
assetRef = Content::LoadAsync<Asset>(assetId);
|
assetRef = Content::LoadAsync<Asset>(assetId);
|
||||||
if (assetRef == nullptr)
|
if (assetRef == nullptr)
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load asset included in build."));
|
LOG(Error, "Failed to load asset {} included in build", assetId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e.Info.TypeName = assetRef->GetTypeName();
|
e.Info.TypeName = assetRef->GetTypeName();
|
||||||
@@ -1173,6 +1183,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
// Cook asset
|
// Cook asset
|
||||||
if (Process(data, cache, assetRef.Get()))
|
if (Process(data, cache, assetRef.Get()))
|
||||||
{
|
{
|
||||||
|
LOG(Error, "Failed to process asset {}", assetRef->ToString());
|
||||||
cache.Save(data);
|
cache.Save(data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1205,10 +1216,17 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
// Copy file
|
// Copy file
|
||||||
if (!FileSystem::FileExists(cookedPath) || FileSystem::GetFileLastEditTime(cookedPath) >= FileSystem::GetFileLastEditTime(filePath))
|
if (!FileSystem::FileExists(cookedPath) || FileSystem::GetFileLastEditTime(cookedPath) >= FileSystem::GetFileLastEditTime(filePath))
|
||||||
{
|
{
|
||||||
if (FileSystem::CreateDirectory(StringUtils::GetDirectoryName(cookedPath)))
|
const String cookedFolder = StringUtils::GetDirectoryName(cookedPath);
|
||||||
|
if (FileSystem::CreateDirectory(cookedFolder))
|
||||||
|
{
|
||||||
|
LOG(Error, "Failed to create directory '{}'", cookedFolder);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (FileSystem::CopyFile(cookedPath, filePath))
|
if (FileSystem::CopyFile(cookedPath, filePath))
|
||||||
|
{
|
||||||
|
LOG(Error, "Failed to copy file from '{}' to '{}'", filePath, cookedPath);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count stats of file extension
|
// Count stats of file extension
|
||||||
@@ -1249,7 +1267,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
*(int32*)(bytes.Get() + 804) = contentKey;
|
*(int32*)(bytes.Get() + 804) = contentKey;
|
||||||
*(Guid*)(bytes.Get() + 808) = gameSettings->SplashScreen;
|
*(Guid*)(bytes.Get() + 808) = gameSettings->SplashScreen;
|
||||||
Encryption::EncryptBytes(bytes.Get(), bytes.Count());
|
Encryption::EncryptBytes(bytes.Get(), bytes.Count());
|
||||||
stream->WriteArray(bytes);
|
stream->Write(bytes);
|
||||||
|
|
||||||
Delete(stream);
|
Delete(stream);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,9 @@ CustomEditorsUtilService CustomEditorsUtilServiceInstance;
|
|||||||
|
|
||||||
struct Entry
|
struct Entry
|
||||||
{
|
{
|
||||||
MClass* DefaultEditor;
|
MClass* DefaultEditor = nullptr;
|
||||||
MClass* CustomEditor;
|
MClass* CustomEditor = nullptr;
|
||||||
|
MType* CustomEditorType = nullptr;
|
||||||
Entry()
|
|
||||||
{
|
|
||||||
DefaultEditor = nullptr;
|
|
||||||
CustomEditor = nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Dictionary<MType*, Entry> Cache(512);
|
Dictionary<MType*, Entry> Cache(512);
|
||||||
@@ -63,11 +58,11 @@ MTypeObject* CustomEditorsUtil::GetCustomEditor(MTypeObject* refType)
|
|||||||
Entry result;
|
Entry result;
|
||||||
if (Cache.TryGet(type, result))
|
if (Cache.TryGet(type, result))
|
||||||
{
|
{
|
||||||
|
if (result.CustomEditorType)
|
||||||
|
return INTERNAL_TYPE_GET_OBJECT(result.CustomEditorType);
|
||||||
MClass* editor = result.CustomEditor ? result.CustomEditor : result.DefaultEditor;
|
MClass* editor = result.CustomEditor ? result.CustomEditor : result.DefaultEditor;
|
||||||
if (editor)
|
if (editor)
|
||||||
{
|
|
||||||
return MUtils::GetType(editor);
|
return MUtils::GetType(editor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -157,7 +152,7 @@ void OnAssemblyLoaded(MAssembly* assembly)
|
|||||||
else if (typeClass)
|
else if (typeClass)
|
||||||
{
|
{
|
||||||
auto& entry = Cache[mclass->GetType()];
|
auto& entry = Cache[mclass->GetType()];
|
||||||
entry.CustomEditor = typeClass;
|
entry.CustomEditorType = type;
|
||||||
|
|
||||||
//LOG(Info, "Custom Editor {0} for type {1}", String(typeClass->GetFullName()), String(mclass->GetFullName()));
|
//LOG(Info, "Custom Editor {0} for type {1}", String(typeClass->GetFullName()), String(mclass->GetFullName()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,20 +405,9 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
// Select object
|
// Select object
|
||||||
if (_value is Actor actor)
|
if (_value is Actor actor)
|
||||||
{
|
Select(actor);
|
||||||
if (PresenterContext is PropertiesWindow)
|
|
||||||
Editor.Instance.SceneEditing.Select(actor);
|
|
||||||
else if (PresenterContext is PrefabWindow prefabWindow)
|
|
||||||
prefabWindow.Select(prefabWindow.Graph.Root.Find(actor));
|
|
||||||
}
|
|
||||||
else if (_value is Script script && script.Actor)
|
else if (_value is Script script && script.Actor)
|
||||||
{
|
Select(script.Actor);
|
||||||
var a = script.Actor;
|
|
||||||
if (PresenterContext is PropertiesWindow)
|
|
||||||
Editor.Instance.SceneEditing.Select(a);
|
|
||||||
else if (PresenterContext is PrefabWindow prefabWindow)
|
|
||||||
prefabWindow.Select(prefabWindow.Graph.Root.Find(a));
|
|
||||||
}
|
|
||||||
else if (_value is Asset asset)
|
else if (_value is Asset asset)
|
||||||
Editor.Instance.Windows.ContentWin.Select(asset);
|
Editor.Instance.Windows.ContentWin.Select(asset);
|
||||||
}
|
}
|
||||||
@@ -436,6 +425,14 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
ShowDropDownMenu();
|
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()
|
private void DoDrag()
|
||||||
{
|
{
|
||||||
// Do the drag drop operation if has selected element
|
// Do the drag drop operation if has selected element
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ public class Editor : EditorModule
|
|||||||
options.ScriptingAPI.SystemReferences.Add("System.Text.RegularExpressions");
|
options.ScriptingAPI.SystemReferences.Add("System.Text.RegularExpressions");
|
||||||
options.ScriptingAPI.SystemReferences.Add("System.IO.Compression.ZipFile");
|
options.ScriptingAPI.SystemReferences.Add("System.IO.Compression.ZipFile");
|
||||||
options.ScriptingAPI.SystemReferences.Add("System.Diagnostics.Process");
|
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
|
// Enable optimizations for Editor, disable this for debugging the editor
|
||||||
if (options.Configuration == TargetConfiguration.Development)
|
if (options.Configuration == TargetConfiguration.Development)
|
||||||
|
|||||||
@@ -79,10 +79,6 @@ bool Editor::CheckProjectUpgrade()
|
|||||||
Delete(file);
|
Delete(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(Warning, "Missing version cache file");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if project is in the old, deprecated layout
|
// Check if project is in the old, deprecated layout
|
||||||
if (EditorImpl::IsOldProjectXmlFormat)
|
if (EditorImpl::IsOldProjectXmlFormat)
|
||||||
@@ -403,7 +399,7 @@ int32 Editor::LoadProduct()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create new project option
|
// Create new project option
|
||||||
if (CommandLine::Options.NewProject)
|
if (CommandLine::Options.NewProject.IsTrue())
|
||||||
{
|
{
|
||||||
Array<String> projectFiles;
|
Array<String> projectFiles;
|
||||||
FileSystem::DirectoryGetFiles(projectFiles, projectPath, TEXT("*.flaxproj"), DirectorySearchOption::TopDirectoryOnly);
|
FileSystem::DirectoryGetFiles(projectFiles, projectPath, TEXT("*.flaxproj"), DirectorySearchOption::TopDirectoryOnly);
|
||||||
@@ -428,7 +424,7 @@ int32 Editor::LoadProduct()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CommandLine::Options.NewProject)
|
if (CommandLine::Options.NewProject.IsTrue())
|
||||||
{
|
{
|
||||||
if (projectPath.IsEmpty())
|
if (projectPath.IsEmpty())
|
||||||
projectPath = Platform::GetWorkingDirectory();
|
projectPath = Platform::GetWorkingDirectory();
|
||||||
@@ -529,7 +525,7 @@ int32 Editor::LoadProduct()
|
|||||||
if (projectPath.IsEmpty())
|
if (projectPath.IsEmpty())
|
||||||
{
|
{
|
||||||
#if PLATFORM_HAS_HEADLESS_MODE
|
#if PLATFORM_HAS_HEADLESS_MODE
|
||||||
if (CommandLine::Options.Headless)
|
if (CommandLine::Options.Headless.IsTrue())
|
||||||
{
|
{
|
||||||
Platform::Fatal(TEXT("Missing project path."));
|
Platform::Fatal(TEXT("Missing project path."));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -612,7 +608,7 @@ int32 Editor::LoadProduct()
|
|||||||
// Validate project min supported version (older engine may try to load newer project)
|
// 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
|
// Special check if project specifies only build number, then major/minor fields are set to 0
|
||||||
const auto engineVersion = FLAXENGINE_VERSION;
|
const auto engineVersion = FLAXENGINE_VERSION;
|
||||||
for (auto e : projects)
|
for (const auto& e : projects)
|
||||||
{
|
{
|
||||||
const auto project = e.Item;
|
const auto project = e.Item;
|
||||||
if (project->MinEngineVersion > engineVersion ||
|
if (project->MinEngineVersion > engineVersion ||
|
||||||
@@ -657,7 +653,7 @@ Window* Editor::CreateMainWindow()
|
|||||||
bool Editor::Init()
|
bool Editor::Init()
|
||||||
{
|
{
|
||||||
// Scripts project files generation from command line
|
// Scripts project files generation from command line
|
||||||
if (CommandLine::Options.GenProjectFiles)
|
if (CommandLine::Options.GenProjectFiles.IsTrue())
|
||||||
{
|
{
|
||||||
const String customArgs = TEXT("-verbose -log -logfile=\"Cache/Intermediate/ProjectFileLog.txt\"");
|
const String customArgs = TEXT("-verbose -log -logfile=\"Cache/Intermediate/ProjectFileLog.txt\"");
|
||||||
const bool failed = ScriptsBuilder::GenerateProject(customArgs);
|
const bool failed = ScriptsBuilder::GenerateProject(customArgs);
|
||||||
|
|||||||
@@ -355,14 +355,14 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Show(Control parent, Float2 location)
|
public override void Show(Control parent, Float2 location, ContextMenuDirection? direction = null)
|
||||||
{
|
{
|
||||||
// Remove last separator to make context menu look better
|
// Remove last separator to make context menu look better
|
||||||
int lastIndex = _panel.Children.Count - 1;
|
int lastIndex = _panel.Children.Count - 1;
|
||||||
if (lastIndex >= 0 && _panel.Children[lastIndex] is ContextMenuSeparator separator)
|
if (lastIndex >= 0 && _panel.Children[lastIndex] is ContextMenuSeparator separator)
|
||||||
separator.Dispose();
|
separator.Dispose();
|
||||||
|
|
||||||
base.Show(parent, location);
|
base.Show(parent, location, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -101,6 +101,16 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Window> ExternalPopups = new List<Window>();
|
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>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -137,21 +147,26 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent">Parent control to attach to it.</param>
|
/// <param name="parent">Parent control to attach to it.</param>
|
||||||
/// <param name="location">Popup menu origin location in parent control coordinates.</param>
|
/// <param name="location">Popup menu origin location in parent control coordinates.</param>
|
||||||
public virtual void Show(Control parent, Float2 location)
|
/// <param name="direction">The custom popup direction. Null to use automatic direction.</param>
|
||||||
|
public virtual void Show(Control parent, Float2 location, ContextMenuDirection? direction = null)
|
||||||
{
|
{
|
||||||
Assert.IsNotNull(parent);
|
Assert.IsNotNull(parent);
|
||||||
|
bool isAlreadyVisible = Visible && _window;
|
||||||
// Ensure to be closed
|
if (!isAlreadyVisible)
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
// Peek parent control window
|
// Peek parent control window
|
||||||
var parentWin = parent.RootWindow;
|
var parentWin = parent.RootWindow;
|
||||||
if (parentWin == null)
|
if (parentWin == null)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if show menu inside the other menu - then link as a child to prevent closing the calling menu window on lost focus
|
// 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)
|
if (_parentCM == null && parentWin.ChildrenCount == 1 && parentWin.Children[0] is ContextMenuBase parentCM)
|
||||||
{
|
{
|
||||||
|
Hide();
|
||||||
parentCM.ShowChild(this, parentCM.PointFromScreen(parent.PointToScreen(location)), false);
|
parentCM.ShowChild(this, parentCM.PointFromScreen(parent.PointToScreen(location)), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -169,7 +184,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
var monitorBounds = Platform.GetMonitorBounds(locationSS);
|
var monitorBounds = Platform.GetMonitorBounds(locationSS);
|
||||||
var rightBottomLocationSS = locationSS + dpiSize;
|
var rightBottomLocationSS = locationSS + dpiSize;
|
||||||
bool isUp = false, isLeft = false;
|
bool isUp = false, isLeft = false;
|
||||||
if (UseAutomaticDirectionFix)
|
if (UseAutomaticDirectionFix && direction == null)
|
||||||
{
|
{
|
||||||
var parentMenu = parent as ContextMenu;
|
var parentMenu = parent as ContextMenu;
|
||||||
if (monitorBounds.Bottom < rightBottomLocationSS.Y)
|
if (monitorBounds.Bottom < rightBottomLocationSS.Y)
|
||||||
@@ -196,6 +211,26 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
locationSS.X -= dpiSize.X;
|
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
|
// Update direction flag
|
||||||
if (isUp)
|
if (isUp)
|
||||||
@@ -203,47 +238,62 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
else
|
else
|
||||||
_direction = isLeft ? ContextMenuDirection.LeftDown : ContextMenuDirection.RightDown;
|
_direction = isLeft ? ContextMenuDirection.LeftDown : ContextMenuDirection.RightDown;
|
||||||
|
|
||||||
// Create window
|
if (isAlreadyVisible)
|
||||||
var desc = CreateWindowSettings.Default;
|
{
|
||||||
desc.Position = locationSS;
|
_window.ClientBounds = new Rectangle(locationSS, dpiSize);
|
||||||
desc.StartPosition = WindowStartPosition.Manual;
|
}
|
||||||
desc.Size = dpiSize;
|
else
|
||||||
desc.Fullscreen = false;
|
{
|
||||||
desc.HasBorder = false;
|
// Create window
|
||||||
desc.SupportsTransparency = false;
|
var desc = CreateWindowSettings.Default;
|
||||||
desc.ShowInTaskbar = false;
|
desc.Position = locationSS;
|
||||||
desc.ActivateWhenFirstShown = true;
|
desc.StartPosition = WindowStartPosition.Manual;
|
||||||
desc.AllowInput = true;
|
desc.Size = dpiSize;
|
||||||
desc.AllowMinimize = false;
|
desc.Fullscreen = false;
|
||||||
desc.AllowMaximize = false;
|
desc.HasBorder = false;
|
||||||
desc.AllowDragAndDrop = false;
|
desc.SupportsTransparency = false;
|
||||||
desc.IsTopmost = true;
|
desc.ShowInTaskbar = false;
|
||||||
desc.Type = WindowType.Popup;
|
desc.ActivateWhenFirstShown = UseInput;
|
||||||
desc.Parent = parentWin.Window;
|
desc.AllowInput = UseInput;
|
||||||
desc.Title = "ContextMenu";
|
desc.AllowMinimize = false;
|
||||||
desc.HasSizingFrame = false;
|
desc.AllowMaximize = false;
|
||||||
OnWindowCreating(ref desc);
|
desc.AllowDragAndDrop = false;
|
||||||
_window = Platform.CreateWindow(ref desc);
|
desc.IsTopmost = true;
|
||||||
_window.GotFocus += OnWindowGotFocus;
|
desc.Type = WindowType.Popup;
|
||||||
_window.LostFocus += OnWindowLostFocus;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
#if USE_IS_FOREGROUND && USE_SDL_WORKAROUNDS
|
#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
|
// The focus between popup and parent windows doesn't change, force hide the popup when clicked on parent
|
||||||
parentWin.Window.MouseDown += OnWindowMouseDown;
|
parentWin.Window.MouseDown += OnWindowMouseDown;
|
||||||
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
|
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Attach to the window
|
// Attach to the window
|
||||||
_parentCM = parent as ContextMenuBase;
|
_parentCM = parent as ContextMenuBase;
|
||||||
Parent = _window.GUI;
|
Parent = _window.GUI;
|
||||||
|
}
|
||||||
|
|
||||||
// Show
|
// Show
|
||||||
Visible = true;
|
Visible = true;
|
||||||
|
if (_window == null)
|
||||||
|
return;
|
||||||
_window.Show();
|
_window.Show();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
_previouslyFocused = parentWin.FocusedControl;
|
if (UseVisibilityControl)
|
||||||
Focus();
|
{
|
||||||
OnShow();
|
_previouslyFocused = parentWin.FocusedControl;
|
||||||
|
Focus();
|
||||||
|
OnShow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -508,7 +558,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
|
|
||||||
// Let root context menu to check if none of the popup windows
|
// Let root context menu to check if none of the popup windows
|
||||||
if (_parentCM == null && !IsForeground)
|
if (_parentCM == null && UseVisibilityControl && !IsForeground)
|
||||||
{
|
{
|
||||||
#if USE_SDL_WORKAROUNDS
|
#if USE_SDL_WORKAROUNDS
|
||||||
if (!IsMouseOver)
|
if (!IsMouseOver)
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ namespace FlaxEditor.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Item> Clicked;
|
public event Action<Item> Clicked;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when items gets focused.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<Item> Focused;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tint color of the text.
|
/// The tint color of the text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -141,6 +146,10 @@ namespace FlaxEditor.GUI
|
|||||||
protected virtual void GetTextRect(out Rectangle rect)
|
protected virtual void GetTextRect(out Rectangle rect)
|
||||||
{
|
{
|
||||||
rect = new Rectangle(2, 0, Width - 4, Height);
|
rect = new Rectangle(2, 0, Width - 4, Height);
|
||||||
|
|
||||||
|
// Indent for drop panel items is handled by drop panel margin
|
||||||
|
if (Parent is not DropPanel)
|
||||||
|
rect.Location += new Float2(Editor.Instance.Icons.ArrowRight12.Size.X + 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -155,10 +164,6 @@ namespace FlaxEditor.GUI
|
|||||||
if (IsMouseOver || IsFocused)
|
if (IsMouseOver || IsFocused)
|
||||||
Render2D.FillRectangle(new Rectangle(Float2.Zero, Size), style.BackgroundHighlighted);
|
Render2D.FillRectangle(new Rectangle(Float2.Zero, Size), style.BackgroundHighlighted);
|
||||||
|
|
||||||
// Indent for drop panel items is handled by drop panel margin
|
|
||||||
if (Parent is not DropPanel)
|
|
||||||
textRect.Location += new Float2(Editor.Instance.Icons.ArrowRight12.Size.X + 2, 0);
|
|
||||||
|
|
||||||
// Draw all highlights
|
// Draw all highlights
|
||||||
if (_highlights != null)
|
if (_highlights != null)
|
||||||
{
|
{
|
||||||
@@ -207,6 +212,14 @@ namespace FlaxEditor.GUI
|
|||||||
base.OnMouseLeave();
|
base.OnMouseLeave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnGotFocus()
|
||||||
|
{
|
||||||
|
base.OnGotFocus();
|
||||||
|
|
||||||
|
Focused?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int Compare(Control other)
|
public override int Compare(Control other)
|
||||||
{
|
{
|
||||||
@@ -227,6 +240,7 @@ namespace FlaxEditor.GUI
|
|||||||
private readonly Panel _scrollPanel;
|
private readonly Panel _scrollPanel;
|
||||||
private List<DropPanel> _categoryPanels;
|
private List<DropPanel> _categoryPanels;
|
||||||
private bool _waitingForInput;
|
private bool _waitingForInput;
|
||||||
|
private string _customSearch;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when any item in this popup menu gets clicked.
|
/// Event fired when any item in this popup menu gets clicked.
|
||||||
@@ -248,26 +262,30 @@ namespace FlaxEditor.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="width">The control width.</param>
|
/// <param name="width">The control width.</param>
|
||||||
/// <param name="height">The control height.</param>
|
/// <param name="height">The control height.</param>
|
||||||
public ItemsListContextMenu(float width = 320, float height = 220)
|
/// <param name="withSearch">Enables search field.</param>
|
||||||
|
public ItemsListContextMenu(float width = 320, float height = 220, bool withSearch = true)
|
||||||
{
|
{
|
||||||
// Context menu dimensions
|
// Context menu dimensions
|
||||||
Size = new Float2(width, height);
|
Size = new Float2(width, height);
|
||||||
|
|
||||||
// Search box
|
if (withSearch)
|
||||||
_searchBox = new SearchBox(false, 1, 1)
|
|
||||||
{
|
{
|
||||||
Parent = this,
|
// Search box
|
||||||
Width = Width - 3,
|
_searchBox = new SearchBox(false, 1, 1)
|
||||||
};
|
{
|
||||||
_searchBox.TextChanged += OnSearchFilterChanged;
|
Parent = this,
|
||||||
_searchBox.ClearSearchButton.Clicked += () => PerformLayout();
|
Width = Width - 3,
|
||||||
|
};
|
||||||
|
_searchBox.TextChanged += OnSearchFilterChanged;
|
||||||
|
_searchBox.ClearSearchButton.Clicked += () => PerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
// Panel with scrollbar
|
// Panel with scrollbar
|
||||||
_scrollPanel = new Panel(ScrollBars.Vertical)
|
_scrollPanel = new Panel(ScrollBars.Vertical)
|
||||||
{
|
{
|
||||||
Parent = this,
|
Parent = this,
|
||||||
AnchorPreset = AnchorPresets.StretchAll,
|
AnchorPreset = AnchorPresets.StretchAll,
|
||||||
Bounds = new Rectangle(0, _searchBox.Bottom + 1, Width, Height - _searchBox.Bottom - 2),
|
Bounds = withSearch ? new Rectangle(0, _searchBox.Bottom + 1, Width, Height - _searchBox.Bottom - 2) : new Rectangle(Float2.Zero, Size),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Items list panel
|
// Items list panel
|
||||||
@@ -286,12 +304,13 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
LockChildrenRecursive();
|
LockChildrenRecursive();
|
||||||
|
|
||||||
|
var searchText = _searchBox?.Text ?? _customSearch;
|
||||||
var items = ItemsPanel.Children;
|
var items = ItemsPanel.Children;
|
||||||
for (int i = 0; i < items.Count; i++)
|
for (int i = 0; i < items.Count; i++)
|
||||||
{
|
{
|
||||||
if (items[i] is Item item)
|
if (items[i] is Item item)
|
||||||
{
|
{
|
||||||
item.UpdateFilter(_searchBox.Text);
|
item.UpdateFilter(searchText);
|
||||||
item.UpdateScore();
|
item.UpdateScore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,13 +324,13 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
if (category.Children[j] is Item item2)
|
if (category.Children[j] is Item item2)
|
||||||
{
|
{
|
||||||
item2.UpdateFilter(_searchBox.Text);
|
item2.UpdateFilter(searchText);
|
||||||
item2.UpdateScore();
|
item2.UpdateScore();
|
||||||
anyVisible |= item2.Visible;
|
anyVisible |= item2.Visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
category.Visible = anyVisible;
|
category.Visible = anyVisible;
|
||||||
if (string.IsNullOrEmpty(_searchBox.Text))
|
if (string.IsNullOrEmpty(searchText))
|
||||||
category.Close(false);
|
category.Close(false);
|
||||||
else
|
else
|
||||||
category.Open(false);
|
category.Open(false);
|
||||||
@@ -322,8 +341,8 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
UnlockChildrenRecursive();
|
UnlockChildrenRecursive();
|
||||||
PerformLayout(true);
|
PerformLayout(true);
|
||||||
_searchBox.Focus();
|
_searchBox?.Focus();
|
||||||
TextChanged?.Invoke(_searchBox.Text);
|
TextChanged?.Invoke(searchText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -355,6 +374,14 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all added items.
|
||||||
|
/// </summary>
|
||||||
|
public void ClearItems()
|
||||||
|
{
|
||||||
|
ItemsPanel.DisposeChildren();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sorts the items list (by item name by default).
|
/// Sorts the items list (by item name by default).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -368,6 +395,34 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Focuses and scroll to the given item to be selected.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item to select.</param>
|
||||||
|
public void SelectItem(Item item)
|
||||||
|
{
|
||||||
|
item.Focus();
|
||||||
|
ScrollViewTo(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies custom search text query on the items list. Works even if search field is disabled
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The custom search text. Null to clear search.</param>
|
||||||
|
public void Search(string text)
|
||||||
|
{
|
||||||
|
if (_searchBox != null)
|
||||||
|
{
|
||||||
|
_searchBox.SetText(text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_customSearch = text;
|
||||||
|
if (VisibleInHierarchy)
|
||||||
|
OnSearchFilterChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the item to the view and registers for the click event.
|
/// Adds the item to the view and registers for the click event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -446,9 +501,11 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_searchBox.Clear();
|
_searchBox?.Clear();
|
||||||
UnlockChildrenRecursive();
|
UnlockChildrenRecursive();
|
||||||
PerformLayout(true);
|
PerformLayout(true);
|
||||||
|
if (_customSearch != null)
|
||||||
|
OnSearchFilterChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Item> GetVisibleItems()
|
private List<Item> GetVisibleItems()
|
||||||
@@ -510,7 +567,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (RootWindow.FocusedControl == null)
|
if (RootWindow.FocusedControl == null)
|
||||||
{
|
{
|
||||||
// Focus search box if nothing is focused
|
// Focus search box if nothing is focused
|
||||||
_searchBox.Focus();
|
_searchBox?.Focus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +593,7 @@ namespace FlaxEditor.GUI
|
|||||||
var focusedIndex = items.IndexOf(focusedItem);
|
var focusedIndex = items.IndexOf(focusedItem);
|
||||||
if (focusedIndex == 0)
|
if (focusedIndex == 0)
|
||||||
{
|
{
|
||||||
_searchBox.Focus();
|
_searchBox?.Focus();
|
||||||
}
|
}
|
||||||
else if (focusedIndex > 0)
|
else if (focusedIndex > 0)
|
||||||
{
|
{
|
||||||
@@ -556,7 +613,7 @@ namespace FlaxEditor.GUI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_waitingForInput)
|
if (_waitingForInput && _searchBox != null)
|
||||||
{
|
{
|
||||||
_waitingForInput = false;
|
_waitingForInput = false;
|
||||||
_searchBox.Focus();
|
_searchBox.Focus();
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ namespace FlaxEditor.Gizmo
|
|||||||
if (_vertexBuffer == null)
|
if (_vertexBuffer == null)
|
||||||
{
|
{
|
||||||
_vertexBuffer = new GPUBuffer();
|
_vertexBuffer = new GPUBuffer();
|
||||||
var desc = GPUBufferDescription.Vertex(sizeof(Float3), 4);
|
var layout = GPUVertexLayout.Get([new VertexElement(VertexElement.Types.Position, 0, 0, false, PixelFormat.R32G32B32_Float)]);
|
||||||
|
var desc = GPUBufferDescription.Vertex(layout, sizeof(Float3), 4);
|
||||||
_vertexBuffer.Init(ref desc);
|
_vertexBuffer.Init(ref desc);
|
||||||
}
|
}
|
||||||
if (_indexBuffer == null)
|
if (_indexBuffer == null)
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ namespace FlaxEditor.Modules
|
|||||||
/// Removes a quick action by name.
|
/// Removes a quick action by name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The action's name.</param>
|
/// <param name="name">The action's name.</param>
|
||||||
/// <returns>True when it succeed, false if there is no Quick Action with this name.</returns>
|
/// <returns>True when it succeeds, false if there is no Quick Action with this name.</returns>
|
||||||
public bool RemoveQuickAction(string name)
|
public bool RemoveQuickAction(string name)
|
||||||
{
|
{
|
||||||
if (_quickActions == null)
|
if (_quickActions == null)
|
||||||
@@ -288,6 +288,16 @@ namespace FlaxEditor.Modules
|
|||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Editor window
|
||||||
|
foreach (var window in Editor.Windows.Windows)
|
||||||
|
{
|
||||||
|
if (window is Windows.Assets.AssetEditorWindow)
|
||||||
|
continue;
|
||||||
|
var windowName = window.Title + " (window)";
|
||||||
|
if (nameRegex.Match(windowName).Success)
|
||||||
|
matches.Add(new SearchResult { Name = windowName, Type = "Window", Item = window });
|
||||||
|
}
|
||||||
|
|
||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
@@ -407,6 +417,9 @@ namespace FlaxEditor.Modules
|
|||||||
Editor.Instance.Windows.EditWin.Viewport.FocusSelection();
|
Editor.Instance.Windows.EditWin.Viewport.FocusSelection();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Windows.EditorWindow window:
|
||||||
|
window.FocusOrShow();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ namespace FlaxEditor.Modules
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly GenerateScriptsProjectFilesProgress GenerateScriptsProjectFiles = new GenerateScriptsProjectFilesProgress();
|
public readonly GenerateScriptsProjectFilesProgress GenerateScriptsProjectFiles = new GenerateScriptsProjectFilesProgress();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The assets loading progress handler.
|
||||||
|
/// </summary>
|
||||||
|
public readonly LoadAssetsProgress LoadAssets = new LoadAssetsProgress();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the first active handler.
|
/// Gets the first active handler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -80,6 +85,7 @@ namespace FlaxEditor.Modules
|
|||||||
RegisterHandler(CodeEditorOpen);
|
RegisterHandler(CodeEditorOpen);
|
||||||
RegisterHandler(NavMeshBuilding);
|
RegisterHandler(NavMeshBuilding);
|
||||||
RegisterHandler(GenerateScriptsProjectFiles);
|
RegisterHandler(GenerateScriptsProjectFiles);
|
||||||
|
RegisterHandler(LoadAssets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -447,6 +447,8 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
private void StateMachineOnStateChanged()
|
private void StateMachineOnStateChanged()
|
||||||
{
|
{
|
||||||
|
if (Editor.StateMachine.CurrentState is States.ClosingState)
|
||||||
|
return;
|
||||||
UpdateToolstrip();
|
UpdateToolstrip();
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
}
|
}
|
||||||
|
|||||||
40
Source/Editor/Progress/Handlers/LoadAssetsProgress.cs
Normal file
40
Source/Editor/Progress/Handlers/LoadAssetsProgress.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
namespace FlaxEditor.Progress.Handlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Loading assets progress reporting handler.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEditor.Progress.ProgressHandler" />
|
||||||
|
public sealed class LoadAssetsProgress : ProgressHandler
|
||||||
|
{
|
||||||
|
private int _loadingAssetsCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LoadAssetsProgress"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public LoadAssetsProgress()
|
||||||
|
{
|
||||||
|
Editor.Instance.EditorUpdate += OnEditorUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEditorUpdate()
|
||||||
|
{
|
||||||
|
var contentStats = FlaxEngine.Content.Stats;
|
||||||
|
if (_loadingAssetsCount == contentStats.LoadingAssetsCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (contentStats.LoadingAssetsCount == 0)
|
||||||
|
OnEnd();
|
||||||
|
else if (_loadingAssetsCount == 0)
|
||||||
|
OnStart();
|
||||||
|
if (contentStats.LoadingAssetsCount > 0)
|
||||||
|
{
|
||||||
|
var progress = (float)contentStats.LoadedAssetsCount / contentStats.AssetsCount;
|
||||||
|
var text = contentStats.LoadingAssetsCount == 1 ? "Loading 1 asset..." : $"Loading {contentStats.LoadingAssetsCount} assets...";
|
||||||
|
OnUpdate(progress, text);
|
||||||
|
}
|
||||||
|
_loadingAssetsCount = contentStats.LoadingAssetsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,19 +80,23 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
|
|
||||||
// Get vertex data for each mesh
|
// Get vertex data for each mesh
|
||||||
var meshes = model.LODs[0].Meshes;
|
var meshes = model.LODs[0].Meshes;
|
||||||
var meshesData = new SkinnedMesh.Vertex0[meshes.Length][];
|
var bonesVertices = new List<Float3>[bones.Length];
|
||||||
var bonesVertices = new List<SkinnedMesh.Vertex0>[bones.Length];
|
|
||||||
var indicesLimit = new Int4(bones.Length - 1);
|
var indicesLimit = new Int4(bones.Length - 1);
|
||||||
for (int i = 0; i < meshes.Length; i++)
|
for (int i = 0; i < meshes.Length; i++)
|
||||||
{
|
{
|
||||||
meshesData[i] = meshes[i].DownloadVertexBuffer0();
|
var assessor = new MeshAccessor();
|
||||||
|
if (assessor.LoadMesh(meshes[i]))
|
||||||
var meshData = meshes[i].DownloadVertexBuffer0();
|
return;
|
||||||
for (int j = 0; j < meshData.Length; j++)
|
var positionStream = assessor.Position();
|
||||||
|
var blendIndicesStream = assessor.BlendIndices();
|
||||||
|
var blendWeightsStream = assessor.BlendWeights();
|
||||||
|
if (!positionStream.IsValid || !blendIndicesStream.IsValid || !blendWeightsStream.IsValid)
|
||||||
|
continue;
|
||||||
|
var count = positionStream.Count;
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
{
|
{
|
||||||
ref var v = ref meshData[j];
|
var weights = blendWeightsStream.GetFloat4(j);
|
||||||
var weights = (Float4)v.BlendWeights;
|
var indices = Int4.Min((Int4)blendIndicesStream.GetFloat4(j), indicesLimit);
|
||||||
var indices = Int4.Min((Int4)v.BlendIndices, indicesLimit);
|
|
||||||
|
|
||||||
// Find the bone with the highest influence on the vertex
|
// Find the bone with the highest influence on the vertex
|
||||||
var maxWeightIndex = 0;
|
var maxWeightIndex = 0;
|
||||||
@@ -104,17 +108,18 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
var maxWeightBone = indices[maxWeightIndex];
|
var maxWeightBone = indices[maxWeightIndex];
|
||||||
|
|
||||||
// Skin vertex position with the current pose
|
// Skin vertex position with the current pose
|
||||||
Float3.Transform(ref v.Position, ref skinningMatrices[indices[0]], out Float3 pos0);
|
var position = positionStream.GetFloat3(j);
|
||||||
Float3.Transform(ref v.Position, ref skinningMatrices[indices[1]], out Float3 pos1);
|
Float3.Transform(ref position, ref skinningMatrices[indices[0]], out Float3 pos0);
|
||||||
Float3.Transform(ref v.Position, ref skinningMatrices[indices[2]], out Float3 pos2);
|
Float3.Transform(ref position, ref skinningMatrices[indices[1]], out Float3 pos1);
|
||||||
Float3.Transform(ref v.Position, ref skinningMatrices[indices[3]], out Float3 pos3);
|
Float3.Transform(ref position, ref skinningMatrices[indices[2]], out Float3 pos2);
|
||||||
v.Position = pos0 * weights[0] + pos1 * weights[1] + pos2 * weights[2] + pos3 * weights[3];
|
Float3.Transform(ref position, ref skinningMatrices[indices[3]], out Float3 pos3);
|
||||||
|
position = pos0 * weights[0] + pos1 * weights[1] + pos2 * weights[2] + pos3 * weights[3];
|
||||||
|
|
||||||
// Add vertex to the bone list
|
// Add vertex to the bone list
|
||||||
ref var boneVertices = ref bonesVertices[maxWeightBone];
|
ref var boneVertices = ref bonesVertices[maxWeightBone];
|
||||||
if (boneVertices == null)
|
if (boneVertices == null)
|
||||||
boneVertices = new List<SkinnedMesh.Vertex0>();
|
boneVertices = new List<Float3>();
|
||||||
boneVertices.Add(v);
|
boneVertices.Add(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +133,10 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
continue; // Skip not used bones
|
continue; // Skip not used bones
|
||||||
|
|
||||||
// Compute bounds of the vertices using this bone (in local space of the actor)
|
// Compute bounds of the vertices using this bone (in local space of the actor)
|
||||||
Float3 boneBoundsMin = boneVertices[0].Position, boneBoundsMax = boneVertices[0].Position;
|
Float3 boneBoundsMin = boneVertices[0], boneBoundsMax = boneVertices[0];
|
||||||
for (int i = 1; i < boneVertices.Count; i++)
|
for (int i = 1; i < boneVertices.Count; i++)
|
||||||
{
|
{
|
||||||
var pos = boneVertices[i].Position;
|
var pos = boneVertices[i];
|
||||||
boneBoundsMin = Float3.Min(boneBoundsMin, pos);
|
boneBoundsMin = Float3.Min(boneBoundsMin, pos);
|
||||||
boneBoundsMax = Float3.Max(boneBoundsMax, pos);
|
boneBoundsMax = Float3.Max(boneBoundsMax, pos);
|
||||||
}
|
}
|
||||||
@@ -165,10 +170,10 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
var boneBounds = BoundingBox.Zero;
|
var boneBounds = BoundingBox.Zero;
|
||||||
if (boneVertices != null)
|
if (boneVertices != null)
|
||||||
{
|
{
|
||||||
boneBounds = new BoundingBox(boneVertices[0].Position, boneVertices[0].Position);
|
boneBounds = new BoundingBox(boneVertices[0], boneVertices[0]);
|
||||||
for (int i = 1; i < boneVertices.Count; i++)
|
for (int i = 1; i < boneVertices.Count; i++)
|
||||||
{
|
{
|
||||||
var pos = boneVertices[i].Position;
|
var pos = boneVertices[i];
|
||||||
boneBounds.Minimum = Float3.Min(boneBounds.Minimum, pos);
|
boneBounds.Minimum = Float3.Min(boneBounds.Minimum, pos);
|
||||||
boneBounds.Minimum = Float3.Max(boneBounds.Maximum, pos);
|
boneBounds.Minimum = Float3.Max(boneBounds.Maximum, pos);
|
||||||
}
|
}
|
||||||
@@ -263,7 +268,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
var boneLocalBounds = BoundingBox.Zero;
|
var boneLocalBounds = BoundingBox.Zero;
|
||||||
for (int i = 0; i < boneVertices.Count; i++)
|
for (int i = 0; i < boneVertices.Count; i++)
|
||||||
{
|
{
|
||||||
var pos = boneTransform.WorldToLocal(boneVertices[i].Position);
|
var pos = boneTransform.WorldToLocal(boneVertices[i]);
|
||||||
Vector3.Min(ref boneLocalBounds.Minimum, ref pos, out boneLocalBounds.Minimum);
|
Vector3.Min(ref boneLocalBounds.Minimum, ref pos, out boneLocalBounds.Minimum);
|
||||||
Vector3.Max(ref boneLocalBounds.Maximum, ref pos, out boneLocalBounds.Maximum);
|
Vector3.Max(ref boneLocalBounds.Maximum, ref pos, out boneLocalBounds.Maximum);
|
||||||
}
|
}
|
||||||
@@ -360,20 +365,20 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
Editor.Instance.Scene.MarkSceneEdited(actor.Scene);
|
Editor.Instance.Scene.MarkSceneEdited(actor.Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe Matrix CalculateCovarianceMatrix(List<SkinnedMesh.Vertex0> vertices)
|
private static unsafe Matrix CalculateCovarianceMatrix(List<Float3> vertices)
|
||||||
{
|
{
|
||||||
// [Reference: https://en.wikipedia.org/wiki/Covariance_matrix]
|
// [Reference: https://en.wikipedia.org/wiki/Covariance_matrix]
|
||||||
|
|
||||||
// Calculate average point
|
// Calculate average point
|
||||||
var avg = Float3.Zero;
|
var avg = Float3.Zero;
|
||||||
for (int i = 0; i < vertices.Count; i++)
|
for (int i = 0; i < vertices.Count; i++)
|
||||||
avg += vertices[i].Position;
|
avg += vertices[i];
|
||||||
avg /= vertices.Count;
|
avg /= vertices.Count;
|
||||||
|
|
||||||
// Calculate distance to average for every point
|
// Calculate distance to average for every point
|
||||||
var errors = new Float3[vertices.Count];
|
var errors = new Float3[vertices.Count];
|
||||||
for (int i = 0; i < vertices.Count; i++)
|
for (int i = 0; i < vertices.Count; i++)
|
||||||
errors[i] = vertices[i].Position - avg;
|
errors[i] = vertices[i] - avg;
|
||||||
|
|
||||||
var covariance = Matrix.Identity;
|
var covariance = Matrix.Identity;
|
||||||
var cj = stackalloc float[3];
|
var cj = stackalloc float[3];
|
||||||
@@ -393,15 +398,9 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
var row = new Float4(cj[0], cj[1], cj[2], 0.0f);
|
var row = new Float4(cj[0], cj[1], cj[2], 0.0f);
|
||||||
switch (j)
|
switch (j)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: covariance.Row1 = row; break;
|
||||||
covariance.Row1 = row;
|
case 1: covariance.Row2 = row; break;
|
||||||
break;
|
case 2: covariance.Row3 = row; break;
|
||||||
case 1:
|
|
||||||
covariance.Row2 = row;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
covariance.Row3 = row;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return covariance;
|
return covariance;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
[HideInEditor]
|
[HideInEditor]
|
||||||
public sealed class StaticModelNode : ActorNode
|
public sealed class StaticModelNode : ActorNode
|
||||||
{
|
{
|
||||||
private Dictionary<IntPtr, Mesh.Vertex[]> _vertices;
|
private Dictionary<IntPtr, Float3[]> _vertices;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public StaticModelNode(Actor actor)
|
public StaticModelNode(Actor actor)
|
||||||
@@ -53,14 +53,17 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
var key = FlaxEngine.Object.GetUnmanagedPtr(mesh);
|
var key = FlaxEngine.Object.GetUnmanagedPtr(mesh);
|
||||||
if (!_vertices.TryGetValue(key, out var verts))
|
if (!_vertices.TryGetValue(key, out var verts))
|
||||||
{
|
{
|
||||||
verts = mesh.DownloadVertexBuffer();
|
var accessor = new MeshAccessor();
|
||||||
|
if (accessor.LoadMesh(mesh))
|
||||||
|
continue;
|
||||||
|
verts = accessor.Positions;
|
||||||
if (verts == null)
|
if (verts == null)
|
||||||
continue;
|
continue;
|
||||||
_vertices.Add(key, verts);
|
_vertices.Add(key, verts);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < verts.Length; i++)
|
for (int i = 0; i < verts.Length; i++)
|
||||||
{
|
{
|
||||||
var v = verts[i].Position;
|
ref var v = ref verts[i];
|
||||||
var distance = Float3.DistanceSquared(ref pointLocal, ref v);
|
var distance = Float3.DistanceSquared(ref pointLocal, ref v);
|
||||||
if (distance <= minDistance)
|
if (distance <= minDistance)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -586,7 +586,7 @@ bool ScriptsBuilderService::Init()
|
|||||||
auto project = Editor::Project;
|
auto project = Editor::Project;
|
||||||
HashSet<ProjectInfo*> projects;
|
HashSet<ProjectInfo*> projects;
|
||||||
project->GetAllProjects(projects);
|
project->GetAllProjects(projects);
|
||||||
for (auto e : projects)
|
for (const auto& e : projects)
|
||||||
{
|
{
|
||||||
ProjectInfo* project = e.Item;
|
ProjectInfo* project = e.Item;
|
||||||
if (project->Name == TEXT("Flax"))
|
if (project->Name == TEXT("Flax"))
|
||||||
|
|||||||
@@ -919,6 +919,17 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
_selectedAnimation.SelectedIndex = 0;
|
_selectedAnimation.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void SetValuesPaste(object[] values)
|
||||||
|
{
|
||||||
|
// Fix Guids pasted as string
|
||||||
|
// TODO: let copy/paste system in Visject handle value types to be strongly typed
|
||||||
|
for (int i = 5; i < values.Length; i += 2)
|
||||||
|
values[i] = Guid.Parse((string)values[i]);
|
||||||
|
|
||||||
|
base.SetValuesPaste(values);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnValuesChanged()
|
public override void OnValuesChanged()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -225,8 +225,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
if (Surface != null)
|
Surface?.RemoveContext(this);
|
||||||
Surface.RemoveContext(this);
|
|
||||||
|
|
||||||
_maxTransitionsPerUpdate = null;
|
_maxTransitionsPerUpdate = null;
|
||||||
_reinitializeOnBecomingRelevant = null;
|
_reinitializeOnBecomingRelevant = null;
|
||||||
@@ -717,9 +716,12 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
LoadTransitions();
|
LoadTransitions();
|
||||||
|
|
||||||
// Register for surface mouse events to handle transition arrows interactions
|
if (Surface != null)
|
||||||
Surface.CustomMouseUp += OnSurfaceMouseUp;
|
{
|
||||||
Surface.CustomMouseDoubleClick += OnSurfaceMouseDoubleClick;
|
// Register for surface mouse events to handle transition arrows interactions
|
||||||
|
Surface.CustomMouseUp += OnSurfaceMouseUp;
|
||||||
|
Surface.CustomMouseDoubleClick += OnSurfaceMouseDoubleClick;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSurfaceMouseUp(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
private void OnSurfaceMouseUp(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
||||||
@@ -1398,7 +1400,8 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
if (context.FindNode(9, 21) == null)
|
if (context.FindNode(9, 21) == null)
|
||||||
{
|
{
|
||||||
var wasEnabled = true;
|
var wasEnabled = true;
|
||||||
if (Surface.Undo != null)
|
var undo = Surface?.Undo;
|
||||||
|
if (undo != null)
|
||||||
{
|
{
|
||||||
wasEnabled = Surface.Undo.Enabled;
|
wasEnabled = Surface.Undo.Enabled;
|
||||||
Surface.Undo.Enabled = false;
|
Surface.Undo.Enabled = false;
|
||||||
@@ -1406,7 +1409,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
context.SpawnNode(9, 21, new Float2(100.0f));
|
context.SpawnNode(9, 21, new Float2(100.0f));
|
||||||
|
|
||||||
if (Surface.Undo != null)
|
if (undo != null)
|
||||||
{
|
{
|
||||||
Surface.Undo.Enabled = wasEnabled;
|
Surface.Undo.Enabled = wasEnabled;
|
||||||
}
|
}
|
||||||
@@ -1492,7 +1495,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
Surface.RemoveContext(this);
|
Surface?.RemoveContext(this);
|
||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
@@ -1886,7 +1889,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
if (context.FindNode(9, 22) == null)
|
if (context.FindNode(9, 22) == null)
|
||||||
{
|
{
|
||||||
var wasEnabled = true;
|
var wasEnabled = true;
|
||||||
var undo = SourceState.Surface.Undo;
|
var undo = SourceState.Surface?.Undo;
|
||||||
if (undo != null)
|
if (undo != null)
|
||||||
{
|
{
|
||||||
wasEnabled = undo.Enabled;
|
wasEnabled = undo.Enabled;
|
||||||
|
|||||||
@@ -15,6 +15,29 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
[HideInEditor]
|
[HideInEditor]
|
||||||
public static class Material
|
public static class Material
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Blend modes (each enum item value maps to box ID).
|
||||||
|
/// </summary>
|
||||||
|
internal enum BlendMode
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
|
Multiply,
|
||||||
|
Screen,
|
||||||
|
Overlay,
|
||||||
|
LinearBurn,
|
||||||
|
LinearLight,
|
||||||
|
Darken,
|
||||||
|
Lighten,
|
||||||
|
Difference,
|
||||||
|
Exclusion,
|
||||||
|
Divide,
|
||||||
|
HardLight,
|
||||||
|
PinLight,
|
||||||
|
HardMix
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Customized <see cref="SurfaceNode"/> for main material node.
|
/// Customized <see cref="SurfaceNode"/> for main material node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1073,6 +1096,49 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float3), 4),
|
NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float3), 4),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 50,
|
||||||
|
Title = "Shift HSV",
|
||||||
|
Description = "Modifies the HSV of a color, values are from -1:1, preserves alpha",
|
||||||
|
Flags = NodeFlags.MaterialGraph,
|
||||||
|
Size = new Float2(175, 80),
|
||||||
|
DefaultValues =
|
||||||
|
[
|
||||||
|
0.0f, // For Hue (index 0)
|
||||||
|
0.0f, // For Sat (index 1)
|
||||||
|
0.0f, // For Val (index 2)
|
||||||
|
],
|
||||||
|
Elements =
|
||||||
|
[
|
||||||
|
NodeElementArchetype.Factory.Input(0, "RGBA", true, typeof(Float4), 0), // No default
|
||||||
|
NodeElementArchetype.Factory.Input(1, "Hue", true, typeof(float), 1, 0), // Uses DefaultValues[0]
|
||||||
|
NodeElementArchetype.Factory.Input(2, "Sat", true, typeof(float), 2, 1), // Uses DefaultValues[1]
|
||||||
|
NodeElementArchetype.Factory.Input(3, "Val", true, typeof(float), 3, 2), // Uses DefaultValues[2]
|
||||||
|
NodeElementArchetype.Factory.Output(0, "RGBA", typeof(Float4), 4),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 51,
|
||||||
|
Title = "Color Blend",
|
||||||
|
Description = "Blends two colors using various blend modes. Passes base alpha through.",
|
||||||
|
Flags = NodeFlags.MaterialGraph,
|
||||||
|
Size = new Float2(180, 80),
|
||||||
|
DefaultValues = new object[]
|
||||||
|
{
|
||||||
|
BlendMode.Normal, // Default blend mode
|
||||||
|
1.0f, // Default blend amount
|
||||||
|
},
|
||||||
|
Elements = new[]
|
||||||
|
{
|
||||||
|
NodeElementArchetype.Factory.Input(1, "Base Color", true, typeof(Float4), 0),
|
||||||
|
NodeElementArchetype.Factory.Input(2, "Blend Color", true, typeof(Float4), 1),
|
||||||
|
NodeElementArchetype.Factory.Input(3, "Intensity", true, typeof(float), 2, 1),
|
||||||
|
NodeElementArchetype.Factory.Enum(0, 0, 120, 0, typeof(BlendMode)), // Blend mode selector
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Result", typeof(Float4), 3),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,9 +123,15 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
AlternativeTitles = new string[] { "UV", "UVs" },
|
AlternativeTitles = new string[] { "UV", "UVs" },
|
||||||
Description = "Texture coordinates",
|
Description = "Texture coordinates",
|
||||||
Flags = NodeFlags.MaterialGraph,
|
Flags = NodeFlags.MaterialGraph,
|
||||||
Size = new Float2(110, 30),
|
Size = new Float2(150, 30),
|
||||||
|
DefaultValues = new object[]
|
||||||
|
{
|
||||||
|
0u
|
||||||
|
},
|
||||||
Elements = new[]
|
Elements = new[]
|
||||||
{
|
{
|
||||||
|
NodeElementArchetype.Factory.Text(0, 1, "Channel:"),
|
||||||
|
NodeElementArchetype.Factory.UnsignedInteger(50, 0, 0, -1, 0, 3),
|
||||||
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -396,21 +402,29 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
new NodeArchetype
|
new NodeArchetype
|
||||||
{
|
{
|
||||||
TypeID = 16,
|
TypeID = 16,
|
||||||
Title = "World Triplanar Texture",
|
Title = "Triplanar Texture",
|
||||||
Description = "Projects a texture using world-space coordinates instead of UVs.",
|
Description = "Projects a texture using world-space coordinates with triplanar mapping.",
|
||||||
Flags = NodeFlags.MaterialGraph,
|
Flags = NodeFlags.MaterialGraph,
|
||||||
Size = new Float2(240, 60),
|
Size = new Float2(280, 100),
|
||||||
DefaultValues = new object[]
|
DefaultValues = new object[]
|
||||||
{
|
{
|
||||||
1.0f,
|
1.0f, // Scale
|
||||||
1.0f
|
1.0f, // Blend
|
||||||
|
Float2.Zero, // Offset
|
||||||
|
2, // Sampler
|
||||||
|
false, // Local
|
||||||
},
|
},
|
||||||
Elements = new[]
|
Elements = new[]
|
||||||
{
|
{
|
||||||
NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
|
NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
|
||||||
NodeElementArchetype.Factory.Input(1, "Scale", true, typeof(Float4), 1, 0),
|
NodeElementArchetype.Factory.Input(1, "Scale", true, typeof(float), 1, 0),
|
||||||
NodeElementArchetype.Factory.Input(2, "Blend", true, typeof(float), 2, 1),
|
NodeElementArchetype.Factory.Input(2, "Blend", true, typeof(float), 2, 1),
|
||||||
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float4), 3)
|
NodeElementArchetype.Factory.Input(3, "Offset", true, typeof(Float2), 3, 2),
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Color", typeof(Float4), 5),
|
||||||
|
NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY * 4, "Sampler"),
|
||||||
|
NodeElementArchetype.Factory.ComboBox(50, Surface.Constants.LayoutOffsetY * 4 - 1, 100, 3, typeof(CommonSamplerType)),
|
||||||
|
NodeElementArchetype.Factory.Text(155, Surface.Constants.LayoutOffsetY * 4, "Local"),
|
||||||
|
NodeElementArchetype.Factory.Bool(190, Surface.Constants.LayoutOffsetY * 4, 4),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new NodeArchetype
|
new NodeArchetype
|
||||||
@@ -450,7 +464,35 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
{
|
{
|
||||||
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 23,
|
||||||
|
Title = "Triplanar Normal Map",
|
||||||
|
Description = "Projects a normal map texture using world-space coordinates with triplanar mapping.",
|
||||||
|
Flags = NodeFlags.MaterialGraph,
|
||||||
|
Size = new Float2(280, 100),
|
||||||
|
DefaultValues = new object[]
|
||||||
|
{
|
||||||
|
1.0f, // Scale
|
||||||
|
1.0f, // Blend
|
||||||
|
Float2.Zero, // Offset
|
||||||
|
2, // Sampler
|
||||||
|
false, // Local
|
||||||
|
},
|
||||||
|
Elements = new[]
|
||||||
|
{
|
||||||
|
NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
|
||||||
|
NodeElementArchetype.Factory.Input(1, "Scale", true, typeof(float), 1, 0),
|
||||||
|
NodeElementArchetype.Factory.Input(2, "Blend", true, typeof(float), 2, 1),
|
||||||
|
NodeElementArchetype.Factory.Input(3, "Offset", true, typeof(Float2), 3, 2),
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Vector", typeof(Float3), 5),
|
||||||
|
NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY * 4, "Sampler"),
|
||||||
|
NodeElementArchetype.Factory.ComboBox(50, Surface.Constants.LayoutOffsetY * 4 - 1, 100, 3, typeof(CommonSamplerType)),
|
||||||
|
NodeElementArchetype.Factory.Text(155, Surface.Constants.LayoutOffsetY * 4, "Local"),
|
||||||
|
NodeElementArchetype.Factory.Bool(190, Surface.Constants.LayoutOffsetY * 4, 4),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1499,12 +1499,12 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
2,
|
2,
|
||||||
|
|
||||||
// Stop 0
|
// Stop 0
|
||||||
0.1f,
|
0.05f,
|
||||||
Color.CornflowerBlue,
|
Color.Black,
|
||||||
|
|
||||||
// Stop 1
|
// Stop 1
|
||||||
0.9f,
|
0.95f,
|
||||||
Color.GreenYellow,
|
Color.White,
|
||||||
|
|
||||||
// Empty stops 2-7
|
// Empty stops 2-7
|
||||||
0.0f, Color.Black,
|
0.0f, Color.Black,
|
||||||
|
|||||||
@@ -759,7 +759,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Show(Control parent, Float2 location)
|
public override void Show(Control parent, Float2 location, ContextMenuDirection? direction = null)
|
||||||
{
|
{
|
||||||
Show(parent, location, null);
|
Show(parent, location, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,11 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
{
|
{
|
||||||
value = (double)toSet;
|
value = (double)toSet;
|
||||||
}
|
}
|
||||||
|
else if (parentNode.GroupArchetype.GroupID != 2)
|
||||||
|
{
|
||||||
|
// Per-component editing is used only by nodes from Constant group, otherwise use float
|
||||||
|
value = toSet;
|
||||||
|
}
|
||||||
else if (value is Vector2 asVector2)
|
else if (value is Vector2 asVector2)
|
||||||
{
|
{
|
||||||
if (arch.BoxID == 0)
|
if (arch.BoxID == 0)
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace FlaxEditor.Surface
|
|||||||
Title = TitleValue;
|
Title = TitleValue;
|
||||||
Color = ColorValue;
|
Color = ColorValue;
|
||||||
var size = SizeValue;
|
var size = SizeValue;
|
||||||
if (Surface.GridSnappingEnabled)
|
if (Surface != null && Surface.GridSnappingEnabled)
|
||||||
size = Surface.SnapToGrid(size, true);
|
size = Surface.SnapToGrid(size, true);
|
||||||
Size = size;
|
Size = size;
|
||||||
|
|
||||||
|
|||||||
@@ -1001,6 +1001,15 @@ namespace FlaxEditor.Surface
|
|||||||
_isDuringValuesEditing = value;
|
_isDuringValuesEditing = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets teh node values from the given pasted source. Can be overriden to perform validation or custom values processing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">The input values array.</param>
|
||||||
|
public virtual void SetValuesPaste(object[] values)
|
||||||
|
{
|
||||||
|
Values = values;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when node values set gets changed.
|
/// Called when node values set gets changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.Surface.Undo;
|
using FlaxEditor.Surface.Undo;
|
||||||
using FlaxEngine;
|
|
||||||
|
|
||||||
namespace FlaxEditor.Surface
|
namespace FlaxEditor.Surface
|
||||||
{
|
{
|
||||||
@@ -57,6 +57,28 @@ namespace FlaxEditor.Surface
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the surface context with the given owning nodes IDs path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodePath">The node ids path.</param>
|
||||||
|
/// <returns>Found context or null if cannot.</returns>
|
||||||
|
public VisjectSurfaceContext OpenContext(Span<uint> nodePath)
|
||||||
|
{
|
||||||
|
OpenContext(RootContext.Context);
|
||||||
|
if (nodePath != null && nodePath.Length != 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nodePath.Length; i++)
|
||||||
|
{
|
||||||
|
var node = Context.FindNode(nodePath[i]);
|
||||||
|
if (node is ISurfaceContext context)
|
||||||
|
OpenContext(context);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Context;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the Visject surface context for the given surface data source context.
|
/// Creates the Visject surface context for the given surface data source context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -101,7 +123,12 @@ namespace FlaxEditor.Surface
|
|||||||
if (_root == null)
|
if (_root == null)
|
||||||
_root = surfaceContext;
|
_root = surfaceContext;
|
||||||
else if (ContextStack.Contains(surfaceContext))
|
else if (ContextStack.Contains(surfaceContext))
|
||||||
throw new ArgumentException("Context has been already added to the stack.");
|
{
|
||||||
|
// Go up until the given context
|
||||||
|
while (ContextStack.First() != surfaceContext)
|
||||||
|
CloseContext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Change stack
|
// Change stack
|
||||||
ContextStack.Push(surfaceContext);
|
ContextStack.Push(surfaceContext);
|
||||||
|
|||||||
@@ -286,13 +286,14 @@ namespace FlaxEditor.Surface
|
|||||||
// Initialize
|
// Initialize
|
||||||
if (nodeData.Values != null && node.Values.Length > 0)
|
if (nodeData.Values != null && node.Values.Length > 0)
|
||||||
{
|
{
|
||||||
if (node.Values != null && node.Values.Length == nodeData.Values.Length)
|
var nodeValues = (object[])node.Values?.Clone();
|
||||||
|
if (nodeValues != null && nodeValues.Length == nodeData.Values.Length)
|
||||||
{
|
{
|
||||||
// Copy and fix values (Json deserializes may output them in a different format)
|
// Copy and fix values (Json deserializes may output them in a different format)
|
||||||
for (int l = 0; l < node.Values.Length; l++)
|
for (int l = 0; l < nodeData.Values.Length; l++)
|
||||||
{
|
{
|
||||||
var src = nodeData.Values[l].Value;
|
var src = nodeData.Values[l].Value;
|
||||||
var dst = node.Values[l];
|
var dst = nodeValues[l];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -364,13 +365,24 @@ namespace FlaxEditor.Surface
|
|||||||
Editor.LogWarning(ex);
|
Editor.LogWarning(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.Values[l] = src;
|
nodeValues[l] = src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node.Archetype.Flags.HasFlag(NodeFlags.VariableValuesSize))
|
||||||
|
{
|
||||||
|
// Copy values
|
||||||
|
nodeValues = new object[nodeData.Values.Length];
|
||||||
|
for (int l = 0; l < nodeData.Values.Length; l++)
|
||||||
|
{
|
||||||
|
nodeValues[l] = nodeData.Values[l].Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Editor.LogWarning("Invalid node custom values.");
|
Editor.LogWarning("Invalid node custom values.");
|
||||||
}
|
}
|
||||||
|
if (nodeValues != null)
|
||||||
|
node.SetValuesPaste(nodeValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.OnControlLoaded(node, SurfaceNodeActions.Paste);
|
Context.OnControlLoaded(node, SurfaceNodeActions.Paste);
|
||||||
@@ -445,7 +457,8 @@ namespace FlaxEditor.Surface
|
|||||||
// Select those nodes
|
// Select those nodes
|
||||||
Select(nodes.Values);
|
Select(nodes.Values);
|
||||||
|
|
||||||
MarkAsEdited();
|
if (nodes.Count > 0)
|
||||||
|
MarkAsEdited();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user