Compare commits
227 Commits
goake
...
woa_suppor
| Author | SHA1 | Date | |
|---|---|---|---|
| 74dcea373c | |||
| 70f8492c01 | |||
| 63acdccd43 | |||
| 03f74b0c50 | |||
| 0d21a3ba1b | |||
| d85a5bcd36 | |||
| 585ebceb6a | |||
| 593c82543f | |||
| 7f1bcd91f5 | |||
| 58214ffc35 | |||
| 67b4b01697 | |||
| bd880c0e2f | |||
| 0bca21a1d4 | |||
| c5e3d4afd3 | |||
| bb1bee40e4 | |||
| 1b0b8998f9 | |||
| e4764c4d84 | |||
| 2de756f761 | |||
| 83f40be4f5 | |||
| 87a73c9b73 | |||
| 7054f942f6 | |||
| 227eaff9e2 | |||
| 563a45633f | |||
| 09e0754902 | |||
| 3dfe0e6c5a | |||
| 9e7af72046 | |||
| 96eb8cb0ca | |||
| ff86057a0a | |||
| 56abd82c9b | |||
| 9777bef9df | |||
| 9fedacb404 | |||
| 84f7fde753 | |||
| a5566d297f | |||
| 3f299f99cd | |||
| 741fc959e6 | |||
| 93fd560723 | |||
| cf48ce6d93 | |||
| bdd3b754bd | |||
| 99c27c9c30 | |||
|
|
97be8ee8cc | ||
|
|
1d6e8c4b7c | ||
|
|
1cd2f6a070 | ||
|
|
35ddfc2455 | ||
|
|
17d1d87268 | ||
|
|
fd871ce830 | ||
|
|
b4a4a8a591 | ||
|
|
24e4015425 | ||
|
|
c670887b1a | ||
|
|
d3cd6a461b | ||
|
|
2625a9d762 | ||
|
|
4fdd9a242b | ||
|
|
a6e8e6f749 | ||
|
|
03eabbcf63 | ||
|
|
13f94dcf11 | ||
|
|
3b44062eb0 | ||
|
|
1457637707 | ||
|
|
d28567111f | ||
|
|
1c7f06e570 | ||
|
|
63cc0fef2e | ||
|
|
57084b3d6c | ||
|
|
fa23619f08 | ||
|
|
1f2456fc67 | ||
|
|
0b71e906a6 | ||
|
|
2e59c35a44 | ||
|
|
6f2bd0e932 | ||
|
|
82bf4238df | ||
|
|
9d2dc91920 | ||
|
|
3ae30a59b3 | ||
|
|
6a883bc7c6 | ||
|
|
17de6388ca | ||
|
|
e028d263f1 | ||
|
|
6962ed6730 | ||
|
|
b66d50ae1b | ||
|
|
a742ce1d32 | ||
|
|
675ce71935 | ||
|
|
833f844d59 | ||
|
|
af08dc1c69 | ||
|
|
3593f835cd | ||
|
|
df086f3b3b | ||
|
|
07628d2ec7 | ||
|
|
aac3dbfe09 | ||
|
|
185f24ce49 | ||
| 77e29109ee | |||
| 8d89b9efb0 | |||
|
|
b2fee31a13 | ||
|
|
fc7628e2ee | ||
|
|
2e3e4959d6 | ||
|
|
f22105c2c3 | ||
|
|
533902d185 | ||
|
|
6b31d51e31 | ||
|
|
f0d143ecaa | ||
|
|
196aa020fd | ||
|
|
ffe5105602 | ||
|
|
4acaa62a07 | ||
|
|
68653fa91f | ||
|
|
dc0aa61a14 | ||
|
|
ee790ff3a9 | ||
|
|
a2a3926aee | ||
|
|
9a70344c1f | ||
|
|
44006dd533 | ||
|
|
f6aabf2d14 | ||
|
|
dc1f15f18d | ||
|
|
7d7808af8f | ||
|
|
5029584a9f | ||
|
|
f353d3f114 | ||
|
|
667e8bc293 | ||
|
|
2edb9cc4d8 | ||
|
|
7018666a8c | ||
|
|
f04926ad94 | ||
|
|
e7508538e0 | ||
| 50f5f0acd9 | |||
|
|
33202a74b0 | ||
|
|
3745979b81 | ||
|
|
db15f6f08a | ||
|
|
e1a2f51d5a | ||
|
|
a8e1fd7a4a | ||
|
|
d46ef6ac92 | ||
|
|
36d21b27c7 | ||
|
|
b1636c27e7 | ||
|
|
5d32fc6c5e | ||
|
|
065dc474c0 | ||
|
|
1fb7b24aad | ||
|
|
f0b72aa025 | ||
|
|
058077736b | ||
|
|
571ba6773d | ||
|
|
40652a0ebc | ||
|
|
481a6de821 | ||
|
|
66b828ae92 | ||
|
|
b91f51fb46 | ||
|
|
b02f011627 | ||
|
|
e51d2dda00 | ||
|
|
a11fa46ee2 | ||
|
|
47f3ecbde2 | ||
|
|
deb2319190 | ||
| ea04c746fd | |||
| 97454fc82e | |||
|
|
4a6afdb108 | ||
|
|
4b8970f674 | ||
|
|
f43cd97907 | ||
|
|
65e852600a | ||
|
|
fedd990c13 | ||
|
|
c0329abe40 | ||
|
|
d8850a56a8 | ||
|
|
e171bb06ec | ||
|
|
3825e07adc | ||
|
|
db8adf7d96 | ||
| e77ae12b9b | |||
|
|
bf4e4aeaf6 | ||
|
|
2107b069db | ||
|
|
ea2005dacb | ||
|
|
d5cded8aaa | ||
|
|
430b22d5d7 | ||
|
|
5b2af6b3d5 | ||
|
|
f604503566 | ||
|
|
388a0f4196 | ||
|
|
754ed56119 | ||
|
|
dca8e391fa | ||
|
|
9d830eb1e2 | ||
|
|
7e3f84f95e | ||
|
|
cddee38d71 | ||
|
|
e030d0461b | ||
|
|
4978c8e0d9 | ||
|
|
dc7b7e6e10 | ||
|
|
1e3eb11b94 | ||
|
|
b15b231b85 | ||
|
|
262992571a | ||
|
|
352bf3f9a7 | ||
|
|
9683868767 | ||
|
|
40284fbbf8 | ||
|
|
0c86a900da | ||
|
|
c1e3eaeab1 | ||
|
|
3c487dff47 | ||
|
|
2260d79e26 | ||
|
|
863794d3c0 | ||
|
|
0d8c9f6626 | ||
|
|
8a45dda98c | ||
|
|
3209320547 | ||
|
|
d1db06a9bb | ||
|
|
1c1d2fd96f | ||
|
|
2e5ad8c48a | ||
|
|
9a6f866956 | ||
|
|
0cdce9dba2 | ||
|
|
97078cda7e | ||
|
|
10c47b8c2a | ||
|
|
3ebf73ec22 | ||
|
|
ebe05d4a51 | ||
|
|
cdeb9a3b15 | ||
|
|
60e8d73079 | ||
|
|
cf23892bd4 | ||
|
|
25f3cef8c3 | ||
|
|
00f2a0b825 | ||
|
|
7342629a86 | ||
|
|
5f860db6a5 | ||
|
|
6233718b06 | ||
|
|
62444315de | ||
|
|
a532ea7b42 | ||
|
|
803249f126 | ||
|
|
4e65b76b8c | ||
|
|
890b2da108 | ||
|
|
eac1d19a09 | ||
|
|
c4949de28f | ||
|
|
340ef194d3 | ||
|
|
b4547ec4d2 | ||
|
|
89f7e442f7 | ||
|
|
e7bef5e880 | ||
|
|
ff7c986fb1 | ||
|
|
708fba5136 | ||
|
|
7d92779e99 | ||
|
|
4c8528dcae | ||
|
|
3efd1e4e84 | ||
|
|
0cc6669cbd | ||
|
|
8bd409e95d | ||
|
|
3d0d41ebff | ||
|
|
61323f8526 | ||
|
|
017def29d4 | ||
|
|
13a04c2941 | ||
|
|
bc9cdf5cdb | ||
|
|
f7470af42d | ||
|
|
5c356ec22a | ||
|
|
06a35da0a8 | ||
|
|
55af307c43 | ||
|
|
4ab572426d | ||
|
|
01d91bf102 | ||
|
|
2dfb1058b2 | ||
|
|
cdbb2cc813 | ||
|
|
0e00f1e0eb | ||
|
|
d13621e631 |
@@ -1,4 +1,4 @@
|
|||||||
# Redirect to our own Git LFS server
|
# Redirect to our own Git LFS server
|
||||||
[lfs]
|
[lfs]
|
||||||
url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
|
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
|
||||||
locksverify = false
|
locksverify = false
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,7 +16,6 @@
|
|||||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||||
@2// Forward Shading: Constants
|
@2// Forward Shading: Constants
|
||||||
LightData DirectionalLight;
|
LightData DirectionalLight;
|
||||||
LightShadowData DirectionalLightShadow;
|
|
||||||
LightData SkyLight;
|
LightData SkyLight;
|
||||||
ProbeData EnvironmentProbe;
|
ProbeData EnvironmentProbe;
|
||||||
ExponentialHeightFogData ExponentialHeightFog;
|
ExponentialHeightFogData ExponentialHeightFog;
|
||||||
@@ -26,9 +25,9 @@ LightData LocalLights[MAX_LOCAL_LIGHTS];
|
|||||||
@3// Forward Shading: Resources
|
@3// Forward Shading: Resources
|
||||||
TextureCube EnvProbe : register(t__SRV__);
|
TextureCube EnvProbe : register(t__SRV__);
|
||||||
TextureCube SkyLightTexture : register(t__SRV__);
|
TextureCube SkyLightTexture : register(t__SRV__);
|
||||||
Texture2DArray DirectionalLightShadowMap : register(t__SRV__);
|
Buffer<float4> ShadowsBuffer : register(t__SRV__);
|
||||||
|
Texture2D<float> ShadowMap : register(t__SRV__);
|
||||||
@4// Forward Shading: Utilities
|
@4// Forward Shading: Utilities
|
||||||
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
|
|
||||||
@5// Forward Shading: Shaders
|
@5// Forward Shading: Shaders
|
||||||
|
|
||||||
// Pixel Shader function for Forward Pass
|
// Pixel Shader function for Forward Pass
|
||||||
@@ -80,11 +79,8 @@ void PS_Forward(
|
|||||||
|
|
||||||
// Calculate lighting from a single directional light
|
// Calculate lighting from a single directional light
|
||||||
float4 shadowMask = 1.0f;
|
float4 shadowMask = 1.0f;
|
||||||
if (DirectionalLight.CastShadows > 0)
|
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
|
||||||
{
|
shadowMask = GetShadowMask(shadow);
|
||||||
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
|
|
||||||
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
|
|
||||||
}
|
|
||||||
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
||||||
|
|
||||||
// Calculate lighting from sky light
|
// Calculate lighting from sky light
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct RibbonInput
|
|||||||
|
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
float4x4 WorldMatrix;
|
float4x3 WorldMatrix;
|
||||||
uint SortedIndicesOffset;
|
uint SortedIndicesOffset;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
int ParticleStride;
|
int ParticleStride;
|
||||||
@@ -45,7 +45,7 @@ int RibbonWidthOffset;
|
|||||||
int RibbonTwistOffset;
|
int RibbonTwistOffset;
|
||||||
int RibbonFacingVectorOffset;
|
int RibbonFacingVectorOffset;
|
||||||
uint RibbonSegmentCount;
|
uint RibbonSegmentCount;
|
||||||
float4x4 WorldMatrixInverseTransposed;
|
float4x3 WorldMatrixInverseTransposed;
|
||||||
@1META_CB_END
|
@1META_CB_END
|
||||||
|
|
||||||
// Particles attributes buffer
|
// Particles attributes buffer
|
||||||
@@ -138,7 +138,7 @@ MaterialInput GetMaterialInput(PixelInput input)
|
|||||||
#if USE_INSTANCING
|
#if USE_INSTANCING
|
||||||
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
|
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
|
||||||
#else
|
#else
|
||||||
#define GetInstanceTransform(input) WorldMatrix;
|
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||||
@@ -264,12 +264,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
|
|||||||
|
|
||||||
float3 TransformParticlePosition(float3 input)
|
float3 TransformParticlePosition(float3 input)
|
||||||
{
|
{
|
||||||
return mul(float4(input, 1.0f), WorldMatrix).xyz;
|
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 TransformParticleVector(float3 input)
|
float3 TransformParticleVector(float3 input)
|
||||||
{
|
{
|
||||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@8
|
@8
|
||||||
@@ -333,7 +333,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
|
|||||||
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
|
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
|
||||||
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
|
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
|
||||||
|
|
||||||
float4x4 world = WorldMatrix;
|
float4x4 world = ToMatrix4x4(WorldMatrix);
|
||||||
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
||||||
float3x3 viewRot = transpose((float3x3)ViewMatrix);
|
float3x3 viewRot = transpose((float3x3)ViewMatrix);
|
||||||
float3 position = mul(float4(particlePosition, 1), world).xyz;
|
float3 position = mul(float4(particlePosition, 1), world).xyz;
|
||||||
@@ -463,11 +463,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read particle data
|
// Read particle data
|
||||||
|
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
|
||||||
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
|
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
|
||||||
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
|
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
|
||||||
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
|
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
|
||||||
int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1;
|
int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1;
|
||||||
float3 position = mul(float4(particlePosition, 1), WorldMatrix).xyz;
|
float3 position = mul(float4(particlePosition, 1), worldMatrix).xyz;
|
||||||
|
|
||||||
// Compute final vertex position in the world
|
// Compute final vertex position in the world
|
||||||
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
||||||
@@ -506,7 +507,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
|||||||
world = mul(world, scaleMatrix);
|
world = mul(world, scaleMatrix);
|
||||||
}
|
}
|
||||||
world = transpose(world);
|
world = transpose(world);
|
||||||
world = mul(world, WorldMatrix);
|
world = mul(world, worldMatrix);
|
||||||
|
|
||||||
// Calculate the vertex position in world space
|
// Calculate the vertex position in world space
|
||||||
output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
|
output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
|
||||||
@@ -520,12 +521,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
|||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = input.Color;
|
output.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
output.InstanceOrigin = WorldMatrix[3].xyz;
|
output.InstanceOrigin = worldMatrix[3].xyz;
|
||||||
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 = CalcTangentToLocal(input);
|
half3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||||
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
half3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
|
||||||
output.TBN = tangentToWorld;
|
output.TBN = tangentToWorld;
|
||||||
|
|
||||||
// Get material input params if need to evaluate any material property
|
// Get material input params if need to evaluate any material property
|
||||||
@@ -625,12 +626,13 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
|
|||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = 1;
|
output.VertexColor = 1;
|
||||||
#endif
|
#endif
|
||||||
output.InstanceOrigin = WorldMatrix[3].xyz;
|
float4x4 world = ToMatrix4x4(WorldMatrix);
|
||||||
|
output.InstanceOrigin = world[3].xyz;
|
||||||
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 = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
|
||||||
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||||
output.TBN = tangentToWorld;
|
output.TBN = tangentToWorld;
|
||||||
|
|
||||||
// Get material input params if need to evaluate any material property
|
// Get material input params if need to evaluate any material property
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
@7
|
@7
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
float4x4 WorldMatrix;
|
float4x3 WorldMatrix;
|
||||||
float4x4 PrevWorldMatrix;
|
float4x3 PrevWorldMatrix;
|
||||||
float2 Dummy0;
|
float2 Dummy0;
|
||||||
float LODDitherFactor;
|
float LODDitherFactor;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
@@ -171,7 +171,7 @@ MaterialInput GetMaterialInput(PixelInput input)
|
|||||||
#if USE_INSTANCING
|
#if USE_INSTANCING
|
||||||
#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
|
#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
|
||||||
#else
|
#else
|
||||||
#define CalculateInstanceTransform(input) float4x4 world = WorldMatrix; output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
|
#define CalculateInstanceTransform(input) float4x4 world = ToMatrix4x4(WorldMatrix); output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||||
@@ -328,7 +328,7 @@ VertexOutput VS(ModelInput input)
|
|||||||
// Compute world space vertex position
|
// Compute world space vertex position
|
||||||
CalculateInstanceTransform(input);
|
CalculateInstanceTransform(input);
|
||||||
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||||
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
|
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
|
||||||
|
|
||||||
// Compute clip space position
|
// Compute clip space position
|
||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
@@ -402,7 +402,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
|
|||||||
#if USE_INSTANCING
|
#if USE_INSTANCING
|
||||||
float4x4 world = GetInstanceTransform(input);
|
float4x4 world = GetInstanceTransform(input);
|
||||||
#else
|
#else
|
||||||
float4x4 world = WorldMatrix;
|
float4x4 world = ToMatrix4x4(WorldMatrix);
|
||||||
#endif
|
#endif
|
||||||
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||||
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
|
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
|
||||||
@@ -508,9 +508,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
|||||||
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
|
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
|
||||||
#if PER_BONE_MOTION_BLUR
|
#if PER_BONE_MOTION_BLUR
|
||||||
float3 prevPosition = SkinPrevPosition(input);
|
float3 prevPosition = SkinPrevPosition(input);
|
||||||
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
|
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
|
||||||
#else
|
#else
|
||||||
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
|
output.Geometry.PrevWorldPosition = mul(float4(position, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compute clip space position
|
// Compute clip space position
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
@7
|
@7
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
float4x4 WorldMatrix;
|
float4x3 WorldMatrix;
|
||||||
float3 WorldInvScale;
|
float3 WorldInvScale;
|
||||||
float WorldDeterminantSign;
|
float WorldDeterminantSign;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
@@ -194,7 +194,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
|||||||
// Transforms a vector from local space to world space
|
// Transforms a vector from local space to world space
|
||||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||||
{
|
{
|
||||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
|
||||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||||
return mul(localVector, localToWorld);
|
return mul(localVector, localToWorld);
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
|||||||
// Transforms a vector from local space to world space
|
// Transforms a vector from local space to world space
|
||||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||||
{
|
{
|
||||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
|
||||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||||
return mul(localToWorld, worldVector);
|
return mul(localToWorld, worldVector);
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
|||||||
// Gets the current object position
|
// Gets the current object position
|
||||||
float3 GetObjectPosition(MaterialInput input)
|
float3 GetObjectPosition(MaterialInput input)
|
||||||
{
|
{
|
||||||
return WorldMatrix[3].xyz;
|
return ToMatrix4x4(WorldMatrix)[3].xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the current object size
|
// Gets the current object size
|
||||||
@@ -365,7 +365,8 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
||||||
|
|
||||||
// Compute world space vertex position
|
// Compute world space vertex position
|
||||||
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
|
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
|
||||||
|
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
|
||||||
|
|
||||||
// Compute clip space position
|
// Compute clip space position
|
||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
@@ -389,7 +390,7 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
|
|
||||||
// Compute world space normal vector
|
// Compute world space normal vector
|
||||||
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
||||||
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
float3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
|
||||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||||
|
|
||||||
// Get material input params if need to evaluate any material property
|
// Get material input params if need to evaluate any material property
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
float4x4 InverseViewProjectionMatrix;
|
float4x4 InverseViewProjectionMatrix;
|
||||||
float4x4 WorldMatrix;
|
float4x3 WorldMatrix;
|
||||||
float4x4 WorldMatrixInverseTransposed;
|
float4x3 WorldMatrixInverseTransposed;
|
||||||
float3 GridSize;
|
float3 GridSize;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
float Dummy0;
|
float Dummy0;
|
||||||
@@ -49,7 +49,7 @@ struct MaterialInput
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GetInstanceTransform(input) WorldMatrix;
|
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
|
||||||
|
|
||||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||||
@@ -170,12 +170,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
|
|||||||
|
|
||||||
float3 TransformParticlePosition(float3 input)
|
float3 TransformParticlePosition(float3 input)
|
||||||
{
|
{
|
||||||
return mul(float4(input, 1.0f), WorldMatrix).xyz;
|
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 TransformParticleVector(float3 input)
|
float3 TransformParticleVector(float3 input)
|
||||||
{
|
{
|
||||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@8
|
@8
|
||||||
@@ -219,7 +219,7 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
|
|||||||
materialInput.ParticleIndex = ParticleIndex;
|
materialInput.ParticleIndex = ParticleIndex;
|
||||||
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
||||||
materialInput.TwoSidedSign = 1.0f;
|
materialInput.TwoSidedSign = 1.0f;
|
||||||
materialInput.InstanceOrigin = WorldMatrix[3].xyz;
|
materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz;
|
||||||
materialInput.InstanceParams = PerInstanceRandom;
|
materialInput.InstanceParams = PerInstanceRandom;
|
||||||
materialInput.SvPosition = clipPos;
|
materialInput.SvPosition = clipPos;
|
||||||
Material material = GetMaterialPS(materialInput);
|
Material material = GetMaterialPS(materialInput);
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Shaders/Lights.flax
LFS
BIN
Content/Shaders/Lights.flax
LFS
Binary file not shown.
BIN
Content/Shaders/Quad.flax
LFS
BIN
Content/Shaders/Quad.flax
LFS
Binary file not shown.
BIN
Content/Shaders/Shadows.flax
LFS
BIN
Content/Shaders/Shadows.flax
LFS
Binary file not shown.
Binary file not shown.
@@ -2,9 +2,9 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 8,
|
"Minor": 9,
|
||||||
"Revision": 1,
|
"Revision": 0,
|
||||||
"Build": 6511
|
"Build": 6601
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ call "Development\Scripts\Windows\CallBuildTool.bat" -genproject %*
|
|||||||
if errorlevel 1 goto BuildToolFailed
|
if errorlevel 1 goto BuildToolFailed
|
||||||
|
|
||||||
:: Build bindings for all editor configurations
|
:: Build bindings for all editor configurations
|
||||||
echo Building C# bindings...
|
::echo Building C# bindings...
|
||||||
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
|
::Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
|
||||||
|
|
||||||
popd
|
popd
|
||||||
echo Done!
|
echo Done!
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
@@ -94,30 +96,8 @@ public class AssetPickerValidator : IContentItemOwner
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string SelectedPath
|
public string SelectedPath
|
||||||
{
|
{
|
||||||
get
|
get => Utilities.Utils.ToPathProject(_selectedItem?.Path ?? _selected?.Path);
|
||||||
{
|
set => SelectedItem = string.IsNullOrEmpty(value) ? null : Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(value));
|
||||||
string path = _selectedItem?.Path ?? _selected?.Path;
|
|
||||||
if (path != null)
|
|
||||||
{
|
|
||||||
// Convert into path relative to the project (cross-platform)
|
|
||||||
var projectFolder = Globals.ProjectFolder;
|
|
||||||
if (path.StartsWith(projectFolder))
|
|
||||||
path = path.Substring(projectFolder.Length + 1);
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
SelectedItem = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var path = StringUtils.IsRelative(value) ? Path.Combine(Globals.ProjectFolder, value) : value;
|
|
||||||
SelectedItem = Editor.Instance.ContentDatabase.Find(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -242,7 +222,7 @@ public class AssetPickerValidator : IContentItemOwner
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="AssetPickerValidator"/> class.
|
/// Initializes a new instance of the <see cref="AssetPickerValidator"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assetType">The assets types that this picker accepts.</param>
|
/// <param name="assetType">The asset types that this picker accepts.</param>
|
||||||
public AssetPickerValidator(ScriptType assetType)
|
public AssetPickerValidator(ScriptType assetType)
|
||||||
{
|
{
|
||||||
_type = assetType;
|
_type = assetType;
|
||||||
|
|||||||
28
Source/Editor/Content/Items/VideoItem.cs
Normal file
28
Source/Editor/Content/Items/VideoItem.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEngine;
|
||||||
|
|
||||||
|
namespace FlaxEditor.Content
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Content item that contains video media file.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEditor.Content.JsonAssetItem" />
|
||||||
|
public sealed class VideoItem : FileItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="VideoItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file path.</param>
|
||||||
|
public VideoItem(string path)
|
||||||
|
: base(path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "Video";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,9 +30,7 @@ namespace FlaxEditor.Content
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether [is virtual proxy].
|
/// Determines whether [is virtual proxy].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>
|
/// <returns><c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.</returns>
|
||||||
/// <c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.
|
|
||||||
/// </returns>
|
|
||||||
public bool IsVirtualProxy()
|
public bool IsVirtualProxy()
|
||||||
{
|
{
|
||||||
return IsVirtual && CanExport == false;
|
return IsVirtual && CanExport == false;
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ namespace FlaxEditor.Content
|
|||||||
return item is CSharpScriptItem;
|
return item is CSharpScriptItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ContentItem ConstructItem(string path)
|
||||||
|
{
|
||||||
|
return new CSharpScriptItem(path);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Create(string outputPath, object arg)
|
public override void Create(string outputPath, object arg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,16 @@ namespace FlaxEditor.Content
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs the item for the file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file path.</param>
|
||||||
|
/// <returns>Created item or null.</returns>
|
||||||
|
public virtual ContentItem ConstructItem(string path)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this proxy if for assets.
|
/// Gets a value indicating whether this proxy if for assets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ namespace FlaxEditor.Content
|
|||||||
return item is CppScriptItem;
|
return item is CppScriptItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ContentItem ConstructItem(string path)
|
||||||
|
{
|
||||||
|
return new CppScriptItem(path);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void GetTemplatePaths(out string headerTemplate, out string sourceTemplate)
|
protected override void GetTemplatePaths(out string headerTemplate, out string sourceTemplate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ namespace FlaxEditor.Content
|
|||||||
return item is FileItem;
|
return item is FileItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ContentItem ConstructItem(string path)
|
||||||
|
{
|
||||||
|
return new FileItem(path);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string FileExtension => string.Empty;
|
public override string FileExtension => string.Empty;
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,16 @@ namespace FlaxEditor.Content
|
|||||||
return targetLocation.CanHaveAssets;
|
return targetLocation.CanHaveAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanReimport(ContentItem item)
|
||||||
|
{
|
||||||
|
if (item is not PrefabItem prefabItem)
|
||||||
|
return base.CanReimport(item);
|
||||||
|
|
||||||
|
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
|
||||||
|
return prefab.GetDefaultInstance().GetScript<ModelPrefab>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Create(string outputPath, object arg)
|
public override void Create(string outputPath, object arg)
|
||||||
{
|
{
|
||||||
|
|||||||
48
Source/Editor/Content/Proxy/VideoProxy.cs
Normal file
48
Source/Editor/Content/Proxy/VideoProxy.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEditor.Windows;
|
||||||
|
using FlaxEditor.Windows.Assets;
|
||||||
|
using FlaxEngine;
|
||||||
|
|
||||||
|
namespace FlaxEditor.Content
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A video media file proxy object.
|
||||||
|
/// </summary>
|
||||||
|
public class VideoProxy : ContentProxy
|
||||||
|
{
|
||||||
|
private readonly string _extension;
|
||||||
|
|
||||||
|
internal VideoProxy(string extension)
|
||||||
|
{
|
||||||
|
_extension = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Name => "Video";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string FileExtension => _extension;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Color AccentColor => Color.FromRGB(0x11f7f1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IsProxyFor(ContentItem item)
|
||||||
|
{
|
||||||
|
return item is VideoItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ContentItem ConstructItem(string path)
|
||||||
|
{
|
||||||
|
return new VideoItem(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override EditorWindow Open(Editor editor, ContentItem item)
|
||||||
|
{
|
||||||
|
return new VideoWindow(editor, (VideoItem)item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -134,6 +134,12 @@ API_ENUM() enum class BuildPlatform
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
|
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
|
||||||
iOSARM64 = 14,
|
iOSARM64 = 14,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Windows (ARM64)
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM(Attributes = "EditorDisplay(null, \"Windows ARM64\")")
|
||||||
|
WindowsARM64 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -285,24 +291,22 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The total assets amount in the build.
|
/// The total assets amount in the build.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 TotalAssets;
|
int32 TotalAssets = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cooked assets (TotalAssets - CookedAssets is amount of reused cached assets).
|
/// The cooked assets (TotalAssets - CookedAssets is amount of reused cached assets).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 CookedAssets;
|
int32 CookedAssets = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The final output content size in MB.
|
/// The final output content size (in bytes).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 ContentSizeMB;
|
uint64 ContentSize = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The asset type stats. Key is the asset typename, value is the stats container.
|
/// The asset type stats. Key is the asset typename, value is the stats container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Dictionary<String, AssetTypeStatistics> AssetStats;
|
Dictionary<String, AssetTypeStatistics> AssetStats;
|
||||||
|
|
||||||
Statistics();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -328,6 +332,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
HashSet<Guid> Assets;
|
HashSet<Guid> Assets;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The final files collection to include in build (valid only after CollectAssetsStep).
|
||||||
|
/// </summary>
|
||||||
|
HashSet<String> Files;
|
||||||
|
|
||||||
struct BinaryModuleInfo
|
struct BinaryModuleInfo
|
||||||
{
|
{
|
||||||
String Name;
|
String Name;
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ const Char* ToString(const BuildPlatform platform)
|
|||||||
return TEXT("Mac ARM64");
|
return TEXT("Mac ARM64");
|
||||||
case BuildPlatform::iOSARM64:
|
case BuildPlatform::iOSARM64:
|
||||||
return TEXT("iOS ARM64");
|
return TEXT("iOS ARM64");
|
||||||
|
case BuildPlatform::WindowsARM64:
|
||||||
|
return TEXT("Windows ARM64");
|
||||||
default:
|
default:
|
||||||
return TEXT("");
|
return TEXT("");
|
||||||
}
|
}
|
||||||
@@ -202,13 +204,6 @@ bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& othe
|
|||||||
return Count > other.Count;
|
return Count > other.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
CookingData::Statistics::Statistics()
|
|
||||||
{
|
|
||||||
TotalAssets = 0;
|
|
||||||
CookedAssets = 0;
|
|
||||||
ContentSizeMB = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CookingData::CookingData(const SpawnParams& params)
|
CookingData::CookingData(const SpawnParams& params)
|
||||||
: ScriptingObject(params)
|
: ScriptingObject(params)
|
||||||
{
|
{
|
||||||
@@ -307,6 +302,10 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
|
|||||||
platform = TEXT("iOS");
|
platform = TEXT("iOS");
|
||||||
architecture = TEXT("ARM64");
|
architecture = TEXT("ARM64");
|
||||||
break;
|
break;
|
||||||
|
case BuildPlatform::WindowsARM64:
|
||||||
|
platform = TEXT("Windows");
|
||||||
|
architecture = TEXT("ARM64");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Unknown or unsupported build platform.");
|
LOG(Fatal, "Unknown or unsupported build platform.");
|
||||||
}
|
}
|
||||||
@@ -393,6 +392,9 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
|||||||
case BuildPlatform::Windows64:
|
case BuildPlatform::Windows64:
|
||||||
result = New<WindowsPlatformTools>(ArchitectureType::x64);
|
result = New<WindowsPlatformTools>(ArchitectureType::x64);
|
||||||
break;
|
break;
|
||||||
|
case BuildPlatform::WindowsARM64:
|
||||||
|
result = New<WindowsPlatformTools>(ArchitectureType::ARM64);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if PLATFORM_TOOLS_UWP
|
#if PLATFORM_TOOLS_UWP
|
||||||
case BuildPlatform::UWPx86:
|
case BuildPlatform::UWPx86:
|
||||||
@@ -554,7 +556,12 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
|
|||||||
switch (PLATFORM_TYPE)
|
switch (PLATFORM_TYPE)
|
||||||
{
|
{
|
||||||
case PlatformType::Windows:
|
case PlatformType::Windows:
|
||||||
buildPlatform = PLATFORM_64BITS ? BuildPlatform::Windows64 : BuildPlatform::Windows32;
|
if (PLATFORM_ARCH == ArchitectureType::x64)
|
||||||
|
buildPlatform = BuildPlatform::Windows64;
|
||||||
|
else if (PLATFORM_ARCH == ArchitectureType::ARM64)
|
||||||
|
buildPlatform = BuildPlatform::WindowsARM64;
|
||||||
|
else
|
||||||
|
buildPlatform = BuildPlatform::Windows32;
|
||||||
break;
|
break;
|
||||||
case PlatformType::XboxOne:
|
case PlatformType::XboxOne:
|
||||||
buildPlatform = BuildPlatform::XboxOne;
|
buildPlatform = BuildPlatform::XboxOne;
|
||||||
|
|||||||
@@ -325,9 +325,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
|
|
||||||
const auto buildSettings = BuildSettings::Get();
|
const auto buildSettings = BuildSettings::Get();
|
||||||
if (buildSettings->SkipPackaging)
|
if (buildSettings->SkipPackaging)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
GameCooker::PackageFiles();
|
GameCooker::PackageFiles();
|
||||||
|
|
||||||
// Validate environment variables
|
// Validate environment variables
|
||||||
@@ -365,7 +363,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
Platform::CreateProcess(procSettings);
|
Platform::CreateProcess(procSettings);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const bool distributionPackage = buildSettings->ForDistribution;
|
const bool distributionPackage = buildSettings->ForDistribution || data.Configuration == BuildConfiguration::Release;
|
||||||
{
|
{
|
||||||
CreateProcessSettings procSettings;
|
CreateProcessSettings procSettings;
|
||||||
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
||||||
|
|||||||
@@ -10,47 +10,26 @@
|
|||||||
#include "Engine/Content/Assets/Shader.h"
|
#include "Engine/Content/Assets/Shader.h"
|
||||||
#include "Engine/Content/Cache/AssetsCache.h"
|
#include "Engine/Content/Cache/AssetsCache.h"
|
||||||
|
|
||||||
bool CollectAssetsStep::Process(CookingData& data, Asset* asset)
|
|
||||||
{
|
|
||||||
// Skip virtual/temporary assets
|
|
||||||
if (asset->IsVirtual())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Keep reference to the asset
|
|
||||||
AssetReference<Asset> ref(asset);
|
|
||||||
|
|
||||||
// Asset should have loaded data
|
|
||||||
if (asset->WaitForLoaded())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Gather asset references
|
|
||||||
_references.Clear();
|
|
||||||
asset->Locker.Lock();
|
|
||||||
asset->GetReferences(_references);
|
|
||||||
asset->Locker.Unlock();
|
|
||||||
_assetsQueue.Add(_references);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CollectAssetsStep::Perform(CookingData& data)
|
bool CollectAssetsStep::Perform(CookingData& data)
|
||||||
{
|
{
|
||||||
LOG(Info, "Searching for assets to include in a build. Using {0} root assets.", data.RootAssets.Count());
|
LOG(Info, "Searching for assets to include in a build. Using {0} root assets.", data.RootAssets.Count());
|
||||||
data.StepProgress(TEXT("Collecting assets"), 0);
|
data.StepProgress(TEXT("Collecting assets"), 0);
|
||||||
|
|
||||||
// Initialize assets queue
|
// Initialize assets queue
|
||||||
_assetsQueue.Clear();
|
Array<Guid> assetsQueue;
|
||||||
_assetsQueue.EnsureCapacity(1024);
|
assetsQueue.Clear();
|
||||||
|
assetsQueue.EnsureCapacity(1024);
|
||||||
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
|
||||||
_assetsQueue.Add(i->Item);
|
assetsQueue.Add(i->Item);
|
||||||
|
|
||||||
// Iterate through the assets graph
|
// Iterate through the assets graph
|
||||||
AssetInfo assetInfo;
|
AssetInfo assetInfo;
|
||||||
while (_assetsQueue.HasItems())
|
Array<Guid> references;
|
||||||
|
Array<String> files;
|
||||||
|
while (assetsQueue.HasItems())
|
||||||
{
|
{
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
const Guid assetId = assetsQueue.Dequeue();
|
||||||
const auto assetId = _assetsQueue.Dequeue();
|
|
||||||
|
|
||||||
// Skip already processed or invalid assets
|
// Skip already processed or invalid assets
|
||||||
if (!assetId.IsValid()
|
if (!assetId.IsValid()
|
||||||
@@ -69,14 +48,31 @@ bool CollectAssetsStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load asset
|
// Load asset
|
||||||
const auto asset = Content::LoadAsync<Asset>(assetId);
|
AssetReference<Asset> asset = Content::LoadAsync<Asset>(assetId);
|
||||||
if (asset == nullptr)
|
if (asset == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Process that asset
|
|
||||||
LOG_STR(Info, asset->GetPath());
|
LOG_STR(Info, asset->GetPath());
|
||||||
data.Assets.Add(assetId);
|
data.Assets.Add(assetId);
|
||||||
Process(data, asset);
|
|
||||||
|
// Skip virtual/temporary assets
|
||||||
|
if (asset->IsVirtual())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Asset should have loaded data
|
||||||
|
if (asset->WaitForLoaded())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Gather asset references
|
||||||
|
references.Clear();
|
||||||
|
asset->Locker.Lock();
|
||||||
|
asset->GetReferences(references, files);
|
||||||
|
asset->Locker.Unlock();
|
||||||
|
assetsQueue.Add(references);
|
||||||
|
for (String& file : files)
|
||||||
|
{
|
||||||
|
if (file.HasChars())
|
||||||
|
data.Files.Add(MoveTemp(file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Stats.TotalAssets = data.Assets.Count();
|
data.Stats.TotalAssets = data.Assets.Count();
|
||||||
|
|||||||
@@ -12,15 +12,7 @@ class Asset;
|
|||||||
/// <seealso cref="GameCooker::BuildStep" />
|
/// <seealso cref="GameCooker::BuildStep" />
|
||||||
class CollectAssetsStep : public GameCooker::BuildStep
|
class CollectAssetsStep : public GameCooker::BuildStep
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
Array<Guid> _assetsQueue;
|
|
||||||
Array<Guid> _references;
|
|
||||||
|
|
||||||
bool Process(CookingData& data, Asset* asset);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// [BuildStep]
|
// [BuildStep]
|
||||||
bool Perform(CookingData& data) override;
|
bool Perform(CookingData& data) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -447,6 +447,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
|||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
case BuildPlatform::Windows32:
|
case BuildPlatform::Windows32:
|
||||||
case BuildPlatform::Windows64:
|
case BuildPlatform::Windows64:
|
||||||
|
case BuildPlatform::WindowsARM64:
|
||||||
{
|
{
|
||||||
const char* platformDefineName = "PLATFORM_WINDOWS";
|
const char* platformDefineName = "PLATFORM_WINDOWS";
|
||||||
const auto settings = WindowsPlatformSettings::Get();
|
const auto settings = WindowsPlatformSettings::Get();
|
||||||
@@ -891,7 +892,6 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, JsonAssetBase*
|
|||||||
class PackageBuilder : public NonCopyable
|
class PackageBuilder : public NonCopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 _packageIndex;
|
int32 _packageIndex;
|
||||||
int32 MaxAssetsPerPackage;
|
int32 MaxAssetsPerPackage;
|
||||||
int32 MaxPackageSize;
|
int32 MaxPackageSize;
|
||||||
@@ -904,7 +904,6 @@ private:
|
|||||||
uint64 packagesSizeTotal;
|
uint64 packagesSizeTotal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="PackageBuilder" /> class.
|
/// Initializes a new instance of the <see cref="PackageBuilder" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -933,7 +932,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
uint64 GetPackagesSizeTotal() const
|
uint64 GetPackagesSizeTotal() const
|
||||||
{
|
{
|
||||||
return packagesSizeTotal;
|
return packagesSizeTotal;
|
||||||
@@ -1042,8 +1040,11 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
float Step1ProgressEnd = 0.6f;
|
float Step1ProgressEnd = 0.6f;
|
||||||
String Step1Info = TEXT("Cooking assets");
|
String Step1Info = TEXT("Cooking assets");
|
||||||
float Step2ProgressStart = Step1ProgressEnd;
|
float Step2ProgressStart = Step1ProgressEnd;
|
||||||
float Step2ProgressEnd = 0.9f;
|
float Step2ProgressEnd = 0.8f;
|
||||||
String Step2Info = TEXT("Packaging assets");
|
String Step2Info = TEXT("Cooking files");
|
||||||
|
float Step3ProgressStart = Step2ProgressStart;
|
||||||
|
float Step3ProgressEnd = 0.9f;
|
||||||
|
String Step3Info = TEXT("Packaging assets");
|
||||||
|
|
||||||
data.StepProgress(TEXT("Loading build cache"), 0);
|
data.StepProgress(TEXT("Loading build cache"), 0);
|
||||||
|
|
||||||
@@ -1100,11 +1101,14 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
#endif
|
#endif
|
||||||
int32 subStepIndex = 0;
|
int32 subStepIndex = 0;
|
||||||
AssetReference<Asset> assetRef;
|
AssetReference<Asset> assetRef;
|
||||||
assetRef.Unload.Bind([]() { LOG(Error, "Asset gets unloaded while cooking it!"); Platform::Sleep(100); });
|
assetRef.Unload.Bind([]
|
||||||
|
{
|
||||||
|
LOG(Error, "Asset got unloaded while cooking it!");
|
||||||
|
Platform::Sleep(100);
|
||||||
|
});
|
||||||
for (auto i = data.Assets.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = data.Assets.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
|
||||||
data.StepProgress(Step1Info, Math::Lerp(Step1ProgressStart, Step1ProgressEnd, static_cast<float>(subStepIndex++) / data.Assets.Count()));
|
data.StepProgress(Step1Info, Math::Lerp(Step1ProgressStart, Step1ProgressEnd, static_cast<float>(subStepIndex++) / data.Assets.Count()));
|
||||||
const Guid assetId = i->Item;
|
const Guid assetId = i->Item;
|
||||||
|
|
||||||
@@ -1184,6 +1188,35 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
// Save build cache header
|
// Save build cache header
|
||||||
cache.Save(data);
|
cache.Save(data);
|
||||||
|
|
||||||
|
// Process all files
|
||||||
|
for (auto i = data.Files.Begin(); i.IsNotEnd(); ++i)
|
||||||
|
{
|
||||||
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
data.StepProgress(Step2Info, Math::Lerp(Step2ProgressStart, Step2ProgressEnd, (float)subStepIndex++ / data.Files.Count()));
|
||||||
|
const String& filePath = i->Item;
|
||||||
|
|
||||||
|
// Calculate destination path
|
||||||
|
String cookedPath = data.DataOutputPath;
|
||||||
|
if (FileSystem::IsRelative(filePath))
|
||||||
|
cookedPath /= filePath;
|
||||||
|
else
|
||||||
|
cookedPath /= String(TEXT("Content")) / StringUtils::GetFileName(filePath);
|
||||||
|
|
||||||
|
// Copy file
|
||||||
|
if (!FileSystem::FileExists(cookedPath) || FileSystem::GetFileLastEditTime(cookedPath) >= FileSystem::GetFileLastEditTime(filePath))
|
||||||
|
{
|
||||||
|
if (FileSystem::CreateDirectory(StringUtils::GetDirectoryName(cookedPath)))
|
||||||
|
return true;
|
||||||
|
if (FileSystem::CopyFile(cookedPath, filePath))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count stats of file extension
|
||||||
|
auto& assetStats = data.Stats.AssetStats[FileSystem::GetExtension(cookedPath)];
|
||||||
|
assetStats.Count++;
|
||||||
|
assetStats.ContentSize += FileSystem::GetFileSize(cookedPath);
|
||||||
|
}
|
||||||
|
|
||||||
// Create build game header
|
// Create build game header
|
||||||
{
|
{
|
||||||
GameHeaderFlags gameFlags = GameHeaderFlags::None;
|
GameHeaderFlags gameFlags = GameHeaderFlags::None;
|
||||||
@@ -1229,13 +1262,11 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
for (auto i = AssetsRegistry.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = AssetsRegistry.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
data.StepProgress(Step3Info, Math::Lerp(Step3ProgressStart, Step3ProgressEnd, (float)subStepIndex++ / AssetsRegistry.Count()));
|
||||||
data.StepProgress(Step2Info, Math::Lerp(Step2ProgressStart, Step2ProgressEnd, static_cast<float>(subStepIndex++) / AssetsRegistry.Count()));
|
|
||||||
const auto assetId = i->Key;
|
const auto assetId = i->Key;
|
||||||
|
|
||||||
String cookedFilePath;
|
String cookedFilePath;
|
||||||
cache.GetFilePath(assetId, cookedFilePath);
|
cache.GetFilePath(assetId, cookedFilePath);
|
||||||
|
|
||||||
if (!FileSystem::FileExists(cookedFilePath))
|
if (!FileSystem::FileExists(cookedFilePath))
|
||||||
{
|
{
|
||||||
LOG(Warning, "Missing cooked file for asset \'{0}\'", assetId);
|
LOG(Warning, "Missing cooked file for asset \'{0}\'", assetId);
|
||||||
@@ -1253,12 +1284,12 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
for (auto& e : data.Stats.AssetStats)
|
for (auto& e : data.Stats.AssetStats)
|
||||||
e.Value.TypeName = e.Key;
|
e.Value.TypeName = e.Key;
|
||||||
data.Stats.ContentSizeMB = static_cast<int32>(packageBuilder.GetPackagesSizeTotal() / (1024 * 1024));
|
data.Stats.ContentSize += packageBuilder.GetPackagesSizeTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
|
||||||
data.StepProgress(TEXT("Creating assets cache"), Step2ProgressEnd);
|
data.StepProgress(TEXT("Creating assets cache"), Step3ProgressEnd);
|
||||||
|
|
||||||
// Create asset paths mapping for the assets.
|
// Create asset paths mapping for the assets.
|
||||||
// Assets mapping is use to convert paths used in Content::Load(path) into the asset id.
|
// Assets mapping is use to convert paths used in Content::Load(path) into the asset id.
|
||||||
@@ -1291,7 +1322,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print stats
|
// Print stats
|
||||||
LOG(Info, "Cooked {0} assets, total assets: {1}, total content packages size: {2} MB", data.Stats.CookedAssets, AssetsRegistry.Count(), data.Stats.ContentSizeMB);
|
LOG(Info, "Cooked {0} assets, total assets: {1}, total content packages size: {2} MB", data.Stats.CookedAssets, AssetsRegistry.Count(), (int32)(data.Stats.ContentSize / (1024 * 1024)));
|
||||||
{
|
{
|
||||||
Array<CookingData::AssetTypeStatistics> assetTypes;
|
Array<CookingData::AssetTypeStatistics> assetTypes;
|
||||||
data.Stats.AssetStats.GetValues(assetTypes);
|
data.Stats.AssetStats.GetValues(assetTypes);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
{
|
{
|
||||||
case BuildPlatform::Windows32:
|
case BuildPlatform::Windows32:
|
||||||
case BuildPlatform::Windows64:
|
case BuildPlatform::Windows64:
|
||||||
|
case BuildPlatform::WindowsARM64:
|
||||||
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
|
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
|
||||||
break;
|
break;
|
||||||
case BuildPlatform::LinuxX64:
|
case BuildPlatform::LinuxX64:
|
||||||
@@ -159,7 +160,20 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("host/fxr") / version, srcDotnet / TEXT("host/fxr") / version, true);
|
// TODO: hostfxr for target platform should be copied from nuget package location: microsoft.netcore.app.runtime.<RID>/<VERSION>/runtimes/<RID>/native/hostfxr.dll
|
||||||
|
String dstHostfxr = dstDotnet / TEXT("host/fxr") / version;
|
||||||
|
if (!FileSystem::DirectoryExists(dstHostfxr))
|
||||||
|
FileSystem::CreateDirectory(dstHostfxr);
|
||||||
|
const Char *platformName, *archName;
|
||||||
|
data.GetBuildPlatformName(platformName, archName);
|
||||||
|
if (data.Platform == BuildPlatform::Windows64 || data.Platform == BuildPlatform::WindowsARM64 || data.Platform == BuildPlatform::Windows32)
|
||||||
|
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dll"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dll"));
|
||||||
|
else if (data.Platform == BuildPlatform::LinuxX64)
|
||||||
|
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.so"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.so"));
|
||||||
|
else if (data.Platform == BuildPlatform::MacOSx64 || data.Platform == BuildPlatform::MacOSARM64)
|
||||||
|
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dylib"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dylib"));
|
||||||
|
else
|
||||||
|
failed |= true;
|
||||||
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
|
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
|
||||||
}
|
}
|
||||||
if (failed)
|
if (failed)
|
||||||
|
|||||||
@@ -377,6 +377,10 @@ namespace FlaxEditor.CustomEditors
|
|||||||
else if (Values.HasDefaultValue && CanRevertDefaultValue)
|
else if (Values.HasDefaultValue && CanRevertDefaultValue)
|
||||||
color = Color.Yellow * 0.8f;
|
color = Color.Yellow * 0.8f;
|
||||||
LinkedLabel.HighlightStripColor = color;
|
LinkedLabel.HighlightStripColor = color;
|
||||||
|
|
||||||
|
// Grey out deprecated members
|
||||||
|
if (Values.IsObsolete)
|
||||||
|
LinkedLabel.TextColor = LinkedLabel.TextColorHighlighted = FlaxEngine.GUI.Style.Current.ForegroundGrey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,13 +52,18 @@ namespace FlaxEditor.CustomEditors
|
|||||||
// Check if use provided editor
|
// Check if use provided editor
|
||||||
if (overrideEditor != null)
|
if (overrideEditor != null)
|
||||||
return overrideEditor;
|
return overrideEditor;
|
||||||
|
ScriptType targetType = values.Type;
|
||||||
|
|
||||||
// Special case if property is a pure object type and all values are the same type
|
// Special case if property is a pure object type and all values are the same type
|
||||||
if (values.Type.Type == typeof(object) && values.Count > 0 && values[0] != null && !values.HasDifferentTypes)
|
if (targetType.Type == typeof(object) && values.Count > 0 && values[0] != null && !values.HasDifferentTypes)
|
||||||
return CreateEditor(TypeUtils.GetObjectType(values[0]), canUseRefPicker);
|
return CreateEditor(TypeUtils.GetObjectType(values[0]), canUseRefPicker);
|
||||||
|
|
||||||
|
// Special case if property is interface but the value is implemented as Scripting Object that should use reference picker
|
||||||
|
if (targetType.IsInterface && canUseRefPicker && values.Count > 0 && values[0] is FlaxEngine.Object)
|
||||||
|
return new DummyEditor();
|
||||||
|
|
||||||
// Use editor for the property type
|
// Use editor for the property type
|
||||||
return CreateEditor(values.Type, canUseRefPicker);
|
return CreateEditor(targetType, canUseRefPicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static CustomEditor CreateEditor(ScriptType targetType, bool canUseRefPicker = true)
|
internal static CustomEditor CreateEditor(ScriptType targetType, bool canUseRefPicker = true)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using FlaxEditor.Content.Settings;
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -12,7 +13,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
[CustomEditor(typeof(LayersMask)), DefaultEditor]
|
[CustomEditor(typeof(LayersMask)), DefaultEditor]
|
||||||
internal class LayersMaskEditor : CustomEditor
|
internal class LayersMaskEditor : CustomEditor
|
||||||
{
|
{
|
||||||
private CheckBox[] _checkBoxes;
|
private List<CheckBox> _checkBoxes;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
@@ -24,16 +25,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkBoxes = new CheckBox[layers.Length];
|
_checkBoxes = new List<CheckBox>();
|
||||||
for (int i = 0; i < layers.Length; i++)
|
for (int i = 0; i < layers.Length; i++)
|
||||||
{
|
{
|
||||||
var layer = layers[i];
|
var layer = layers[i];
|
||||||
var property = layout.AddPropertyItem(layer);
|
if (string.IsNullOrEmpty(layer))
|
||||||
|
continue;
|
||||||
|
var property = layout.AddPropertyItem($"{i}: {layer}");
|
||||||
var checkbox = property.Checkbox().CheckBox;
|
var checkbox = property.Checkbox().CheckBox;
|
||||||
UpdateCheckbox(checkbox, i);
|
UpdateCheckbox(checkbox, i);
|
||||||
checkbox.Tag = i;
|
checkbox.Tag = i;
|
||||||
checkbox.StateChanged += OnCheckboxStateChanged;
|
checkbox.StateChanged += OnCheckboxStateChanged;
|
||||||
_checkBoxes[i] = checkbox;
|
_checkBoxes.Add(checkbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,9 +53,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
if (_checkBoxes != null)
|
if (_checkBoxes != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _checkBoxes.Length; i++)
|
for (int i = 0; i < _checkBoxes.Count; i++)
|
||||||
{
|
{
|
||||||
UpdateCheckbox(_checkBoxes[i], i);
|
UpdateCheckbox(_checkBoxes[i], (int)_checkBoxes[i].Tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -456,14 +456,57 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
for (int i = 0; i < layout.Children.Count; i++)
|
for (int i = 0; i < layout.Children.Count; i++)
|
||||||
{
|
{
|
||||||
if (layout.Children[i] is GroupElement group && group.Panel.HeaderText == "Transform")
|
if (layout.Children[i] is GroupElement group && group.Panel.HeaderText.Equals("Transform", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
VerticalPanelElement mainHor = VerticalPanelWithoutMargin(group);
|
layout.Children.Remove(group);
|
||||||
CreateTransformElements(mainHor, ValuesTypes);
|
layout.ContainerControl.Children.Remove(group.Panel);
|
||||||
group.ContainerControl.ChangeChildIndex(mainHor.Control, 0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup transform
|
||||||
|
if (Presenter is LayoutElementsContainer l)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < l.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (l.Children[i] is GroupElement g && g.Panel.HeaderText.Equals("Transform", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
l.Children.Remove(g);
|
||||||
|
l.ContainerControl.Children.Remove(g.Panel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var transformGroup = l.Group("Transform");
|
||||||
|
VerticalPanelElement mainHor = VerticalPanelWithoutMargin(transformGroup);
|
||||||
|
CreateTransformElements(mainHor, ValuesTypes);
|
||||||
|
|
||||||
|
ScriptMemberInfo scaleInfo = ValuesTypes[0].GetProperty("Scale");
|
||||||
|
ItemInfo scaleItem = new ItemInfo(scaleInfo);
|
||||||
|
transformGroup.Property("Scale", scaleItem.GetValues(Values));
|
||||||
|
|
||||||
|
ScriptMemberInfo pivotInfo = ValuesTypes[0].GetProperty("Pivot");
|
||||||
|
ItemInfo pivotItem = new ItemInfo(pivotInfo);
|
||||||
|
transformGroup.Property("Pivot", pivotItem.GetValues(Values));
|
||||||
|
|
||||||
|
ScriptMemberInfo shearInfo = ValuesTypes[0].GetProperty("Shear");
|
||||||
|
ItemInfo shearItem = new ItemInfo(shearInfo);
|
||||||
|
transformGroup.Property("Shear", shearItem.GetValues(Values));
|
||||||
|
|
||||||
|
ScriptMemberInfo rotationInfo = ValuesTypes[0].GetProperty("Rotation");
|
||||||
|
ItemInfo rotationItem = new ItemInfo(rotationInfo);
|
||||||
|
transformGroup.Property("Rotation", rotationItem.GetValues(Values));
|
||||||
|
|
||||||
|
// Get position of general tab
|
||||||
|
for (int i = 0; i < l.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (l.Children[i] is GroupElement g && g.Panel.HeaderText.Equals("General", StringComparison.Ordinal) && i + 1 <= l.Children.Count)
|
||||||
|
{
|
||||||
|
Presenter.ContainerControl.ChangeChildIndex(transformGroup.Control, i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateTransformElements(LayoutElementsContainer main, ScriptType[] valueTypes)
|
private void CreateTransformElements(LayoutElementsContainer main, ScriptType[] valueTypes)
|
||||||
@@ -645,7 +688,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
var grid = UniformGridTwoByOne(el);
|
var grid = UniformGridTwoByOne(el);
|
||||||
grid.CustomControl.SlotPadding = new Margin(5, 5, 1, 1);
|
grid.CustomControl.SlotPadding = new Margin(5, 5, 1, 1);
|
||||||
var label = grid.Label(text);
|
var label = grid.Label(text, TextAlignment.Far);
|
||||||
var editor = grid.Object(values);
|
var editor = grid.Object(values);
|
||||||
if (editor is FloatEditor floatEditor && floatEditor.Element is FloatValueElement floatEditorElement)
|
if (editor is FloatEditor floatEditor && floatEditor.Element is FloatValueElement floatEditorElement)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using FlaxEditor.Content;
|
|||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Utilities;
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Editors
|
namespace FlaxEditor.CustomEditors.Editors
|
||||||
@@ -50,7 +51,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (HasDifferentTypes)
|
if (HasDifferentTypes)
|
||||||
return;
|
return;
|
||||||
Picker = layout.Custom<AssetPicker>().CustomControl;
|
Picker = layout.Custom<AssetPicker>().CustomControl;
|
||||||
|
|
||||||
var value = Values[0];
|
var value = Values[0];
|
||||||
_valueType = Values.Type.Type != typeof(object) || value == null ? Values.Type : TypeUtils.GetObjectType(value);
|
_valueType = Values.Type.Type != typeof(object) || value == null ? Values.Type : TypeUtils.GetObjectType(value);
|
||||||
var assetType = _valueType;
|
var assetType = _valueType;
|
||||||
@@ -58,37 +58,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
assetType = new ScriptType(typeof(Asset));
|
assetType = new ScriptType(typeof(Asset));
|
||||||
else if (_valueType.Type != null && _valueType.Type.Name == typeof(JsonAssetReference<>).Name)
|
else if (_valueType.Type != null && _valueType.Type.Name == typeof(JsonAssetReference<>).Name)
|
||||||
assetType = new ScriptType(_valueType.Type.GenericTypeArguments[0]);
|
assetType = new ScriptType(_valueType.Type.GenericTypeArguments[0]);
|
||||||
|
|
||||||
float height = 48;
|
|
||||||
var attributes = Values.GetAttributes();
|
|
||||||
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
|
||||||
if (assetReference != null)
|
|
||||||
{
|
|
||||||
if (assetReference.UseSmallPicker)
|
|
||||||
height = 32;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(assetReference.TypeName))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
|
|
||||||
{
|
|
||||||
// Generic file picker
|
|
||||||
assetType = ScriptType.Null;
|
|
||||||
Picker.Validator.FileExtension = assetReference.TypeName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var customType = TypeUtils.GetType(assetReference.TypeName);
|
|
||||||
if (customType != ScriptType.Null)
|
|
||||||
assetType = customType;
|
|
||||||
else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName))
|
|
||||||
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
|
|
||||||
else
|
|
||||||
assetType = ScriptType.Void;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Picker.Validator.AssetType = assetType;
|
Picker.Validator.AssetType = assetType;
|
||||||
|
ApplyAssetReferenceAttribute(Values, out var height, Picker.Validator);
|
||||||
Picker.Height = height;
|
Picker.Height = height;
|
||||||
Picker.SelectedItemChanged += OnSelectedItemChanged;
|
Picker.SelectedItemChanged += OnSelectedItemChanged;
|
||||||
}
|
}
|
||||||
@@ -115,6 +86,37 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
SetValue(Picker.Validator.SelectedAsset);
|
SetValue(Picker.Validator.SelectedAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void ApplyAssetReferenceAttribute(ValueContainer values, out float height, AssetPickerValidator validator)
|
||||||
|
{
|
||||||
|
height = 48;
|
||||||
|
var attributes = values.GetAttributes();
|
||||||
|
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
||||||
|
if (assetReference != null)
|
||||||
|
{
|
||||||
|
if (assetReference.UseSmallPicker)
|
||||||
|
height = 32;
|
||||||
|
if (string.IsNullOrEmpty(assetReference.TypeName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
|
||||||
|
{
|
||||||
|
// Generic file picker
|
||||||
|
validator.AssetType = ScriptType.Null;
|
||||||
|
validator.FileExtension = assetReference.TypeName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var customType = TypeUtils.GetType(assetReference.TypeName);
|
||||||
|
if (customType != ScriptType.Null)
|
||||||
|
validator.AssetType = customType;
|
||||||
|
else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName))
|
||||||
|
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
|
||||||
|
else
|
||||||
|
validator.AssetType = ScriptType.Void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Refresh()
|
public override void Refresh()
|
||||||
{
|
{
|
||||||
@@ -140,4 +142,155 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default implementation of the inspector used to edit reference to the files via path (absolute or relative to the project).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Supports editing reference to the asset via path using various containers: <see cref="Asset"/> or <see cref="AssetItem"/> or <see cref="System.String"/>.</remarks>
|
||||||
|
public class FilePathEditor : CustomEditor
|
||||||
|
{
|
||||||
|
private sealed class TextBoxWithPicker : TextBox
|
||||||
|
{
|
||||||
|
private const float DropdownIconMargin = 3.0f;
|
||||||
|
private const float DropdownIconSize = 12.0f;
|
||||||
|
private Rectangle DropdownRect => new Rectangle(Width - DropdownIconSize - DropdownIconMargin, DropdownIconMargin, DropdownIconSize, DropdownIconSize);
|
||||||
|
|
||||||
|
public Action ShowPicker;
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
base.Draw();
|
||||||
|
|
||||||
|
var style = FlaxEngine.GUI.Style.Current;
|
||||||
|
var dropdownRect = DropdownRect;
|
||||||
|
Render2D.DrawSprite(style.ArrowDown, dropdownRect, Enabled ? (DropdownRect.Contains(PointFromWindow(RootWindow.MousePosition)) ? style.BorderSelected : style.Foreground) : style.ForegroundDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||||
|
{
|
||||||
|
if (DropdownRect.Contains(ref location))
|
||||||
|
{
|
||||||
|
Focus();
|
||||||
|
ShowPicker();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnMouseDown(location, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnMouseMove(Float2 location)
|
||||||
|
{
|
||||||
|
base.OnMouseMove(location);
|
||||||
|
|
||||||
|
if (DropdownRect.Contains(ref location))
|
||||||
|
Cursor = CursorType.Default;
|
||||||
|
else
|
||||||
|
Cursor = CursorType.IBeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Rectangle TextRectangle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = base.TextRectangle;
|
||||||
|
result.Size.X -= DropdownIconSize + DropdownIconMargin * 2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Rectangle TextClipRectangle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = base.TextClipRectangle;
|
||||||
|
result.Size.X -= DropdownIconSize + DropdownIconMargin * 2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextBoxWithPicker _textBox;
|
||||||
|
private AssetPickerValidator _validator;
|
||||||
|
private bool _isRefreshing;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override DisplayStyle Style => DisplayStyle.Inline;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
if (HasDifferentTypes)
|
||||||
|
return;
|
||||||
|
_textBox = layout.Custom<TextBoxWithPicker>().CustomControl;
|
||||||
|
_textBox.ShowPicker = OnShowPicker;
|
||||||
|
_textBox.EditEnd += OnEditEnd;
|
||||||
|
_validator = new AssetPickerValidator(ScriptType.Null);
|
||||||
|
AssetRefEditor.ApplyAssetReferenceAttribute(Values, out _, _validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShowPicker()
|
||||||
|
{
|
||||||
|
if (_validator.AssetType != ScriptType.Null)
|
||||||
|
AssetSearchPopup.Show(_textBox, _textBox.BottomLeft, _validator.IsValid, SetPickerPath);
|
||||||
|
else
|
||||||
|
ContentSearchPopup.Show(_textBox, _textBox.BottomLeft, _validator.IsValid, SetPickerPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPickerPath(ContentItem item)
|
||||||
|
{
|
||||||
|
var path = Utilities.Utils.ToPathProject(item.Path);
|
||||||
|
SetPath(path);
|
||||||
|
|
||||||
|
_isRefreshing = true;
|
||||||
|
_textBox.Defocus();
|
||||||
|
_textBox.Text = path;
|
||||||
|
_isRefreshing = false;
|
||||||
|
|
||||||
|
_textBox.RootWindow.Focus();
|
||||||
|
_textBox.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEditEnd()
|
||||||
|
{
|
||||||
|
SetPath(_textBox.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetPath()
|
||||||
|
{
|
||||||
|
var value = Values[0];
|
||||||
|
if (value is AssetItem assetItem)
|
||||||
|
return Utilities.Utils.ToPathProject(assetItem.Path);
|
||||||
|
if (value is Asset asset)
|
||||||
|
return Utilities.Utils.ToPathProject(asset.Path);
|
||||||
|
if (value is string str)
|
||||||
|
return str;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPath(string path)
|
||||||
|
{
|
||||||
|
if (_isRefreshing)
|
||||||
|
return;
|
||||||
|
var value = Values[0];
|
||||||
|
if (value is AssetItem)
|
||||||
|
SetValue(Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(path)));
|
||||||
|
else if (value is Asset)
|
||||||
|
SetValue(FlaxEngine.Content.LoadAsync(path));
|
||||||
|
else if (value is string)
|
||||||
|
SetValue(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
base.Refresh();
|
||||||
|
|
||||||
|
if (!HasDifferentValues)
|
||||||
|
{
|
||||||
|
_isRefreshing = true;
|
||||||
|
_textBox.Text = GetPath();
|
||||||
|
_isRefreshing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,17 +57,18 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
menu.ItemsContainer.RemoveChildren();
|
menu.ItemsContainer.RemoveChildren();
|
||||||
|
|
||||||
menu.AddButton("Copy", linkedEditor.Copy);
|
menu.AddButton("Copy", linkedEditor.Copy);
|
||||||
var paste = menu.AddButton("Paste", linkedEditor.Paste);
|
var b = menu.AddButton("Paste", linkedEditor.Paste);
|
||||||
paste.Enabled = linkedEditor.CanPaste;
|
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
|
||||||
|
|
||||||
menu.AddSeparator();
|
menu.AddSeparator();
|
||||||
var moveUpButton = menu.AddButton("Move up", OnMoveUpClicked);
|
b = menu.AddButton("Move up", OnMoveUpClicked);
|
||||||
moveUpButton.Enabled = Index > 0;
|
b.Enabled = Index > 0 && !Editor._readOnly;
|
||||||
|
|
||||||
var moveDownButton = menu.AddButton("Move down", OnMoveDownClicked);
|
b = menu.AddButton("Move down", OnMoveDownClicked);
|
||||||
moveDownButton.Enabled = Index + 1 < Editor.Count;
|
b.Enabled = Index + 1 < Editor.Count && !Editor._readOnly;
|
||||||
|
|
||||||
menu.AddButton("Remove", OnRemoveClicked);
|
b = menu.AddButton("Remove", OnRemoveClicked);
|
||||||
|
b.Enabled = !Editor._readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMoveUpClicked()
|
private void OnMoveUpClicked()
|
||||||
@@ -177,6 +178,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
private IntValueBox _sizeBox;
|
private IntValueBox _sizeBox;
|
||||||
private Color _background;
|
private Color _background;
|
||||||
private int _elementsCount, _minCount, _maxCount;
|
private int _elementsCount, _minCount, _maxCount;
|
||||||
|
private bool _readOnly;
|
||||||
private bool _canResize;
|
private bool _canResize;
|
||||||
private bool _canReorderItems;
|
private bool _canReorderItems;
|
||||||
private CollectionAttribute.DisplayType _displayType;
|
private CollectionAttribute.DisplayType _displayType;
|
||||||
@@ -209,6 +211,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var size = Count;
|
var size = Count;
|
||||||
|
_readOnly = false;
|
||||||
_canResize = true;
|
_canResize = true;
|
||||||
_canReorderItems = true;
|
_canReorderItems = true;
|
||||||
_minCount = 0;
|
_minCount = 0;
|
||||||
@@ -225,6 +228,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (collection != null)
|
if (collection != null)
|
||||||
{
|
{
|
||||||
_canResize = !collection.ReadOnly;
|
_canResize = !collection.ReadOnly;
|
||||||
|
_readOnly = collection.ReadOnly;
|
||||||
_minCount = collection.MinCount;
|
_minCount = collection.MinCount;
|
||||||
_maxCount = collection.MaxCount;
|
_maxCount = collection.MaxCount;
|
||||||
_canReorderItems = collection.CanReorderItems;
|
_canReorderItems = collection.CanReorderItems;
|
||||||
@@ -235,6 +239,12 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
spacing = collection.Spacing;
|
spacing = collection.Spacing;
|
||||||
_displayType = collection.Display;
|
_displayType = collection.Display;
|
||||||
}
|
}
|
||||||
|
if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute))
|
||||||
|
{
|
||||||
|
_readOnly = true;
|
||||||
|
_canResize = false;
|
||||||
|
_canReorderItems = false;
|
||||||
|
}
|
||||||
if (_maxCount == 0)
|
if (_maxCount == 0)
|
||||||
_maxCount = ushort.MaxValue;
|
_maxCount = ushort.MaxValue;
|
||||||
_canResize &= _minCount < _maxCount;
|
_canResize &= _minCount < _maxCount;
|
||||||
@@ -243,8 +253,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
dragArea.CustomControl.Editor = this;
|
dragArea.CustomControl.Editor = this;
|
||||||
dragArea.CustomControl.ElementType = ElementType;
|
dragArea.CustomControl.ElementType = ElementType;
|
||||||
|
|
||||||
// Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter
|
// Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter which scripts can be dragged over and dropped on this collection editor
|
||||||
// which scripts can be dragged over and dropped on this collection editor.
|
|
||||||
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
|
||||||
if (assetReference != null)
|
if (assetReference != null)
|
||||||
{
|
{
|
||||||
@@ -333,6 +342,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var property = panel.AddPropertyItem(itemLabel);
|
var property = panel.AddPropertyItem(itemLabel);
|
||||||
var itemLayout = (LayoutElementsContainer)property;
|
var itemLayout = (LayoutElementsContainer)property;
|
||||||
itemLabel.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
|
itemLabel.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
|
||||||
|
if (_readOnly && itemLayout.Children.Count > 0)
|
||||||
|
GenericEditor.OnReadOnlyProperty(itemLayout);
|
||||||
}
|
}
|
||||||
else if (_displayType == CollectionAttribute.DisplayType.Header || (_displayType == CollectionAttribute.DisplayType.Default && !single))
|
else if (_displayType == CollectionAttribute.DisplayType.Header || (_displayType == CollectionAttribute.DisplayType.Default && !single))
|
||||||
{
|
{
|
||||||
@@ -340,13 +351,15 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
cdp.CustomControl.Setup(this, i, _canReorderItems);
|
cdp.CustomControl.Setup(this, i, _canReorderItems);
|
||||||
var itemLayout = cdp.VerticalPanel();
|
var itemLayout = cdp.VerticalPanel();
|
||||||
cdp.CustomControl.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
|
cdp.CustomControl.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
|
||||||
|
if (_readOnly && itemLayout.Children.Count > 0)
|
||||||
|
GenericEditor.OnReadOnlyProperty(itemLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_elementsCount = size;
|
_elementsCount = size;
|
||||||
|
|
||||||
// Add/Remove buttons
|
// Add/Remove buttons
|
||||||
if (_canResize)
|
if (_canResize && !_readOnly)
|
||||||
{
|
{
|
||||||
var panel = dragArea.HorizontalPanel();
|
var panel = dragArea.HorizontalPanel();
|
||||||
panel.Panel.Size = new Float2(0, 20);
|
panel.Panel.Size = new Float2(0, 20);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
if (button == MouseButton.Left)
|
if (button == MouseButton.Left && _editor._canEditKeys)
|
||||||
{
|
{
|
||||||
OnEditClicked(null);
|
OnEditClicked(null);
|
||||||
return true;
|
return true;
|
||||||
@@ -197,6 +197,11 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
spacing = collection.Spacing;
|
spacing = collection.Spacing;
|
||||||
_displayType = collection.Display;
|
_displayType = collection.Display;
|
||||||
}
|
}
|
||||||
|
if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute))
|
||||||
|
{
|
||||||
|
_readOnly = true;
|
||||||
|
_canEditKeys = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Size
|
// Size
|
||||||
if (layout.ContainerControl is DropPanel dropPanel)
|
if (layout.ContainerControl is DropPanel dropPanel)
|
||||||
@@ -239,14 +244,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var keysEnumerable = ((IDictionary)Values[0]).Keys.OfType<object>();
|
var keysEnumerable = ((IDictionary)Values[0]).Keys.OfType<object>();
|
||||||
var keys = keysEnumerable as object[] ?? keysEnumerable.ToArray();
|
var keys = keysEnumerable as object[] ?? keysEnumerable.ToArray();
|
||||||
var valuesType = new ScriptType(valueType);
|
var valuesType = new ScriptType(valueType);
|
||||||
|
|
||||||
bool single = valuesType.IsPrimitive ||
|
|
||||||
valuesType.Equals(new ScriptType(typeof(string))) ||
|
|
||||||
valuesType.IsEnum ||
|
|
||||||
(valuesType.GetFields().Length == 1 && valuesType.GetProperties().Length == 0) ||
|
|
||||||
(valuesType.GetProperties().Length == 1 && valuesType.GetFields().Length == 0) ||
|
|
||||||
valuesType.Equals(new ScriptType(typeof(JsonAsset))) ||
|
|
||||||
valuesType.Equals(new ScriptType(typeof(SettingsBase)));
|
|
||||||
|
|
||||||
// Use separate layout cells for each collection items to improve layout updates for them in separation
|
// Use separate layout cells for each collection items to improve layout updates for them in separation
|
||||||
var useSharedLayout = valueType.IsPrimitive || valueType.IsEnum;
|
var useSharedLayout = valueType.IsPrimitive || valueType.IsEnum;
|
||||||
@@ -263,6 +260,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key));
|
var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key));
|
||||||
var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel();
|
var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel();
|
||||||
itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor);
|
itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor);
|
||||||
|
if (_readOnly && itemLayout.Children.Count > 0)
|
||||||
|
GenericEditor.OnReadOnlyProperty(itemLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_elementsCount = size;
|
_elementsCount = size;
|
||||||
|
|||||||
17
Source/Editor/CustomEditors/Editors/DummyEditor.cs
Normal file
17
Source/Editor/CustomEditors/Editors/DummyEditor.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Editors
|
||||||
|
{
|
||||||
|
internal sealed class DummyEditor : CustomEditor
|
||||||
|
{
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
string valueName;
|
||||||
|
if (Values.Count != 0 && Values[0] != null)
|
||||||
|
valueName = Values[0].ToString();
|
||||||
|
else
|
||||||
|
valueName = "null";
|
||||||
|
layout.Label($"{valueName} ({Values.Type})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -581,6 +581,43 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void OnReadOnlyProperty(LayoutElementsContainer itemLayout, int labelIndex = -1)
|
||||||
|
{
|
||||||
|
PropertiesListElement list = null;
|
||||||
|
int firstChildControlIndex = 0;
|
||||||
|
bool disableSingle = true;
|
||||||
|
var control = itemLayout.Children[itemLayout.Children.Count - 1];
|
||||||
|
if (control is GroupElement group && group.Children.Count > 0)
|
||||||
|
{
|
||||||
|
list = group.Children[0] as PropertiesListElement;
|
||||||
|
disableSingle = false; // Disable all nested editors
|
||||||
|
}
|
||||||
|
else if (control is PropertiesListElement list1 && labelIndex != -1)
|
||||||
|
{
|
||||||
|
list = list1;
|
||||||
|
firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex;
|
||||||
|
}
|
||||||
|
else if (control?.Control != null)
|
||||||
|
{
|
||||||
|
control.Control.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list != null)
|
||||||
|
{
|
||||||
|
// Disable controls added to the editor
|
||||||
|
var count = list.Properties.Children.Count;
|
||||||
|
for (int j = firstChildControlIndex; j < count; j++)
|
||||||
|
{
|
||||||
|
var child = list.Properties.Children[j];
|
||||||
|
if (disableSingle && child is PropertyNameLabel)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
child.Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluate the <see cref="VisibleIfAttribute"/> cache for a given property item.
|
/// Evaluate the <see cref="VisibleIfAttribute"/> cache for a given property item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -660,35 +697,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
if (item.IsReadOnly && itemLayout.Children.Count > 0)
|
if (item.IsReadOnly && itemLayout.Children.Count > 0)
|
||||||
{
|
{
|
||||||
PropertiesListElement list = null;
|
OnReadOnlyProperty(itemLayout, labelIndex);
|
||||||
int firstChildControlIndex = 0;
|
|
||||||
bool disableSingle = true;
|
|
||||||
var control = itemLayout.Children[itemLayout.Children.Count - 1];
|
|
||||||
if (control is GroupElement group && group.Children.Count > 0)
|
|
||||||
{
|
|
||||||
list = group.Children[0] as PropertiesListElement;
|
|
||||||
disableSingle = false; // Disable all nested editors
|
|
||||||
}
|
|
||||||
else if (control is PropertiesListElement list1)
|
|
||||||
{
|
|
||||||
list = list1;
|
|
||||||
firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list != null)
|
|
||||||
{
|
|
||||||
// Disable controls added to the editor
|
|
||||||
var count = list.Properties.Children.Count;
|
|
||||||
for (int j = firstChildControlIndex; j < count; j++)
|
|
||||||
{
|
|
||||||
var child = list.Properties.Children[j];
|
|
||||||
if (disableSingle && child is PropertyNameLabel)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (child != null)
|
|
||||||
child.Enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EvaluateVisibleIf(itemLayout, item, labelIndex);
|
EvaluateVisibleIf(itemLayout, item, labelIndex);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
new OptionType("Linear Gradient", typeof(LinearGradientBrush)),
|
new OptionType("Linear Gradient", typeof(LinearGradientBrush)),
|
||||||
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
||||||
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
||||||
|
new OptionType("Video", typeof(VideoBrush)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
float namesWidth = _splitterValue * Width;
|
float namesWidth = _splitterValue * Width;
|
||||||
int count = _element.Labels.Count;
|
int count = _element.Labels.Count;
|
||||||
float[] yStarts = new float[count + 1];
|
float[] yStarts = new float[count + 1];
|
||||||
for (int i = 1; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var label = _element.Labels[i];
|
var label = _element.Labels[i];
|
||||||
|
|
||||||
@@ -251,9 +251,13 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
else if (_children.Count <= label.FirstChildControlIndex)
|
else if (_children.Count <= label.FirstChildControlIndex)
|
||||||
yStarts[i] = y;
|
yStarts[i] = y;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
yStarts[i] = _children[label.FirstChildControlIndex].Top;
|
yStarts[i] = _children[label.FirstChildControlIndex].Top;
|
||||||
|
if (i == count - 1)
|
||||||
|
yStarts[i + 1] = _children[label.FirstChildControlIndex].Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
yStarts[count] = y;
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var label = _element.Labels[i];
|
var label = _element.Labels[i];
|
||||||
|
|||||||
@@ -139,6 +139,11 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsArray => Type != ScriptType.Null && Type.IsArray;
|
public bool IsArray => Type != ScriptType.Null && Type.IsArray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if member or type has <see cref="System.ObsoleteAttribute"/> that marks it as obsolete.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsObsolete { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the values types array (without duplicates).
|
/// Gets the values types array (without duplicates).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -160,6 +165,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
{
|
{
|
||||||
Info = info;
|
Info = info;
|
||||||
Type = Info.ValueType;
|
Type = Info.ValueType;
|
||||||
|
IsObsolete = Info.HasAttribute(typeof(ObsoleteAttribute), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ using System.IO;
|
|||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Utilities;
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Utilities;
|
|
||||||
|
|
||||||
namespace FlaxEditor.GUI
|
namespace FlaxEditor.GUI
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
{
|
{
|
||||||
Text = "+",
|
Text = "+",
|
||||||
Parent = this,
|
Parent = this,
|
||||||
|
TooltipText = "Save Color.",
|
||||||
Tag = null,
|
Tag = null,
|
||||||
};
|
};
|
||||||
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);
|
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);
|
||||||
@@ -370,9 +371,25 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
|
Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
|
||||||
|
|
||||||
// Color difference
|
// Color difference
|
||||||
var newRect = new Rectangle(_cOK.X, _cHex.Bottom + PickerMargin, _cCancel.Right - _cOK.Left, 0);
|
var newRect = new Rectangle(_cOK.X - 3, _cHex.Bottom + PickerMargin, 130, 0);
|
||||||
newRect.Size.Y = _cValue.Bottom - newRect.Y;
|
newRect.Size.Y = 50;
|
||||||
Render2D.FillRectangle(newRect, _value * _value.A);
|
Render2D.FillRectangle(newRect, Color.White);
|
||||||
|
var smallRectSize = 10;
|
||||||
|
var numHor = Mathf.FloorToInt(newRect.Width / smallRectSize);
|
||||||
|
var numVer = Mathf.FloorToInt(newRect.Height / smallRectSize);
|
||||||
|
// Draw checkerboard for background of color to help with transparency
|
||||||
|
for (int i = 0; i < numHor; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < numVer; j++)
|
||||||
|
{
|
||||||
|
if ((i + j) % 2 == 0 )
|
||||||
|
{
|
||||||
|
var rect = new Rectangle(newRect.X + smallRectSize * i, newRect.Y + smallRectSize * j, new Float2(smallRectSize));
|
||||||
|
Render2D.FillRectangle(rect, Color.Gray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Render2D.FillRectangle(newRect, _value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -498,6 +515,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
{
|
{
|
||||||
Text = "+",
|
Text = "+",
|
||||||
Parent = this,
|
Parent = this,
|
||||||
|
TooltipText = "Save Color.",
|
||||||
Tag = null,
|
Tag = null,
|
||||||
};
|
};
|
||||||
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);
|
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);
|
||||||
|
|||||||
@@ -311,7 +311,9 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
// Alpha
|
// Alpha
|
||||||
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
||||||
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
||||||
Render2D.FillRectangle(_slider2Rect, _color, _color, Color.Transparent, Color.Transparent);
|
var color = _color;
|
||||||
|
color.A = 1; // Keep slider 2 fill rect from changing color alpha while selecting.
|
||||||
|
Render2D.FillRectangle(_slider2Rect, color, color, Color.Transparent, Color.Transparent);
|
||||||
Render2D.DrawRectangle(_slider2Rect, _isMouseDownSlider2 ? style.BackgroundSelected : Color.Black);
|
Render2D.DrawRectangle(_slider2Rect, _isMouseDownSlider2 ? style.BackgroundSelected : Color.Black);
|
||||||
Render2D.DrawRectangle(alphaR, _isMouseDownSlider2 ? Color.White : Color.Gray);
|
Render2D.DrawRectangle(alphaR, _isMouseDownSlider2 ? Color.White : Color.Gray);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,9 +418,19 @@ namespace FlaxEditor.GUI.Tabs
|
|||||||
{
|
{
|
||||||
// If scroll bar is visible it covers part of the tab header so include this in tab size to improve usability
|
// If scroll bar is visible it covers part of the tab header so include this in tab size to improve usability
|
||||||
if (_orientation == Orientation.Horizontal && TabsPanel.HScrollBar.Visible)
|
if (_orientation == Orientation.Horizontal && TabsPanel.HScrollBar.Visible)
|
||||||
|
{
|
||||||
tabsSize.Y += TabsPanel.HScrollBar.Height;
|
tabsSize.Y += TabsPanel.HScrollBar.Height;
|
||||||
|
var style = Style.Current;
|
||||||
|
TabsPanel.HScrollBar.TrackColor = style.Background;
|
||||||
|
TabsPanel.HScrollBar.ThumbColor = style.ForegroundGrey;
|
||||||
|
}
|
||||||
else if (_orientation == Orientation.Vertical && TabsPanel.VScrollBar.Visible)
|
else if (_orientation == Orientation.Vertical && TabsPanel.VScrollBar.Visible)
|
||||||
|
{
|
||||||
tabsSize.X += TabsPanel.VScrollBar.Width;
|
tabsSize.X += TabsPanel.VScrollBar.Width;
|
||||||
|
var style = Style.Current;
|
||||||
|
TabsPanel.VScrollBar.TrackColor = style.Background;
|
||||||
|
TabsPanel.VScrollBar.ThumbColor = style.ForegroundGrey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fit the tabs panel
|
// Fit the tabs panel
|
||||||
|
|||||||
@@ -698,6 +698,38 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show tree guide lines
|
||||||
|
if (Editor.Instance.Options.Options.Interface.ShowTreeLines)
|
||||||
|
{
|
||||||
|
TreeNode parentNode = Parent as TreeNode;
|
||||||
|
bool thisNodeIsLast = false;
|
||||||
|
while (parentNode != null && parentNode != ParentTree.Children[0])
|
||||||
|
{
|
||||||
|
float bottomOffset = 0;
|
||||||
|
float topOffset = 0;
|
||||||
|
|
||||||
|
if (Parent == parentNode && this == Parent.Children[0])
|
||||||
|
topOffset = 2;
|
||||||
|
|
||||||
|
if (thisNodeIsLast && parentNode.Children.Count == 1)
|
||||||
|
bottomOffset = topOffset != 0 ? 4 : 2;
|
||||||
|
|
||||||
|
if (Parent == parentNode && this == Parent.Children[Parent.Children.Count - 1] && !_opened)
|
||||||
|
{
|
||||||
|
thisNodeIsLast = true;
|
||||||
|
bottomOffset = topOffset != 0 ? 4 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
float leftOffset = 9;
|
||||||
|
// Adjust offset for icon image
|
||||||
|
if (_iconCollaped.IsValid)
|
||||||
|
leftOffset += 18;
|
||||||
|
var lineRect1 = new Rectangle(parentNode.TextRect.Left - leftOffset, parentNode.HeaderRect.Top + topOffset, 1, parentNode.HeaderRect.Height - bottomOffset);
|
||||||
|
Render2D.FillRectangle(lineRect1, isSelected ? style.ForegroundGrey : style.LightBackground);
|
||||||
|
parentNode = parentNode.Parent as TreeNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Base
|
// Base
|
||||||
if (_opened)
|
if (_opened)
|
||||||
{
|
{
|
||||||
@@ -729,7 +761,7 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
|
|
||||||
// Try to estimate the rough location of the first node, assuming the node height is constant
|
// Try to estimate the rough location of the first node, assuming the node height is constant
|
||||||
var firstChildGlobalRect = GetChildGlobalRectangle(children[0], ref globalTransform);
|
var firstChildGlobalRect = GetChildGlobalRectangle(children[0], ref globalTransform);
|
||||||
var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Y - firstChildGlobalRect.Top) / firstChildGlobalRect.Height) + 1, 0, children.Count - 1);
|
var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Y - firstChildGlobalRect.Top) / _headerHeight) + 1, 0, children.Count - 1);
|
||||||
if (GetChildGlobalRectangle(children[firstVisibleChild], ref globalTransform).Top > globalClipping.Top || !children[firstVisibleChild].Visible)
|
if (GetChildGlobalRectangle(children[firstVisibleChild], ref globalTransform).Top > globalClipping.Top || !children[firstVisibleChild].Visible)
|
||||||
{
|
{
|
||||||
// Estimate overshoot, either it's partially visible or hidden in the tree
|
// Estimate overshoot, either it's partially visible or hidden in the tree
|
||||||
|
|||||||
@@ -499,6 +499,15 @@ namespace FlaxEditor
|
|||||||
bool drawAnySelectedControl = false;
|
bool drawAnySelectedControl = false;
|
||||||
var transformGizmo = TransformGizmo;
|
var transformGizmo = TransformGizmo;
|
||||||
var mousePos = PointFromWindow(RootWindow.MousePosition);
|
var mousePos = PointFromWindow(RootWindow.MousePosition);
|
||||||
|
if (EnableSelecting && !_mouseMovesControl && !_mouseMovesWidget && IsMouseOver)
|
||||||
|
{
|
||||||
|
// Highlight control under mouse for easier selecting (except if already selected)
|
||||||
|
if (RayCastControl(ref mousePos, out var hitControl) &&
|
||||||
|
(transformGizmo == null || !transformGizmo.Selection.Any(x => x.EditableObject is UIControl controlActor && controlActor.Control == hitControl)))
|
||||||
|
{
|
||||||
|
DrawControl(null, hitControl, false, ref mousePos, ref drawAnySelectedControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (transformGizmo != null)
|
if (transformGizmo != null)
|
||||||
{
|
{
|
||||||
// Selected UI controls outline
|
// Selected UI controls outline
|
||||||
@@ -511,15 +520,6 @@ namespace FlaxEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (EnableSelecting && !_mouseMovesControl && !_mouseMovesWidget && IsMouseOver)
|
|
||||||
{
|
|
||||||
// Highlight control under mouse for easier selecting (except if already selected)
|
|
||||||
if (RayCastControl(ref mousePos, out var hitControl) &&
|
|
||||||
(transformGizmo == null || !transformGizmo.Selection.Any(x => x.EditableObject is UIControl controlActor && controlActor.Control == hitControl)))
|
|
||||||
{
|
|
||||||
DrawControl(null, hitControl, false, ref mousePos, ref drawAnySelectedControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (drawAnySelectedControl)
|
if (drawAnySelectedControl)
|
||||||
Render2D.PopTransform();
|
Render2D.PopTransform();
|
||||||
|
|
||||||
@@ -617,40 +617,39 @@ namespace FlaxEditor
|
|||||||
// Draw sizing widgets
|
// Draw sizing widgets
|
||||||
if (_widgets == null)
|
if (_widgets == null)
|
||||||
_widgets = new List<Widget>();
|
_widgets = new List<Widget>();
|
||||||
var widgetSize = 8.0f;
|
var widgetSize = 10.0f;
|
||||||
var viewScale = ViewScale;
|
var viewScale = ViewScale;
|
||||||
if (viewScale < 0.7f)
|
if (viewScale < 0.7f)
|
||||||
widgetSize *= viewScale;
|
widgetSize *= viewScale;
|
||||||
var controlSize = control.Size.Absolute.MinValue / 50.0f;
|
var controlSize = control.Size.Absolute.MinValue / 50.0f;
|
||||||
if (controlSize < 1.0f)
|
if (controlSize < 1.0f)
|
||||||
widgetSize *= Mathf.Clamp(controlSize + 0.1f, 0.1f, 1.0f);
|
widgetSize *= Mathf.Clamp(controlSize + 0.1f, 0.1f, 1.0f);
|
||||||
var cornerSize = new Float2(widgetSize);
|
var widgetHandleSize = new Float2(widgetSize);
|
||||||
DrawControlWidget(uiControl, ref ul, ref mousePos, ref cornerSize, new Float2(-1, -1), CursorType.SizeNWSE);
|
DrawControlWidget(uiControl, ref ul, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, -1), CursorType.SizeNWSE);
|
||||||
DrawControlWidget(uiControl, ref ur, ref mousePos, ref cornerSize, new Float2(1, -1), CursorType.SizeNESW);
|
DrawControlWidget(uiControl, ref ur, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, -1), CursorType.SizeNESW);
|
||||||
DrawControlWidget(uiControl, ref bl, ref mousePos, ref cornerSize, new Float2(-1, 1), CursorType.SizeNESW);
|
DrawControlWidget(uiControl, ref bl, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 1), CursorType.SizeNESW);
|
||||||
DrawControlWidget(uiControl, ref br, ref mousePos, ref cornerSize, new Float2(1, 1), CursorType.SizeNWSE);
|
DrawControlWidget(uiControl, ref br, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 1), CursorType.SizeNWSE);
|
||||||
var edgeSizeV = new Float2(widgetSize * 2, widgetSize);
|
|
||||||
var edgeSizeH = new Float2(edgeSizeV.Y, edgeSizeV.X);
|
|
||||||
Float2.Lerp(ref ul, ref bl, 0.5f, out var el);
|
Float2.Lerp(ref ul, ref bl, 0.5f, out var el);
|
||||||
Float2.Lerp(ref ur, ref br, 0.5f, out var er);
|
Float2.Lerp(ref ur, ref br, 0.5f, out var er);
|
||||||
Float2.Lerp(ref ul, ref ur, 0.5f, out var eu);
|
Float2.Lerp(ref ul, ref ur, 0.5f, out var eu);
|
||||||
Float2.Lerp(ref bl, ref br, 0.5f, out var eb);
|
Float2.Lerp(ref bl, ref br, 0.5f, out var eb);
|
||||||
DrawControlWidget(uiControl, ref el, ref mousePos, ref edgeSizeH, new Float2(-1, 0), CursorType.SizeWE);
|
DrawControlWidget(uiControl, ref el, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 0), CursorType.SizeWE);
|
||||||
DrawControlWidget(uiControl, ref er, ref mousePos, ref edgeSizeH, new Float2(1, 0), CursorType.SizeWE);
|
DrawControlWidget(uiControl, ref er, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 0), CursorType.SizeWE);
|
||||||
DrawControlWidget(uiControl, ref eu, ref mousePos, ref edgeSizeV, new Float2(0, -1), CursorType.SizeNS);
|
DrawControlWidget(uiControl, ref eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS);
|
||||||
DrawControlWidget(uiControl, ref eb, ref mousePos, ref edgeSizeV, new Float2(0, 1), CursorType.SizeNS);
|
DrawControlWidget(uiControl, ref eb, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, 1), CursorType.SizeNS);
|
||||||
|
|
||||||
// TODO: draw anchors
|
// TODO: draw anchors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size, Float2 resizeAxis, CursorType cursor)
|
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size,float scale, Float2 resizeAxis, CursorType cursor)
|
||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var rect = new Rectangle(pos - size * 0.5f, size);
|
var rect = new Rectangle((pos + resizeAxis * 10 * scale) - size * 0.5f, size);
|
||||||
if (rect.Contains(ref mousePos))
|
if (rect.Contains(ref mousePos))
|
||||||
{
|
{
|
||||||
Render2D.FillRectangle(rect, style.Foreground);
|
Render2D.FillRectangle(rect, style.Foreground);
|
||||||
|
Render2D.DrawRectangle(rect, style.SelectionBorder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -129,12 +129,9 @@ namespace FlaxEditor.Modules
|
|||||||
for (int i = 0; i < Proxy.Count; i++)
|
for (int i = 0; i < Proxy.Count; i++)
|
||||||
{
|
{
|
||||||
if (Proxy[i].IsProxyFor(item))
|
if (Proxy[i].IsProxyFor(item))
|
||||||
{
|
|
||||||
return Proxy[i];
|
return Proxy[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,11 +144,8 @@ namespace FlaxEditor.Modules
|
|||||||
for (int i = 0; i < Proxy.Count; i++)
|
for (int i = 0; i < Proxy.Count; i++)
|
||||||
{
|
{
|
||||||
if (Proxy[i].IsProxyFor<T>())
|
if (Proxy[i].IsProxyFor<T>())
|
||||||
{
|
|
||||||
return Proxy[i];
|
return Proxy[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,17 +158,12 @@ namespace FlaxEditor.Modules
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(extension))
|
if (string.IsNullOrEmpty(extension))
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
extension = StringUtils.NormalizeExtension(extension);
|
extension = StringUtils.NormalizeExtension(extension);
|
||||||
|
|
||||||
for (int i = 0; i < Proxy.Count; i++)
|
for (int i = 0; i < Proxy.Count; i++)
|
||||||
{
|
{
|
||||||
if (Proxy[i].FileExtension == extension)
|
if (string.Equals(Proxy[i].FileExtension, extension, StringComparison.Ordinal))
|
||||||
{
|
|
||||||
return Proxy[i];
|
return Proxy[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,30 +178,23 @@ namespace FlaxEditor.Modules
|
|||||||
for (int i = 0; i < Proxy.Count; i++)
|
for (int i = 0; i < Proxy.Count; i++)
|
||||||
{
|
{
|
||||||
if (Proxy[i] is AssetProxy proxy && proxy.AcceptsAsset(typeName, path))
|
if (Proxy[i] is AssetProxy proxy && proxy.AcceptsAsset(typeName, path))
|
||||||
{
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the virtual proxy object from given path.
|
/// Gets the virtual proxy object from given path.
|
||||||
/// <br></br>use case if the asset u trying to display is not a flax asset but u like to add custom functionality
|
|
||||||
/// <br></br>to context menu,or display it the asset
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The asset path.</param>
|
/// <param name="path">The asset path.</param>
|
||||||
/// <returns>Asset proxy or null if cannot find.</returns>
|
/// <returns>Asset proxy or null if cannot find.</returns>
|
||||||
public AssetProxy GetAssetVirtuallProxy(string path)
|
public AssetProxy GetAssetVirtualProxy(string path)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Proxy.Count; i++)
|
for (int i = 0; i < Proxy.Count; i++)
|
||||||
{
|
{
|
||||||
if (Proxy[i] is AssetProxy proxy && proxy.IsVirtualProxy() && path.EndsWith(proxy.FileExtension, StringComparison.OrdinalIgnoreCase))
|
if (Proxy[i] is AssetProxy proxy && proxy.IsVirtualProxy() && path.EndsWith(proxy.FileExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1016,11 +998,13 @@ namespace FlaxEditor.Modules
|
|||||||
}
|
}
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
var proxy = GetAssetVirtuallProxy(path);
|
var proxy = GetAssetVirtualProxy(path);
|
||||||
item = proxy?.ConstructItem(path, assetInfo.TypeName, ref assetInfo.ID);
|
item = proxy?.ConstructItem(path, assetInfo.TypeName, ref assetInfo.ID);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
item = new FileItem(path);
|
item = GetProxy(Path.GetExtension(path))?.ConstructItem(path);
|
||||||
|
if (item == null)
|
||||||
|
item = new FileItem(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1106,6 +1090,7 @@ namespace FlaxEditor.Modules
|
|||||||
Proxy.Add(new VisualScriptProxy());
|
Proxy.Add(new VisualScriptProxy());
|
||||||
Proxy.Add(new BehaviorTreeProxy());
|
Proxy.Add(new BehaviorTreeProxy());
|
||||||
Proxy.Add(new LocalizedStringTableProxy());
|
Proxy.Add(new LocalizedStringTableProxy());
|
||||||
|
Proxy.Add(new VideoProxy("mp4"));
|
||||||
Proxy.Add(new WidgetProxy());
|
Proxy.Add(new WidgetProxy());
|
||||||
Proxy.Add(new FileProxy());
|
Proxy.Add(new FileProxy());
|
||||||
Proxy.Add(new SpawnableJsonAssetProxy<PhysicalMaterial>());
|
Proxy.Add(new SpawnableJsonAssetProxy<PhysicalMaterial>());
|
||||||
|
|||||||
@@ -210,6 +210,13 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Interface"), EditorOrder(310)]
|
[EditorDisplay("Interface"), EditorOrder(310)]
|
||||||
public bool SeparateValueAndUnit { get; set; }
|
public bool SeparateValueAndUnit { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the option to put a space between numbers and units for unit formatting.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
[EditorDisplay("Interface"), EditorOrder(320)]
|
||||||
|
public bool ShowTreeLines { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the timestamps prefix mode for output log messages.
|
/// Gets or sets the timestamps prefix mode for output log messages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -255,6 +255,17 @@ namespace FlaxEditor.Options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure custom fonts are valid, reset if not
|
||||||
|
var defaultInterfaceOptions = new InterfaceOptions();
|
||||||
|
if (Style.Current.FontTitle == null)
|
||||||
|
Style.Current.FontTitle = defaultInterfaceOptions.TitleFont.GetFont();
|
||||||
|
if (Style.Current.FontSmall == null)
|
||||||
|
Style.Current.FontSmall = defaultInterfaceOptions.SmallFont.GetFont();
|
||||||
|
if (Style.Current.FontMedium == null)
|
||||||
|
Style.Current.FontMedium = defaultInterfaceOptions.MediumFont.GetFont();
|
||||||
|
if (Style.Current.FontLarge == null)
|
||||||
|
Style.Current.FontLarge = defaultInterfaceOptions.LargeFont.GetFont();
|
||||||
|
|
||||||
// Set fallback fonts
|
// Set fallback fonts
|
||||||
var fallbackFonts = Options.Interface.FallbackFonts;
|
var fallbackFonts = Options.Interface.FallbackFonts;
|
||||||
if (fallbackFonts == null || fallbackFonts.Length == 0 || fallbackFonts.All(x => x == null))
|
if (fallbackFonts == null || fallbackFonts.Length == 0 || fallbackFonts.All(x => x == null))
|
||||||
|
|||||||
69
Source/Editor/SceneGraph/Actors/VideoPlayerEditor.cs
Normal file
69
Source/Editor/SceneGraph/Actors/VideoPlayerEditor.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="VideoPlayer"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CustomEditor(typeof(VideoPlayer)), DefaultEditor]
|
||||||
|
public class VideoPlayerEditor : ActorEditor
|
||||||
|
{
|
||||||
|
private Label _infoLabel;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
base.Initialize(layout);
|
||||||
|
|
||||||
|
// Show playback options during simulation
|
||||||
|
if (Editor.IsPlayMode)
|
||||||
|
{
|
||||||
|
var playbackGroup = layout.Group("Playback");
|
||||||
|
playbackGroup.Panel.Open();
|
||||||
|
|
||||||
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
|
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
||||||
|
var gridControl = grid.CustomControl;
|
||||||
|
gridControl.ClipChildren = false;
|
||||||
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
gridControl.SlotsHorizontally = 3;
|
||||||
|
gridControl.SlotsVertically = 1;
|
||||||
|
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
|
||||||
|
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
|
||||||
|
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
base.Refresh();
|
||||||
|
|
||||||
|
if (_infoLabel != null)
|
||||||
|
{
|
||||||
|
var text = string.Empty;
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is VideoPlayer player)
|
||||||
|
text += $"Time: {player.Time:##0.0}s / {player.Duration:##0.0}s\nResolution: {player.Size.X}x{player.Size.Y}, Frame Rate: {player.FrameRate}";
|
||||||
|
}
|
||||||
|
_infoLabel.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Foreach(Action<VideoPlayer> func)
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is VideoPlayer player)
|
||||||
|
func(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ using FlaxEditor.Windows.Assets;
|
|||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Utilities;
|
using FlaxEngine.Utilities;
|
||||||
|
using Object = FlaxEngine.Object;
|
||||||
|
|
||||||
namespace FlaxEditor.SceneGraph.GUI
|
namespace FlaxEditor.SceneGraph.GUI
|
||||||
{
|
{
|
||||||
@@ -355,7 +356,7 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
private void OnRenamed(RenamePopup renamePopup)
|
private void OnRenamed(RenamePopup renamePopup)
|
||||||
{
|
{
|
||||||
using (new UndoBlock(ActorNode.Root.Undo, Actor, "Rename"))
|
using (new UndoBlock(ActorNode.Root.Undo, Actor, "Rename"))
|
||||||
Actor.Name = renamePopup.Text;
|
Actor.Name = renamePopup.Text.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -625,6 +626,7 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
{
|
{
|
||||||
var item = _dragScriptItems.Objects[i];
|
var item = _dragScriptItems.Objects[i];
|
||||||
var actorType = Editor.Instance.CodeEditing.Actors.Get(item);
|
var actorType = Editor.Instance.CodeEditing.Actors.Get(item);
|
||||||
|
var scriptType = Editor.Instance.CodeEditing.Scripts.Get(item);
|
||||||
if (actorType != ScriptType.Null)
|
if (actorType != ScriptType.Null)
|
||||||
{
|
{
|
||||||
var actor = actorType.CreateInstance() as Actor;
|
var actor = actorType.CreateInstance() as Actor;
|
||||||
@@ -639,6 +641,18 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
ActorNode.Root.Spawn(actor, spawnParent);
|
ActorNode.Root.Spawn(actor, spawnParent);
|
||||||
actor.OrderInParent = newOrder;
|
actor.OrderInParent = newOrder;
|
||||||
}
|
}
|
||||||
|
else if (scriptType != ScriptType.Null)
|
||||||
|
{
|
||||||
|
if (DragOverMode == DragItemPositioning.Above || DragOverMode == DragItemPositioning.Below)
|
||||||
|
{
|
||||||
|
Editor.LogWarning("Failed to spawn script of type " + actorType.TypeName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IUndoAction action = new AddRemoveScript(true, newParent, scriptType);
|
||||||
|
Select();
|
||||||
|
ActorNode.Root.Undo?.AddAction(action);
|
||||||
|
action.Do();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result = DragDropEffect.Move;
|
result = DragDropEffect.Move;
|
||||||
}
|
}
|
||||||
@@ -699,9 +713,9 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType);
|
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragScriptItem(ScriptItem script)
|
private bool ValidateDragScriptItem(ScriptItem script)
|
||||||
{
|
{
|
||||||
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
|
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null || Editor.Instance.CodeEditing.Scripts.Get(script) != ScriptType.Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Title = "Smoothstep",
|
Title = "Smoothstep",
|
||||||
Description = "Returns a smooth Hermite interpolation between 0 and 1, if value is in the range [min, max].",
|
Description = "Returns a smooth Hermite interpolation between 0 and 1, if value is in the range [min, max].",
|
||||||
Flags = NodeFlags.MaterialGraph,
|
Flags = NodeFlags.MaterialGraph,
|
||||||
Size = new Float2(120, 60),
|
Size = new Float2(200, 60),
|
||||||
ConnectionsHints = ConnectionsHint.Numeric,
|
ConnectionsHints = ConnectionsHint.Numeric,
|
||||||
IndependentBoxes = new[] { 0, 1, 2 },
|
IndependentBoxes = new[] { 0, 1, 2 },
|
||||||
DependentBoxes = new[] { 3 },
|
DependentBoxes = new[] { 3 },
|
||||||
|
|||||||
@@ -1471,5 +1471,27 @@ namespace FlaxEditor.Utilities
|
|||||||
inputActions.Add(options => options.GenerateScriptsProject, () => Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync());
|
inputActions.Add(options => options.GenerateScriptsProject, () => Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync());
|
||||||
inputActions.Add(options => options.RecompileScripts, ScriptsBuilder.Compile);
|
inputActions.Add(options => options.RecompileScripts, ScriptsBuilder.Compile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string ToPathProject(string path)
|
||||||
|
{
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
// Convert into path relative to the project (cross-platform)
|
||||||
|
var projectFolder = Globals.ProjectFolder;
|
||||||
|
if (path.StartsWith(projectFolder))
|
||||||
|
path = path.Substring(projectFolder.Length + 1);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ToPathAbsolute(string path)
|
||||||
|
{
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
// Convert into global path to if relative to the project
|
||||||
|
path = StringUtils.IsRelative(path) ? Path.Combine(Globals.ProjectFolder, path) : path;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "Engine/Level/Actors/Sky.h"
|
#include "Engine/Level/Actors/Sky.h"
|
||||||
#include "Engine/Level/Actors/SkyLight.h"
|
#include "Engine/Level/Actors/SkyLight.h"
|
||||||
#include "Engine/Level/Actors/SpotLight.h"
|
#include "Engine/Level/Actors/SpotLight.h"
|
||||||
|
#include "Engine/Video/VideoPlayer.h"
|
||||||
|
|
||||||
#define ICON_RADIUS 7.0f
|
#define ICON_RADIUS 7.0f
|
||||||
|
|
||||||
@@ -283,6 +284,7 @@ bool ViewportIconsRendererService::Init()
|
|||||||
MAP_TYPE(Sky, Skybox);
|
MAP_TYPE(Sky, Skybox);
|
||||||
MAP_TYPE(SkyLight, SkyLight);
|
MAP_TYPE(SkyLight, SkyLight);
|
||||||
MAP_TYPE(SpotLight, PointLight);
|
MAP_TYPE(SpotLight, PointLight);
|
||||||
|
MAP_TYPE(VideoPlayer, SceneAnimationPlayer);
|
||||||
#undef MAP_TYPE
|
#undef MAP_TYPE
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
||||||
{
|
{
|
||||||
|
if (renderContext.View.Pass == DrawPass.Depth)
|
||||||
|
return;
|
||||||
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
||||||
if (ShowNavigation)
|
if (ShowNavigation)
|
||||||
Editor.Internal_DrawNavMesh();
|
Editor.Internal_DrawNavMesh();
|
||||||
@@ -620,12 +622,12 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private static bool ValidateDragActorType(ScriptType actorType)
|
private static bool ValidateDragActorType(ScriptType actorType)
|
||||||
{
|
{
|
||||||
return Level.IsAnySceneLoaded;
|
return Level.IsAnySceneLoaded && Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragScriptItem(ScriptItem script)
|
private static bool ValidateDragScriptItem(ScriptItem script)
|
||||||
{
|
{
|
||||||
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
|
return Level.IsAnySceneLoaded && Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ namespace FlaxEditor.Viewport
|
|||||||
ShowDebugDraw = true;
|
ShowDebugDraw = true;
|
||||||
ShowEditorPrimitives = true;
|
ShowEditorPrimitives = true;
|
||||||
Gizmos = new GizmosCollection(this);
|
Gizmos = new GizmosCollection(this);
|
||||||
var inputOptions = window.Editor.Options.Options.Input;
|
|
||||||
|
|
||||||
// Prepare rendering task
|
// Prepare rendering task
|
||||||
Task.ActorsSource = ActorsSources.CustomActors;
|
Task.ActorsSource = ActorsSources.CustomActors;
|
||||||
@@ -219,6 +218,8 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
||||||
{
|
{
|
||||||
|
if (renderContext.View.Pass == DrawPass.Depth)
|
||||||
|
return;
|
||||||
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
||||||
_debugDrawData.OnDraw(ref renderContext);
|
_debugDrawData.OnDraw(ref renderContext);
|
||||||
}
|
}
|
||||||
@@ -498,7 +499,7 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private static bool ValidateDragActorType(ScriptType actorType)
|
private static bool ValidateDragActorType(ScriptType actorType)
|
||||||
{
|
{
|
||||||
return true;
|
return Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragScriptItem(ScriptItem script)
|
private static bool ValidateDragScriptItem(ScriptItem script)
|
||||||
|
|||||||
@@ -459,8 +459,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
protected virtual bool SaveToOriginal()
|
protected virtual bool SaveToOriginal()
|
||||||
{
|
{
|
||||||
// Wait until temporary asset file be fully loaded
|
if (_asset.LastLoadFailed)
|
||||||
if (_asset.WaitForLoaded())
|
|
||||||
{
|
{
|
||||||
Editor.LogError(string.Format("Cannot save asset {0}. Wait for temporary asset loaded failed.", _item.Path));
|
Editor.LogError(string.Format("Cannot save asset {0}. Wait for temporary asset loaded failed.", _item.Path));
|
||||||
return true;
|
return true;
|
||||||
@@ -494,12 +493,6 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload original asset
|
|
||||||
if (originalAsset)
|
|
||||||
{
|
|
||||||
originalAsset.Reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh thumbnail
|
// Refresh thumbnail
|
||||||
_item.RefreshThumbnail();
|
_item.RefreshThumbnail();
|
||||||
|
|
||||||
|
|||||||
@@ -302,8 +302,17 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
// TODO: improve the UI
|
// TODO: improve the UI
|
||||||
layout.Space(40);
|
layout.Space(40);
|
||||||
var addParamType = layout.ComboBox().ComboBox;
|
var addParamType = layout.ComboBox().ComboBox;
|
||||||
addParamType.Items = AllowedTypes.Select(CustomEditorsUtil.GetTypeNameUI).ToList();
|
object lastValue = null;
|
||||||
addParamType.SelectedIndex = 0;
|
foreach (var e in _proxy.DefaultValues)
|
||||||
|
lastValue = e.Value;
|
||||||
|
|
||||||
|
var allowedTypes = AllowedTypes.Select(CustomEditorsUtil.GetTypeNameUI).ToList();
|
||||||
|
int index = 0;
|
||||||
|
if (lastValue != null)
|
||||||
|
index = allowedTypes.FindIndex(x => x.Equals(CustomEditorsUtil.GetTypeNameUI(lastValue.GetType()), StringComparison.Ordinal));
|
||||||
|
|
||||||
|
addParamType.Items = allowedTypes;
|
||||||
|
addParamType.SelectedIndex = index;
|
||||||
_addParamType = addParamType;
|
_addParamType = addParamType;
|
||||||
var addParamButton = layout.Button("Add").Button;
|
var addParamButton = layout.Button("Add").Button;
|
||||||
addParamButton.Clicked += OnAddParamButtonClicked;
|
addParamButton.Clicked += OnAddParamButtonClicked;
|
||||||
|
|||||||
@@ -355,7 +355,6 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
Editor.LogError("Failed to save surface data");
|
Editor.LogError("Failed to save surface data");
|
||||||
}
|
}
|
||||||
_asset.Reload();
|
_asset.Reload();
|
||||||
_asset.WaitForLoaded();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
234
Source/Editor/Windows/Assets/VideoWindow.cs
Normal file
234
Source/Editor/Windows/Assets/VideoWindow.cs
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEditor.Content;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.Windows.Assets
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Editor window to view video media.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class VideoWindow : EditorWindow, IContentItemOwner
|
||||||
|
{
|
||||||
|
private VideoItem _item;
|
||||||
|
private Image _frame;
|
||||||
|
private VideoPlayer _videoPlayer;
|
||||||
|
private Image _seekBegin, _seekEnd, _seekLeft, _seekRight, _playPause, _stop;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public VideoWindow(Editor editor, VideoItem item)
|
||||||
|
: base(editor, false, ScrollBars.None)
|
||||||
|
{
|
||||||
|
_item = item;
|
||||||
|
_item.AddReference(this);
|
||||||
|
Title = _item.ShortName;
|
||||||
|
|
||||||
|
// Setup video player
|
||||||
|
_videoPlayer = new VideoPlayer
|
||||||
|
{
|
||||||
|
PlayOnStart = false,
|
||||||
|
Url = item.Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup UI
|
||||||
|
var style = Style.Current;
|
||||||
|
var icons = Editor.Icons;
|
||||||
|
var playbackButtonsSize = 24.0f;
|
||||||
|
var playbackButtonsMouseOverColor = Color.FromBgra(0xFFBBBBBB);
|
||||||
|
_frame = new Image
|
||||||
|
{
|
||||||
|
Brush = new VideoBrush(_videoPlayer),
|
||||||
|
AnchorPreset = AnchorPresets.StretchAll,
|
||||||
|
Offsets = new Margin(0.0f, 0.0f, 0.0f, playbackButtonsSize),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
var playbackButtonsArea = new ContainerControl
|
||||||
|
{
|
||||||
|
AutoFocus = false,
|
||||||
|
ClipChildren = false,
|
||||||
|
BackgroundColor = style.LightBackground,
|
||||||
|
AnchorPreset = AnchorPresets.HorizontalStretchBottom,
|
||||||
|
Offsets = new Margin(0, 0, -playbackButtonsSize, playbackButtonsSize),
|
||||||
|
Parent = this
|
||||||
|
};
|
||||||
|
var playbackButtonsPanel = new ContainerControl
|
||||||
|
{
|
||||||
|
AutoFocus = false,
|
||||||
|
ClipChildren = false,
|
||||||
|
AnchorPreset = AnchorPresets.VerticalStretchCenter,
|
||||||
|
Offsets = Margin.Zero,
|
||||||
|
Parent = playbackButtonsArea,
|
||||||
|
};
|
||||||
|
_seekBegin = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Rewind to timeline start (Home)",
|
||||||
|
Brush = new SpriteBrush(icons.Skip64),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Rotation = 180.0f,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_seekBegin.Clicked += (image, button) => SeekBegin();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
_seekLeft = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Move one frame back (Left Arrow)",
|
||||||
|
Brush = new SpriteBrush(icons.Left32),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_seekLeft.Clicked += (image, button) => SeekLeft();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
_stop = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Stop playback",
|
||||||
|
Brush = new SpriteBrush(icons.Stop64),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_stop.Clicked += (image, button) => Stop();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
_playPause = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Play/pause playback (Space)",
|
||||||
|
Brush = new SpriteBrush(icons.Play64),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_playPause.Clicked += (image, button) => PlayPause();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
_seekRight = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Move one frame forward (Right Arrow)",
|
||||||
|
Brush = new SpriteBrush(icons.Right32),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_seekRight.Clicked += (image, button) => SeekRight();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
_seekEnd = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
|
||||||
|
{
|
||||||
|
TooltipText = "Rewind to timeline end (End)",
|
||||||
|
Brush = new SpriteBrush(icons.Skip64),
|
||||||
|
MouseOverColor = playbackButtonsMouseOverColor,
|
||||||
|
Parent = playbackButtonsPanel
|
||||||
|
};
|
||||||
|
_seekEnd.Clicked += (image, button) => SeekEnd();
|
||||||
|
playbackButtonsPanel.Width += playbackButtonsSize;
|
||||||
|
playbackButtonsPanel.X = (playbackButtonsPanel.Parent.Width - playbackButtonsPanel.Width) * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlayPause()
|
||||||
|
{
|
||||||
|
if (_videoPlayer.State == VideoPlayer.States.Playing)
|
||||||
|
_videoPlayer.Pause();
|
||||||
|
else
|
||||||
|
_videoPlayer.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Stop()
|
||||||
|
{
|
||||||
|
_videoPlayer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SeekBegin()
|
||||||
|
{
|
||||||
|
_videoPlayer.Time = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SeekEnd()
|
||||||
|
{
|
||||||
|
_videoPlayer.Time = _videoPlayer.Duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SeekLeft()
|
||||||
|
{
|
||||||
|
if (_videoPlayer.State == VideoPlayer.States.Paused)
|
||||||
|
_videoPlayer.Time -= 1.0f / _videoPlayer.FrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SeekRight()
|
||||||
|
{
|
||||||
|
if (_videoPlayer.State == VideoPlayer.States.Paused)
|
||||||
|
_videoPlayer.Time += 1.0f / _videoPlayer.FrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
|
{
|
||||||
|
if (base.OnKeyDown(key))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case KeyboardKeys.ArrowLeft:
|
||||||
|
SeekLeft();
|
||||||
|
return true;
|
||||||
|
case KeyboardKeys.ArrowRight:
|
||||||
|
SeekRight();
|
||||||
|
return true;
|
||||||
|
case KeyboardKeys.Home:
|
||||||
|
SeekBegin();
|
||||||
|
return true;
|
||||||
|
case KeyboardKeys.End:
|
||||||
|
SeekEnd();
|
||||||
|
return true;
|
||||||
|
case KeyboardKeys.Spacebar:
|
||||||
|
PlayPause();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
// Update UI
|
||||||
|
var state = _videoPlayer.State;
|
||||||
|
var icons = Editor.Icons;
|
||||||
|
_stop.Enabled = state != VideoPlayer.States.Stopped;
|
||||||
|
_seekLeft.Enabled = _seekRight.Enabled = state != VideoPlayer.States.Playing;
|
||||||
|
((SpriteBrush)_playPause.Brush).Sprite = state == VideoPlayer.States.Playing ? icons.Pause64 : icons.Play64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnDestroy()
|
||||||
|
{
|
||||||
|
if (IsDisposing)
|
||||||
|
return;
|
||||||
|
_videoPlayer.Stop();
|
||||||
|
Object.Destroy(ref _videoPlayer);
|
||||||
|
_item.RemoveReference(this);
|
||||||
|
_item = null;
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnItemDeleted(ContentItem item)
|
||||||
|
{
|
||||||
|
if (item == _item)
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnItemRenamed(ContentItem item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnItemReimported(ContentItem item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void OnItemDispose(ContentItem item)
|
||||||
|
{
|
||||||
|
if (item == _item)
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -311,6 +311,23 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
if (selection[i] is BinaryAssetItem binaryAssetItem)
|
if (selection[i] is BinaryAssetItem binaryAssetItem)
|
||||||
Editor.ContentImporting.Reimport(binaryAssetItem);
|
Editor.ContentImporting.Reimport(binaryAssetItem);
|
||||||
|
else if (selection[i] is PrefabItem prefabItem)
|
||||||
|
{
|
||||||
|
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
|
||||||
|
var modelPrefab = prefab.GetDefaultInstance().GetScript<ModelPrefab>();
|
||||||
|
if (!modelPrefab)
|
||||||
|
continue;
|
||||||
|
var importPath = modelPrefab.ImportPath;
|
||||||
|
var editor = Editor.Instance;
|
||||||
|
if (editor.ContentImporting.GetReimportPath("Model Prefab", ref importPath))
|
||||||
|
continue;
|
||||||
|
var folder = editor.ContentDatabase.Find(Path.GetDirectoryName(prefab.Path)) as ContentFolder;
|
||||||
|
if (folder == null)
|
||||||
|
continue;
|
||||||
|
var importOptions = modelPrefab.ImportOptions;
|
||||||
|
importOptions.Type = FlaxEngine.Tools.ModelTool.ModelType.Prefab;
|
||||||
|
editor.ContentImporting.Import(importPath, folder, true, importOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -542,6 +542,8 @@ namespace FlaxEditor.Windows
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newShortName = newShortName.Trim();
|
||||||
|
|
||||||
// Cache data
|
// Cache data
|
||||||
string extension = item.IsFolder ? "" : Path.GetExtension(item.Path);
|
string extension = item.IsFolder ? "" : Path.GetExtension(item.Path);
|
||||||
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);
|
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);
|
||||||
|
|||||||
@@ -767,13 +767,6 @@ namespace FlaxEditor.Windows
|
|||||||
Platform = BuildPlatform.Windows64,
|
Platform = BuildPlatform.Windows64,
|
||||||
Mode = BuildConfiguration.Development,
|
Mode = BuildConfiguration.Development,
|
||||||
},
|
},
|
||||||
new BuildTarget
|
|
||||||
{
|
|
||||||
Name = "Windows 32bit",
|
|
||||||
Output = "Output\\Win32",
|
|
||||||
Platform = BuildPlatform.Windows32,
|
|
||||||
Mode = BuildConfiguration.Development,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_data = presets;
|
_data = presets;
|
||||||
@@ -793,9 +786,9 @@ namespace FlaxEditor.Windows
|
|||||||
Array.Copy(_data[_selectedPresetIndex].Targets, targets, count);
|
Array.Copy(_data[_selectedPresetIndex].Targets, targets, count);
|
||||||
targets[count] = new BuildTarget
|
targets[count] = new BuildTarget
|
||||||
{
|
{
|
||||||
Name = "Xbox One",
|
Name = "Windows 64bit",
|
||||||
Output = "Output\\XboxOne",
|
Output = "Output\\Win64",
|
||||||
Platform = BuildPlatform.XboxOne,
|
Platform = BuildPlatform.Windows64,
|
||||||
Mode = BuildConfiguration.Development,
|
Mode = BuildConfiguration.Development,
|
||||||
};
|
};
|
||||||
_data[_selectedPresetIndex].Targets = targets;
|
_data[_selectedPresetIndex].Targets = targets;
|
||||||
|
|||||||
@@ -470,6 +470,10 @@ namespace FlaxEditor.Windows
|
|||||||
IsMaximized = false;
|
IsMaximized = false;
|
||||||
IsBorderless = false;
|
IsBorderless = false;
|
||||||
Cursor = CursorType.Default;
|
Cursor = CursorType.Default;
|
||||||
|
Screen.CursorLock = CursorLockMode.None;
|
||||||
|
if (Screen.MainWindow.IsMouseTracking)
|
||||||
|
Screen.MainWindow.EndTrackingMouse();
|
||||||
|
RootControl.GameRoot.EndMouseCapture();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -478,7 +482,7 @@ namespace FlaxEditor.Windows
|
|||||||
base.OnMouseLeave();
|
base.OnMouseLeave();
|
||||||
|
|
||||||
// Remove focus from game window when mouse moves out and the cursor is hidden during game
|
// Remove focus from game window when mouse moves out and the cursor is hidden during game
|
||||||
if ((IsFocused || ContainsFocus) && Parent != null && Editor.IsPlayMode && !Screen.CursorVisible)
|
if (ContainsFocus && Parent != null && Editor.IsPlayMode && !Screen.CursorVisible && Screen.CursorLock == CursorLockMode.None)
|
||||||
{
|
{
|
||||||
Parent.Focus();
|
Parent.Focus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using FlaxEditor.CustomEditors;
|
using FlaxEditor.CustomEditors;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -96,14 +95,6 @@ namespace FlaxEditor.Windows
|
|||||||
set => Graphics.ShadowMapsQuality = value;
|
set => Graphics.ShadowMapsQuality = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[EditorOrder(1320), EditorDisplay("Quality", "Allow CSM Blending"), Tooltip("Enables cascades splits blending for directional light shadows.")]
|
|
||||||
public bool AllowCSMBlending
|
|
||||||
{
|
|
||||||
get => Graphics.AllowCSMBlending;
|
|
||||||
set => Graphics.AllowCSMBlending = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NoSerialize, DefaultValue(1.0f), Limit(0.05f, 5, 0)]
|
[NoSerialize, DefaultValue(1.0f), Limit(0.05f, 5, 0)]
|
||||||
[EditorOrder(1400), EditorDisplay("Quality")]
|
[EditorOrder(1400), EditorDisplay("Quality")]
|
||||||
[Tooltip("The scale of the rendering resolution relative to the output dimensions. If lower than 1 the scene and postprocessing will be rendered at a lower resolution and upscaled to the output backbuffer.")]
|
[Tooltip("The scale of the rendering resolution relative to the output dimensions. If lower than 1 the scene and postprocessing will be rendered at a lower resolution and upscaled to the output backbuffer.")]
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ namespace FlaxEditor.Windows
|
|||||||
if (IsLayoutLocked)
|
if (IsLayoutLocked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_hScroll.Maximum = _output.TextSize.X;
|
_hScroll.Maximum = Mathf.Max(_output.TextSize.X, _hScroll.Minimum);
|
||||||
_vScroll.Maximum = Mathf.Max(_output.TextSize.Y - _output.Height, _vScroll.Minimum);
|
_vScroll.Maximum = Mathf.Max(_output.TextSize.Y - _output.Height, _vScroll.Minimum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -367,6 +367,7 @@ namespace FlaxEditor.Windows
|
|||||||
var tree = new Tree(false)
|
var tree = new Tree(false)
|
||||||
{
|
{
|
||||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||||
|
Margin = new Margin(0, 0, 0, panel.ScrollBarsSize),
|
||||||
IsScrollable = true,
|
IsScrollable = true,
|
||||||
Parent = panel
|
Parent = panel
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -232,12 +232,12 @@ void BehaviorTree::OnScriptsReloadEnd()
|
|||||||
Graph.Setup(this);
|
Graph.Setup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorTree::GetReferences(Array<Guid>& output) const
|
void BehaviorTree::GetReferences(Array<Guid>& assets, Array<String>& files) const
|
||||||
{
|
{
|
||||||
// Base
|
// Base
|
||||||
BinaryAsset::GetReferences(output);
|
BinaryAsset::GetReferences(assets, files);
|
||||||
|
|
||||||
Graph.GetReferences(output);
|
Graph.GetReferences(assets);
|
||||||
|
|
||||||
// Extract refs from serialized nodes data
|
// Extract refs from serialized nodes data
|
||||||
for (const BehaviorTreeGraphNode& n : Graph.Nodes)
|
for (const BehaviorTreeGraphNode& n : Graph.Nodes)
|
||||||
@@ -246,7 +246,7 @@ void BehaviorTree::GetReferences(Array<Guid>& output) const
|
|||||||
continue;
|
continue;
|
||||||
const Variant& data = n.Values[1];
|
const Variant& data = n.Values[1];
|
||||||
if (data.Type == VariantType::Blob)
|
if (data.Type == VariantType::Blob)
|
||||||
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), output);
|
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), assets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public:
|
|||||||
// [BinaryAsset]
|
// [BinaryAsset]
|
||||||
void OnScriptingDispose() override;
|
void OnScriptingDispose() override;
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
void GetReferences(Array<Guid>& output) const override;
|
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user