Merge remote-tracking branch 'origin/1.9'
This commit is contained in:
BIN
Content/Editor/Camera/M_Camera.flax
(Stored with Git LFS)
BIN
Content/Editor/Camera/M_Camera.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
@@ -26,14 +26,12 @@ void PS_GBuffer(
|
||||
)
|
||||
{
|
||||
Light = float4(0, 0, 0, 1);
|
||||
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
ClipLODTransition(materialInput);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Distortion(PixelInput input) : SV_Target0
|
||||
{
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
ClipLODTransition(materialInput);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||
@2// Forward Shading: Constants
|
||||
LightData DirectionalLight;
|
||||
LightShadowData DirectionalLightShadow;
|
||||
LightData SkyLight;
|
||||
ProbeData EnvironmentProbe;
|
||||
ExponentialHeightFogData ExponentialHeightFog;
|
||||
@@ -26,9 +25,9 @@ LightData LocalLights[MAX_LOCAL_LIGHTS];
|
||||
@3// Forward Shading: Resources
|
||||
TextureCube EnvProbe : 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
|
||||
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
|
||||
@5// Forward Shading: Shaders
|
||||
|
||||
// Pixel Shader function for Forward Pass
|
||||
@@ -39,14 +38,12 @@ void PS_Forward(
|
||||
)
|
||||
{
|
||||
output = 0;
|
||||
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
ClipLODTransition(materialInput);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
@@ -80,11 +77,8 @@ void PS_Forward(
|
||||
|
||||
// Calculate lighting from a single directional light
|
||||
float4 shadowMask = 1.0f;
|
||||
if (DirectionalLight.CastShadows > 0)
|
||||
{
|
||||
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
|
||||
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
|
||||
}
|
||||
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
|
||||
shadowMask = GetShadowMask(shadow);
|
||||
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
||||
|
||||
// Calculate lighting from sky light
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#define CAN_USE_LIGHTMAP 1
|
||||
@1// Lightmap: Includes
|
||||
@2// Lightmap: Constants
|
||||
float4 LightmapArea;
|
||||
@3// Lightmap: Resources
|
||||
#if USE_LIGHTMAP
|
||||
// Irradiance and directionality prebaked lightmaps
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION || MATERIAL_MASKED
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
ClipLODTransition(materialInput);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MATERIAL_MASKED
|
||||
// Perform per pixel clipping if material requries it
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
GlobalSDFData GlobalSDF;
|
||||
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
|
||||
@3// SDF Reflections: Resources
|
||||
Texture3D<float> GlobalSDFTex : register(t__SRV__);
|
||||
Texture3D<float> GlobalSDFMip : register(t__SRV__);
|
||||
Texture3D<snorm float> GlobalSDFTex : register(t__SRV__);
|
||||
Texture3D<snorm float> GlobalSDFMip : register(t__SRV__);
|
||||
ByteAddressBuffer GlobalSurfaceAtlasChunks : register(t__SRV__);
|
||||
ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t__SRV__);
|
||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t__SRV__);
|
||||
@@ -21,9 +21,8 @@ bool TraceSDFSoftwareReflections(GBufferSample gBuffer, float3 reflectWS, out fl
|
||||
{
|
||||
GlobalSDFTrace sdfTrace;
|
||||
float maxDistance = GLOBAL_SDF_WORLD_SIZE;
|
||||
float selfOcclusionBias = GlobalSDF.CascadeVoxelSize[0];
|
||||
sdfTrace.Init(gBuffer.WorldPos + gBuffer.Normal * selfOcclusionBias, reflectWS, 0.0f, maxDistance);
|
||||
GlobalSDFHit sdfHit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, sdfTrace);
|
||||
sdfTrace.Init(gBuffer.WorldPos, reflectWS, 0.0f, maxDistance);
|
||||
GlobalSDFHit sdfHit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, sdfTrace, 2.0f);
|
||||
if (sdfHit.IsHit())
|
||||
{
|
||||
float3 hitPosition = sdfHit.GetHitPosition(sdfTrace);
|
||||
|
||||
@@ -33,8 +33,13 @@ struct TessalationDSToPS
|
||||
MaterialInput GetMaterialInput(TessalationDSToPS input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
#if USE_PER_DRAW_CONSTANTS
|
||||
output.Object = LoadObject(ObjectsBuffer, input.Geometry.ObjectIndex);
|
||||
#else
|
||||
LoadObjectFromCB(output.Object);
|
||||
#endif
|
||||
output.SvPosition = input.Position;
|
||||
output.TwoSidedSign = WorldDeterminantSign;
|
||||
output.TwoSidedSign = output.Object.WorldDeterminantSign;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ struct RibbonInput
|
||||
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WorldMatrix;
|
||||
float4x3 WorldMatrix;
|
||||
uint SortedIndicesOffset;
|
||||
float PerInstanceRandom;
|
||||
int ParticleStride;
|
||||
@@ -45,7 +45,7 @@ int RibbonWidthOffset;
|
||||
int RibbonTwistOffset;
|
||||
int RibbonFacingVectorOffset;
|
||||
uint RibbonSegmentCount;
|
||||
float4x4 WorldMatrixInverseTransposed;
|
||||
float4x3 WorldMatrixInverseTransposed;
|
||||
@1META_CB_END
|
||||
|
||||
// Particles attributes buffer
|
||||
@@ -138,7 +138,7 @@ MaterialInput GetMaterialInput(PixelInput input)
|
||||
#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))
|
||||
#else
|
||||
#define GetInstanceTransform(input) WorldMatrix;
|
||||
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
{
|
||||
return mul(float4(input, 1.0f), WorldMatrix).xyz;
|
||||
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
|
||||
}
|
||||
|
||||
float3 TransformParticleVector(float3 input)
|
||||
{
|
||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
||||
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
|
||||
}
|
||||
|
||||
@8
|
||||
@@ -333,7 +333,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
|
||||
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
|
||||
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
|
||||
|
||||
float4x4 world = WorldMatrix;
|
||||
float4x4 world = ToMatrix4x4(WorldMatrix);
|
||||
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
||||
float3x3 viewRot = transpose((float3x3)ViewMatrix);
|
||||
float3 position = mul(float4(particlePosition, 1), world).xyz;
|
||||
@@ -463,11 +463,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
||||
}
|
||||
|
||||
// Read particle data
|
||||
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
|
||||
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
|
||||
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
|
||||
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
|
||||
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
|
||||
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
|
||||
@@ -506,7 +507,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
|
||||
world = mul(world, scaleMatrix);
|
||||
}
|
||||
world = transpose(world);
|
||||
world = mul(world, WorldMatrix);
|
||||
world = mul(world, worldMatrix);
|
||||
|
||||
// Calculate the vertex position in world space
|
||||
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
|
||||
output.VertexColor = input.Color;
|
||||
#endif
|
||||
output.InstanceOrigin = WorldMatrix[3].xyz;
|
||||
output.InstanceOrigin = worldMatrix[3].xyz;
|
||||
output.InstanceParams = PerInstanceRandom;
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
half3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
||||
half3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
|
||||
output.TBN = tangentToWorld;
|
||||
|
||||
// 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
|
||||
output.VertexColor = 1;
|
||||
#endif
|
||||
output.InstanceOrigin = WorldMatrix[3].xyz;
|
||||
float4x4 world = ToMatrix4x4(WorldMatrix);
|
||||
output.InstanceOrigin = world[3].xyz;
|
||||
output.InstanceParams = PerInstanceRandom;
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
|
||||
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
||||
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||
output.TBN = tangentToWorld;
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
#define USE_PER_DRAW_CONSTANTS 1
|
||||
@3
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
@@ -10,17 +11,19 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 PrevWorldMatrix;
|
||||
float2 Dummy0;
|
||||
float LODDitherFactor;
|
||||
float PerInstanceRandom;
|
||||
float3 GeometrySize;
|
||||
float WorldDeterminantSign;
|
||||
@1META_CB_END
|
||||
|
||||
// Shader resources
|
||||
@2
|
||||
Buffer<float4> ObjectsBuffer : register(t0);
|
||||
#if USE_SKINNING
|
||||
// The skeletal bones matrix buffer (stored as 4x3, 3 float4 behind each other)
|
||||
Buffer<float4> BoneMatrices : register(t1);
|
||||
#if PER_BONE_MOTION_BLUR
|
||||
// The skeletal bones matrix buffer from the previous frame
|
||||
Buffer<float4> PrevBoneMatrices : register(t2);
|
||||
#endif
|
||||
#endif
|
||||
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||
struct GeometryData
|
||||
{
|
||||
@@ -32,12 +35,8 @@ struct GeometryData
|
||||
#endif
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float4 WorldTangent : TEXCOORD4;
|
||||
nointerpolation float3 InstanceOrigin : TEXCOORD5;
|
||||
nointerpolation float2 InstanceParams : TEXCOORD6; // x-PerInstanceRandom, y-LODDitherFactor
|
||||
float3 PrevWorldPosition : TEXCOORD7;
|
||||
nointerpolation float3 InstanceTransform1 : TEXCOORD8;
|
||||
nointerpolation float3 InstanceTransform2 : TEXCOORD9;
|
||||
nointerpolation float3 InstanceTransform3 : TEXCOORD10;
|
||||
nointerpolation uint ObjectIndex : TEXCOORD8;
|
||||
};
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
@@ -80,11 +79,8 @@ struct MaterialInput
|
||||
float4 SvPosition;
|
||||
float3 PreSkinnedPosition;
|
||||
float3 PreSkinnedNormal;
|
||||
float3 InstanceOrigin;
|
||||
float2 InstanceParams;
|
||||
float3 InstanceTransform1;
|
||||
float3 InstanceTransform2;
|
||||
float3 InstanceTransform3;
|
||||
uint ObjectIndex;
|
||||
ObjectData Object;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
|
||||
#endif
|
||||
@@ -103,11 +99,7 @@ MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||
output.VertexColor = geometry.VertexColor;
|
||||
#endif
|
||||
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
|
||||
output.InstanceOrigin = geometry.InstanceOrigin;
|
||||
output.InstanceParams = geometry.InstanceParams;
|
||||
output.InstanceTransform1 = geometry.InstanceTransform1;
|
||||
output.InstanceTransform2 = geometry.InstanceTransform2;
|
||||
output.InstanceTransform3 = geometry.InstanceTransform3;
|
||||
output.ObjectIndex = geometry.ObjectIndex;
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -143,11 +135,7 @@ GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, flo
|
||||
output.WorldNormal = normalize(output.WorldNormal);
|
||||
output.WorldTangent = p0.WorldTangent * w0 + p1.WorldTangent * w1 + p2.WorldTangent * w2;
|
||||
output.WorldTangent.xyz = normalize(output.WorldTangent.xyz);
|
||||
output.InstanceOrigin = p0.InstanceOrigin;
|
||||
output.InstanceParams = p0.InstanceParams;
|
||||
output.InstanceTransform1 = p0.InstanceTransform1;
|
||||
output.InstanceTransform2 = p0.InstanceTransform2;
|
||||
output.InstanceTransform3 = p0.InstanceTransform3;
|
||||
output.ObjectIndex = p0.ObjectIndex;
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -156,7 +144,8 @@ GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, flo
|
||||
MaterialInput GetMaterialInput(PixelInput input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.Object = LoadObject(ObjectsBuffer, input.Geometry.ObjectIndex);
|
||||
output.TwoSidedSign = output.Object.WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.SvPosition = input.Position;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
@@ -164,16 +153,6 @@ MaterialInput GetMaterialInput(PixelInput input)
|
||||
return output;
|
||||
}
|
||||
|
||||
// Gets the local to world transform matrix
|
||||
#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))
|
||||
|
||||
// Extarcts the world matrix and instancce transform vector
|
||||
#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;
|
||||
#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;
|
||||
#endif
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
{
|
||||
@@ -218,7 +197,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
float3x3 localToWorld = (float3x3)input.Object.WorldMatrix;
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localVector, localToWorld);
|
||||
}
|
||||
@@ -226,7 +205,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
float3x3 localToWorld = (float3x3)input.Object.WorldMatrix;
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localToWorld, worldVector);
|
||||
}
|
||||
@@ -234,30 +213,26 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
// Gets the current object position (supports instancing)
|
||||
float3 GetObjectPosition(MaterialInput input)
|
||||
{
|
||||
return input.InstanceOrigin.xyz;
|
||||
return input.Object.WorldMatrix[3].xyz;
|
||||
}
|
||||
|
||||
// Gets the current object size (supports instancing)
|
||||
float3 GetObjectSize(MaterialInput input)
|
||||
{
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
return GeometrySize * float3(world._m00, world._m11, world._m22);
|
||||
float4x4 world = input.Object.WorldMatrix;
|
||||
return input.Object.GeometrySize * float3(world._m00, world._m11, world._m22);
|
||||
}
|
||||
|
||||
// Get the current object random value (supports instancing)
|
||||
float GetPerInstanceRandom(MaterialInput input)
|
||||
{
|
||||
return input.InstanceParams.x;
|
||||
return input.Object.PerInstanceRandom;
|
||||
}
|
||||
|
||||
// Get the current object LOD transition dither factor (supports instancing)
|
||||
float GetLODDitherFactor(MaterialInput input)
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
return input.InstanceParams.y;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
return input.Object.LODDitherFactor;
|
||||
}
|
||||
|
||||
// Gets the interpolated vertex color (in linear space)
|
||||
@@ -316,19 +291,22 @@ META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true
|
||||
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(COLOR, 0, R8G8B8A8_UNORM, 2, 0, PER_VERTEX, 0, USE_VERTEX_COLOR)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32G32B32A32_FLOAT,3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,1, R32G32B32A32_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,2, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,3, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,4, R16G16B16A16_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32_UINT, 3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
VertexOutput VS(ModelInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
// Load object data
|
||||
#if USE_INSTANCING
|
||||
output.Geometry.ObjectIndex = input.ObjectIndex;
|
||||
#else
|
||||
output.Geometry.ObjectIndex = DrawObjectIndex;
|
||||
#endif
|
||||
ObjectData object = LoadObject(ObjectsBuffer, output.Geometry.ObjectIndex);
|
||||
|
||||
// Compute world space vertex position
|
||||
CalculateInstanceTransform(input);
|
||||
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
|
||||
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), object.WorldMatrix).xyz;
|
||||
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), object.PrevWorldMatrix).xyz;
|
||||
|
||||
// Compute clip space position
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
@@ -338,22 +316,15 @@ VertexOutput VS(ModelInput input)
|
||||
#if USE_VERTEX_COLOR
|
||||
output.Geometry.VertexColor = input.Color;
|
||||
#endif
|
||||
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||
#if USE_INSTANCING
|
||||
output.Geometry.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy;
|
||||
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||
#else
|
||||
#if CAN_USE_LIGHTMAP
|
||||
output.Geometry.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy;
|
||||
output.Geometry.LightmapUV = input.LightmapUV * object.LightmapArea.zw + object.LightmapArea.xy;
|
||||
#else
|
||||
output.Geometry.LightmapUV = input.LightmapUV;
|
||||
#endif
|
||||
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||
#endif
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(object.WorldMatrix, tangentToLocal);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||
@@ -361,10 +332,11 @@ VertexOutput VS(ModelInput input)
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.TwoSidedSign = object.WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||
materialInput.Object = object;
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
@@ -392,33 +364,27 @@ META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_INSTANCING=0)
|
||||
META_PERMUTATION_1(USE_INSTANCING=1)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32G32B32A32_FLOAT,3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,1, R32G32B32A32_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,2, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,3, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,4, R16G16B16A16_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32_UINT, 3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
|
||||
{
|
||||
// Load object data
|
||||
#if USE_INSTANCING
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
uint objectIndex = input.ObjectIndex;
|
||||
#else
|
||||
float4x4 world = WorldMatrix;
|
||||
uint objectIndex = DrawObjectIndex;
|
||||
#endif
|
||||
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||
ObjectData object = LoadObject(ObjectsBuffer, objectIndex);
|
||||
|
||||
// Transform vertex position into the screen
|
||||
float3 worldPosition = mul(float4(input.Position.xyz, 1), object.WorldMatrix).xyz;
|
||||
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
|
||||
return position;
|
||||
}
|
||||
|
||||
#if USE_SKINNING
|
||||
|
||||
// The skeletal bones matrix buffer (stored as 4x3, 3 float4 behind each other)
|
||||
Buffer<float4> BoneMatrices : register(t0);
|
||||
|
||||
#if PER_BONE_MOTION_BLUR
|
||||
|
||||
// The skeletal bones matrix buffer from the previous frame
|
||||
Buffer<float4> PrevBoneMatrices : register(t1);
|
||||
|
||||
float3x4 GetPrevBoneMatrix(int index)
|
||||
{
|
||||
float4 a = PrevBoneMatrices[index * 3];
|
||||
@@ -497,6 +463,10 @@ META_VS_IN_ELEMENT(BLENDWEIGHT, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0,
|
||||
VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
// Load object data
|
||||
output.Geometry.ObjectIndex = DrawObjectIndex;
|
||||
ObjectData object = LoadObject(ObjectsBuffer, output.Geometry.ObjectIndex);
|
||||
|
||||
// Perform skinning
|
||||
float3x4 boneMatrix = GetBoneMatrix(input);
|
||||
@@ -504,13 +474,12 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
float3x3 tangentToLocal = SkinTangents(input, boneMatrix);
|
||||
|
||||
// Compute world space vertex position
|
||||
CalculateInstanceTransform(input);
|
||||
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
|
||||
output.Geometry.WorldPosition = mul(float4(position, 1), object.WorldMatrix).xyz;
|
||||
#if PER_BONE_MOTION_BLUR
|
||||
float3 prevPosition = SkinPrevPosition(input);
|
||||
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
|
||||
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), object.PrevWorldMatrix).xyz;
|
||||
#else
|
||||
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
|
||||
output.Geometry.PrevWorldPosition = mul(float4(position, 1), object.PrevWorldMatrix).xyz;
|
||||
#endif
|
||||
|
||||
// Compute clip space position
|
||||
@@ -522,15 +491,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
output.Geometry.VertexColor = float4(0, 0, 0, 1);
|
||||
#endif
|
||||
output.Geometry.LightmapUV = float2(0, 0);
|
||||
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||
#if USE_INSTANCING
|
||||
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||
#else
|
||||
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||
#endif
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(object.WorldMatrix, tangentToLocal);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||
@@ -538,10 +501,11 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.TwoSidedSign = object.WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||
materialInput.Object = object;
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
@@ -568,12 +532,12 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
|
||||
void ClipLODTransition(PixelInput input)
|
||||
void ClipLODTransition(MaterialInput input)
|
||||
{
|
||||
float ditherFactor = input.Geometry.InstanceParams.y;
|
||||
float ditherFactor = input.Object.LODDitherFactor;
|
||||
if (abs(ditherFactor) > 0.001)
|
||||
{
|
||||
float randGrid = cos(dot(floor(input.Position.xy), float2(347.83452793, 3343.28371863)));
|
||||
float randGrid = cos(dot(floor(input.SvPosition.xy), float2(347.83452793, 3343.28371863)));
|
||||
float randGridFrac = frac(randGrid * 1000.0);
|
||||
half mask = (ditherFactor < 0.0) ? (ditherFactor + 1.0 > randGridFrac) : (ditherFactor < randGridFrac);
|
||||
clip(mask - 0.001);
|
||||
@@ -586,14 +550,13 @@ void ClipLODTransition(PixelInput input)
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
void PS_Depth(PixelInput input)
|
||||
{
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
ClipLODTransition(materialInput);
|
||||
#endif
|
||||
|
||||
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Perform per pixel clipping
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
#define LoadObjectFromCB(var) var = GetObject()
|
||||
@3
|
||||
// Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour)
|
||||
#define USE_SMOOTH_LOD_TRANSITION 1
|
||||
@@ -17,7 +18,7 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WorldMatrix;
|
||||
float4x3 WorldMatrix;
|
||||
float3 WorldInvScale;
|
||||
float WorldDeterminantSign;
|
||||
float PerInstanceRandom;
|
||||
@@ -28,6 +29,7 @@ float4 HeightmapUVScaleBias;
|
||||
float4 NeighborLOD;
|
||||
float2 OffsetUV;
|
||||
float2 Dummy0;
|
||||
float4 LightmapArea;
|
||||
@1META_CB_END
|
||||
|
||||
// Terrain data
|
||||
@@ -88,6 +90,7 @@ struct MaterialInput
|
||||
float3 PreSkinnedPosition;
|
||||
float3 PreSkinnedNormal;
|
||||
float HolesMask;
|
||||
ObjectData Object;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE];
|
||||
#endif
|
||||
@@ -147,9 +150,23 @@ GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, flo
|
||||
|
||||
#endif
|
||||
|
||||
ObjectData GetObject()
|
||||
{
|
||||
ObjectData object = (ObjectData)0;
|
||||
object.WorldMatrix = ToMatrix4x4(WorldMatrix);
|
||||
object.PrevWorldMatrix = object.WorldMatrix;
|
||||
object.GeometrySize = float3(1, 1, 1);
|
||||
object.PerInstanceRandom = PerInstanceRandom;
|
||||
object.WorldDeterminantSign = WorldDeterminantSign;
|
||||
object.LODDitherFactor = 0.0f;
|
||||
object.LightmapArea = LightmapArea;
|
||||
return object;
|
||||
}
|
||||
|
||||
MaterialInput GetMaterialInput(PixelInput input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.Object = GetObject();
|
||||
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.SvPosition = input.Position;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
@@ -194,7 +211,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localVector, localToWorld);
|
||||
}
|
||||
@@ -202,7 +219,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localToWorld, worldVector);
|
||||
}
|
||||
@@ -210,7 +227,7 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
// Gets the current object position
|
||||
float3 GetObjectPosition(MaterialInput input)
|
||||
{
|
||||
return WorldMatrix[3].xyz;
|
||||
return ToMatrix4x4(WorldMatrix)[3].xyz;
|
||||
}
|
||||
|
||||
// Gets the current object size
|
||||
@@ -365,7 +382,8 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
||||
|
||||
// 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
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
@@ -389,12 +407,13 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
|
||||
// Compute world space normal vector
|
||||
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = (MaterialInput)0;
|
||||
materialInput.Object = GetObject();
|
||||
materialInput.WorldPosition = output.Geometry.WorldPosition;
|
||||
materialInput.TexCoord = output.Geometry.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 InverseViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 WorldMatrixInverseTransposed;
|
||||
float4x3 WorldMatrix;
|
||||
float4x3 WorldMatrixInverseTransposed;
|
||||
float3 GridSize;
|
||||
float PerInstanceRandom;
|
||||
float Dummy0;
|
||||
@@ -49,7 +49,7 @@ struct MaterialInput
|
||||
#endif
|
||||
};
|
||||
|
||||
#define GetInstanceTransform(input) WorldMatrix;
|
||||
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
@@ -170,12 +170,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
|
||||
|
||||
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)
|
||||
{
|
||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
||||
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
|
||||
}
|
||||
|
||||
@8
|
||||
@@ -219,7 +219,7 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
|
||||
materialInput.ParticleIndex = ParticleIndex;
|
||||
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
||||
materialInput.TwoSidedSign = 1.0f;
|
||||
materialInput.InstanceOrigin = WorldMatrix[3].xyz;
|
||||
materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz;
|
||||
materialInput.InstanceParams = PerInstanceRandom;
|
||||
materialInput.SvPosition = clipPos;
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Smoke.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Smoke.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Sparks.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Sparks.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Capsule.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Capsule.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Cylinder.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cylinder.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Primitives/Sphere.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Sphere.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/CAS.flax
(Stored with Git LFS)
Normal file
BIN
Content/Shaders/CAS.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Lights.flax
(Stored with Git LFS)
BIN
Content/Shaders/Lights.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Quad.flax
(Stored with Git LFS)
BIN
Content/Shaders/Quad.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/SDF.flax
(Stored with Git LFS)
Normal file
BIN
Content/Shaders/SDF.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Shaders/SSAO.flax
(Stored with Git LFS)
BIN
Content/Shaders/SSAO.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/SSR.flax
(Stored with Git LFS)
BIN
Content/Shaders/SSR.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Shadows.flax
(Stored with Git LFS)
BIN
Content/Shaders/Shadows.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
Binary file not shown.
@@ -2,9 +2,9 @@
|
||||
"Name": "Flax",
|
||||
"Version": {
|
||||
"Major": 1,
|
||||
"Minor": 8,
|
||||
"Revision": 2,
|
||||
"Build": 6512
|
||||
"Minor": 9,
|
||||
"Revision": 0,
|
||||
"Build": 6603
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using FlaxEditor.Scripting;
|
||||
@@ -94,30 +96,8 @@ public class AssetPickerValidator : IContentItemOwner
|
||||
/// </summary>
|
||||
public string SelectedPath
|
||||
{
|
||||
get
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
get => Utilities.Utils.ToPathProject(_selectedItem?.Path ?? _selected?.Path);
|
||||
set => SelectedItem = string.IsNullOrEmpty(value) ? null : Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -242,7 +222,7 @@ public class AssetPickerValidator : IContentItemOwner
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetPickerValidator"/> class.
|
||||
/// </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)
|
||||
{
|
||||
_type = assetType;
|
||||
|
||||
@@ -388,7 +388,7 @@ namespace FlaxEditor.Content
|
||||
{
|
||||
sb.Append("Type: ").Append(TypeDescription).AppendLine();
|
||||
if (File.Exists(Path))
|
||||
sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine();
|
||||
sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((ulong)new FileInfo(Path).Length)).AppendLine();
|
||||
sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine();
|
||||
}
|
||||
|
||||
|
||||
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>
|
||||
/// Determines whether [is virtual proxy].
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.</returns>
|
||||
public bool IsVirtualProxy()
|
||||
{
|
||||
return IsVirtual && CanExport == false;
|
||||
|
||||
@@ -31,6 +31,12 @@ namespace FlaxEditor.Content
|
||||
/// <param name="path">The path to the template</param>
|
||||
protected abstract void GetTemplatePath(out string path);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ContentItem ConstructItem(string path)
|
||||
{
|
||||
return new CSharpScriptItem(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Create(string outputPath, object arg)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,16 @@ namespace FlaxEditor.Content
|
||||
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>
|
||||
/// Gets a value indicating whether this proxy if for assets.
|
||||
/// </summary>
|
||||
|
||||
@@ -87,6 +87,12 @@ namespace FlaxEditor.Content
|
||||
return item is CppScriptItem;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ContentItem ConstructItem(string path)
|
||||
{
|
||||
return new CppScriptItem(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePaths(out string headerTemplate, out string sourceTemplate)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace FlaxEditor.Content
|
||||
return item is FileItem;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ContentItem ConstructItem(string path)
|
||||
{
|
||||
return new FileItem(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => string.Empty;
|
||||
|
||||
|
||||
@@ -94,7 +94,10 @@ namespace FlaxEditor.Content
|
||||
_preview.Model = (Model)request.Asset;
|
||||
_preview.Parent = guiRoot;
|
||||
_preview.SyncBackbufferSize();
|
||||
_preview.ViewportCamera.SetArcBallView(_preview.Model.GetBox());
|
||||
var bounds = _preview.Model.GetBox();
|
||||
var maxSize = Math.Max(0.001f, (float)bounds.Size.MaxValue);
|
||||
_preview.ViewportCamera.SetArcBallView(bounds);
|
||||
_preview.FarPlane = Mathf.Max(1000.0f, maxSize * 2 + 100.0f);
|
||||
|
||||
_preview.Task.OnDraw();
|
||||
}
|
||||
|
||||
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>
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
|
||||
iOSARM64 = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Windows (ARM64)
|
||||
/// </summary>
|
||||
API_ENUM(Attributes = "EditorDisplay(null, \"Windows ARM64\")")
|
||||
WindowsARM64 = 15,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -285,24 +291,22 @@ public:
|
||||
/// <summary>
|
||||
/// The total assets amount in the build.
|
||||
/// </summary>
|
||||
int32 TotalAssets;
|
||||
int32 TotalAssets = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The cooked assets (TotalAssets - CookedAssets is amount of reused cached assets).
|
||||
/// </summary>
|
||||
int32 CookedAssets;
|
||||
int32 CookedAssets = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The final output content size in MB.
|
||||
/// The final output content size (in bytes).
|
||||
/// </summary>
|
||||
int32 ContentSizeMB;
|
||||
uint64 ContentSize = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The asset type stats. Key is the asset typename, value is the stats container.
|
||||
/// </summary>
|
||||
Dictionary<String, AssetTypeStatistics> AssetStats;
|
||||
|
||||
Statistics();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -328,6 +332,11 @@ public:
|
||||
/// </summary>
|
||||
HashSet<Guid> Assets;
|
||||
|
||||
/// <summary>
|
||||
/// The final files collection to include in build (valid only after CollectAssetsStep).
|
||||
/// </summary>
|
||||
HashSet<String> Files;
|
||||
|
||||
struct BinaryModuleInfo
|
||||
{
|
||||
String Name;
|
||||
|
||||
@@ -148,6 +148,8 @@ const Char* ToString(const BuildPlatform platform)
|
||||
return TEXT("Mac ARM64");
|
||||
case BuildPlatform::iOSARM64:
|
||||
return TEXT("iOS ARM64");
|
||||
case BuildPlatform::WindowsARM64:
|
||||
return TEXT("Windows ARM64");
|
||||
default:
|
||||
return TEXT("");
|
||||
}
|
||||
@@ -202,13 +204,6 @@ bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& othe
|
||||
return Count > other.Count;
|
||||
}
|
||||
|
||||
CookingData::Statistics::Statistics()
|
||||
{
|
||||
TotalAssets = 0;
|
||||
CookedAssets = 0;
|
||||
ContentSizeMB = 0;
|
||||
}
|
||||
|
||||
CookingData::CookingData(const SpawnParams& params)
|
||||
: ScriptingObject(params)
|
||||
{
|
||||
@@ -307,6 +302,10 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
|
||||
platform = TEXT("iOS");
|
||||
architecture = TEXT("ARM64");
|
||||
break;
|
||||
case BuildPlatform::WindowsARM64:
|
||||
platform = TEXT("Windows");
|
||||
architecture = TEXT("ARM64");
|
||||
break;
|
||||
default:
|
||||
LOG(Fatal, "Unknown or unsupported build platform.");
|
||||
}
|
||||
@@ -393,6 +392,9 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
||||
case BuildPlatform::Windows64:
|
||||
result = New<WindowsPlatformTools>(ArchitectureType::x64);
|
||||
break;
|
||||
case BuildPlatform::WindowsARM64:
|
||||
result = New<WindowsPlatformTools>(ArchitectureType::ARM64);
|
||||
break;
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_UWP
|
||||
case BuildPlatform::UWPx86:
|
||||
@@ -554,7 +556,12 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
|
||||
switch (PLATFORM_TYPE)
|
||||
{
|
||||
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;
|
||||
case PlatformType::XboxOne:
|
||||
buildPlatform = BuildPlatform::XboxOne;
|
||||
|
||||
@@ -325,9 +325,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
|
||||
const auto buildSettings = BuildSettings::Get();
|
||||
if (buildSettings->SkipPackaging)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GameCooker::PackageFiles();
|
||||
|
||||
// Validate environment variables
|
||||
|
||||
@@ -146,7 +146,7 @@ bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* pla
|
||||
sb.Append(TEXT(" </ExecutableList>\n"));
|
||||
sb.AppendFormat(TEXT(" <ShellVisuals DefaultDisplayName=\"{0}\"\n"), gameSettings->ProductName);
|
||||
sb.AppendFormat(TEXT(" PublisherDisplayName=\"{0}\"\n"), platformSettings->PublisherDisplayName.HasChars() ? platformSettings->PublisherDisplayName : gameSettings->CompanyName);
|
||||
sb.AppendFormat(TEXT(" BackgroundColor=\"#{0}\"\n"), platformSettings->BackgroundColor.ToHexString());
|
||||
sb.AppendFormat(TEXT(" BackgroundColor=\"#{0}\"\n"), platformSettings->BackgroundColor.ToHexString().Left(6));
|
||||
sb.AppendFormat(TEXT(" ForegroundText=\"{0}\"\n"), platformSettings->ForegroundText);
|
||||
sb.Append(TEXT(" Square150x150Logo=\"Assets\\Square150x150Logo.png\"\n"));
|
||||
sb.Append(TEXT(" Square480x480Logo=\"Assets\\Square480x480Logo.png\"\n"));
|
||||
|
||||
@@ -10,47 +10,26 @@
|
||||
#include "Engine/Content/Assets/Shader.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)
|
||||
{
|
||||
LOG(Info, "Searching for assets to include in a build. Using {0} root assets.", data.RootAssets.Count());
|
||||
data.StepProgress(TEXT("Collecting assets"), 0);
|
||||
|
||||
// Initialize assets queue
|
||||
_assetsQueue.Clear();
|
||||
_assetsQueue.EnsureCapacity(1024);
|
||||
Array<Guid> assetsQueue;
|
||||
assetsQueue.Clear();
|
||||
assetsQueue.EnsureCapacity(1024);
|
||||
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
|
||||
_assetsQueue.Add(i->Item);
|
||||
assetsQueue.Add(i->Item);
|
||||
|
||||
// Iterate through the assets graph
|
||||
AssetInfo assetInfo;
|
||||
while (_assetsQueue.HasItems())
|
||||
Array<Guid> references;
|
||||
Array<String> files;
|
||||
while (assetsQueue.HasItems())
|
||||
{
|
||||
BUILD_STEP_CANCEL_CHECK;
|
||||
|
||||
const auto assetId = _assetsQueue.Dequeue();
|
||||
const Guid assetId = assetsQueue.Dequeue();
|
||||
|
||||
// Skip already processed or invalid assets
|
||||
if (!assetId.IsValid()
|
||||
@@ -69,14 +48,31 @@ bool CollectAssetsStep::Perform(CookingData& data)
|
||||
}
|
||||
|
||||
// Load asset
|
||||
const auto asset = Content::LoadAsync<Asset>(assetId);
|
||||
AssetReference<Asset> asset = Content::LoadAsync<Asset>(assetId);
|
||||
if (asset == nullptr)
|
||||
continue;
|
||||
|
||||
// Process that asset
|
||||
LOG_STR(Info, asset->GetPath());
|
||||
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();
|
||||
|
||||
@@ -12,15 +12,7 @@ class Asset;
|
||||
/// <seealso cref="GameCooker::BuildStep" />
|
||||
class CollectAssetsStep : public GameCooker::BuildStep
|
||||
{
|
||||
private:
|
||||
|
||||
Array<Guid> _assetsQueue;
|
||||
Array<Guid> _references;
|
||||
|
||||
bool Process(CookingData& data, Asset* asset);
|
||||
|
||||
public:
|
||||
|
||||
// [BuildStep]
|
||||
bool Perform(CookingData& data) override;
|
||||
};
|
||||
|
||||
@@ -447,6 +447,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
#if PLATFORM_TOOLS_WINDOWS
|
||||
case BuildPlatform::Windows32:
|
||||
case BuildPlatform::Windows64:
|
||||
case BuildPlatform::WindowsARM64:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_WINDOWS";
|
||||
const auto settings = WindowsPlatformSettings::Get();
|
||||
@@ -891,7 +892,6 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, JsonAssetBase*
|
||||
class PackageBuilder : public NonCopyable
|
||||
{
|
||||
private:
|
||||
|
||||
int32 _packageIndex;
|
||||
int32 MaxAssetsPerPackage;
|
||||
int32 MaxPackageSize;
|
||||
@@ -904,7 +904,6 @@ private:
|
||||
uint64 packagesSizeTotal;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PackageBuilder" /> class.
|
||||
/// </summary>
|
||||
@@ -933,7 +932,6 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
uint64 GetPackagesSizeTotal() const
|
||||
{
|
||||
return packagesSizeTotal;
|
||||
@@ -1042,8 +1040,11 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
float Step1ProgressEnd = 0.6f;
|
||||
String Step1Info = TEXT("Cooking assets");
|
||||
float Step2ProgressStart = Step1ProgressEnd;
|
||||
float Step2ProgressEnd = 0.9f;
|
||||
String Step2Info = TEXT("Packaging assets");
|
||||
float Step2ProgressEnd = 0.8f;
|
||||
String Step2Info = TEXT("Cooking files");
|
||||
float Step3ProgressStart = Step2ProgressStart;
|
||||
float Step3ProgressEnd = 0.9f;
|
||||
String Step3Info = TEXT("Packaging assets");
|
||||
|
||||
data.StepProgress(TEXT("Loading build cache"), 0);
|
||||
|
||||
@@ -1100,11 +1101,14 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
#endif
|
||||
int32 subStepIndex = 0;
|
||||
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)
|
||||
{
|
||||
BUILD_STEP_CANCEL_CHECK;
|
||||
|
||||
data.StepProgress(Step1Info, Math::Lerp(Step1ProgressStart, Step1ProgressEnd, static_cast<float>(subStepIndex++) / data.Assets.Count()));
|
||||
const Guid assetId = i->Item;
|
||||
|
||||
@@ -1184,6 +1188,35 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
// Save build cache header
|
||||
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
|
||||
{
|
||||
GameHeaderFlags gameFlags = GameHeaderFlags::None;
|
||||
@@ -1229,13 +1262,11 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
for (auto i = AssetsRegistry.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
BUILD_STEP_CANCEL_CHECK;
|
||||
|
||||
data.StepProgress(Step2Info, Math::Lerp(Step2ProgressStart, Step2ProgressEnd, static_cast<float>(subStepIndex++) / AssetsRegistry.Count()));
|
||||
data.StepProgress(Step3Info, Math::Lerp(Step3ProgressStart, Step3ProgressEnd, (float)subStepIndex++ / AssetsRegistry.Count()));
|
||||
const auto assetId = i->Key;
|
||||
|
||||
String cookedFilePath;
|
||||
cache.GetFilePath(assetId, cookedFilePath);
|
||||
|
||||
if (!FileSystem::FileExists(cookedFilePath))
|
||||
{
|
||||
LOG(Warning, "Missing cooked file for asset \'{0}\'", assetId);
|
||||
@@ -1253,12 +1284,12 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
return true;
|
||||
for (auto& e : data.Stats.AssetStats)
|
||||
e.Value.TypeName = e.Key;
|
||||
data.Stats.ContentSizeMB = static_cast<int32>(packageBuilder.GetPackagesSizeTotal() / (1024 * 1024));
|
||||
data.Stats.ContentSize += packageBuilder.GetPackagesSizeTotal();
|
||||
}
|
||||
|
||||
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.
|
||||
// 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
|
||||
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;
|
||||
data.Stats.AssetStats.GetValues(assetTypes);
|
||||
|
||||
@@ -73,6 +73,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
{
|
||||
case BuildPlatform::Windows32:
|
||||
case BuildPlatform::Windows64:
|
||||
case BuildPlatform::WindowsARM64:
|
||||
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
|
||||
break;
|
||||
case BuildPlatform::LinuxX64:
|
||||
@@ -159,7 +160,24 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("host/fxr") / version, srcDotnet / TEXT("host/fxr") / version, true);
|
||||
#else
|
||||
// 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;
|
||||
#endif
|
||||
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
|
||||
}
|
||||
if (failed)
|
||||
@@ -355,6 +373,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
data.AddRootEngineAsset(TEXT("Shaders/Sky"));
|
||||
data.AddRootEngineAsset(TEXT("Shaders/SSAO"));
|
||||
data.AddRootEngineAsset(TEXT("Shaders/SSR"));
|
||||
data.AddRootEngineAsset(TEXT("Shaders/SDF"));
|
||||
data.AddRootEngineAsset(TEXT("Shaders/VolumetricFog"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/DefaultMaterial"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/DefaultDeformableMaterial"));
|
||||
|
||||
@@ -392,6 +392,10 @@ namespace FlaxEditor.CustomEditors
|
||||
else if (Values.HasDefaultValue && CanRevertDefaultValue)
|
||||
color = Color.Yellow * 0.8f;
|
||||
LinkedLabel.HighlightStripColor = color;
|
||||
|
||||
// Grey out deprecated members
|
||||
if (Values.IsObsolete)
|
||||
LinkedLabel.TextColor = LinkedLabel.TextColorHighlighted = FlaxEngine.GUI.Style.Current.ForegroundGrey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
// Show instanced parameters to view/edit at runtime
|
||||
if (Values.IsSingleObject && Editor.Instance.StateMachine.IsPlayMode)
|
||||
{
|
||||
var group = layout.Group("Parameters");
|
||||
var group = SurfaceUtils.InitGraphParametersGroup(layout);
|
||||
group.Panel.Open(false);
|
||||
group.Panel.IndexInParent -= 2;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using FlaxEditor.Content;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Utilities;
|
||||
|
||||
namespace FlaxEditor.CustomEditors.Editors
|
||||
@@ -50,7 +51,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
if (HasDifferentTypes)
|
||||
return;
|
||||
Picker = layout.Custom<AssetPicker>().CustomControl;
|
||||
|
||||
var value = Values[0];
|
||||
_valueType = Values.Type.Type != typeof(object) || value == null ? Values.Type : TypeUtils.GetObjectType(value);
|
||||
var assetType = _valueType;
|
||||
@@ -58,37 +58,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
assetType = new ScriptType(typeof(Asset));
|
||||
else if (_valueType.Type != null && _valueType.Type.Name == typeof(JsonAssetReference<>).Name)
|
||||
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;
|
||||
ApplyAssetReferenceAttribute(Values, out var height, Picker.Validator);
|
||||
Picker.Height = height;
|
||||
Picker.SelectedItemChanged += OnSelectedItemChanged;
|
||||
}
|
||||
@@ -115,6 +86,37 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
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 />
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,6 +535,15 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
_groupsPool.Add(groups);
|
||||
}
|
||||
|
||||
internal static GroupElement OnGroup(LayoutElementsContainer layout, string name)
|
||||
{
|
||||
// Add new group
|
||||
var group = layout.Group(name);
|
||||
group.Panel.Tag = group;
|
||||
group.Panel.MouseButtonRightClicked += OnGroupPanelMouseButtonRightClicked;
|
||||
return group;
|
||||
}
|
||||
|
||||
internal static LayoutElementsContainer OnGroup(LayoutElementsContainer layout, EditorDisplayAttribute display)
|
||||
{
|
||||
if (display?.Group != null)
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
new OptionType("Linear Gradient", typeof(LinearGradientBrush)),
|
||||
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
||||
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
||||
new OptionType("Video", typeof(VideoBrush)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +33,25 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
names.Add(mapping.Name);
|
||||
}
|
||||
_comboBox.Items = names;
|
||||
if (Values[0] is InputEvent inputEvent && names.Contains(inputEvent.Name))
|
||||
var prev = GetValue();
|
||||
if (prev is InputEvent inputEvent && names.Contains(inputEvent.Name))
|
||||
_comboBox.SelectedItem = inputEvent.Name;
|
||||
else if (prev is string name && names.Contains(name))
|
||||
_comboBox.SelectedItem = name;
|
||||
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
}
|
||||
|
||||
private object GetValue()
|
||||
{
|
||||
if (Values[0] is InputEvent inputEvent)
|
||||
return inputEvent;
|
||||
if (Values[0] is string str)
|
||||
return str;
|
||||
if (Values.Type.Type == typeof(string))
|
||||
return string.Empty;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkedEditor)
|
||||
{
|
||||
var button = menu.AddButton("Set to null");
|
||||
@@ -46,7 +60,16 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
|
||||
private void OnSelectedIndexChanged(ComboBox comboBox)
|
||||
{
|
||||
SetValue(comboBox.SelectedItem == null ? null : new InputEvent(comboBox.SelectedItem));
|
||||
object value = null;
|
||||
if (comboBox.SelectedItem != null)
|
||||
{
|
||||
var prev = GetValue();
|
||||
if (prev is InputEvent)
|
||||
value = new InputEvent(comboBox.SelectedItem);
|
||||
else if (prev is string)
|
||||
value = comboBox.SelectedItem;
|
||||
}
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -59,8 +82,11 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Values[0] is InputEvent inputEvent && _comboBox.Items.Contains(inputEvent.Name))
|
||||
var prev = GetValue();
|
||||
if (prev is InputEvent inputEvent && _comboBox.Items.Contains(inputEvent.Name))
|
||||
_comboBox.SelectedItem = inputEvent.Name;
|
||||
else if (prev is string name && _comboBox.Items.Contains(name))
|
||||
_comboBox.SelectedItem = name;
|
||||
else
|
||||
_comboBox.SelectedItem = null;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace FlaxEditor.CustomEditors.Elements
|
||||
/// <summary>
|
||||
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
||||
/// </summary>
|
||||
[System.Obsolete("Deprecated in 1.4, use ValueBox instead")]
|
||||
[System.Obsolete("Use ValueBox instead")]
|
||||
public DoubleValueBox DoubleValue => ValueBox;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace FlaxEditor.CustomEditors.Elements
|
||||
/// <summary>
|
||||
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
||||
/// </summary>
|
||||
[System.Obsolete("Deprecated in 1.4, use ValueBox instead")]
|
||||
[System.Obsolete("Use ValueBox instead")]
|
||||
public FloatValueBox FloatValue => ValueBox;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -139,6 +139,11 @@ namespace FlaxEditor.CustomEditors
|
||||
/// </summary>
|
||||
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>
|
||||
/// Gets the values types array (without duplicates).
|
||||
/// </summary>
|
||||
@@ -160,6 +165,7 @@ namespace FlaxEditor.CustomEditors
|
||||
{
|
||||
Info = info;
|
||||
Type = Info.ValueType;
|
||||
IsObsolete = Info.HasAttribute(typeof(ObsoleteAttribute), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
using System.Threading.Tasks;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Content.Settings;
|
||||
using FlaxEditor.Content.Thumbnails;
|
||||
@@ -856,7 +857,7 @@ namespace FlaxEditor
|
||||
/// New asset types allowed to create.
|
||||
/// [Deprecated in v1.8]
|
||||
/// </summary>
|
||||
[Obsolete("Use CreateAsset with named tag.")]
|
||||
[Obsolete("Use CreateAsset with named tag instead")]
|
||||
public enum NewAssetType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -1037,7 +1038,7 @@ namespace FlaxEditor
|
||||
/// </summary>
|
||||
/// <param name="type">New asset type.</param>
|
||||
/// <param name="outputPath">Output asset path.</param>
|
||||
[Obsolete("Use CreateAsset with named tag.")]
|
||||
[Obsolete("Use CreateAsset with named tag instead")]
|
||||
public static bool CreateAsset(NewAssetType type, string outputPath)
|
||||
{
|
||||
// [Deprecated on 18.02.2024, expires on 18.02.2025]
|
||||
@@ -1345,20 +1346,33 @@ namespace FlaxEditor
|
||||
/// </summary>
|
||||
public void BuildAllMeshesSDF()
|
||||
{
|
||||
// TODO: async maybe with progress reporting?
|
||||
var models = new List<Model>();
|
||||
Scene.ExecuteOnGraph(node =>
|
||||
{
|
||||
if (node is StaticModelNode staticModelNode && staticModelNode.Actor is StaticModel staticModel)
|
||||
{
|
||||
if (staticModel.DrawModes.HasFlag(DrawPass.GlobalSDF) && staticModel.Model != null && !staticModel.Model.IsVirtual && staticModel.Model.SDF.Texture == null)
|
||||
var model = staticModel.Model;
|
||||
if (staticModel.DrawModes.HasFlag(DrawPass.GlobalSDF) &&
|
||||
model != null &&
|
||||
!models.Contains(model) &&
|
||||
!model.IsVirtual &&
|
||||
model.SDF.Texture == null)
|
||||
{
|
||||
Log("Generating SDF for " + staticModel.Model);
|
||||
if (!staticModel.Model.GenerateSDF())
|
||||
staticModel.Model.Save();
|
||||
models.Add(model);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
Task.Run(() =>
|
||||
{
|
||||
for (int i = 0; i < models.Count; i++)
|
||||
{
|
||||
var model = models[i];
|
||||
Log($"[{i}/{models.Count}] Generating SDF for {model}");
|
||||
if (!model.GenerateSDF())
|
||||
model.Save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.IO;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.GUI.Drag;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEditor.Utilities;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Utilities;
|
||||
@@ -151,7 +150,7 @@ namespace FlaxEditor.GUI
|
||||
TextAlignment.Center);
|
||||
Render2D.DrawText(
|
||||
style.FontSmall,
|
||||
$"{TypeUtils.GetTypeDisplayName(Validator.AssetType.Type)}",
|
||||
$"{Validator.AssetType.Type.GetTypeDisplayName()}",
|
||||
new Rectangle(button1Rect.Right + 2, ButtonsSize + 2, sizeForTextLeft, ButtonsSize),
|
||||
style.ForegroundGrey,
|
||||
TextAlignment.Near,
|
||||
@@ -180,7 +179,7 @@ namespace FlaxEditor.GUI
|
||||
TextAlignment.Center);
|
||||
Render2D.DrawText(
|
||||
style.FontSmall,
|
||||
$"{TypeUtils.GetTypeDisplayName(Validator.AssetType.Type)}",
|
||||
$"{Validator.AssetType.Type.GetTypeDisplayName()}",
|
||||
new Rectangle(button1Rect.Right + 2, ButtonsSize + 2, sizeForTextLeft, ButtonsSize),
|
||||
style.ForegroundGrey,
|
||||
TextAlignment.Near,
|
||||
@@ -204,7 +203,7 @@ namespace FlaxEditor.GUI
|
||||
TextAlignment.Center);
|
||||
Render2D.DrawText(
|
||||
style.FontSmall,
|
||||
$"{TypeUtils.GetTypeDisplayName(Validator.AssetType.Type)}",
|
||||
$"{Validator.AssetType.Type.GetTypeDisplayName()}",
|
||||
new Rectangle(button1Rect.Right + 2, ButtonsSize + 2, sizeForTextLeft, ButtonsSize),
|
||||
style.ForegroundGrey,
|
||||
TextAlignment.Near,
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace FlaxEditor.GUI.Docking
|
||||
{
|
||||
private DockPanel _panel;
|
||||
private double _dragEnterTime = -1;
|
||||
#if PLATFORM_WINDOWS
|
||||
private const bool HideTabForSingleTab = true;
|
||||
#else
|
||||
private const bool HideTabForSingleTab = false;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The is mouse down flag (left button).
|
||||
@@ -51,7 +56,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
public DockWindow StartDragAsyncWindow;
|
||||
|
||||
private Rectangle HeaderRectangle => new Rectangle(0, 0, Width, DockPanel.DefaultHeaderHeight);
|
||||
private bool IsSingleFloatingWindow => _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
|
||||
private bool IsSingleFloatingWindow => HideTabForSingleTab && _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DockPanelProxy"/> class.
|
||||
|
||||
@@ -610,7 +610,8 @@ Array<Guid> ManagedEditor::GetAssetReferences(const Guid& assetId)
|
||||
Array<Guid> result;
|
||||
if (auto* asset = Content::Load<Asset>(assetId))
|
||||
{
|
||||
asset->GetReferences(result);
|
||||
Array<String> files;
|
||||
asset->GetReferences(result, files);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -129,12 +129,9 @@ namespace FlaxEditor.Modules
|
||||
for (int i = 0; i < Proxy.Count; i++)
|
||||
{
|
||||
if (Proxy[i].IsProxyFor(item))
|
||||
{
|
||||
return Proxy[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -147,11 +144,8 @@ namespace FlaxEditor.Modules
|
||||
for (int i = 0; i < Proxy.Count; i++)
|
||||
{
|
||||
if (Proxy[i].IsProxyFor<T>())
|
||||
{
|
||||
return Proxy[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -164,17 +158,12 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
if (string.IsNullOrEmpty(extension))
|
||||
throw new ArgumentNullException();
|
||||
|
||||
extension = StringUtils.NormalizeExtension(extension);
|
||||
|
||||
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 null;
|
||||
}
|
||||
|
||||
@@ -189,29 +178,23 @@ namespace FlaxEditor.Modules
|
||||
for (int i = 0; i < Proxy.Count; i++)
|
||||
{
|
||||
if (Proxy[i] is AssetProxy proxy && proxy.AcceptsAsset(typeName, path))
|
||||
{
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the virtual proxy object from given path.
|
||||
/// <br></br>Useful if the asset that needs to be displayed is not a Flax asset but needs custom functionality.
|
||||
/// </summary>
|
||||
/// <param name="path">The asset path.</param>
|
||||
/// <returns>Asset proxy or null if not found.</returns>
|
||||
/// <returns>Asset proxy or null if cannot find.</returns>
|
||||
public AssetProxy GetAssetVirtualProxy(string path)
|
||||
{
|
||||
for (int i = 0; i < Proxy.Count; i++)
|
||||
{
|
||||
if (Proxy[i] is AssetProxy proxy && proxy.IsVirtualProxy() && path.EndsWith(proxy.FileExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1009,9 @@ namespace FlaxEditor.Modules
|
||||
item = proxy?.ConstructItem(path, assetInfo.TypeName, ref assetInfo.ID);
|
||||
if (item == null)
|
||||
{
|
||||
item = new FileItem(path);
|
||||
item = GetProxy(Path.GetExtension(path))?.ConstructItem(path);
|
||||
if (item == null)
|
||||
item = new FileItem(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1113,6 +1098,7 @@ namespace FlaxEditor.Modules
|
||||
Proxy.Add(new VisualScriptProxy());
|
||||
Proxy.Add(new BehaviorTreeProxy());
|
||||
Proxy.Add(new LocalizedStringTableProxy());
|
||||
Proxy.Add(new VideoProxy("mp4"));
|
||||
Proxy.Add(new WidgetProxy());
|
||||
Proxy.Add(new FileProxy());
|
||||
Proxy.Add(new SpawnableJsonAssetProxy<PhysicalMaterial>());
|
||||
|
||||
@@ -841,7 +841,6 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
// Open project, then close it
|
||||
Editor.OpenProject(Editor.GameProject.ProjectPath);
|
||||
Editor.Windows.MainWindow.Close(ClosingReason.User);
|
||||
}
|
||||
|
||||
private void OnMenuFileShowHide(Control control)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,11 +368,13 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
Title = "Sample Global SDF",
|
||||
Description = "Samples the Global SDF to get the distance to the closest surface (in world-space). Requires models SDF to be generated and checking `Enable Global SDF` in Graphics Settings.",
|
||||
Flags = NodeFlags.MaterialGraph | NodeFlags.ParticleEmitterGraph,
|
||||
Size = new Float2(200, 20),
|
||||
Size = new Float2(200, 40),
|
||||
DefaultValues = new object[] { 0 },
|
||||
Elements = new[]
|
||||
{
|
||||
NodeElementArchetype.Factory.Output(0, "Distance", typeof(float), 0),
|
||||
NodeElementArchetype.Factory.Input(0, "World Position", true, typeof(Float3), 1),
|
||||
NodeElementArchetype.Factory.Input(1, "Start Cascade", true, typeof(int), 2, 0),
|
||||
}
|
||||
},
|
||||
new NodeArchetype
|
||||
@@ -382,11 +384,13 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
Description = "Samples the Global SDF to get the gradient and distance to the closest surface (in world-space). Normalize gradient to get SDF surface normal vector. Requires models SDF to be generated and checking `Enable Global SDF` in Graphics Settings.",
|
||||
Flags = NodeFlags.MaterialGraph | NodeFlags.ParticleEmitterGraph,
|
||||
Size = new Float2(260, 40),
|
||||
DefaultValues = new object[] { 0 },
|
||||
Elements = new[]
|
||||
{
|
||||
NodeElementArchetype.Factory.Output(0, "Gradient", typeof(Float3), 0),
|
||||
NodeElementArchetype.Factory.Output(1, "Distance", typeof(float), 2),
|
||||
NodeElementArchetype.Factory.Input(0, "World Position", true, typeof(Float3), 1),
|
||||
NodeElementArchetype.Factory.Input(1, "Start Cascade", true, typeof(int), 3, 0),
|
||||
}
|
||||
},
|
||||
new NodeArchetype
|
||||
|
||||
@@ -104,6 +104,11 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
}
|
||||
|
||||
internal static GroupElement InitGraphParametersGroup(LayoutElementsContainer layout)
|
||||
{
|
||||
return CustomEditors.Editors.GenericEditor.OnGroup(layout, "Parameters");
|
||||
}
|
||||
|
||||
private sealed class DummyMaterialSurfaceOwner : IVisjectSurfaceOwner
|
||||
{
|
||||
public Asset SurfaceAsset => null;
|
||||
|
||||
@@ -146,19 +146,14 @@ namespace FlaxEditor.Utilities
|
||||
|
||||
/// <summary>
|
||||
/// Formats the amount of bytes to get a human-readable data size in bytes with abbreviation. Eg. 32 kB
|
||||
/// [Deprecated in v1.9]
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <returns>The formatted amount of bytes.</returns>
|
||||
[Obsolete("Use FormatBytesCount with ulong instead")]
|
||||
public static string FormatBytesCount(int bytes)
|
||||
{
|
||||
int order = 0;
|
||||
while (bytes >= 1024 && order < MemorySizePostfixes.Length - 1)
|
||||
{
|
||||
order++;
|
||||
bytes /= 1024;
|
||||
}
|
||||
|
||||
return string.Format("{0:0.##} {1}", bytes, MemorySizePostfixes[order]);
|
||||
return FormatBytesCount((ulong)bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -169,12 +164,15 @@ namespace FlaxEditor.Utilities
|
||||
public static string FormatBytesCount(ulong bytes)
|
||||
{
|
||||
int order = 0;
|
||||
ulong bytesPrev = bytes;
|
||||
while (bytes >= 1024 && order < MemorySizePostfixes.Length - 1)
|
||||
{
|
||||
bytesPrev = bytes;
|
||||
order++;
|
||||
bytes /= 1024;
|
||||
}
|
||||
|
||||
if (order >= 3) // GB or higher use up to 2 decimal places for more precision
|
||||
return string.Format("{0:0.##} {1}", FlaxEngine.Utils.RoundTo2DecimalPlaces(bytesPrev / 1024.0f), MemorySizePostfixes[order]);
|
||||
return string.Format("{0:0.##} {1}", bytes, MemorySizePostfixes[order]);
|
||||
}
|
||||
|
||||
@@ -1471,5 +1469,27 @@ namespace FlaxEditor.Utilities
|
||||
inputActions.Add(options => options.GenerateScriptsProject, () => Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync());
|
||||
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/SkyLight.h"
|
||||
#include "Engine/Level/Actors/SpotLight.h"
|
||||
#include "Engine/Video/VideoPlayer.h"
|
||||
|
||||
#define ICON_RADIUS 7.0f
|
||||
|
||||
@@ -283,6 +284,7 @@ bool ViewportIconsRendererService::Init()
|
||||
MAP_TYPE(Sky, Skybox);
|
||||
MAP_TYPE(SkyLight, SkyLight);
|
||||
MAP_TYPE(SpotLight, PointLight);
|
||||
MAP_TYPE(VideoPlayer, SceneAnimationPlayer);
|
||||
#undef MAP_TYPE
|
||||
|
||||
return false;
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
group.Label("Frames: " + info.FramesCount);
|
||||
group.Label("Channels: " + info.ChannelsCount);
|
||||
group.Label("Keyframes: " + info.KeyframesCount);
|
||||
group.Label("Memory Usage: " + Utilities.Utils.FormatBytesCount(info.MemoryUsage));
|
||||
group.Label("Memory Usage: " + Utilities.Utils.FormatBytesCount((ulong)info.MemoryUsage));
|
||||
}
|
||||
|
||||
base.Initialize(layout);
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
if (parameters.Length == 0)
|
||||
return;
|
||||
|
||||
var parametersGroup = layout.Group("Parameters");
|
||||
var parametersGroup = SurfaceUtils.InitGraphParametersGroup(layout);
|
||||
var settingButton = parametersGroup.AddSettingsButton();
|
||||
settingButton.Clicked += (image, button) => OnSettingsButtonClicked(image, button, proxy.Window);
|
||||
var baseMaterial = materialInstance.BaseMaterial;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Content.Import;
|
||||
using FlaxEditor.CustomEditors;
|
||||
@@ -11,6 +13,7 @@ using FlaxEditor.Viewport.Cameras;
|
||||
using FlaxEditor.Viewport.Previews;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Json;
|
||||
using FlaxEngine.Tools;
|
||||
using FlaxEngine.Utilities;
|
||||
using Object = FlaxEngine.Object;
|
||||
@@ -185,6 +188,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
// SDF
|
||||
{
|
||||
var group = layout.Group("SDF");
|
||||
var sdfOptions = proxy.Window._sdfOptions;
|
||||
|
||||
var sdf = proxy.Asset.SDF;
|
||||
if (sdf.Texture != null)
|
||||
@@ -204,11 +208,26 @@ namespace FlaxEditor.Windows.Assets
|
||||
resolution.ValueBox.BoxValueChanged += b => { proxy.Window._importSettings.Settings.SDFResolution = b.Value; };
|
||||
proxy.Window._importSettings.Settings.SDFResolution = sdf.ResolutionScale;
|
||||
|
||||
var backfacesThreshold = group.FloatValue("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
|
||||
var gpu = group.Checkbox("Bake on GPU", "If checked, SDF generation will be calculated using GPU on Compute Shader, otherwise CPU will use Job System. GPU generation is fast but result in artifacts in various meshes (eg. foliage).");
|
||||
gpu.CheckBox.Checked = sdfOptions.GPU;
|
||||
|
||||
var backfacesThresholdProp = group.AddPropertyItem("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
|
||||
var backfacesThreshold = backfacesThresholdProp.FloatValue();
|
||||
var backfacesThresholdLabel = backfacesThresholdProp.Labels.Last();
|
||||
backfacesThreshold.ValueBox.MinValue = 0.001f;
|
||||
backfacesThreshold.ValueBox.MaxValue = 1.0f;
|
||||
backfacesThreshold.ValueBox.Value = proxy.Window._backfacesThreshold;
|
||||
backfacesThreshold.ValueBox.BoxValueChanged += b => { proxy.Window._backfacesThreshold = b.Value; };
|
||||
backfacesThreshold.ValueBox.Value = sdfOptions.BackfacesThreshold;
|
||||
backfacesThreshold.ValueBox.BoxValueChanged += b => { proxy.Window._sdfOptions.BackfacesThreshold = b.Value; };
|
||||
|
||||
// Toggle Backfaces Threshold visibility (CPU-only option)
|
||||
gpu.CheckBox.StateChanged += c =>
|
||||
{
|
||||
proxy.Window._sdfOptions.GPU = c.Checked;
|
||||
backfacesThresholdLabel.Visible = !c.Checked;
|
||||
backfacesThreshold.ValueBox.Visible = !c.Checked;
|
||||
};
|
||||
backfacesThresholdLabel.Visible = !gpu.CheckBox.Checked;
|
||||
backfacesThreshold.ValueBox.Visible = !gpu.CheckBox.Checked;
|
||||
|
||||
var lodIndex = group.IntegerValue("LOD Index", "Index of the model Level of Detail to use for SDF data building. By default uses the lowest quality LOD for fast building.");
|
||||
lodIndex.IntValue.MinValue = 0;
|
||||
@@ -294,9 +313,22 @@ namespace FlaxEditor.Windows.Assets
|
||||
private void OnRebuildSDF()
|
||||
{
|
||||
var proxy = (MeshesPropertiesProxy)Values[0];
|
||||
proxy.Asset.GenerateSDF(proxy.Window._importSettings.Settings.SDFResolution, _sdfModelLodIndex.Value, true, proxy.Window._backfacesThreshold);
|
||||
proxy.Window.MarkAsEdited();
|
||||
Presenter.BuildLayoutOnUpdate();
|
||||
proxy.Window.Enabled = false;
|
||||
Task.Run(() =>
|
||||
{
|
||||
var sdfOptions = proxy.Window._sdfOptions;
|
||||
bool failed = proxy.Asset.GenerateSDF(proxy.Window._importSettings.Settings.SDFResolution, _sdfModelLodIndex.Value, true, sdfOptions.BackfacesThreshold, sdfOptions.GPU);
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
||||
{
|
||||
proxy.Window.Enabled = true;
|
||||
if (!failed)
|
||||
proxy.Window.MarkAsEdited();
|
||||
Presenter.BuildLayoutOnUpdate();
|
||||
|
||||
// Save some SDF options locally in the project cache
|
||||
proxy.Window.Editor.ProjectCache.SetCustomData(JsonSerializer.GetStringID(proxy.Window.Item.ID) + ".SDF", JsonSerializer.Serialize(sdfOptions));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void OnRemoveSDF()
|
||||
@@ -774,17 +806,33 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
}
|
||||
|
||||
private struct ModelSdfOptions
|
||||
{
|
||||
public bool GPU;
|
||||
public float BackfacesThreshold;
|
||||
}
|
||||
|
||||
private readonly ModelPreview _preview;
|
||||
private StaticModel _highlightActor;
|
||||
private MeshDataCache _meshData;
|
||||
private ModelImportSettings _importSettings = new ModelImportSettings();
|
||||
private float _backfacesThreshold = 0.6f;
|
||||
private ModelSdfOptions _sdfOptions;
|
||||
private ToolStripButton _showCurrentLODButton;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ModelWindow(Editor editor, AssetItem item)
|
||||
: base(editor, item)
|
||||
{
|
||||
// Try to restore SDF options from project cache (not saved in the asset)
|
||||
if (Editor.ProjectCache.TryGetCustomData(JsonSerializer.GetStringID(Item.ID) + ".SDF", out string sdOptionsStr))
|
||||
_sdfOptions = JsonSerializer.Deserialize<ModelSdfOptions>(sdOptionsStr);
|
||||
else
|
||||
_sdfOptions = new ModelSdfOptions
|
||||
{
|
||||
GPU = true,
|
||||
BackfacesThreshold = 0.6f,
|
||||
};
|
||||
|
||||
// Toolstrip
|
||||
_toolstrip.AddSeparator();
|
||||
_showCurrentLODButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Info64, () => _preview.ShowCurrentLOD = !_preview.ShowCurrentLOD).LinkTooltip("Show LOD statistics");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user