Compare commits
3 Commits
mac_change
...
master_fix
| Author | SHA1 | Date | |
|---|---|---|---|
| 824ff7050e | |||
| 042843fe42 | |||
| 8631b389c1 |
5
.github/workflows/build_linux.yml
vendored
5
.github/workflows/build_linux.yml
vendored
@@ -16,8 +16,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
|
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
@@ -45,7 +44,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev libwayland-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
|
|||||||
6
.github/workflows/cd.yml
vendored
6
.github/workflows/cd.yml
vendored
@@ -87,8 +87,7 @@ jobs:
|
|||||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
@@ -119,8 +118,7 @@ jobs:
|
|||||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
|
|||||||
3
.github/workflows/tests.yml
vendored
3
.github/workflows/tests.yml
vendored
@@ -28,8 +28,7 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8
|
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8
|
||||||
|
|||||||
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.
@@ -4,8 +4,8 @@
|
|||||||
#define MAX_LOCAL_LIGHTS 4
|
#define MAX_LOCAL_LIGHTS 4
|
||||||
@1// Forward Shading: Includes
|
@1// Forward Shading: Includes
|
||||||
#include "./Flax/LightingCommon.hlsl"
|
#include "./Flax/LightingCommon.hlsl"
|
||||||
#include "./Flax/ReflectionsCommon.hlsl"
|
|
||||||
#if USE_REFLECTIONS
|
#if USE_REFLECTIONS
|
||||||
|
#include "./Flax/ReflectionsCommon.hlsl"
|
||||||
#define MATERIAL_REFLECTIONS_SSR 1
|
#define MATERIAL_REFLECTIONS_SSR 1
|
||||||
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
||||||
#include "./Flax/SSR.hlsl"
|
#include "./Flax/SSR.hlsl"
|
||||||
@@ -14,13 +14,11 @@
|
|||||||
#include "./Flax/Lighting.hlsl"
|
#include "./Flax/Lighting.hlsl"
|
||||||
#include "./Flax/ShadowsSampling.hlsl"
|
#include "./Flax/ShadowsSampling.hlsl"
|
||||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||||
#include "./Flax/VolumetricFog.hlsl"
|
|
||||||
@2// Forward Shading: Constants
|
@2// Forward Shading: Constants
|
||||||
LightData DirectionalLight;
|
LightData DirectionalLight;
|
||||||
LightData SkyLight;
|
LightData SkyLight;
|
||||||
EnvProbeData EnvironmentProbe;
|
ProbeData EnvironmentProbe;
|
||||||
ExponentialHeightFogData ExponentialHeightFog;
|
ExponentialHeightFogData ExponentialHeightFog;
|
||||||
VolumetricFogData VolumetricFog;
|
|
||||||
float3 Dummy2;
|
float3 Dummy2;
|
||||||
uint LocalLightsCount;
|
uint LocalLightsCount;
|
||||||
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
||||||
@@ -30,14 +28,12 @@ TextureCube SkyLightTexture : register(t__SRV__);
|
|||||||
Buffer<float4> ShadowsBuffer : register(t__SRV__);
|
Buffer<float4> ShadowsBuffer : register(t__SRV__);
|
||||||
Texture2D<float> ShadowMap : register(t__SRV__);
|
Texture2D<float> ShadowMap : register(t__SRV__);
|
||||||
Texture3D VolumetricFogTexture : register(t__SRV__);
|
Texture3D VolumetricFogTexture : register(t__SRV__);
|
||||||
Texture2D PreIntegratedGF : register(t__SRV__);
|
|
||||||
@4// Forward Shading: Utilities
|
@4// Forward Shading: Utilities
|
||||||
// Public accessors for lighting data, use them as data binding might change but those methods will remain.
|
// Public accessors for lighting data, use them as data binding might change but those methods will remain.
|
||||||
LightData GetDirectionalLight() { return DirectionalLight; }
|
LightData GetDirectionalLight() { return DirectionalLight; }
|
||||||
LightData GetSkyLight() { return SkyLight; }
|
LightData GetSkyLight() { return SkyLight; }
|
||||||
EnvProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
|
ProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
|
||||||
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
|
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
|
||||||
VolumetricFogData GetVolumetricFog() { return VolumetricFog; }
|
|
||||||
uint GetLocalLightsCount() { return LocalLightsCount; }
|
uint GetLocalLightsCount() { return LocalLightsCount; }
|
||||||
LightData GetLocalLight(uint i) { return LocalLights[i]; }
|
LightData GetLocalLight(uint i) { return LocalLights[i]; }
|
||||||
@5// Forward Shading: Shaders
|
@5// Forward Shading: Shaders
|
||||||
@@ -112,8 +108,7 @@ void PS_Forward(
|
|||||||
|
|
||||||
// Calculate reflections
|
// Calculate reflections
|
||||||
#if USE_REFLECTIONS
|
#if USE_REFLECTIONS
|
||||||
float4 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness);
|
float3 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness).rgb;
|
||||||
reflections.rgb *= reflections.a;
|
|
||||||
|
|
||||||
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
||||||
// Screen Space Reflections
|
// Screen Space Reflections
|
||||||
@@ -121,7 +116,7 @@ void PS_Forward(
|
|||||||
Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR;
|
Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR;
|
||||||
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
||||||
float stepSize = ScreenSize.z; // 1 / screenWidth
|
float stepSize = ScreenSize.z; // 1 / screenWidth
|
||||||
float maxSamples = 50;
|
float maxSamples = 48;
|
||||||
float worldAntiSelfOcclusionBias = 0.1f;
|
float worldAntiSelfOcclusionBias = 0.1f;
|
||||||
float brdfBias = 0.82f;
|
float brdfBias = 0.82f;
|
||||||
float drawDistance = 5000.0f;
|
float drawDistance = 5000.0f;
|
||||||
@@ -129,7 +124,7 @@ void PS_Forward(
|
|||||||
if (hit.z > 0)
|
if (hit.z > 0)
|
||||||
{
|
{
|
||||||
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
||||||
reflections.rgb = lerp(reflections.rgb, screenColor, hit.z);
|
reflections = lerp(reflections, screenColor, hit.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to software tracing if possible
|
// Fallback to software tracing if possible
|
||||||
@@ -141,17 +136,17 @@ void PS_Forward(
|
|||||||
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
|
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
|
||||||
{
|
{
|
||||||
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
||||||
reflections.rgb = lerp(surfaceAtlas, float4(screenColor, 1), hit.z);
|
reflections = lerp(surfaceAtlas, float4(screenColor, 1), hit.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
light.rgb += reflections.rgb * GetReflectionSpecularLighting(PreIntegratedGF, ViewPos, gBuffer);
|
light.rgb += reflections * GetReflectionSpecularLighting(ViewPos, gBuffer) * light.a;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add lighting
|
// Add lighting (apply ambient occlusion)
|
||||||
output.rgb += light.rgb;
|
output.rgb += light.rgb * gBuffer.AO;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -163,13 +158,17 @@ void PS_Forward(
|
|||||||
#else
|
#else
|
||||||
float fogSceneDistance = gBuffer.ViewPos.z;
|
float fogSceneDistance = gBuffer.ViewPos.z;
|
||||||
#endif
|
#endif
|
||||||
float fogSkipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
|
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, fogSceneDistance);
|
||||||
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, fogSkipDistance, fogSceneDistance);
|
|
||||||
if (ExponentialHeightFog.VolumetricFogMaxDistance > 0)
|
if (ExponentialHeightFog.VolumetricFogMaxDistance > 0)
|
||||||
{
|
{
|
||||||
// Sample volumetric fog and mix it in
|
// Sample volumetric fog and mix it in
|
||||||
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
||||||
float4 volumetricFog = SampleVolumetricFog(VolumetricFogTexture, VolumetricFog, materialInput.WorldPosition - ViewPos, screenUV, TemporalAAJitter);
|
float3 viewVector = materialInput.WorldPosition - ViewPos;
|
||||||
|
float sceneDepth = length(viewVector);
|
||||||
|
float depthSlice = sceneDepth / ExponentialHeightFog.VolumetricFogMaxDistance;
|
||||||
|
float3 volumeUV = float3(screenUV, depthSlice);
|
||||||
|
float4 volumetricFog = VolumetricFogTexture.SampleLevel(SamplerLinearClamp, volumeUV, 0);
|
||||||
fog = CombineVolumetricFog(fog, volumetricFog);
|
fog = CombineVolumetricFog(fog, volumetricFog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ struct VertexOutput
|
|||||||
#endif
|
#endif
|
||||||
float4 ClipExtents : TEXCOORD3;
|
float4 ClipExtents : TEXCOORD3;
|
||||||
float2 ClipOrigin : TEXCOORD4;
|
float2 ClipOrigin : TEXCOORD4;
|
||||||
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
@@ -56,7 +55,6 @@ struct PixelInput
|
|||||||
#endif
|
#endif
|
||||||
float4 ClipExtents : TEXCOORD3;
|
float4 ClipExtents : TEXCOORD3;
|
||||||
float2 ClipOrigin : TEXCOORD4;
|
float2 ClipOrigin : TEXCOORD4;
|
||||||
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
@@ -69,7 +67,6 @@ struct MaterialInput
|
|||||||
float3 WorldPosition;
|
float3 WorldPosition;
|
||||||
float TwoSidedSign;
|
float TwoSidedSign;
|
||||||
float2 TexCoord;
|
float2 TexCoord;
|
||||||
float2 CustomData; // x-per-geometry type, y-features mask
|
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
half4 VertexColor;
|
half4 VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -87,7 +84,6 @@ MaterialInput GetMaterialInput(Render2DVertex input, VertexOutput output)
|
|||||||
MaterialInput result;
|
MaterialInput result;
|
||||||
result.WorldPosition = output.WorldPosition;
|
result.WorldPosition = output.WorldPosition;
|
||||||
result.TexCoord = output.TexCoord;
|
result.TexCoord = output.TexCoord;
|
||||||
result.CustomData = input.CustomDataAndClipOrigin.xy;
|
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = output.VertexColor;
|
result.VertexColor = output.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -107,7 +103,6 @@ MaterialInput GetMaterialInput(PixelInput input)
|
|||||||
MaterialInput result;
|
MaterialInput result;
|
||||||
result.WorldPosition = input.WorldPosition;
|
result.WorldPosition = input.WorldPosition;
|
||||||
result.TexCoord = input.TexCoord;
|
result.TexCoord = input.TexCoord;
|
||||||
result.CustomData = input.CustomData;
|
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = input.VertexColor;
|
result.VertexColor = input.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -234,7 +229,6 @@ VertexOutput VS_GUI(Render2DVertex input)
|
|||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = input.Color;
|
output.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
output.CustomData = input.CustomDataAndClipOrigin.xy;
|
|
||||||
output.ClipOrigin = input.CustomDataAndClipOrigin.zw;
|
output.ClipOrigin = input.CustomDataAndClipOrigin.zw;
|
||||||
output.ClipExtents = input.ClipExtents;
|
output.ClipExtents = input.ClipExtents;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "./Flax/Common.hlsl"
|
#include "./Flax/Common.hlsl"
|
||||||
#include "./Flax/MaterialCommon.hlsl"
|
#include "./Flax/MaterialCommon.hlsl"
|
||||||
#include "./Flax/GBufferCommon.hlsl"
|
#include "./Flax/GBufferCommon.hlsl"
|
||||||
#include "./Flax/VolumetricFog.hlsl"
|
|
||||||
@7
|
@7
|
||||||
|
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
@@ -22,7 +21,6 @@ float Dummy0;
|
|||||||
float VolumetricFogMaxDistance;
|
float VolumetricFogMaxDistance;
|
||||||
int ParticleStride;
|
int ParticleStride;
|
||||||
int ParticleIndex;
|
int ParticleIndex;
|
||||||
float4 GridSliceParameters;
|
|
||||||
@1META_CB_END
|
@1META_CB_END
|
||||||
|
|
||||||
// Particles attributes buffer
|
// Particles attributes buffer
|
||||||
@@ -204,19 +202,19 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
META_PS(true, FEATURE_LEVEL_SM5)
|
META_PS(true, FEATURE_LEVEL_SM5)
|
||||||
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
|
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
|
||||||
{
|
{
|
||||||
// Reproject grid position back to the screen and world space
|
|
||||||
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
|
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
|
||||||
float3 cellOffset = 0.5f;
|
float3 cellOffset = 0.5f;
|
||||||
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
|
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
|
||||||
float sceneDepth = GetDepthFromSlice(GridSliceParameters, gridCoordinate.z + cellOffset.z) / ViewFar;
|
float zSlice = gridCoordinate.z + cellOffset.z;
|
||||||
|
float sceneDepth = (zSlice / GridSize.z) * VolumetricFogMaxDistance / ViewFar;
|
||||||
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
|
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
|
||||||
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
||||||
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
||||||
wsPos.xyz /= wsPos.w;
|
float3 positionWS = wsPos.xyz / wsPos.w;
|
||||||
|
|
||||||
// Get material parameters
|
// Get material parameters
|
||||||
MaterialInput materialInput = (MaterialInput)0;
|
MaterialInput materialInput = (MaterialInput)0;
|
||||||
materialInput.WorldPosition = wsPos.xyz;
|
materialInput.WorldPosition = positionWS;
|
||||||
materialInput.TexCoord = input.Vertex.TexCoord;
|
materialInput.TexCoord = input.Vertex.TexCoord;
|
||||||
materialInput.ParticleIndex = ParticleIndex;
|
materialInput.ParticleIndex = ParticleIndex;
|
||||||
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
||||||
@@ -227,10 +225,9 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
|
|||||||
Material material = GetMaterialPS(materialInput);
|
Material material = GetMaterialPS(materialInput);
|
||||||
|
|
||||||
// Compute fog properties
|
// Compute fog properties
|
||||||
material.Opacity *= material.Mask;
|
|
||||||
float3 albedo = material.Color;
|
float3 albedo = material.Color;
|
||||||
float extinction = material.Opacity * 0.001f;
|
float extinction = material.Opacity * material.Mask * 0.001f;
|
||||||
float3 emission = material.Emissive * material.Opacity;
|
float3 emission = material.Emissive;
|
||||||
float3 scattering = albedo * extinction;
|
float3 scattering = albedo * extinction;
|
||||||
float absorption = max(0.0f, extinction - Luminance(scattering));
|
float absorption = max(0.0f, extinction - Luminance(scattering));
|
||||||
|
|
||||||
|
|||||||
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/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/ColorGrading.flax
(Stored with Git LFS)
BIN
Content/Shaders/ColorGrading.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Fog.flax
(Stored with Git LFS)
BIN
Content/Shaders/Fog.flax
(Stored with Git LFS)
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.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:615dff65b01507be6c4de722e126324aba20fc197f8e12dafaa94a05e46cba6e
|
oid sha256:0f34bf867df5f4296ca66ac691c2bca4efa168fb9e21ca4e613e8086669575cf
|
||||||
size 13222
|
size 13296
|
||||||
|
|||||||
BIN
Content/Shaders/GUI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GUI.flax
(Stored with Git LFS)
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:1f07ebb16820897e8598ae7a0627cb75b3d28e9dceea3ad4bd9ff543d5cdd01c
|
oid sha256:064f54786958f109222c49cbc0358ff4f345b30010fcd5e8cc1fab7bdc68c4fe
|
||||||
size 13979
|
size 13349
|
||||||
|
|||||||
BIN
Content/Shaders/Histogram.flax
(Stored with Git LFS)
BIN
Content/Shaders/Histogram.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/MultiScaler.flax
(Stored with Git LFS)
BIN
Content/Shaders/MultiScaler.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Reflections.flax
(Stored with Git LFS)
BIN
Content/Shaders/Reflections.flax
(Stored with Git LFS)
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/Sky.flax
(Stored with Git LFS)
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/TAA.flax
(Stored with Git LFS)
BIN
Content/Shaders/TAA.flax
(Stored with Git LFS)
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:706adde844360c2b0e65ecabaf1d2e2cc4eb4ac7ca9d483d0dd04ec8163b3d97
|
oid sha256:872ac3560279bfd0aeb989ebac1b49750dd142b985bc40058888dfd2b63fe9b2
|
||||||
size 13081
|
size 13214
|
||||||
|
|||||||
@@ -2,18 +2,17 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 12,
|
"Minor": 11,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6905
|
"Build": 6805
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
||||||
"GameTarget": "FlaxGame",
|
"GameTarget": "FlaxGame",
|
||||||
"EditorTarget": "FlaxEditor",
|
"EditorTarget": "FlaxEditor",
|
||||||
"Configuration": {
|
"Configuration": {
|
||||||
"UseCSharp": true,
|
"UseCSharp": true,
|
||||||
"UseLargeWorlds": false,
|
"UseLargeWorlds": false,
|
||||||
"UseDotNet": true,
|
"UseDotNet": true
|
||||||
"UseSDL": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">ALWAYS</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ cd "`dirname "$0"`"
|
|||||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --genproject "$@"
|
bash ./Development/Scripts/Mac/CallBuildTool.sh --genproject "$@"
|
||||||
|
|
||||||
# Build bindings for all editor configurations
|
# Build bindings for all editor configurations
|
||||||
#echo Building C# bindings...
|
echo Building C# bindings...
|
||||||
# TODO: Detect the correct architecture here
|
# TODO: Detect the correct architecture here
|
||||||
#Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor
|
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor
|
||||||
|
|||||||
@@ -187,11 +187,6 @@ namespace FlaxEditor.Content.Import
|
|||||||
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
||||||
_settings.Settings.Type = TextureFormatType.GrayScale;
|
_settings.Settings.Type = TextureFormatType.GrayScale;
|
||||||
}
|
}
|
||||||
else if (_settings.Settings.Type == TextureFormatType.ColorRGB)
|
|
||||||
{
|
|
||||||
// Blind guess that common color texture is sRGB
|
|
||||||
_settings.Settings.sRGB = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to restore target asset texture import options (useful for fast reimport)
|
// Try to restore target asset texture import options (useful for fast reimport)
|
||||||
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
if (data is DragDataFiles)
|
if (data is DragDataFiles)
|
||||||
return DragDropEffect.Copy;
|
return DragDropEffect.Copy;
|
||||||
return _dragOverItems?.Effect ?? DragDropEffect.None;
|
return _dragOverItems.Effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace FlaxEditor.Content
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string TypeDescription => Path.EndsWith(".h") || Path.EndsWith(".hpp") ? "C++ Header File" : "C++ Source Code";
|
public override string TypeDescription => Path.EndsWith(".h") ? "C++ Header File" : "C++ Source Code";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
||||||
|
|||||||
@@ -21,12 +21,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
if (Values.HasDifferentTypes == false)
|
if (Values.HasDifferentTypes == false)
|
||||||
{
|
{
|
||||||
var group = layout.Group("Probe");
|
var group = layout.Group("Bake");
|
||||||
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
||||||
_bake = group.Button("Bake").Button;
|
_bake = group.Button("Bake").Button;
|
||||||
_bake.Clicked += BakeButtonClicked;
|
_bake.Clicked += BakeButtonClicked;
|
||||||
var view = group.Button("View", "Opens the probe texture viewer");
|
|
||||||
view.Button.Clicked += OnViewButtonClicked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,14 +50,5 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnViewButtonClicked()
|
|
||||||
{
|
|
||||||
foreach (var value in Values)
|
|
||||||
{
|
|
||||||
if (value is EnvironmentProbe probe && probe.ProbeAsset)
|
|
||||||
Editor.Instance.ContentEditing.Open(probe.ProbeAsset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,12 +190,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
FindNewKeysCSharp(file, newKeys, allKeys);
|
FindNewKeysCSharp(file, newKeys, allKeys);
|
||||||
|
|
||||||
// C/C++
|
// C++
|
||||||
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.c", SearchOption.AllDirectories)).ToArray();
|
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories);
|
||||||
filesCount += files.Length;
|
filesCount += files.Length;
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
FindNewKeysCpp(file, newKeys, allKeys);
|
FindNewKeysCpp(file, newKeys, allKeys);
|
||||||
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray();
|
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories);
|
||||||
filesCount += files.Length;
|
filesCount += files.Length;
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
FindNewKeysCpp(file, newKeys, allKeys);
|
FindNewKeysCpp(file, newKeys, allKeys);
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
using FlaxEngine;
|
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Custom editor for <see cref="NavMeshBoundsVolume"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="ActorEditor" />
|
|
||||||
[CustomEditor(typeof(NavMeshBoundsVolume)), DefaultEditor]
|
|
||||||
internal class NavMeshBoundsVolumeEditor : ActorEditor
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
|
||||||
{
|
|
||||||
base.Initialize(layout);
|
|
||||||
|
|
||||||
if (Values.HasDifferentTypes == false)
|
|
||||||
{
|
|
||||||
var button = layout.Button("Build");
|
|
||||||
button.Button.Clicked += OnBuildClicked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBuildClicked()
|
|
||||||
{
|
|
||||||
foreach (var value in Values)
|
|
||||||
{
|
|
||||||
if (value is NavMeshBoundsVolume volume)
|
|
||||||
{
|
|
||||||
Navigation.BuildNavMesh(volume.Box, volume.Scene);
|
|
||||||
Editor.Instance.Scene.MarkSceneEdited(volume.Scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection.Emit;
|
||||||
using FlaxEditor.CustomEditors.GUI;
|
using FlaxEditor.CustomEditors.GUI;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|||||||
@@ -909,8 +909,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
settingsButton.Tag = script;
|
settingsButton.Tag = script;
|
||||||
settingsButton.Clicked += OnSettingsButtonClicked;
|
settingsButton.Clicked += OnSettingsButtonClicked;
|
||||||
|
|
||||||
// Adjust margin to not overlap with other ui elements in the header
|
group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2);
|
||||||
group.Panel.HeaderTextMargin = group.Panel.HeaderTextMargin with { Left = scriptDrag.Right - 12, Right = settingsButton.Width + Utilities.Constants.UIMargin };
|
|
||||||
group.Object(values, editor);
|
group.Object(values, editor);
|
||||||
// Remove drop down arrows and containment lines if no objects in the group
|
// Remove drop down arrows and containment lines if no objects in the group
|
||||||
if (group.Children.Count == 0)
|
if (group.Children.Count == 0)
|
||||||
|
|||||||
@@ -450,7 +450,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
protected bool NotNullItems;
|
protected bool NotNullItems;
|
||||||
|
|
||||||
private IntValueBox _sizeBox;
|
private IntValueBox _sizeBox;
|
||||||
private Label _label;
|
|
||||||
private Color _background;
|
private Color _background;
|
||||||
private int _elementsCount, _minCount, _maxCount;
|
private int _elementsCount, _minCount, _maxCount;
|
||||||
private bool _readOnly;
|
private bool _readOnly;
|
||||||
@@ -567,7 +566,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Parent = dropPanel,
|
Parent = dropPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
_label = new Label
|
var label = new Label
|
||||||
{
|
{
|
||||||
Text = "Size",
|
Text = "Size",
|
||||||
AnchorPreset = AnchorPresets.TopRight,
|
AnchorPreset = AnchorPresets.TopRight,
|
||||||
@@ -593,12 +592,11 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
panel.Panel.Offsets = new Margin(7, 7, 0, 0);
|
panel.Panel.Offsets = new Margin(7, 7, 0, 0);
|
||||||
panel.Panel.BackgroundColor = _background;
|
panel.Panel.BackgroundColor = _background;
|
||||||
var elementType = ElementType;
|
var elementType = ElementType;
|
||||||
var bindingAttr = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public;
|
|
||||||
bool single = elementType.IsPrimitive ||
|
bool single = elementType.IsPrimitive ||
|
||||||
elementType.Equals(new ScriptType(typeof(string))) ||
|
elementType.Equals(new ScriptType(typeof(string))) ||
|
||||||
elementType.IsEnum ||
|
elementType.IsEnum ||
|
||||||
(elementType.GetFields(bindingAttr).Length == 1 && elementType.GetProperties(bindingAttr).Length == 0) ||
|
(elementType.GetFields().Length == 1 && elementType.GetProperties().Length == 0) ||
|
||||||
(elementType.GetProperties(bindingAttr).Length == 1 && elementType.GetFields(bindingAttr).Length == 0) ||
|
(elementType.GetProperties().Length == 1 && elementType.GetFields().Length == 0) ||
|
||||||
elementType.Equals(new ScriptType(typeof(JsonAsset))) ||
|
elementType.Equals(new ScriptType(typeof(JsonAsset))) ||
|
||||||
elementType.Equals(new ScriptType(typeof(SettingsBase)));
|
elementType.Equals(new ScriptType(typeof(SettingsBase)));
|
||||||
if (_cachedDropPanels == null)
|
if (_cachedDropPanels == null)
|
||||||
@@ -674,8 +672,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Resize(Count + 1);
|
Resize(Count + 1);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout.ContainerControl.SizeChanged += OnLayoutSizeChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSetupContextMenu(ContextMenu menu, DropPanel panel)
|
private void OnSetupContextMenu(ContextMenu menu, DropPanel panel)
|
||||||
@@ -700,24 +696,10 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLayoutSizeChanged(Control control)
|
|
||||||
{
|
|
||||||
if (Layout.ContainerControl is DropPanel dropPanel)
|
|
||||||
{
|
|
||||||
// Hide "Size" text when array editor title overlaps
|
|
||||||
var headerTextSize = dropPanel.HeaderTextFont.GetFont().MeasureText(dropPanel.HeaderText);
|
|
||||||
if (headerTextSize.X + DropPanel.DropDownIconSize >= _label.Left)
|
|
||||||
_label.TextColor = _label.TextColorHighlighted = Color.Transparent;
|
|
||||||
else
|
|
||||||
_label.TextColor = _label.TextColorHighlighted = FlaxEngine.GUI.Style.Current.Foreground;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Deinitialize()
|
protected override void Deinitialize()
|
||||||
{
|
{
|
||||||
_sizeBox = null;
|
_sizeBox = null;
|
||||||
Layout.ContainerControl.SizeChanged -= OnLayoutSizeChanged;
|
|
||||||
|
|
||||||
base.Deinitialize();
|
base.Deinitialize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
return inputEvent;
|
return inputEvent;
|
||||||
if (Values[0] is string str)
|
if (Values[0] is string str)
|
||||||
return str;
|
return str;
|
||||||
if (Values.Type.Type == typeof(InputEvent))
|
|
||||||
return new InputEvent();
|
|
||||||
if (Values.Type.Type == typeof(string))
|
if (Values.Type.Type == typeof(string))
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ namespace FlaxEditor.CustomEditors.Elements
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var settingsButtonSize = Panel.HeaderHeight;
|
var settingsButtonSize = Panel.HeaderHeight;
|
||||||
Panel.HeaderTextMargin = Panel.HeaderTextMargin with { Right = settingsButtonSize + Utilities.Constants.UIMargin };
|
return new Image
|
||||||
; return new Image
|
|
||||||
{
|
{
|
||||||
TooltipText = "Settings",
|
TooltipText = "Settings",
|
||||||
AutoFocus = true,
|
AutoFocus = true,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ using FlaxEngine.Assertions;
|
|||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Interop;
|
using FlaxEngine.Interop;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
using FlaxEngine.Utilities;
|
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
@@ -1371,7 +1370,7 @@ namespace FlaxEditor
|
|||||||
public void BuildCSG()
|
public void BuildCSG()
|
||||||
{
|
{
|
||||||
var scenes = Level.Scenes;
|
var scenes = Level.Scenes;
|
||||||
scenes.ForEach(x => x.BuildCSG(0));
|
scenes.ToList().ForEach(x => x.BuildCSG(0));
|
||||||
Scene.MarkSceneEdited(scenes);
|
Scene.MarkSceneEdited(scenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1381,7 +1380,7 @@ namespace FlaxEditor
|
|||||||
public void BuildNavMesh()
|
public void BuildNavMesh()
|
||||||
{
|
{
|
||||||
var scenes = Level.Scenes;
|
var scenes = Level.Scenes;
|
||||||
Navigation.BuildNavMesh();
|
scenes.ToList().ForEach(x => Navigation.BuildNavMesh(x, 0));
|
||||||
Scene.MarkSceneEdited(scenes);
|
Scene.MarkSceneEdited(scenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -502,7 +502,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
if (base.OnKeyDown(key))
|
if (base.OnKeyDown(key))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Keyboard navigation around the menu
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case KeyboardKeys.ArrowDown:
|
case KeyboardKeys.ArrowDown:
|
||||||
@@ -527,20 +526,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyboardKeys.ArrowRight:
|
|
||||||
for (int i = 0; i < _panel.Children.Count; i++)
|
|
||||||
{
|
|
||||||
if (_panel.Children[i] is ContextMenuChildMenu item && item.Visible && item.IsFocused && !item.ContextMenu.IsOpened)
|
|
||||||
{
|
|
||||||
item.ShowChild(this);
|
|
||||||
item.ContextMenu._panel.Children.FirstOrDefault(x => x is ContextMenuButton && x.Visible)?.Focus();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KeyboardKeys.ArrowLeft:
|
|
||||||
ParentCM?.RootWindow.Focus();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
#if PLATFORM_WINDOWS || PLATFORM_SDL
|
#if PLATFORM_WINDOWS
|
||||||
#define USE_IS_FOREGROUND
|
#define USE_IS_FOREGROUND
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
#if PLATFORM_SDL
|
|
||||||
#define USE_SDL_WORKAROUNDS
|
|
||||||
#endif
|
|
||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -75,11 +72,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasChildCMOpened => _childCM != null;
|
public bool HasChildCMOpened => _childCM != null;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parent context menu (if exists).
|
|
||||||
/// </summary>
|
|
||||||
public ContextMenuBase ParentCM => _parentCM;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the topmost context menu.
|
/// Gets the topmost context menu.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -89,7 +81,9 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
{
|
{
|
||||||
var cm = this;
|
var cm = this;
|
||||||
while (cm._parentCM != null && cm._isSubMenu)
|
while (cm._parentCM != null && cm._isSubMenu)
|
||||||
|
{
|
||||||
cm = cm._parentCM;
|
cm = cm._parentCM;
|
||||||
|
}
|
||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,11 +108,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseInput = true;
|
public bool UseInput = true;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional flag that can disable UI navigation (tab/enter).
|
|
||||||
/// </summary>
|
|
||||||
public bool UseNavigation = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -133,7 +122,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shows the empty menu popup on a screen.
|
/// Shows the empty menu popup o na screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="control">The target control.</param>
|
/// <param name="control">The target control.</param>
|
||||||
/// <param name="area">The target control area to cover.</param>
|
/// <param name="area">The target control area to cover.</param>
|
||||||
@@ -268,9 +257,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
desc.AllowMaximize = false;
|
desc.AllowMaximize = false;
|
||||||
desc.AllowDragAndDrop = false;
|
desc.AllowDragAndDrop = false;
|
||||||
desc.IsTopmost = true;
|
desc.IsTopmost = true;
|
||||||
desc.Type = WindowType.Popup;
|
desc.IsRegularWindow = false;
|
||||||
desc.Parent = parentWin.Window;
|
|
||||||
desc.Title = "ContextMenu";
|
|
||||||
desc.HasSizingFrame = false;
|
desc.HasSizingFrame = false;
|
||||||
OnWindowCreating(ref desc);
|
OnWindowCreating(ref desc);
|
||||||
_window = Platform.CreateWindow(ref desc);
|
_window = Platform.CreateWindow(ref desc);
|
||||||
@@ -280,12 +267,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
_window.LostFocus += OnWindowLostFocus;
|
_window.LostFocus += OnWindowLostFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_IS_FOREGROUND && USE_SDL_WORKAROUNDS
|
|
||||||
// The focus between popup and parent windows doesn't change, force hide the popup when clicked on parent
|
|
||||||
parentWin.Window.MouseDown += OnWindowMouseDown;
|
|
||||||
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Attach to the window
|
// Attach to the window
|
||||||
_parentCM = parent as ContextMenuBase;
|
_parentCM = parent as ContextMenuBase;
|
||||||
Parent = _window.GUI;
|
Parent = _window.GUI;
|
||||||
@@ -460,17 +441,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_SDL_WORKAROUNDS
|
|
||||||
private void OnWindowGotFocus()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWindowMouseDown(ref Float2 mousePosition, MouseButton button, ref bool handled)
|
|
||||||
{
|
|
||||||
// The user clicked outside the popup window
|
|
||||||
Hide();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
private void OnWindowGotFocus()
|
private void OnWindowGotFocus()
|
||||||
{
|
{
|
||||||
var child = _childCM;
|
var child = _childCM;
|
||||||
@@ -484,7 +454,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
private void OnWindowLostFocus()
|
private void OnWindowLostFocus()
|
||||||
{
|
{
|
||||||
@@ -583,12 +552,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
// Let root context menu to check if none of the popup windows
|
// Let root context menu to check if none of the popup windows
|
||||||
if (_parentCM == null && UseVisibilityControl && !IsForeground)
|
if (_parentCM == null && UseVisibilityControl && !IsForeground)
|
||||||
{
|
{
|
||||||
#if USE_SDL_WORKAROUNDS
|
|
||||||
if (!IsMouseOver)
|
|
||||||
Hide();
|
|
||||||
#else
|
|
||||||
Hide();
|
Hide();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -630,21 +594,6 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
case KeyboardKeys.Escape:
|
case KeyboardKeys.Escape:
|
||||||
Hide();
|
Hide();
|
||||||
return true;
|
return true;
|
||||||
case KeyboardKeys.Return:
|
|
||||||
if (UseNavigation && Root?.FocusedControl != null)
|
|
||||||
{
|
|
||||||
Root.SubmitFocused();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KeyboardKeys.Tab:
|
|
||||||
if (UseNavigation && Root != null)
|
|
||||||
{
|
|
||||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
|
||||||
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
CloseMenuOnClick = false;
|
CloseMenuOnClick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ShowChild(ContextMenu parentContextMenu)
|
private void ShowChild(ContextMenu parentContextMenu)
|
||||||
{
|
{
|
||||||
// Hide parent CM popups and set itself as child
|
// Hide parent CM popups and set itself as child
|
||||||
var vAlign = parentContextMenu.ItemsAreaMargin.Top;
|
var vAlign = parentContextMenu.ItemsAreaMargin.Top;
|
||||||
|
|||||||
@@ -522,16 +522,6 @@ namespace FlaxEditor.GUI
|
|||||||
cm.AddButton("Show whole curve", _editor.ShowWholeCurve);
|
cm.AddButton("Show whole curve", _editor.ShowWholeCurve);
|
||||||
cm.AddButton("Reset view", _editor.ResetView);
|
cm.AddButton("Reset view", _editor.ResetView);
|
||||||
}
|
}
|
||||||
cm.AddSeparator();
|
|
||||||
var presetCm = cm.AddChildMenu("Apply preset");
|
|
||||||
foreach (var value in Enum.GetValues(typeof(CurvePreset)))
|
|
||||||
{
|
|
||||||
CurvePreset preset = (CurvePreset)value;
|
|
||||||
string name = Utilities.Utils.GetPropertyNameUI(preset.ToString());
|
|
||||||
var b = presetCm.ContextMenu.AddButton(name, () => _editor.ApplyPreset(preset));
|
|
||||||
b.Enabled = !(_editor is LinearCurveEditor<T> && (preset != CurvePreset.Constant && preset != CurvePreset.Linear));
|
|
||||||
}
|
|
||||||
|
|
||||||
_editor.OnShowContextMenu(cm, selectionCount);
|
_editor.OnShowContextMenu(cm, selectionCount);
|
||||||
cm.Show(this, location);
|
cm.Show(this, location);
|
||||||
}
|
}
|
||||||
@@ -629,33 +619,6 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of avaliable curve presets for the <see cref="CurveEditor{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public enum CurvePreset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A curve where every point has the same value.
|
|
||||||
/// </summary>
|
|
||||||
Constant,
|
|
||||||
/// <summary>
|
|
||||||
/// A curve linear curve.
|
|
||||||
/// </summary>
|
|
||||||
Linear,
|
|
||||||
/// <summary>
|
|
||||||
/// A curve that starts a slowly and then accelerates until the end.
|
|
||||||
/// </summary>
|
|
||||||
EaseIn,
|
|
||||||
/// <summary>
|
|
||||||
/// A curve that starts a steep and then flattens until the end.
|
|
||||||
/// </summary>
|
|
||||||
EaseOut,
|
|
||||||
/// <summary>
|
|
||||||
/// A combination of the <see cref="CurvePreset.EaseIn"/> and <see cref="CurvePreset.EaseOut"/> preset.
|
|
||||||
/// </summary>
|
|
||||||
Smoothstep
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnKeyframesDeselect(IKeyframesEditor editor)
|
public override void OnKeyframesDeselect(IKeyframesEditor editor)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,48 +19,6 @@ namespace FlaxEditor.GUI
|
|||||||
/// <seealso cref="CurveEditorBase" />
|
/// <seealso cref="CurveEditorBase" />
|
||||||
public abstract partial class CurveEditor<T> : CurveEditorBase where T : new()
|
public abstract partial class CurveEditor<T> : CurveEditorBase where T : new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Represents a single point in a <see cref="CurveEditorPreset"/>.
|
|
||||||
/// </summary>
|
|
||||||
protected struct CurvePresetPoint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The time.
|
|
||||||
/// </summary>
|
|
||||||
public float Time;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The value.
|
|
||||||
/// </summary>
|
|
||||||
public float Value;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The in tangent. Will be ignored in <see cref="LinearCurveEditor{T}"/>
|
|
||||||
/// </summary>
|
|
||||||
public float TangentIn;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The out tangent. Will be ignored in <see cref="LinearCurveEditor{T}"/>
|
|
||||||
/// </summary>
|
|
||||||
public float TangentOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A curve preset.
|
|
||||||
/// </summary>
|
|
||||||
protected struct CurveEditorPreset()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// If the tangents will be linear or smooth.
|
|
||||||
/// </summary>
|
|
||||||
public bool LinearTangents;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The points of the preset.
|
|
||||||
/// </summary>
|
|
||||||
public List<CurvePresetPoint> Points;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Popup : ContextMenuBase
|
private class Popup : ContextMenuBase
|
||||||
{
|
{
|
||||||
private CustomEditorPresenter _presenter;
|
private CustomEditorPresenter _presenter;
|
||||||
@@ -68,12 +26,11 @@ namespace FlaxEditor.GUI
|
|||||||
private List<int> _keyframeIndices;
|
private List<int> _keyframeIndices;
|
||||||
private bool _isDirty;
|
private bool _isDirty;
|
||||||
|
|
||||||
public Popup(CurveEditor<T> editor, object[] selection, List<int> keyframeIndices = null, float maxHeight = 140.0f)
|
public Popup(CurveEditor<T> editor, object[] selection, List<int> keyframeIndices = null, float height = 140.0f)
|
||||||
: this(editor, maxHeight)
|
: this(editor, height)
|
||||||
{
|
{
|
||||||
_presenter.Select(selection);
|
_presenter.Select(selection);
|
||||||
_presenter.OpenAllGroups();
|
_presenter.OpenAllGroups();
|
||||||
Size = new Float2(Size.X, Mathf.Min(_presenter.ContainerControl.Size.Y, maxHeight));
|
|
||||||
_keyframeIndices = keyframeIndices;
|
_keyframeIndices = keyframeIndices;
|
||||||
if (keyframeIndices != null && selection.Length != keyframeIndices.Count)
|
if (keyframeIndices != null && selection.Length != keyframeIndices.Count)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
@@ -212,7 +169,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (IsSelected)
|
if (IsSelected)
|
||||||
color = Editor.ContainsFocus ? style.SelectionBorder : Color.Lerp(style.ForegroundDisabled, style.SelectionBorder, 0.4f);
|
color = Editor.ContainsFocus ? style.SelectionBorder : Color.Lerp(style.ForegroundDisabled, style.SelectionBorder, 0.4f);
|
||||||
if (IsMouseOver)
|
if (IsMouseOver)
|
||||||
color *= 1.5f;
|
color *= 1.1f;
|
||||||
Render2D.FillRectangle(rect, color);
|
Render2D.FillRectangle(rect, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +285,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The keyframes size.
|
/// The keyframes size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected static readonly Float2 KeyframesSize = new Float2(8.0f);
|
protected static readonly Float2 KeyframesSize = new Float2(7.0f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The colors for the keyframe points.
|
/// The colors for the keyframe points.
|
||||||
@@ -369,63 +326,6 @@ namespace FlaxEditor.GUI
|
|||||||
private Color _labelsColor;
|
private Color _labelsColor;
|
||||||
private Font _labelsFont;
|
private Font _labelsFont;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preset values for <see cref="CurvePreset"/> to be applied to a <see cref="CurveEditor{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
protected Dictionary<CurvePreset, CurveEditorPreset> Presets = new Dictionary<CurvePreset, CurveEditorPreset>
|
|
||||||
{
|
|
||||||
{ CurvePreset.Constant, new CurveEditorPreset
|
|
||||||
{
|
|
||||||
LinearTangents = true,
|
|
||||||
Points = new List<CurvePresetPoint>
|
|
||||||
{
|
|
||||||
new CurvePresetPoint { Time = 0f, Value = 0.5f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
new CurvePresetPoint { Time = 1f, Value = 0.5f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ CurvePreset.EaseIn, new CurveEditorPreset
|
|
||||||
{
|
|
||||||
LinearTangents = false,
|
|
||||||
Points = new List<CurvePresetPoint>
|
|
||||||
{
|
|
||||||
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = -1.4f, TangentOut = 0f },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ CurvePreset.EaseOut, new CurveEditorPreset
|
|
||||||
{
|
|
||||||
LinearTangents = false,
|
|
||||||
Points = new List<CurvePresetPoint>
|
|
||||||
{
|
|
||||||
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 1.4f },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ CurvePreset.Linear, new CurveEditorPreset
|
|
||||||
{
|
|
||||||
LinearTangents = true,
|
|
||||||
Points = new List<CurvePresetPoint>
|
|
||||||
{
|
|
||||||
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ CurvePreset.Smoothstep, new CurveEditorPreset
|
|
||||||
{
|
|
||||||
LinearTangents = false,
|
|
||||||
Points = new List<CurvePresetPoint>
|
|
||||||
{
|
|
||||||
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The keyframe UI points.
|
/// The keyframe UI points.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -668,28 +568,6 @@ namespace FlaxEditor.GUI
|
|||||||
/// <param name="indicesToRemove">The list of indices of the keyframes to remove.</param>
|
/// <param name="indicesToRemove">The list of indices of the keyframes to remove.</param>
|
||||||
protected abstract void RemoveKeyframesInternal(HashSet<int> indicesToRemove);
|
protected abstract void RemoveKeyframesInternal(HashSet<int> indicesToRemove);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to convert a float to the type of the type wildcard of the curve editor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The float.</param>
|
|
||||||
/// <returns>The converted value.</returns>
|
|
||||||
public static object ConvertCurvePresetValueToCurveEditorType(float value)
|
|
||||||
{
|
|
||||||
if (typeof(T) == typeof(Float2))
|
|
||||||
return new Float2(value);
|
|
||||||
if (typeof(T) == typeof(Float3))
|
|
||||||
return new Float3(value);
|
|
||||||
if (typeof(T) == typeof(Float4))
|
|
||||||
return new Float4(value);
|
|
||||||
if (typeof(T) == typeof(Vector2))
|
|
||||||
return new Vector2(value);
|
|
||||||
if (typeof(T) == typeof(Vector3))
|
|
||||||
return new Vector3(value);
|
|
||||||
if (typeof(T) == typeof(Vector4))
|
|
||||||
return new Vector4(value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when showing a context menu. Can be used to add custom buttons with actions.
|
/// Called when showing a context menu. Can be used to add custom buttons with actions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -874,17 +752,6 @@ namespace FlaxEditor.GUI
|
|||||||
ShowCurve(false);
|
ShowCurve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies a <see cref="CurvePreset"/> to the curve editor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="preset">The preset.</param>
|
|
||||||
public virtual void ApplyPreset(CurvePreset preset)
|
|
||||||
{
|
|
||||||
// Remove existing keyframes
|
|
||||||
SelectAll();
|
|
||||||
RemoveKeyframes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Evaluate(out object result, float time, bool loop = false)
|
public override void Evaluate(out object result, float time, bool loop = false)
|
||||||
{
|
{
|
||||||
@@ -1161,31 +1028,6 @@ namespace FlaxEditor.GUI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool left = key == KeyboardKeys.ArrowLeft;
|
|
||||||
bool right = key == KeyboardKeys.ArrowRight;
|
|
||||||
bool up = key == KeyboardKeys.ArrowUp;
|
|
||||||
bool down = key == KeyboardKeys.ArrowDown;
|
|
||||||
|
|
||||||
if (left || right || up || down)
|
|
||||||
{
|
|
||||||
bool shift = Root.GetKey(KeyboardKeys.Shift);
|
|
||||||
bool alt = Root.GetKey(KeyboardKeys.Alt);
|
|
||||||
float deltaValue = 10f;
|
|
||||||
if (shift || alt)
|
|
||||||
deltaValue = shift ? 2.5f : 5f;
|
|
||||||
|
|
||||||
Float2 moveDelta = Float2.Zero;
|
|
||||||
if (left || right)
|
|
||||||
moveDelta.X = left ? -deltaValue : deltaValue;
|
|
||||||
if (up || down)
|
|
||||||
moveDelta.Y = up ? -deltaValue : deltaValue;
|
|
||||||
|
|
||||||
_contents.OnMoveStart(Float2.Zero);
|
|
||||||
_contents.OnMove(moveDelta);
|
|
||||||
_contents.OnMoveEnd(Float2.Zero);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1684,22 +1526,6 @@ namespace FlaxEditor.GUI
|
|||||||
_tangents[i].Visible = false;
|
_tangents[i].Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void ApplyPreset(CurvePreset preset)
|
|
||||||
{
|
|
||||||
base.ApplyPreset(preset);
|
|
||||||
|
|
||||||
CurveEditorPreset data = Presets[preset];
|
|
||||||
foreach (var point in data.Points)
|
|
||||||
{
|
|
||||||
float time = point.Time;
|
|
||||||
object value = ConvertCurvePresetValueToCurveEditorType((float)point.Value);
|
|
||||||
AddKeyframe(time, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowWholeCurve();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void DrawCurve(ref Rectangle viewRect)
|
protected override void DrawCurve(ref Rectangle viewRect)
|
||||||
{
|
{
|
||||||
@@ -2486,30 +2312,6 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void ApplyPreset(CurvePreset preset)
|
|
||||||
{
|
|
||||||
base.ApplyPreset(preset);
|
|
||||||
|
|
||||||
CurveEditorPreset data = Presets[preset];
|
|
||||||
|
|
||||||
foreach (var point in data.Points)
|
|
||||||
{
|
|
||||||
float time = point.Time;
|
|
||||||
object value = ConvertCurvePresetValueToCurveEditorType((float)point.Value);
|
|
||||||
object tangentIn = ConvertCurvePresetValueToCurveEditorType((float)point.TangentIn);
|
|
||||||
object tangentOut = ConvertCurvePresetValueToCurveEditorType((float)point.TangentOut);
|
|
||||||
|
|
||||||
AddKeyframe(time, value, tangentIn, tangentOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectAll();
|
|
||||||
if (data.LinearTangents)
|
|
||||||
SetTangentsLinear();
|
|
||||||
|
|
||||||
ShowWholeCurve();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void SetScaleInternal(ref Float2 scale)
|
protected override void SetScaleInternal(ref Float2 scale)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
private bool _useDynamicEditing;
|
private bool _useDynamicEditing;
|
||||||
private bool _activeEyedropper;
|
private bool _activeEyedropper;
|
||||||
private bool _canPassLastChangeEvent = true;
|
private bool _canPassLastChangeEvent = true;
|
||||||
private bool _linear;
|
|
||||||
private ColorValueBox.ColorPickerEvent _onChanged;
|
private ColorValueBox.ColorPickerEvent _onChanged;
|
||||||
private ColorValueBox.ColorPickerClosedEvent _onClosed;
|
private ColorValueBox.ColorPickerClosedEvent _onClosed;
|
||||||
|
|
||||||
@@ -57,7 +56,6 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
private Button _cCancel;
|
private Button _cCancel;
|
||||||
private Button _cOK;
|
private Button _cOK;
|
||||||
private Button _cEyedropper;
|
private Button _cEyedropper;
|
||||||
private Button _cLinearSRGB;
|
|
||||||
|
|
||||||
private List<Color> _savedColors = new List<Color>();
|
private List<Color> _savedColors = new List<Color>();
|
||||||
private List<Button> _savedColorButtons = new List<Button>();
|
private List<Button> _savedColorButtons = new List<Button>();
|
||||||
@@ -120,7 +118,6 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
_value = Color.Transparent;
|
_value = Color.Transparent;
|
||||||
_onChanged = colorChanged;
|
_onChanged = colorChanged;
|
||||||
_onClosed = pickerClosed;
|
_onClosed = pickerClosed;
|
||||||
_linear = !Graphics.GammaColorSpace;
|
|
||||||
|
|
||||||
// Get saved colors if they exist
|
// Get saved colors if they exist
|
||||||
if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out string savedColors))
|
if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out string savedColors))
|
||||||
@@ -230,25 +227,6 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
_cEyedropper.Width = _cEyedropper.Height;
|
_cEyedropper.Width = _cEyedropper.Height;
|
||||||
_cEyedropper.X -= _cEyedropper.Width;
|
_cEyedropper.X -= _cEyedropper.Width;
|
||||||
|
|
||||||
// Linear/sRGB toggle button
|
|
||||||
_cLinearSRGB = new Button(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin)
|
|
||||||
{
|
|
||||||
TooltipText = "Toggles between color preview in Linear and sRGB",
|
|
||||||
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.SplineAligned64),
|
|
||||||
BackgroundColor = _cEyedropper.BackgroundColor,
|
|
||||||
BackgroundColorHighlighted = _cEyedropper.BackgroundColorHighlighted,
|
|
||||||
BorderColor = _linear ? Color.Transparent : style.Foreground,
|
|
||||||
BorderColorHighlighted = _cEyedropper.BorderColorHighlighted,
|
|
||||||
Size = _cEyedropper.Size,
|
|
||||||
Parent = this,
|
|
||||||
Location = _cEyedropper.BottomLeft + new Float2(0, 4),
|
|
||||||
};
|
|
||||||
_cLinearSRGB.Clicked += () =>
|
|
||||||
{
|
|
||||||
_linear = !_linear;
|
|
||||||
_cLinearSRGB.BorderColor = _linear ? Color.Transparent : style.Foreground;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set initial color
|
// Set initial color
|
||||||
SelectedColor = initialValue;
|
SelectedColor = initialValue;
|
||||||
}
|
}
|
||||||
@@ -303,22 +281,16 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
if (_activeEyedropper)
|
if (_activeEyedropper)
|
||||||
{
|
{
|
||||||
_activeEyedropper = false;
|
_activeEyedropper = false;
|
||||||
if (colorPicked != Color.Transparent)
|
SelectedColor = colorPicked;
|
||||||
{
|
ScreenUtilities.PickColorDone -= OnColorPicked;
|
||||||
Color color = colorPicked;
|
|
||||||
if (_linear)
|
|
||||||
color = color.ToLinear();
|
|
||||||
SelectedColor = color;
|
|
||||||
}
|
|
||||||
Platform.PickScreenColorDone -= OnColorPicked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEyedropStart()
|
private void OnEyedropStart()
|
||||||
{
|
{
|
||||||
_activeEyedropper = true;
|
_activeEyedropper = true;
|
||||||
Platform.PickScreenColor();
|
ScreenUtilities.PickColor();
|
||||||
Platform.PickScreenColorDone += OnColorPicked;
|
ScreenUtilities.PickColorDone += OnColorPicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRGBAChanged()
|
private void OnRGBAChanged()
|
||||||
@@ -354,15 +326,8 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
// Update eye dropper tool
|
// Update eye dropper tool
|
||||||
if (_activeEyedropper)
|
if (_activeEyedropper)
|
||||||
{
|
{
|
||||||
// Try reading the color under the cursor in realtime if supported by the platform
|
|
||||||
Float2 mousePosition = Platform.MousePosition;
|
Float2 mousePosition = Platform.MousePosition;
|
||||||
Color color = Platform.GetScreenColorAt(mousePosition);
|
SelectedColor = ScreenUtilities.GetColorAt(mousePosition);
|
||||||
if (color != Color.Transparent)
|
|
||||||
{
|
|
||||||
if (_linear)
|
|
||||||
color = color.ToLinear();
|
|
||||||
SelectedColor = color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +388,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Render2D.FillRectangle(newRect, _linear ? _value.ToSRgb() : _value);
|
Render2D.FillRectangle(newRect, _value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -444,7 +409,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
{
|
{
|
||||||
// Cancel eye dropping
|
// Cancel eye dropping
|
||||||
_activeEyedropper = false;
|
_activeEyedropper = false;
|
||||||
Platform.PickScreenColorDone -= OnColorPicked;
|
ScreenUtilities.PickColorDone -= OnColorPicked;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -310,26 +310,6 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
Render2D.DrawRectangle(_slider1Rect, _isMouseDownSlider1 ? style.BackgroundSelected : Color.Black);
|
Render2D.DrawRectangle(_slider1Rect, _isMouseDownSlider1 ? style.BackgroundSelected : Color.Black);
|
||||||
Render2D.DrawRectangle(valueR, _isMouseDownSlider1 ? Color.White : Color.Gray);
|
Render2D.DrawRectangle(valueR, _isMouseDownSlider1 ? Color.White : Color.Gray);
|
||||||
|
|
||||||
// Draw checkerboard pattern to part of the alpha slider background
|
|
||||||
var alphaRect = _slider2Rect;
|
|
||||||
Render2D.FillRectangle(alphaRect, Color.White);
|
|
||||||
var smallRectSize = alphaRect.Width * 0.5f;
|
|
||||||
var numHor = Mathf.CeilToInt(alphaRect.Width / smallRectSize);
|
|
||||||
var numVer = Mathf.CeilToInt(alphaRect.Height / smallRectSize);
|
|
||||||
for (int i = 0; i < numHor; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < numVer; j++)
|
|
||||||
{
|
|
||||||
if ((i + j) % 2 == 0)
|
|
||||||
{
|
|
||||||
var rect = new Rectangle(alphaRect.X + smallRectSize * i, alphaRect.Y + smallRectSize * j, new Float2(smallRectSize));
|
|
||||||
Render2D.PushClip(alphaRect);
|
|
||||||
Render2D.FillRectangle(rect, Color.Gray);
|
|
||||||
Render2D.PopClip();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alpha
|
// Alpha
|
||||||
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
||||||
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
||||||
|
|||||||
545
Source/Editor/GUI/Docking/DockHintWindow.cs
Normal file
545
Source/Editor/GUI/Docking/DockHintWindow.cs
Normal file
@@ -0,0 +1,545 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.GUI.Docking
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class used to handle docking windows dragging and docking.
|
||||||
|
/// </summary>
|
||||||
|
public class DockHintWindow
|
||||||
|
{
|
||||||
|
private FloatWindowDockPanel _toMove;
|
||||||
|
|
||||||
|
private Float2 _dragOffset;
|
||||||
|
private Float2 _defaultWindowSize;
|
||||||
|
private Rectangle _rectDock;
|
||||||
|
private Rectangle _rectWindow;
|
||||||
|
private Float2 _mouse;
|
||||||
|
private DockState _toSet;
|
||||||
|
private DockPanel _toDock;
|
||||||
|
private bool _lateDragOffsetUpdate;
|
||||||
|
|
||||||
|
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
|
||||||
|
|
||||||
|
private DockHintWindow(FloatWindowDockPanel toMove)
|
||||||
|
{
|
||||||
|
_toMove = toMove;
|
||||||
|
_toSet = DockState.Float;
|
||||||
|
var window = toMove.Window.Window;
|
||||||
|
|
||||||
|
// Remove focus from drag target
|
||||||
|
_toMove.Focus();
|
||||||
|
_toMove.Defocus();
|
||||||
|
|
||||||
|
// Focus window
|
||||||
|
window.Focus();
|
||||||
|
|
||||||
|
// Check if window is maximized and restore window.
|
||||||
|
if (window.IsMaximized)
|
||||||
|
{
|
||||||
|
// Restore window and set position to mouse.
|
||||||
|
var mousePos = window.MousePosition;
|
||||||
|
var previousSize = window.Size;
|
||||||
|
window.Restore();
|
||||||
|
window.Position = Platform.MousePosition - mousePos * window.Size / previousSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate dragging offset and move window to the destination position
|
||||||
|
var mouseScreenPosition = Platform.MousePosition;
|
||||||
|
|
||||||
|
// If the _toMove window was not focused when initializing this window, the result vector only contains zeros
|
||||||
|
// and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler.
|
||||||
|
if (mouseScreenPosition != Float2.Zero)
|
||||||
|
CalculateDragOffset(mouseScreenPosition);
|
||||||
|
else
|
||||||
|
_lateDragOffsetUpdate = true;
|
||||||
|
|
||||||
|
// Get initial size
|
||||||
|
_defaultWindowSize = window.Size;
|
||||||
|
|
||||||
|
// Init proxy window
|
||||||
|
Proxy.Init(ref _defaultWindowSize);
|
||||||
|
|
||||||
|
// Bind events
|
||||||
|
Proxy.Window.MouseUp += OnMouseUp;
|
||||||
|
Proxy.Window.MouseMove += OnMouseMove;
|
||||||
|
Proxy.Window.LostFocus += OnLostFocus;
|
||||||
|
|
||||||
|
// Start tracking mouse
|
||||||
|
Proxy.Window.StartTrackingMouse(false);
|
||||||
|
|
||||||
|
// Update window GUI
|
||||||
|
Proxy.Window.GUI.PerformLayout();
|
||||||
|
|
||||||
|
// Update rectangles
|
||||||
|
UpdateRects();
|
||||||
|
|
||||||
|
// Hide base window
|
||||||
|
window.Hide();
|
||||||
|
|
||||||
|
// Enable hit window presentation
|
||||||
|
Proxy.Window.RenderingEnabled = true;
|
||||||
|
Proxy.Window.Show();
|
||||||
|
Proxy.Window.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases unmanaged and - optionally - managed resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// End tracking mouse
|
||||||
|
Proxy.Window.EndTrackingMouse();
|
||||||
|
|
||||||
|
// Disable rendering
|
||||||
|
Proxy.Window.RenderingEnabled = false;
|
||||||
|
|
||||||
|
// Unbind events
|
||||||
|
Proxy.Window.MouseUp -= OnMouseUp;
|
||||||
|
Proxy.Window.MouseMove -= OnMouseMove;
|
||||||
|
Proxy.Window.LostFocus -= OnLostFocus;
|
||||||
|
|
||||||
|
// Hide the proxy
|
||||||
|
Proxy.Hide();
|
||||||
|
|
||||||
|
if (_toMove == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if window won't be docked
|
||||||
|
if (_toSet == DockState.Float)
|
||||||
|
{
|
||||||
|
var window = _toMove.Window?.Window;
|
||||||
|
if (window == null)
|
||||||
|
return;
|
||||||
|
var mouse = Platform.MousePosition;
|
||||||
|
|
||||||
|
// Move base window
|
||||||
|
window.Position = mouse - _dragOffset;
|
||||||
|
|
||||||
|
// Show base window
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
|
||||||
|
|
||||||
|
// Check if window has only single tab
|
||||||
|
if (hasNoChildPanels && _toMove.TabsCount == 1)
|
||||||
|
{
|
||||||
|
// Dock window
|
||||||
|
_toMove.GetTab(0).Show(_toSet, _toDock);
|
||||||
|
}
|
||||||
|
// Check if dock as tab and has no child panels
|
||||||
|
else if (hasNoChildPanels && _toSet == DockState.DockFill)
|
||||||
|
{
|
||||||
|
// Dock all tabs
|
||||||
|
while (_toMove.TabsCount > 0)
|
||||||
|
{
|
||||||
|
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var selectedTab = _toMove.SelectedTab;
|
||||||
|
|
||||||
|
// Dock the first tab into the target location
|
||||||
|
var firstTab = _toMove.GetTab(0);
|
||||||
|
firstTab.Show(_toSet, _toDock);
|
||||||
|
|
||||||
|
// Dock rest of the tabs
|
||||||
|
while (_toMove.TabsCount > 0)
|
||||||
|
{
|
||||||
|
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep selected tab being selected
|
||||||
|
selectedTab?.SelectTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus target window
|
||||||
|
_toDock.Root.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
_toMove = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the new dragging hit window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toMove">Floating dock panel to move.</param>
|
||||||
|
/// <returns>The dock hint window object.</returns>
|
||||||
|
public static DockHintWindow Create(FloatWindowDockPanel toMove)
|
||||||
|
{
|
||||||
|
if (toMove == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
return new DockHintWindow(toMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the new dragging hit window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toMove">Dock window to move.</param>
|
||||||
|
/// <returns>The dock hint window object.</returns>
|
||||||
|
public static DockHintWindow Create(DockWindow toMove)
|
||||||
|
{
|
||||||
|
if (toMove == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
// Show floating
|
||||||
|
toMove.ShowFloating();
|
||||||
|
|
||||||
|
// Move window to the mouse position (with some offset for caption bar)
|
||||||
|
var window = (WindowRootControl)toMove.Root;
|
||||||
|
var mouse = Platform.MousePosition;
|
||||||
|
window.Window.Position = mouse - new Float2(8, 8);
|
||||||
|
|
||||||
|
// Get floating panel
|
||||||
|
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
|
||||||
|
|
||||||
|
return new DockHintWindow(floatingPanelToMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates window rectangle in the dock window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Window dock state.</param>
|
||||||
|
/// <param name="rect">Dock panel rectangle.</param>
|
||||||
|
/// <returns>Calculated window rectangle.</returns>
|
||||||
|
public static Rectangle CalculateDockRect(DockState state, ref Rectangle rect)
|
||||||
|
{
|
||||||
|
Rectangle result = rect;
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case DockState.DockFill:
|
||||||
|
result.Location.Y += Editor.Instance.Options.Options.Interface.TabHeight;
|
||||||
|
result.Size.Y -= Editor.Instance.Options.Options.Interface.TabHeight;
|
||||||
|
break;
|
||||||
|
case DockState.DockTop:
|
||||||
|
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
||||||
|
break;
|
||||||
|
case DockState.DockLeft:
|
||||||
|
result.Size.X *= DockPanel.DefaultSplitterValue;
|
||||||
|
break;
|
||||||
|
case DockState.DockBottom:
|
||||||
|
result.Location.Y += result.Size.Y * (1 - DockPanel.DefaultSplitterValue);
|
||||||
|
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
||||||
|
break;
|
||||||
|
case DockState.DockRight:
|
||||||
|
result.Location.X += result.Size.X * (1 - DockPanel.DefaultSplitterValue);
|
||||||
|
result.Size.X *= DockPanel.DefaultSplitterValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateDragOffset(Float2 mouseScreenPosition)
|
||||||
|
{
|
||||||
|
var baseWinPos = _toMove.Window.Window.Position;
|
||||||
|
_dragOffset = mouseScreenPosition - baseWinPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRects()
|
||||||
|
{
|
||||||
|
// Cache mouse position
|
||||||
|
_mouse = Platform.MousePosition;
|
||||||
|
|
||||||
|
// Check intersection with any dock panel
|
||||||
|
var uiMouse = _mouse;
|
||||||
|
_toDock = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
|
||||||
|
|
||||||
|
// Check dock state to use
|
||||||
|
bool showProxyHints = _toDock != null;
|
||||||
|
bool showBorderHints = showProxyHints;
|
||||||
|
bool showCenterHint = showProxyHints;
|
||||||
|
if (showProxyHints)
|
||||||
|
{
|
||||||
|
// If moved window has not only tabs but also child panels disable docking as tab
|
||||||
|
if (_toMove.ChildPanelsCount > 0)
|
||||||
|
showCenterHint = false;
|
||||||
|
|
||||||
|
// Disable docking windows with one or more dock panels inside
|
||||||
|
if (_toMove.ChildPanelsCount > 0)
|
||||||
|
showBorderHints = false;
|
||||||
|
|
||||||
|
// Get dock area
|
||||||
|
_rectDock = _toDock.DockAreaBounds;
|
||||||
|
|
||||||
|
// Cache dock rectangles
|
||||||
|
var size = _rectDock.Size;
|
||||||
|
var offset = _rectDock.Location;
|
||||||
|
var borderMargin = 4.0f;
|
||||||
|
var hintWindowsSize = Proxy.HintWindowsSize * Platform.DpiScale;
|
||||||
|
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
||||||
|
var centerX = size.X * 0.5f;
|
||||||
|
var centerY = size.Y * 0.5f;
|
||||||
|
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
|
||||||
|
// Hit test
|
||||||
|
DockState toSet = DockState.Float;
|
||||||
|
if (showBorderHints)
|
||||||
|
{
|
||||||
|
if (_rUpper.Contains(_mouse))
|
||||||
|
toSet = DockState.DockTop;
|
||||||
|
else if (_rBottom.Contains(_mouse))
|
||||||
|
toSet = DockState.DockBottom;
|
||||||
|
else if (_rLeft.Contains(_mouse))
|
||||||
|
toSet = DockState.DockLeft;
|
||||||
|
else if (_rRight.Contains(_mouse))
|
||||||
|
toSet = DockState.DockRight;
|
||||||
|
}
|
||||||
|
if (showCenterHint && _rCenter.Contains(_mouse))
|
||||||
|
toSet = DockState.DockFill;
|
||||||
|
_toSet = toSet;
|
||||||
|
|
||||||
|
// Show proxy hint windows
|
||||||
|
Proxy.Down.Position = _rBottom.Location;
|
||||||
|
Proxy.Left.Position = _rLeft.Location;
|
||||||
|
Proxy.Right.Position = _rRight.Location;
|
||||||
|
Proxy.Up.Position = _rUpper.Location;
|
||||||
|
Proxy.Center.Position = _rCenter.Location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_toSet = DockState.Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update proxy hint windows visibility
|
||||||
|
Proxy.Down.IsVisible = showProxyHints & showBorderHints;
|
||||||
|
Proxy.Left.IsVisible = showProxyHints & showBorderHints;
|
||||||
|
Proxy.Right.IsVisible = showProxyHints & showBorderHints;
|
||||||
|
Proxy.Up.IsVisible = showProxyHints & showBorderHints;
|
||||||
|
Proxy.Center.IsVisible = showProxyHints & showCenterHint;
|
||||||
|
|
||||||
|
// Calculate proxy/dock/window rectangles
|
||||||
|
if (_toDock == null)
|
||||||
|
{
|
||||||
|
// Floating window over nothing
|
||||||
|
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_toSet == DockState.Float)
|
||||||
|
{
|
||||||
|
// Floating window over dock panel
|
||||||
|
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use only part of the dock panel to show hint
|
||||||
|
_rectWindow = CalculateDockRect(_toSet, ref _rectDock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update proxy window
|
||||||
|
Proxy.Window.ClientBounds = _rectWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
||||||
|
{
|
||||||
|
if (button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMouseMove(ref Float2 mousePos)
|
||||||
|
{
|
||||||
|
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
|
||||||
|
if (_lateDragOffsetUpdate)
|
||||||
|
{
|
||||||
|
// Calculate dragging offset and move window to the destination position
|
||||||
|
CalculateDragOffset(mousePos);
|
||||||
|
|
||||||
|
// Reset state
|
||||||
|
_lateDragOffsetUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateRects();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLostFocus()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
|
||||||
|
/// </summary>
|
||||||
|
public static class Proxy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The drag proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Window;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The left hint proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Left;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The right hint proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Right;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The up hint proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Up;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The down hint proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Down;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The center hint proxy window.
|
||||||
|
/// </summary>
|
||||||
|
public static Window Center;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hint windows size.
|
||||||
|
/// </summary>
|
||||||
|
public const float HintWindowsSize = 32.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the hit proxy windows. Those windows are used to indicate drag target areas (left, right, top, bottom, etc.).
|
||||||
|
/// </summary>
|
||||||
|
public static void InitHitProxy()
|
||||||
|
{
|
||||||
|
CreateProxy(ref Left, "DockHint.Left");
|
||||||
|
CreateProxy(ref Right, "DockHint.Right");
|
||||||
|
CreateProxy(ref Up, "DockHint.Up");
|
||||||
|
CreateProxy(ref Down, "DockHint.Down");
|
||||||
|
CreateProxy(ref Center, "DockHint.Center");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the hint window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="initSize">Initial size of the proxy window.</param>
|
||||||
|
public static void Init(ref Float2 initSize)
|
||||||
|
{
|
||||||
|
if (Window == null)
|
||||||
|
{
|
||||||
|
var settings = CreateWindowSettings.Default;
|
||||||
|
settings.Title = "DockHint.Window";
|
||||||
|
settings.Size = initSize;
|
||||||
|
settings.AllowInput = true;
|
||||||
|
settings.AllowMaximize = false;
|
||||||
|
settings.AllowMinimize = false;
|
||||||
|
settings.HasBorder = false;
|
||||||
|
settings.HasSizingFrame = false;
|
||||||
|
settings.IsRegularWindow = false;
|
||||||
|
settings.SupportsTransparency = true;
|
||||||
|
settings.ShowInTaskbar = false;
|
||||||
|
settings.ShowAfterFirstPaint = false;
|
||||||
|
settings.IsTopmost = true;
|
||||||
|
|
||||||
|
Window = Platform.CreateWindow(ref settings);
|
||||||
|
Window.Opacity = 0.6f;
|
||||||
|
Window.GUI.BackgroundColor = Style.Current.Selection;
|
||||||
|
Window.GUI.AddChild<DragVisuals>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Resize proxy
|
||||||
|
Window.ClientSize = initSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitHitProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class DragVisuals : Control
|
||||||
|
{
|
||||||
|
public DragVisuals()
|
||||||
|
{
|
||||||
|
AnchorPreset = AnchorPresets.StretchAll;
|
||||||
|
Offsets = Margin.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateProxy(ref Window win, string name)
|
||||||
|
{
|
||||||
|
if (win != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var settings = CreateWindowSettings.Default;
|
||||||
|
settings.Title = name;
|
||||||
|
settings.Size = new Float2(HintWindowsSize * Platform.DpiScale);
|
||||||
|
settings.AllowInput = false;
|
||||||
|
settings.AllowMaximize = false;
|
||||||
|
settings.AllowMinimize = false;
|
||||||
|
settings.HasBorder = false;
|
||||||
|
settings.HasSizingFrame = false;
|
||||||
|
settings.IsRegularWindow = false;
|
||||||
|
settings.SupportsTransparency = true;
|
||||||
|
settings.ShowInTaskbar = false;
|
||||||
|
settings.ActivateWhenFirstShown = false;
|
||||||
|
settings.IsTopmost = true;
|
||||||
|
settings.ShowAfterFirstPaint = false;
|
||||||
|
|
||||||
|
win = Platform.CreateWindow(ref settings);
|
||||||
|
win.Opacity = 0.6f;
|
||||||
|
win.GUI.BackgroundColor = Style.Current.Selection;
|
||||||
|
win.GUI.AddChild<DragVisuals>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides proxy windows.
|
||||||
|
/// </summary>
|
||||||
|
public static void Hide()
|
||||||
|
{
|
||||||
|
HideProxy(ref Window);
|
||||||
|
HideProxy(ref Left);
|
||||||
|
HideProxy(ref Right);
|
||||||
|
HideProxy(ref Up);
|
||||||
|
HideProxy(ref Down);
|
||||||
|
HideProxy(ref Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HideProxy(ref Window win)
|
||||||
|
{
|
||||||
|
if (win)
|
||||||
|
{
|
||||||
|
win.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases proxy data and windows.
|
||||||
|
/// </summary>
|
||||||
|
public static void Dispose()
|
||||||
|
{
|
||||||
|
DisposeProxy(ref Window);
|
||||||
|
DisposeProxy(ref Left);
|
||||||
|
DisposeProxy(ref Right);
|
||||||
|
DisposeProxy(ref Up);
|
||||||
|
DisposeProxy(ref Down);
|
||||||
|
DisposeProxy(ref Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DisposeProxy(ref Window win)
|
||||||
|
{
|
||||||
|
if (win)
|
||||||
|
{
|
||||||
|
win.Close(ClosingReason.User);
|
||||||
|
win = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -469,7 +469,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
var childPanels = _childPanels.ToArray();
|
var childPanels = _childPanels.ToArray();
|
||||||
if (childPanels.Length != 0)
|
if (childPanels.Length != 0)
|
||||||
{
|
{
|
||||||
// Fallback: move tabs from child panels into this one.
|
// Move tabs from child panels into this one
|
||||||
DockWindow selectedTab = null;
|
DockWindow selectedTab = null;
|
||||||
foreach (var childPanel in childPanels)
|
foreach (var childPanel in childPanels)
|
||||||
{
|
{
|
||||||
@@ -490,8 +490,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
{
|
{
|
||||||
// Unlink splitter
|
// Unlink splitter
|
||||||
var splitterParent = splitter.Parent;
|
var splitterParent = splitter.Parent;
|
||||||
if (splitterParent == null)
|
Assert.IsNotNull(splitterParent);
|
||||||
return;
|
|
||||||
splitter.Parent = null;
|
splitter.Parent = null;
|
||||||
|
|
||||||
// Move controls from second split panel to the split panel parent
|
// Move controls from second split panel to the split panel parent
|
||||||
@@ -508,63 +507,17 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
splitter.Dispose();
|
splitter.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsMaster && _childPanels.Count != 0)
|
|
||||||
{
|
|
||||||
if (TryCollapseSplitter(_tabsProxy?.Parent as Panel))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!IsMaster)
|
else if (!IsMaster)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_childPanels.Count != 0)
|
|
||||||
{
|
|
||||||
if (TryCollapseSplitter(_tabsProxy?.Parent as Panel))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!IsMaster)
|
else if (!IsMaster)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool CollapseEmptyTabsProxy()
|
|
||||||
{
|
|
||||||
if (TabsCount == 0 && ChildPanelsCount > 0)
|
|
||||||
{
|
|
||||||
return TryCollapseSplitter(_tabsProxy?.Parent as Panel);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryCollapseSplitter(Panel removedPanelParent)
|
|
||||||
{
|
|
||||||
if (removedPanelParent == null)
|
|
||||||
return false;
|
|
||||||
if (!(removedPanelParent.Parent is SplitPanel tabsSplitter))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var splitterParent = tabsSplitter.Parent;
|
|
||||||
if (splitterParent == null)
|
|
||||||
return false;
|
|
||||||
tabsSplitter.Parent = null;
|
|
||||||
|
|
||||||
var scrPanel = removedPanelParent == tabsSplitter.Panel2 ? tabsSplitter.Panel1 : tabsSplitter.Panel2;
|
|
||||||
var srcPanelChildrenCount = scrPanel.ChildrenCount;
|
|
||||||
for (int i = srcPanelChildrenCount - 1; i >= 0 && scrPanel.ChildrenCount > 0; i--)
|
|
||||||
{
|
|
||||||
scrPanel.GetChild(i).Parent = splitterParent;
|
|
||||||
}
|
|
||||||
Assert.IsTrue(scrPanel.ChildrenCount == 0);
|
|
||||||
Assert.IsTrue(splitterParent.ChildrenCount == srcPanelChildrenCount);
|
|
||||||
|
|
||||||
tabsSplitter.Dispose();
|
|
||||||
if (_tabsProxy != null && _tabsProxy.Parent == removedPanelParent)
|
|
||||||
_tabsProxy = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void DockWindowInternal(DockState state, DockWindow window, bool autoSelect = true, float? splitterValue = null)
|
internal virtual void DockWindowInternal(DockState state, DockWindow window, bool autoSelect = true, float? splitterValue = null)
|
||||||
{
|
{
|
||||||
DockWindow(state, window, autoSelect, splitterValue);
|
DockWindow(state, window, autoSelect, splitterValue);
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
|
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
|
||||||
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
|
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
|
||||||
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
|
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
|
||||||
private readonly bool _hideTabForSingleTab = Utilities.Utils.HideSingleTabWindowTabBars();
|
#if PLATFORM_WINDOWS
|
||||||
|
private readonly bool _hideTabForSingleTab = Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
|
||||||
|
#else
|
||||||
|
private readonly bool _hideTabForSingleTab = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The is mouse down flag (left button).
|
/// The is mouse down flag (left button).
|
||||||
@@ -51,11 +55,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Float2 MousePosition = Float2.Minimum;
|
public Float2 MousePosition = Float2.Minimum;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The mouse position.
|
|
||||||
/// </summary>
|
|
||||||
public Float2 MouseStartPosition = Float2.Minimum;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start drag asynchronous window.
|
/// The start drag asynchronous window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -197,7 +196,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
|
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
|
||||||
{
|
{
|
||||||
// Create docking hint window but in an async manner
|
// Create docking hint window but in an async manner
|
||||||
WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
|
DockHintWindow.Create(_panel as FloatWindowDockPanel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -208,7 +207,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
_panel.SelectTab(index - 1);
|
_panel.SelectTab(index - 1);
|
||||||
|
|
||||||
// Create docking hint window
|
// Create docking hint window
|
||||||
WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
|
DockHintWindow.Create(win);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,7 +393,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
if (IsSingleFloatingWindow)
|
if (IsSingleFloatingWindow)
|
||||||
return base.OnMouseDown(location, button);
|
return base.OnMouseDown(location, button);
|
||||||
MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross);
|
MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross);
|
||||||
MouseStartPosition = location;
|
|
||||||
|
|
||||||
// Check buttons
|
// Check buttons
|
||||||
if (button == MouseButton.Left)
|
if (button == MouseButton.Left)
|
||||||
@@ -481,20 +479,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
StartDrag(MouseDownWindow);
|
StartDrag(MouseDownWindow);
|
||||||
MouseDownWindow = null;
|
MouseDownWindow = null;
|
||||||
}
|
}
|
||||||
// Check if single tab is tried to be moved
|
|
||||||
else if (MouseDownWindow != null && _panel.TabsCount <= 1)
|
|
||||||
{
|
|
||||||
if ((MousePosition - MouseStartPosition).Length > 3)
|
|
||||||
{
|
|
||||||
// Clear flag
|
|
||||||
IsMouseLeftButtonDown = false;
|
|
||||||
|
|
||||||
// Check tab under the mouse
|
|
||||||
if (!IsMouseDownOverCross && MouseDownWindow != null)
|
|
||||||
StartDrag(MouseDownWindow);
|
|
||||||
MouseDownWindow = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if has more than one tab to change order
|
// Check if has more than one tab to change order
|
||||||
else if (MouseDownWindow != null && _panel.TabsCount > 1)
|
else if (MouseDownWindow != null && _panel.TabsCount > 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -182,26 +182,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
|
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
|
||||||
/// <param name="position">Window location.</param>
|
/// <param name="position">Window location.</param>
|
||||||
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
|
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
|
||||||
{
|
|
||||||
CreateFloating(location, size, position, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates the window in a floating state.
|
|
||||||
/// </summary>
|
|
||||||
public void CreateFloating()
|
|
||||||
{
|
|
||||||
CreateFloating(Float2.Zero, Float2.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates the window in a floating state.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="location">Window location.</param>
|
|
||||||
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
|
|
||||||
/// <param name="position">Window location.</param>
|
|
||||||
/// <param name="showWindow">Window visibility.</param>
|
|
||||||
public void CreateFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent, bool showWindow = false)
|
|
||||||
{
|
{
|
||||||
Undock();
|
Undock();
|
||||||
|
|
||||||
@@ -219,17 +199,14 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
windowGUI.UnlockChildrenRecursive();
|
windowGUI.UnlockChildrenRecursive();
|
||||||
windowGUI.PerformLayout();
|
windowGUI.PerformLayout();
|
||||||
|
|
||||||
if (showWindow)
|
// Show
|
||||||
{
|
window.Show();
|
||||||
// Show
|
window.BringToFront();
|
||||||
window.Show();
|
window.Focus();
|
||||||
window.BringToFront();
|
OnShow();
|
||||||
window.Focus();
|
|
||||||
OnShow();
|
|
||||||
|
|
||||||
// Perform layout again
|
// Perform layout again
|
||||||
windowGUI.PerformLayout();
|
windowGUI.PerformLayout();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,42 +11,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
/// <seealso cref="DockPanel" />
|
/// <seealso cref="DockPanel" />
|
||||||
public class FloatWindowDockPanel : DockPanel
|
public class FloatWindowDockPanel : DockPanel
|
||||||
{
|
{
|
||||||
private class FloatWindowDecorations : WindowDecorations
|
|
||||||
{
|
|
||||||
private FloatWindowDockPanel _panel;
|
|
||||||
|
|
||||||
public FloatWindowDecorations(FloatWindowDockPanel panel)
|
|
||||||
: base(panel.RootWindow)
|
|
||||||
{
|
|
||||||
_panel = panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
|
||||||
{
|
|
||||||
if (Title.Bounds.Contains(location) && button == MouseButton.Left)
|
|
||||||
{
|
|
||||||
_panel.BeginDrag();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.OnMouseDown(location, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !PLATFORM_WINDOWS
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override WindowHitCodes OnHitTest(ref Float2 mouse)
|
|
||||||
{
|
|
||||||
var hit = base.OnHitTest(ref mouse);
|
|
||||||
if (hit == WindowHitCodes.Caption)
|
|
||||||
{
|
|
||||||
// Override the system behaviour when interacting with the caption area
|
|
||||||
hit = WindowHitCodes.Client;
|
|
||||||
}
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private MasterDockPanel _masterPanel;
|
private MasterDockPanel _masterPanel;
|
||||||
private WindowRootControl _window;
|
private WindowRootControl _window;
|
||||||
|
|
||||||
@@ -76,26 +40,6 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
Parent = window;
|
Parent = window;
|
||||||
_window.Window.Closing += OnClosing;
|
_window.Window.Closing += OnClosing;
|
||||||
_window.Window.LeftButtonHit += OnLeftButtonHit;
|
_window.Window.LeftButtonHit += OnLeftButtonHit;
|
||||||
|
|
||||||
if (Utilities.Utils.UseCustomWindowDecorations())
|
|
||||||
{
|
|
||||||
var decorations = Parent.AddChild(new FloatWindowDecorations(this));
|
|
||||||
decorations.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void PerformLayoutBeforeChildren()
|
|
||||||
{
|
|
||||||
base.PerformLayoutBeforeChildren();
|
|
||||||
|
|
||||||
var decorations = Parent.GetChild<FloatWindowDecorations>();
|
|
||||||
if (decorations != null)
|
|
||||||
{
|
|
||||||
// Apply offset for the title bar
|
|
||||||
foreach (var child in Children)
|
|
||||||
child.Bounds = child.Bounds with { Y = decorations.Height, Height = Parent.Height - decorations.Height };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -108,11 +52,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Create docking hint window
|
// Create docking hint window
|
||||||
Window dragSourceWindow = null;
|
DockHintWindow.Create(this);
|
||||||
#if !PLATFORM_SDL
|
|
||||||
dragSourceWindow = _window?.Window;
|
|
||||||
#endif
|
|
||||||
WindowDragHelper.StartDragging(this, dragSourceWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -131,33 +71,23 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
settings.Title = title;
|
settings.Title = title;
|
||||||
settings.Size = size;
|
settings.Size = size;
|
||||||
settings.Position = location;
|
settings.Position = location;
|
||||||
settings.MinimumSize = new Float2(100, 100);
|
settings.MinimumSize = new Float2(1);
|
||||||
settings.MaximumSize = Float2.Zero; // Unlimited size
|
settings.MaximumSize = Float2.Zero; // Unlimited size
|
||||||
settings.Fullscreen = false;
|
settings.Fullscreen = false;
|
||||||
settings.HasBorder = true;
|
settings.HasBorder = true;
|
||||||
#if PLATFORM_SDL
|
|
||||||
settings.SupportsTransparency = true;
|
|
||||||
#else
|
|
||||||
settings.SupportsTransparency = false;
|
settings.SupportsTransparency = false;
|
||||||
#endif
|
|
||||||
settings.ActivateWhenFirstShown = true;
|
settings.ActivateWhenFirstShown = true;
|
||||||
settings.AllowInput = true;
|
settings.AllowInput = true;
|
||||||
settings.AllowMinimize = true;
|
settings.AllowMinimize = true;
|
||||||
settings.AllowMaximize = true;
|
settings.AllowMaximize = true;
|
||||||
settings.AllowDragAndDrop = true;
|
settings.AllowDragAndDrop = true;
|
||||||
settings.IsTopmost = false;
|
settings.IsTopmost = false;
|
||||||
settings.Type = WindowType.Regular;
|
settings.IsRegularWindow = true;
|
||||||
settings.HasSizingFrame = true;
|
settings.HasSizingFrame = true;
|
||||||
settings.ShowAfterFirstPaint = false;
|
settings.ShowAfterFirstPaint = false;
|
||||||
settings.ShowInTaskbar = true;
|
settings.ShowInTaskbar = true;
|
||||||
settings.StartPosition = startPosition;
|
settings.StartPosition = startPosition;
|
||||||
|
|
||||||
if (Utilities.Utils.UseCustomWindowDecorations())
|
|
||||||
{
|
|
||||||
settings.HasBorder = false;
|
|
||||||
//settings.HasSizingFrame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
return Platform.CreateWindow(ref settings);
|
return Platform.CreateWindow(ref settings);
|
||||||
}
|
}
|
||||||
@@ -221,12 +151,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
base.OnSelectedTabChanged();
|
base.OnSelectedTabChanged();
|
||||||
|
|
||||||
if (_window != null && SelectedTab != null)
|
if (_window != null && SelectedTab != null)
|
||||||
{
|
|
||||||
_window.Title = SelectedTab.Title;
|
_window.Title = SelectedTab.Title;
|
||||||
var decorations = Parent.GetChild<FloatWindowDecorations>();
|
|
||||||
if (decorations != null)
|
|
||||||
decorations.PerformLayout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
|
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
|
||||||
{
|
{
|
||||||
// Check all floating windows
|
// Check all floating windows
|
||||||
|
// TODO: gather windows order and take it into account when performing test
|
||||||
for (int i = 0; i < FloatingPanels.Count; i++)
|
for (int i = 0; i < FloatingPanels.Count; i++)
|
||||||
{
|
{
|
||||||
var win = FloatingPanels[i];
|
var win = FloatingPanels[i];
|
||||||
@@ -93,44 +94,9 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Base
|
// Base
|
||||||
//if (!Root?.RootWindow.Window.IsFocused ?? false)
|
|
||||||
// return null;
|
|
||||||
return base.HitTest(ref position);
|
return base.HitTest(ref position);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs hit test over dock panel.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="position">Window space position to test.</param>
|
|
||||||
/// <param name="excluded">Floating window to omit during searching (and all docked to that one).</param>
|
|
||||||
/// <param name="hitResults">Results of the hit test</param>
|
|
||||||
/// <returns>True if any dock panels were hit, otherwise false.</returns>
|
|
||||||
public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
|
|
||||||
{
|
|
||||||
// Check all floating windows
|
|
||||||
List<DockPanel> results = new(FloatingPanels.Count);
|
|
||||||
for (int i = 0; i < FloatingPanels.Count; i++)
|
|
||||||
{
|
|
||||||
var win = FloatingPanels[i];
|
|
||||||
if (win.Visible && win != excluded)
|
|
||||||
{
|
|
||||||
var result = win.HitTest(ref position);
|
|
||||||
if (result != null)
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base
|
|
||||||
//if (!Root?.RootWindow.Window.IsFocused ?? false)
|
|
||||||
// return null;
|
|
||||||
var baseResult = base.HitTest(ref position);
|
|
||||||
if (baseResult != null)
|
|
||||||
results.Add(baseResult);
|
|
||||||
|
|
||||||
hitResults = results.ToArray();
|
|
||||||
return hitResults.Length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void LinkWindow(DockWindow window)
|
internal void LinkWindow(DockWindow window)
|
||||||
{
|
{
|
||||||
// Add to the windows list
|
// Add to the windows list
|
||||||
|
|||||||
@@ -1,514 +0,0 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using FlaxEngine;
|
|
||||||
using FlaxEngine.GUI;
|
|
||||||
|
|
||||||
namespace FlaxEditor.GUI.Docking
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Helper class used to handle docking windows dragging and docking.
|
|
||||||
/// </summary>
|
|
||||||
public class WindowDragHelper
|
|
||||||
{
|
|
||||||
private FloatWindowDockPanel _toMove;
|
|
||||||
|
|
||||||
private Float2 _dragOffset;
|
|
||||||
private Rectangle _rectDock;
|
|
||||||
private Float2 _mouse;
|
|
||||||
private DockState _toSet;
|
|
||||||
private DockPanel _toDock;
|
|
||||||
private Window _dragSourceWindow;
|
|
||||||
|
|
||||||
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
|
|
||||||
private Control _dockHintDown, _dockHintUp, _dockHintLeft, _dockHintRight, _dockHintCenter;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The hint control size.
|
|
||||||
/// </summary>
|
|
||||||
public const float HintControlSize = 48.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The opacity of the dragged window when hint controls are shown.
|
|
||||||
/// </summary>
|
|
||||||
public const float DragWindowOpacity = 0.4f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns true if any windows are being dragged.
|
|
||||||
/// </summary>
|
|
||||||
public static bool IsDragActive { get; private set; }
|
|
||||||
|
|
||||||
private WindowDragHelper(FloatWindowDockPanel toMove, Window dragSourceWindow)
|
|
||||||
{
|
|
||||||
IsDragActive = true;
|
|
||||||
_toMove = toMove;
|
|
||||||
_toSet = DockState.Float;
|
|
||||||
var window = toMove.Window.Window;
|
|
||||||
var mousePos = Platform.MousePosition;
|
|
||||||
|
|
||||||
// Check if window is maximized and restore window for correct dragging
|
|
||||||
if (window.IsMaximized)
|
|
||||||
{
|
|
||||||
var windowMousePos = mousePos - window.Position;
|
|
||||||
var previousSize = window.Size;
|
|
||||||
window.Restore();
|
|
||||||
window.Position = mousePos - windowMousePos * window.Size / previousSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When drag starts from a tabs the window might not be shown yet
|
|
||||||
if (!window.IsVisible)
|
|
||||||
{
|
|
||||||
window.Show();
|
|
||||||
window.Position = mousePos - new Float2(40, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind events
|
|
||||||
FlaxEngine.Scripting.Update += OnUpdate;
|
|
||||||
window.MouseUp += OnMouseUp;
|
|
||||||
#if !PLATFORM_SDL
|
|
||||||
window.StartTrackingMouse(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update rectangles
|
|
||||||
UpdateRects(mousePos);
|
|
||||||
|
|
||||||
// Ensure the dragged window stays on top of every other window
|
|
||||||
window.IsAlwaysOnTop = true;
|
|
||||||
|
|
||||||
_dragSourceWindow = dragSourceWindow;
|
|
||||||
if (_dragSourceWindow != null) // Detaching a tab from existing window
|
|
||||||
{
|
|
||||||
#if PLATFORM_SDL
|
|
||||||
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
|
|
||||||
#else
|
|
||||||
_dragOffset = mousePos - window.Position;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The mouse up event is sent to the source window on Windows
|
|
||||||
_dragSourceWindow.MouseUp += OnMouseUp;
|
|
||||||
|
|
||||||
// TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
|
|
||||||
var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
|
|
||||||
window.DoDragDrop(window.Title, _dragOffset, dragSourceWindowWayland);
|
|
||||||
#if !PLATFORM_SDL
|
|
||||||
_dragSourceWindow.BringToFront();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dragOffset = window.MousePosition;
|
|
||||||
window.DoDragDrop(window.Title, _dragOffset, window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases unmanaged and - optionally - managed resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
IsDragActive = false;
|
|
||||||
var window = _toMove?.Window?.Window;
|
|
||||||
|
|
||||||
// Unbind events
|
|
||||||
FlaxEngine.Scripting.Update -= OnUpdate;
|
|
||||||
if (window != null)
|
|
||||||
{
|
|
||||||
window.MouseUp -= OnMouseUp;
|
|
||||||
#if !PLATFORM_SDL
|
|
||||||
window.EndTrackingMouse();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (_dragSourceWindow != null)
|
|
||||||
_dragSourceWindow.MouseUp -= OnMouseUp;
|
|
||||||
|
|
||||||
RemoveDockHints();
|
|
||||||
|
|
||||||
if (_toMove == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (window != null)
|
|
||||||
{
|
|
||||||
window.Opacity = 1.0f;
|
|
||||||
window.IsAlwaysOnTop = false;
|
|
||||||
window.BringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if window won't be docked
|
|
||||||
if (_toSet == DockState.Float)
|
|
||||||
{
|
|
||||||
if (window == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Show base window
|
|
||||||
window.Show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
|
|
||||||
|
|
||||||
// Check if window has only single tab
|
|
||||||
if (hasNoChildPanels && _toMove.TabsCount == 1)
|
|
||||||
{
|
|
||||||
// Dock window
|
|
||||||
_toMove.GetTab(0).Show(_toSet, _toDock);
|
|
||||||
}
|
|
||||||
// Check if dock as tab and has no child panels
|
|
||||||
else if (hasNoChildPanels && _toSet == DockState.DockFill)
|
|
||||||
{
|
|
||||||
// Dock all tabs
|
|
||||||
while (_toMove.TabsCount > 0)
|
|
||||||
{
|
|
||||||
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var selectedTab = _toMove.SelectedTab;
|
|
||||||
|
|
||||||
// Dock the first tab into the target location
|
|
||||||
if (_toMove.TabsCount > 0)
|
|
||||||
{
|
|
||||||
var firstTab = _toMove.GetTab(0);
|
|
||||||
firstTab.Show(_toSet, _toDock);
|
|
||||||
|
|
||||||
// Dock rest of the tabs
|
|
||||||
while (_toMove.TabsCount > 0)
|
|
||||||
{
|
|
||||||
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep selected tab being selected
|
|
||||||
selectedTab?.SelectTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus target window
|
|
||||||
_toDock.Root.Focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
_toMove = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start dragging a floating dock panel.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="toMove">Floating dock panel to move.</param>
|
|
||||||
/// <param name="dragSourceWindow">The window where dragging started from.</param>
|
|
||||||
/// <returns>The window drag helper object.</returns>
|
|
||||||
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove, Window dragSourceWindow = null)
|
|
||||||
{
|
|
||||||
if (toMove == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
|
|
||||||
return new WindowDragHelper(toMove, dragSourceWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start dragging a docked panel into a floating window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="toMove">Dock window to move.</param>
|
|
||||||
/// <param name="dragSourceWindow">The window where dragging started from.</param>
|
|
||||||
/// <returns>The window drag helper object.</returns>
|
|
||||||
public static WindowDragHelper StartDragging(DockWindow toMove, Window dragSourceWindow)
|
|
||||||
{
|
|
||||||
if (toMove == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
|
|
||||||
// Create floating window
|
|
||||||
toMove.CreateFloating();
|
|
||||||
|
|
||||||
// Get floating panel
|
|
||||||
var window = (WindowRootControl)toMove.Root;
|
|
||||||
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
|
|
||||||
|
|
||||||
return new WindowDragHelper(floatingPanelToMove, dragSourceWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DragVisuals : Control
|
|
||||||
{
|
|
||||||
public DragVisuals()
|
|
||||||
{
|
|
||||||
AnchorPreset = AnchorPresets.StretchAll;
|
|
||||||
Offsets = Margin.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw()
|
|
||||||
{
|
|
||||||
base.Draw();
|
|
||||||
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddDockHints()
|
|
||||||
{
|
|
||||||
if (_toDock == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_toDock.RootWindow.Window != _dragSourceWindow)
|
|
||||||
_toDock.RootWindow.Window.MouseUp += OnMouseUp;
|
|
||||||
|
|
||||||
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
|
|
||||||
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
|
|
||||||
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
|
|
||||||
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
|
|
||||||
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
|
|
||||||
|
|
||||||
Control AddHintControl(Float2 pivot)
|
|
||||||
{
|
|
||||||
DragVisuals hintControl = _toDock.AddChild<DragVisuals>();
|
|
||||||
hintControl.Size = new Float2(HintControlSize);
|
|
||||||
hintControl.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
|
||||||
hintControl.Pivot = pivot;
|
|
||||||
hintControl.PivotRelative = true;
|
|
||||||
return hintControl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemoveDockHints()
|
|
||||||
{
|
|
||||||
if (_toDock == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_toDock.RootWindow.Window != _dragSourceWindow)
|
|
||||||
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
|
|
||||||
|
|
||||||
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
|
|
||||||
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
|
|
||||||
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
|
|
||||||
_dockHintRight?.Parent.RemoveChild(_dockHintRight);
|
|
||||||
_dockHintCenter?.Parent.RemoveChild(_dockHintCenter);
|
|
||||||
_dockHintDown = _dockHintUp = _dockHintLeft = _dockHintRight = _dockHintCenter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateRects(Float2 mousePos)
|
|
||||||
{
|
|
||||||
// Cache mouse position
|
|
||||||
_mouse = mousePos;
|
|
||||||
|
|
||||||
// Check intersection with any dock panel
|
|
||||||
DockPanel dockPanel = null;
|
|
||||||
if (_toMove.MasterPanel.HitTest(ref _mouse, _toMove, out var hitResults))
|
|
||||||
{
|
|
||||||
dockPanel = hitResults[0];
|
|
||||||
|
|
||||||
// Prefer panel which currently has focus
|
|
||||||
foreach (var hit in hitResults)
|
|
||||||
{
|
|
||||||
if (hit.RootWindow.Window.IsFocused)
|
|
||||||
{
|
|
||||||
dockPanel = hit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer panel in the same window we hit earlier
|
|
||||||
// TODO: this doesn't allow docking window into another floating window over the main window
|
|
||||||
/*if (dockPanel?.RootWindow != _toDock?.RootWindow)
|
|
||||||
{
|
|
||||||
foreach (var hit in hitResults)
|
|
||||||
{
|
|
||||||
if (hit.RootWindow == _toDock?.RootWindow)
|
|
||||||
{
|
|
||||||
dockPanel = _toDock;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dockPanel != _toDock)
|
|
||||||
{
|
|
||||||
RemoveDockHints();
|
|
||||||
_toDock = dockPanel;
|
|
||||||
AddDockHints();
|
|
||||||
|
|
||||||
// Make sure the all the dock hint areas are not under other windows
|
|
||||||
if (_toDock != Editor.Instance.UI.MasterPanel)
|
|
||||||
_toDock?.RootWindow.Window.BringToFront();
|
|
||||||
//_toDock?.RootWindow.Window.Focus();
|
|
||||||
|
|
||||||
#if PLATFORM_SDL
|
|
||||||
// Make the dragged window transparent when dock hints are visible
|
|
||||||
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
|
|
||||||
#else
|
|
||||||
// Bring the drop source always to the top
|
|
||||||
if (_dragSourceWindow != null)
|
|
||||||
_dragSourceWindow.BringToFront();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check dock state to use
|
|
||||||
bool showProxyHints = _toDock != null;
|
|
||||||
bool showBorderHints = showProxyHints;
|
|
||||||
bool showCenterHint = showProxyHints;
|
|
||||||
Control hoveredHintControl = null;
|
|
||||||
Float2 hoveredLocationOffset = Float2.Zero;
|
|
||||||
Float2 hoveredSizeOverride = Float2.Zero;
|
|
||||||
DockState prevToSet = _toSet;
|
|
||||||
float hoveredMargin = 1.0f;
|
|
||||||
if (showProxyHints)
|
|
||||||
{
|
|
||||||
// If moved window has not only tabs but also child panels disable docking as tab
|
|
||||||
if (_toMove.ChildPanelsCount > 0)
|
|
||||||
showCenterHint = false;
|
|
||||||
|
|
||||||
// Disable docking windows with one or more dock panels inside
|
|
||||||
if (_toMove.ChildPanelsCount > 0)
|
|
||||||
showBorderHints = false;
|
|
||||||
|
|
||||||
// Get dock area
|
|
||||||
_rectDock = _toDock.DockAreaBounds;
|
|
||||||
|
|
||||||
// Cache dock rectangles
|
|
||||||
var size = _rectDock.Size / Platform.DpiScale;
|
|
||||||
var offset = _toDock.PointFromScreen(_rectDock.Location);
|
|
||||||
var borderMargin = 10.0f;
|
|
||||||
var hintWindowsSize = HintControlSize;
|
|
||||||
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
|
||||||
var hintPreviewSize = new Float2(Math.Max(HintControlSize * 2, size.X * 0.5f), Math.Max(HintControlSize * 2, size.Y * 0.5f));
|
|
||||||
var centerX = size.X * 0.5f;
|
|
||||||
var centerY = size.Y * 0.5f;
|
|
||||||
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
|
|
||||||
// Hit test, and calculate the approximation for filled area when hovered over the hint
|
|
||||||
var toSet = DockState.Float;
|
|
||||||
var hintTestPoint = _toDock.PointFromScreen(_mouse);
|
|
||||||
if (showBorderHints)
|
|
||||||
{
|
|
||||||
if (_rUpper.Contains(ref hintTestPoint))
|
|
||||||
{
|
|
||||||
toSet = DockState.DockTop;
|
|
||||||
hoveredHintControl = _dockHintUp;
|
|
||||||
hoveredSizeOverride = new Float2(size.X, size.Y * DockPanel.DefaultSplitterValue);
|
|
||||||
hoveredLocationOffset.Y -= borderMargin - hoveredMargin;
|
|
||||||
}
|
|
||||||
else if (_rBottom.Contains(ref hintTestPoint))
|
|
||||||
{
|
|
||||||
toSet = DockState.DockBottom;
|
|
||||||
hoveredHintControl = _dockHintDown;
|
|
||||||
hoveredSizeOverride = new Float2(size.X, size.Y * DockPanel.DefaultSplitterValue);
|
|
||||||
hoveredLocationOffset.Y += borderMargin - hoveredMargin;
|
|
||||||
}
|
|
||||||
else if (_rLeft.Contains(ref hintTestPoint))
|
|
||||||
{
|
|
||||||
toSet = DockState.DockLeft;
|
|
||||||
hoveredHintControl = _dockHintLeft;
|
|
||||||
hoveredSizeOverride = new Float2(size.X * DockPanel.DefaultSplitterValue, size.Y);
|
|
||||||
hoveredLocationOffset.X -= borderMargin - hoveredMargin;
|
|
||||||
}
|
|
||||||
else if (_rRight.Contains(ref hintTestPoint))
|
|
||||||
{
|
|
||||||
toSet = DockState.DockRight;
|
|
||||||
hoveredHintControl = _dockHintRight;
|
|
||||||
hoveredSizeOverride = new Float2(size.X * DockPanel.DefaultSplitterValue, size.Y);
|
|
||||||
hoveredLocationOffset.X += borderMargin - hoveredMargin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (showCenterHint && _rCenter.Contains(ref hintTestPoint))
|
|
||||||
{
|
|
||||||
toSet = DockState.DockFill;
|
|
||||||
hoveredHintControl = _dockHintCenter;
|
|
||||||
hoveredSizeOverride = new Float2(size.X, size.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
_toSet = toSet;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_toSet = DockState.Float;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sizes and opacity of hint controls
|
|
||||||
if (_toDock != null)
|
|
||||||
{
|
|
||||||
var mainColor = Style.Current.Selection;
|
|
||||||
if (hoveredHintControl != _dockHintDown)
|
|
||||||
{
|
|
||||||
_dockHintDown.Size = new Float2(HintControlSize);
|
|
||||||
_dockHintDown.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
|
||||||
}
|
|
||||||
if (hoveredHintControl != _dockHintLeft)
|
|
||||||
{
|
|
||||||
_dockHintLeft.Size = new Float2(HintControlSize);
|
|
||||||
_dockHintLeft.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
|
||||||
}
|
|
||||||
if (hoveredHintControl != _dockHintRight)
|
|
||||||
{
|
|
||||||
_dockHintRight.Size = new Float2(HintControlSize);
|
|
||||||
_dockHintRight.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
|
||||||
}
|
|
||||||
if (hoveredHintControl != _dockHintUp)
|
|
||||||
{
|
|
||||||
_dockHintUp.Size = new Float2(HintControlSize);
|
|
||||||
_dockHintUp.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
|
||||||
}
|
|
||||||
if (hoveredHintControl != _dockHintCenter)
|
|
||||||
{
|
|
||||||
_dockHintCenter.Size = new Float2(HintControlSize);
|
|
||||||
_dockHintCenter.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_toSet != DockState.Float)
|
|
||||||
{
|
|
||||||
if (hoveredHintControl != null)
|
|
||||||
{
|
|
||||||
hoveredHintControl.BackgroundColor = mainColor;
|
|
||||||
if (_toSet != prevToSet)
|
|
||||||
hoveredHintControl.Location += hoveredLocationOffset;
|
|
||||||
hoveredHintControl.Size = hoveredSizeOverride - hoveredMargin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update hint controls visibility and location
|
|
||||||
if (showProxyHints)
|
|
||||||
{
|
|
||||||
if (hoveredHintControl != _dockHintDown)
|
|
||||||
_dockHintDown.Location = _rBottom.Location;
|
|
||||||
if (hoveredHintControl != _dockHintLeft)
|
|
||||||
_dockHintLeft.Location = _rLeft.Location;
|
|
||||||
if (hoveredHintControl != _dockHintRight)
|
|
||||||
_dockHintRight.Location = _rRight.Location;
|
|
||||||
if (hoveredHintControl != _dockHintUp)
|
|
||||||
_dockHintUp.Location = _rUpper.Location;
|
|
||||||
if (hoveredHintControl != _dockHintCenter)
|
|
||||||
_dockHintCenter.Location = _rCenter.Location;
|
|
||||||
|
|
||||||
_dockHintDown.Visible = showProxyHints & showBorderHints;
|
|
||||||
_dockHintLeft.Visible = showProxyHints & showBorderHints;
|
|
||||||
_dockHintRight.Visible = showProxyHints & showBorderHints;
|
|
||||||
_dockHintUp.Visible = showProxyHints & showBorderHints;
|
|
||||||
_dockHintCenter.Visible = showProxyHints & showCenterHint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
|
||||||
{
|
|
||||||
if (button == MouseButton.Left)
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdate()
|
|
||||||
{
|
|
||||||
// If the engine lost focus during dragging, end the action
|
|
||||||
if (!Engine.HasFocus)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mousePos = Platform.MousePosition;
|
|
||||||
if (_mouse != mousePos)
|
|
||||||
{
|
|
||||||
if (_dragSourceWindow != null)
|
|
||||||
_toMove.Window.Window.Position = mousePos - _dragOffset;
|
|
||||||
|
|
||||||
UpdateRects(mousePos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -242,15 +242,6 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
FieldInfo[] fields = type.GetFields();
|
FieldInfo[] fields = type.GetFields();
|
||||||
entries.Capacity = Mathf.Max(fields.Length - 1, entries.Capacity);
|
entries.Capacity = Mathf.Max(fields.Length - 1, entries.Capacity);
|
||||||
if (formatMode == EnumDisplayAttribute.FormatMode.Default)
|
|
||||||
{
|
|
||||||
// Override display mode from enum itself
|
|
||||||
var attr = type.GetCustomAttribute<EnumDisplayAttribute>();
|
|
||||||
if (attr != null)
|
|
||||||
{
|
|
||||||
formatMode = attr.Mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fields.Length; i++)
|
for (int i = 0; i < fields.Length; i++)
|
||||||
{
|
{
|
||||||
var field = fields[i];
|
var field = fields[i];
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
public class ColorValueBox : Control
|
public class ColorValueBox : Control
|
||||||
{
|
{
|
||||||
private bool _isMouseDown;
|
private bool _isMouseDown;
|
||||||
private bool _linear;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delegate function used for the color picker events handling.
|
/// Delegate function used for the color picker events handling.
|
||||||
@@ -102,7 +101,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
public ColorValueBox()
|
public ColorValueBox()
|
||||||
: base(0, 0, 32, 18)
|
: base(0, 0, 32, 18)
|
||||||
{
|
{
|
||||||
_linear = !Graphics.GammaColorSpace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -115,7 +113,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
: base(x, y, 32, 18)
|
: base(x, y, 32, 18)
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
_linear = !Graphics.GammaColorSpace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -132,10 +129,8 @@ namespace FlaxEditor.GUI.Input
|
|||||||
{
|
{
|
||||||
base.Draw();
|
base.Draw();
|
||||||
|
|
||||||
var value = _value;
|
bool isTransparent = _value.A < 1;
|
||||||
if (_linear)
|
|
||||||
value = value.ToSRgb();
|
|
||||||
var isTransparent = value.A < 1;
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var fullRect = new Rectangle(0, 0, Width, Height);
|
var fullRect = new Rectangle(0, 0, Width, Height);
|
||||||
var colorRect = new Rectangle(0, 0, isTransparent ? Width * 0.7f : Width, Height);
|
var colorRect = new Rectangle(0, 0, isTransparent ? Width * 0.7f : Width, Height);
|
||||||
@@ -162,10 +157,10 @@ namespace FlaxEditor.GUI.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Render2D.FillRectangle(alphaRect, value);
|
Render2D.FillRectangle(alphaRect, _value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Render2D.FillRectangle(colorRect, value with { A = 1 });
|
Render2D.FillRectangle(colorRect, _value with { A = 1 });
|
||||||
Render2D.DrawRectangle(fullRect, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black);
|
Render2D.DrawRectangle(fullRect, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,11 +99,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action SlidingEnd;
|
public event Action SlidingEnd;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If enabled, pressing the arrow up or down key increments/ decrements the value.
|
|
||||||
/// </summary>
|
|
||||||
public bool ArrowKeysIncrement = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the slider speed. Use value 0 to disable and hide slider UI.
|
/// Gets or sets the slider speed. Use value 0 to disable and hide slider UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -244,27 +239,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
ResetViewOffset();
|
ResetViewOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool OnKeyDown(KeyboardKeys key)
|
|
||||||
{
|
|
||||||
if (ArrowKeysIncrement && (key == KeyboardKeys.ArrowUp || key == KeyboardKeys.ArrowDown))
|
|
||||||
{
|
|
||||||
bool altDown = Root.GetKey(KeyboardKeys.Alt);
|
|
||||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
|
||||||
bool controlDown = Root.GetKey(KeyboardKeys.Control);
|
|
||||||
float deltaValue = altDown ? 0.1f : (shiftDown ? 10f : (controlDown ? 100f : 1f));
|
|
||||||
float slideDelta = key == KeyboardKeys.ArrowUp ? deltaValue : -deltaValue;
|
|
||||||
|
|
||||||
_startSlideValue = Value;
|
|
||||||
ApplySliding(slideDelta);
|
|
||||||
EndSliding();
|
|
||||||
Focus();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnKeyDown(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
@@ -292,7 +266,6 @@ namespace FlaxEditor.GUI.Input
|
|||||||
return base.OnMouseDown(location, button);
|
return base.OnMouseDown(location, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PLATFORM_SDL
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnMouseMove(Float2 location)
|
public override void OnMouseMove(Float2 location)
|
||||||
{
|
{
|
||||||
@@ -319,45 +292,13 @@ namespace FlaxEditor.GUI.Input
|
|||||||
base.OnMouseMove(location);
|
base.OnMouseMove(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void OnMouseMoveRelative(Float2 motion)
|
|
||||||
{
|
|
||||||
var location = Root.TrackingMouseOffset;
|
|
||||||
if (_isSliding)
|
|
||||||
{
|
|
||||||
// Update sliding
|
|
||||||
ApplySliding(Root.TrackingMouseOffset.X * _slideSpeed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update cursor type so user knows they can slide value
|
|
||||||
if (CanUseSliding && SlideRect.Contains(location) && !_isSliding)
|
|
||||||
{
|
|
||||||
Cursor = CursorType.SizeWE;
|
|
||||||
_cursorChanged = true;
|
|
||||||
}
|
|
||||||
else if (_cursorChanged && !_isSliding)
|
|
||||||
{
|
|
||||||
Cursor = CursorType.Default;
|
|
||||||
_cursorChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.OnMouseMoveRelative(motion);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
if (button == MouseButton.Left && _isSliding)
|
if (button == MouseButton.Left && _isSliding)
|
||||||
{
|
{
|
||||||
#if !PLATFORM_SDL
|
|
||||||
// End sliding and return mouse to original location
|
// End sliding and return mouse to original location
|
||||||
RootWindow.MousePosition = _mouseClickedPosition;
|
RootWindow.MousePosition = _mouseClickedPosition;
|
||||||
#endif
|
|
||||||
EndSliding();
|
EndSliding();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,12 +59,12 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when items gets clicked by the user.
|
/// Occurs when items gets clicked by the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Item> ItemClicked;
|
public event Action<Item> Clicked;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when items gets focused.
|
/// Occurs when items gets focused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Item> ItemFocused;
|
public event Action<Item> Focused;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tint color of the text.
|
/// The tint color of the text.
|
||||||
@@ -203,7 +203,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (button == MouseButton.Left && _isMouseDown)
|
if (button == MouseButton.Left && _isMouseDown)
|
||||||
{
|
{
|
||||||
_isMouseDown = false;
|
_isMouseDown = false;
|
||||||
ItemClicked?.Invoke(this);
|
Clicked?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.OnMouseUp(location, button);
|
return base.OnMouseUp(location, button);
|
||||||
@@ -222,7 +222,7 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
base.OnGotFocus();
|
base.OnGotFocus();
|
||||||
|
|
||||||
ItemFocused?.Invoke(this);
|
Focused?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -434,7 +434,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
public void AddItem(Item item)
|
public void AddItem(Item item)
|
||||||
{
|
{
|
||||||
item.ItemClicked += OnClickItem;
|
item.Clicked += OnClickItem;
|
||||||
ContainerControl parent = ItemsPanel;
|
ContainerControl parent = ItemsPanel;
|
||||||
if (!string.IsNullOrEmpty(item.Category))
|
if (!string.IsNullOrEmpty(item.Category))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ namespace FlaxEditor.GUI
|
|||||||
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
|
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
|
||||||
public sealed class MainMenu : ContainerControl
|
public sealed class MainMenu : ContainerControl
|
||||||
{
|
{
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
private bool _useCustomWindowSystem;
|
||||||
|
private Image _icon;
|
||||||
|
private Label _title;
|
||||||
|
private Button _closeButton;
|
||||||
|
private Button _minimizeButton;
|
||||||
|
private Button _maximizeButton;
|
||||||
|
private LocalizedString _charChromeRestore, _charChromeMaximize;
|
||||||
|
private Window _window;
|
||||||
|
#endif
|
||||||
private MainMenuButton _selected;
|
private MainMenuButton _selected;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -50,12 +60,200 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="MainMenu"/> class.
|
/// Initializes a new instance of the <see cref="MainMenu"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MainMenu()
|
/// <param name="mainWindow">The main window.</param>
|
||||||
|
public MainMenu(RootControl mainWindow)
|
||||||
: base(0, 0, 0, 20)
|
: base(0, 0, 0, 20)
|
||||||
{
|
{
|
||||||
AutoFocus = false;
|
AutoFocus = false;
|
||||||
AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
||||||
BackgroundColor = Style.Current.LightBackground;
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
_useCustomWindowSystem = !Editor.Instance.Options.Options.Interface.UseNativeWindowSystem;
|
||||||
|
if (_useCustomWindowSystem)
|
||||||
|
{
|
||||||
|
BackgroundColor = Style.Current.LightBackground;
|
||||||
|
Height = 28;
|
||||||
|
|
||||||
|
var windowIcon = FlaxEngine.Content.LoadAsyncInternal<Texture>(EditorAssets.WindowIcon);
|
||||||
|
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.WindowIconsFont);
|
||||||
|
Font iconFont = windowIconsFont?.CreateFont(9);
|
||||||
|
|
||||||
|
_window = mainWindow.RootWindow.Window;
|
||||||
|
_window.HitTest += OnHitTest;
|
||||||
|
_window.Closed += OnWindowClosed;
|
||||||
|
|
||||||
|
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
|
||||||
|
|
||||||
|
_icon = new Image
|
||||||
|
{
|
||||||
|
Margin = new Margin(6, 6, 6, 6),
|
||||||
|
Brush = new TextureBrush(windowIcon),
|
||||||
|
Color = Style.Current.Foreground,
|
||||||
|
KeepAspectRatio = false,
|
||||||
|
TooltipText = string.Format("{0}\nVersion {1}\nConfiguration {3}\nGraphics {2}", _window.Title, Globals.EngineVersion, GPUDevice.Instance.RendererType, configuration),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
_title = new Label(0, 0, Width, Height)
|
||||||
|
{
|
||||||
|
Text = _window.Title,
|
||||||
|
HorizontalAlignment = TextAlignment.Center,
|
||||||
|
VerticalAlignment = TextAlignment.Center,
|
||||||
|
ClipText = true,
|
||||||
|
TextColor = Style.Current.ForegroundGrey,
|
||||||
|
TextColorHighlighted = Style.Current.ForegroundGrey,
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
_closeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Color.Transparent,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Color.Red,
|
||||||
|
BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_closeButton.Clicked += () => _window.Close(ClosingReason.User);
|
||||||
|
|
||||||
|
_minimizeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Color.Transparent,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_minimizeButton.Clicked += () => _window.Minimize();
|
||||||
|
|
||||||
|
_maximizeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Color.Transparent,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_maximizeButton.Clicked += () =>
|
||||||
|
{
|
||||||
|
if (_window.IsMaximized)
|
||||||
|
_window.Restore();
|
||||||
|
else
|
||||||
|
_window.Maximize();
|
||||||
|
};
|
||||||
|
_charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
|
||||||
|
_charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
BackgroundColor = Style.Current.LightBackground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (_maximizeButton != null)
|
||||||
|
{
|
||||||
|
_maximizeButton.Text = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWindowClosed()
|
||||||
|
{
|
||||||
|
if (_window != null)
|
||||||
|
{
|
||||||
|
_window.HitTest = null;
|
||||||
|
_window = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WindowHitCodes OnHitTest(ref Float2 mouse)
|
||||||
|
{
|
||||||
|
var dpiScale = _window.DpiScale;
|
||||||
|
|
||||||
|
if (_window.IsMinimized)
|
||||||
|
return WindowHitCodes.NoWhere;
|
||||||
|
|
||||||
|
if (!_window.IsMaximized)
|
||||||
|
{
|
||||||
|
var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
|
||||||
|
var winSize = _window.Size;
|
||||||
|
|
||||||
|
// Distance from which the mouse is considered to be on the border/corner
|
||||||
|
float distance = 5.0f * dpiScale;
|
||||||
|
|
||||||
|
if (pos.Y > winSize.Y - distance && pos.X < distance)
|
||||||
|
return WindowHitCodes.BottomLeft;
|
||||||
|
|
||||||
|
if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
|
||||||
|
return WindowHitCodes.BottomRight;
|
||||||
|
|
||||||
|
if (pos.Y < distance && pos.X < distance)
|
||||||
|
return WindowHitCodes.TopLeft;
|
||||||
|
|
||||||
|
if (pos.Y < distance && pos.X > winSize.X - distance)
|
||||||
|
return WindowHitCodes.TopRight;
|
||||||
|
|
||||||
|
if (pos.X > winSize.X - distance)
|
||||||
|
return WindowHitCodes.Right;
|
||||||
|
|
||||||
|
if (pos.X < distance)
|
||||||
|
return WindowHitCodes.Left;
|
||||||
|
|
||||||
|
if (pos.Y < distance)
|
||||||
|
return WindowHitCodes.Top;
|
||||||
|
|
||||||
|
if (pos.Y > winSize.Y - distance)
|
||||||
|
return WindowHitCodes.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mousePos = PointFromScreen(mouse * dpiScale);
|
||||||
|
var controlUnderMouse = GetChildAt(mousePos);
|
||||||
|
var isMouseOverSth = controlUnderMouse != null && controlUnderMouse != _title;
|
||||||
|
var rb = GetRightButton();
|
||||||
|
if (rb != null && _minimizeButton != null && new Rectangle(rb.UpperRight, _minimizeButton.BottomLeft - rb.UpperRight).Contains(ref mousePos) && !isMouseOverSth)
|
||||||
|
return WindowHitCodes.Caption;
|
||||||
|
|
||||||
|
return WindowHitCodes.Client;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the rightmost button.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Rightmost button, null if there is no <see cref="MainMenuButton"/></returns>
|
||||||
|
private MainMenuButton GetRightButton()
|
||||||
|
{
|
||||||
|
MainMenuButton b = null;
|
||||||
|
foreach (var control in Children)
|
||||||
|
{
|
||||||
|
if (b == null && control is MainMenuButton)
|
||||||
|
b = (MainMenuButton)control;
|
||||||
|
|
||||||
|
if (control is MainMenuButton && control.Right > b.Right)
|
||||||
|
b = (MainMenuButton)control;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -100,6 +298,26 @@ namespace FlaxEditor.GUI
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
|
{
|
||||||
|
if (base.OnMouseDoubleClick(location, button))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
var child = GetChildAtRecursive(location);
|
||||||
|
if (_useCustomWindowSystem && child is not Button && child is not MainMenuButton)
|
||||||
|
{
|
||||||
|
if (_window.IsMaximized)
|
||||||
|
_window.Restore();
|
||||||
|
else
|
||||||
|
_window.Maximize();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnKeyDown(KeyboardKeys key)
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
{
|
{
|
||||||
@@ -115,8 +333,16 @@ namespace FlaxEditor.GUI
|
|||||||
protected override void PerformLayoutAfterChildren()
|
protected override void PerformLayoutAfterChildren()
|
||||||
{
|
{
|
||||||
float x = 0;
|
float x = 0;
|
||||||
WindowDecorations decorations = Parent.GetChild<WindowDecorations>();
|
|
||||||
x += decorations?.Icon?.Width ?? 0;
|
#if PLATFORM_WINDOWS
|
||||||
|
if (_useCustomWindowSystem)
|
||||||
|
{
|
||||||
|
// Icon
|
||||||
|
_icon.X = x;
|
||||||
|
_icon.Size = new Float2(Height);
|
||||||
|
x += _icon.Width;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Arrange controls
|
// Arrange controls
|
||||||
MainMenuButton rightMostButton = null;
|
MainMenuButton rightMostButton = null;
|
||||||
@@ -136,20 +362,36 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill the right side if title and buttons are not present
|
#if PLATFORM_WINDOWS
|
||||||
if (decorations?.Title == null)
|
if (_useCustomWindowSystem)
|
||||||
Width = Parent.Width;
|
{
|
||||||
else
|
// Buttons
|
||||||
Width = x;
|
_closeButton.Height = Height;
|
||||||
|
_closeButton.X = Width - _closeButton.Width;
|
||||||
|
_maximizeButton.Height = Height;
|
||||||
|
_maximizeButton.X = _closeButton.X - _maximizeButton.Width;
|
||||||
|
_minimizeButton.Height = Height;
|
||||||
|
_minimizeButton.X = _maximizeButton.X - _minimizeButton.Width;
|
||||||
|
|
||||||
|
// Title
|
||||||
|
_title.Bounds = new Rectangle(x + 2, 0, _minimizeButton.Left - x - 4, Height);
|
||||||
|
//_title.Text = _title.Width < 300.0f ? Editor.Instance.ProjectInfo.Name : _window.Title;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
|
|
||||||
if (_selected != null)
|
if (_window != null)
|
||||||
Selected = null;
|
{
|
||||||
|
_window.Closed -= OnWindowClosed;
|
||||||
|
OnWindowClosed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,14 @@ namespace FlaxEditor.GUI
|
|||||||
Text = text;
|
Text = text;
|
||||||
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
if (!Utilities.Utils.UseCustomWindowDecorations())
|
#if PLATFORM_WINDOWS
|
||||||
|
if (Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
|
||||||
{
|
{
|
||||||
BackgroundColorMouseOver = style.BackgroundHighlighted;
|
BackgroundColorMouseOver = style.BackgroundHighlighted;
|
||||||
BackgroundColorMouseOverOpened = style.Background;
|
BackgroundColorMouseOverOpened = style.Background;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
BackgroundColorMouseOver = BackgroundColorMouseOverOpened = style.LightBackground * 1.3f;
|
BackgroundColorMouseOver = BackgroundColorMouseOverOpened = style.LightBackground * 1.3f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1140,11 +1140,8 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
ParentTree.DraggedOverNode = this;
|
ParentTree.DraggedOverNode = this;
|
||||||
|
|
||||||
// Expand node if mouse goes over arrow
|
// Expand node if mouse goes over arrow
|
||||||
if (ArrowRect.Contains(location) && HasAnyVisibleChild && IsCollapsed)
|
if (ArrowRect.Contains(location) && HasAnyVisibleChild)
|
||||||
{
|
|
||||||
Expand(true);
|
Expand(true);
|
||||||
ParentTree?.FlushPendingPerformLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = OnDragEnterHeader(data);
|
result = OnDragEnterHeader(data);
|
||||||
}
|
}
|
||||||
@@ -1175,11 +1172,8 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
ParentTree.DraggedOverNode = this;
|
ParentTree.DraggedOverNode = this;
|
||||||
|
|
||||||
// Expand node if mouse goes over arrow
|
// Expand node if mouse goes over arrow
|
||||||
if (ArrowRect.Contains(location) && HasAnyVisibleChild && IsCollapsed)
|
if (ArrowRect.Contains(location) && HasAnyVisibleChild)
|
||||||
{
|
|
||||||
Expand(true);
|
Expand(true);
|
||||||
ParentTree?.FlushPendingPerformLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_isDragOverHeader)
|
if (!_isDragOverHeader)
|
||||||
result = OnDragEnterHeader(data);
|
result = OnDragEnterHeader(data);
|
||||||
|
|||||||
@@ -1,339 +0,0 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
using FlaxEngine;
|
|
||||||
using FlaxEngine.GUI;
|
|
||||||
|
|
||||||
namespace FlaxEditor.GUI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents the title bar of the window with buttons.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
|
|
||||||
public class WindowDecorations : ContainerControl
|
|
||||||
{
|
|
||||||
private Image _icon;
|
|
||||||
private Label _title;
|
|
||||||
private Button _closeButton;
|
|
||||||
private Button _minimizeButton;
|
|
||||||
private Button _maximizeButton;
|
|
||||||
private LocalizedString _charChromeRestore, _charChromeMaximize;
|
|
||||||
private Window _window;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The title label in the title bar.
|
|
||||||
/// </summary>
|
|
||||||
public Label Title => _title;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The icon used in the title bar.
|
|
||||||
/// </summary>
|
|
||||||
public Image Icon => _icon;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The tooltip shown when hovering over the icon.
|
|
||||||
/// </summary>
|
|
||||||
public string IconTooltipText
|
|
||||||
{
|
|
||||||
get => _icon?.TooltipText ?? null;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_icon != null)
|
|
||||||
_icon.TooltipText = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="WindowDecorations"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="window">The window.</param>
|
|
||||||
/// <param name="iconOnly">When set, omit drawing title and buttons.</param>
|
|
||||||
public WindowDecorations(RootControl window, bool iconOnly = false)
|
|
||||||
: base(0, 0, 0, 20)
|
|
||||||
{
|
|
||||||
_window = window.RootWindow.Window;
|
|
||||||
|
|
||||||
AutoFocus = false;
|
|
||||||
AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
|
||||||
BackgroundColor = Color.Transparent;
|
|
||||||
|
|
||||||
var windowIcon = FlaxEngine.Content.LoadAsyncInternal<Texture>(EditorAssets.WindowIcon);
|
|
||||||
|
|
||||||
_icon = new Image
|
|
||||||
{
|
|
||||||
Margin = new Margin(4, 4, 4, 4),
|
|
||||||
Brush = new TextureBrush(windowIcon),
|
|
||||||
Color = Style.Current.Foreground,
|
|
||||||
BackgroundColor = Style.Current.LightBackground,
|
|
||||||
KeepAspectRatio = false,
|
|
||||||
Parent = this,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!iconOnly)
|
|
||||||
{
|
|
||||||
_icon.Margin = new Margin(6, 6, 6, 6);
|
|
||||||
Height = 28;
|
|
||||||
|
|
||||||
_window.HitTest += OnHitTest;
|
|
||||||
_window.Closed += OnWindowClosed;
|
|
||||||
|
|
||||||
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.WindowIconsFont);
|
|
||||||
Font iconFont = windowIconsFont?.CreateFont(9);
|
|
||||||
|
|
||||||
_title = new Label(0, 0, Width, Height)
|
|
||||||
{
|
|
||||||
Text = _window.Title,
|
|
||||||
HorizontalAlignment = TextAlignment.Center,
|
|
||||||
VerticalAlignment = TextAlignment.Center,
|
|
||||||
ClipText = true,
|
|
||||||
TextColor = Style.Current.ForegroundGrey,
|
|
||||||
TextColorHighlighted = Style.Current.ForegroundGrey,
|
|
||||||
BackgroundColor = Style.Current.LightBackground,
|
|
||||||
Parent = this,
|
|
||||||
};
|
|
||||||
|
|
||||||
_closeButton = new Button
|
|
||||||
{
|
|
||||||
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
|
|
||||||
Font = new FontReference(iconFont),
|
|
||||||
BackgroundColor = Style.Current.LightBackground,
|
|
||||||
BorderColor = Color.Transparent,
|
|
||||||
BorderColorHighlighted = Color.Transparent,
|
|
||||||
BorderColorSelected = Color.Transparent,
|
|
||||||
TextColor = Style.Current.Foreground,
|
|
||||||
Width = 46,
|
|
||||||
BackgroundColorHighlighted = Color.Red,
|
|
||||||
BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
|
|
||||||
Parent = this,
|
|
||||||
};
|
|
||||||
_closeButton.Clicked += () => _window.Close(ClosingReason.User);
|
|
||||||
|
|
||||||
_minimizeButton = new Button
|
|
||||||
{
|
|
||||||
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
|
|
||||||
Font = new FontReference(iconFont),
|
|
||||||
BackgroundColor = Style.Current.LightBackground,
|
|
||||||
BorderColor = Color.Transparent,
|
|
||||||
BorderColorHighlighted = Color.Transparent,
|
|
||||||
BorderColorSelected = Color.Transparent,
|
|
||||||
TextColor = Style.Current.Foreground,
|
|
||||||
Width = 46,
|
|
||||||
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
|
||||||
Parent = this,
|
|
||||||
};
|
|
||||||
_minimizeButton.Clicked += () => _window.Minimize();
|
|
||||||
|
|
||||||
_maximizeButton = new Button
|
|
||||||
{
|
|
||||||
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
|
|
||||||
Font = new FontReference(iconFont),
|
|
||||||
BackgroundColor = Style.Current.LightBackground,
|
|
||||||
BorderColor = Color.Transparent,
|
|
||||||
BorderColorHighlighted = Color.Transparent,
|
|
||||||
BorderColorSelected = Color.Transparent,
|
|
||||||
TextColor = Style.Current.Foreground,
|
|
||||||
Width = 46,
|
|
||||||
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
|
||||||
Parent = this,
|
|
||||||
};
|
|
||||||
_maximizeButton.Clicked += () =>
|
|
||||||
{
|
|
||||||
if (_window.IsMaximized)
|
|
||||||
_window.Restore();
|
|
||||||
else
|
|
||||||
_window.Maximize();
|
|
||||||
};
|
|
||||||
|
|
||||||
_charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
|
|
||||||
_charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Update(float deltaTime)
|
|
||||||
{
|
|
||||||
base.Update(deltaTime);
|
|
||||||
|
|
||||||
if (_maximizeButton != null)
|
|
||||||
{
|
|
||||||
var maximizeText = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
|
|
||||||
if (_maximizeButton.Text != maximizeText)
|
|
||||||
_maximizeButton.Text = maximizeText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWindowClosed()
|
|
||||||
{
|
|
||||||
if (_window != null)
|
|
||||||
{
|
|
||||||
_window.HitTest -= OnHitTest;
|
|
||||||
_window = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Perform hit test on the window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mouse">The mouse position</param>
|
|
||||||
/// <returns>The hit code for given position.</returns>
|
|
||||||
protected virtual WindowHitCodes OnHitTest(ref Float2 mouse)
|
|
||||||
{
|
|
||||||
if (_window.IsMinimized)
|
|
||||||
return WindowHitCodes.NoWhere;
|
|
||||||
|
|
||||||
var dpiScale = _window.DpiScale;
|
|
||||||
var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
|
|
||||||
if (!_window.IsMaximized)
|
|
||||||
{
|
|
||||||
var winSize = _window.Size;
|
|
||||||
|
|
||||||
// Distance from which the mouse is considered to be on the border/corner
|
|
||||||
float distance = 5.0f * dpiScale;
|
|
||||||
|
|
||||||
if (pos.Y > winSize.Y - distance && pos.X < distance)
|
|
||||||
return WindowHitCodes.BottomLeft;
|
|
||||||
|
|
||||||
if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
|
|
||||||
return WindowHitCodes.BottomRight;
|
|
||||||
|
|
||||||
if (pos.Y < distance && pos.X < distance)
|
|
||||||
return WindowHitCodes.TopLeft;
|
|
||||||
|
|
||||||
if (pos.Y < distance && pos.X > winSize.X - distance)
|
|
||||||
return WindowHitCodes.TopRight;
|
|
||||||
|
|
||||||
if (pos.X > winSize.X - distance)
|
|
||||||
return WindowHitCodes.Right;
|
|
||||||
|
|
||||||
if (pos.X < distance)
|
|
||||||
return WindowHitCodes.Left;
|
|
||||||
|
|
||||||
if (pos.Y < distance)
|
|
||||||
return WindowHitCodes.Top;
|
|
||||||
|
|
||||||
if (pos.Y > winSize.Y - distance)
|
|
||||||
return WindowHitCodes.Bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
var controlUnderMouse = GetChildAt(pos, control => control != _title);
|
|
||||||
if (_title.Bounds.Contains(pos) && controlUnderMouse == null)
|
|
||||||
return WindowHitCodes.Caption;
|
|
||||||
|
|
||||||
return WindowHitCodes.Client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
|
||||||
{
|
|
||||||
// These may not work with main window due to SDL not passing mouse events
|
|
||||||
// when interacting with hit tests on caption area...
|
|
||||||
|
|
||||||
if (Title.Bounds.Contains(location) && button == MouseButton.Left)
|
|
||||||
{
|
|
||||||
if (_window.IsMaximized)
|
|
||||||
_window.Restore();
|
|
||||||
else
|
|
||||||
_window.Maximize();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (Icon.Bounds.Contains(location) && button == MouseButton.Left)
|
|
||||||
{
|
|
||||||
_window.Close(ClosingReason.User);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.OnMouseDoubleClick(location, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void PerformLayoutAfterChildren()
|
|
||||||
{
|
|
||||||
// Calculate extents for title bounds area excluding the icon and main menu area
|
|
||||||
float x = 0;
|
|
||||||
|
|
||||||
// Icon
|
|
||||||
if (_icon != null)
|
|
||||||
{
|
|
||||||
_icon.X = x;
|
|
||||||
_icon.Size = new Float2(Height);
|
|
||||||
x += _icon.Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main menu if present
|
|
||||||
if (Parent.GetChild<MainMenu>() is MainMenu mainMenu)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mainMenu.Children.Count; i++)
|
|
||||||
{
|
|
||||||
var c = mainMenu.Children[i];
|
|
||||||
if (c is MainMenuButton b && c.Visible)
|
|
||||||
{
|
|
||||||
b.Bounds = new Rectangle(x, 0, b.Width, Height);
|
|
||||||
x += b.Width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
float rightMostButtonX = Width;
|
|
||||||
if (_closeButton != null)
|
|
||||||
{
|
|
||||||
_closeButton.Height = Height;
|
|
||||||
_closeButton.X = rightMostButtonX - _closeButton.Width;
|
|
||||||
rightMostButtonX = _closeButton.X;
|
|
||||||
}
|
|
||||||
if (_maximizeButton != null)
|
|
||||||
{
|
|
||||||
_maximizeButton.Height = Height;
|
|
||||||
_maximizeButton.X = rightMostButtonX - _maximizeButton.Width;
|
|
||||||
rightMostButtonX = _maximizeButton.X;
|
|
||||||
}
|
|
||||||
if (_minimizeButton != null)
|
|
||||||
{
|
|
||||||
_minimizeButton.Height = Height;
|
|
||||||
_minimizeButton.X = rightMostButtonX - _minimizeButton.Width;
|
|
||||||
rightMostButtonX = _minimizeButton.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Title
|
|
||||||
if (_title != null)
|
|
||||||
{
|
|
||||||
_title.Text = _window.Title;
|
|
||||||
_title.Bounds = new Rectangle(x, 0, rightMostButtonX - x, Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Draw()
|
|
||||||
{
|
|
||||||
base.Draw();
|
|
||||||
DrawBorders();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draw borders around the window.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void DrawBorders()
|
|
||||||
{
|
|
||||||
var win = RootWindow.Window;
|
|
||||||
if (win.IsMaximized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Editor.Instance.UI.StatusBar == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const float thickness = 1.0f;
|
|
||||||
Color color = Editor.Instance.UI.StatusBar.StatusColor;
|
|
||||||
Rectangle rect = new Rectangle(thickness * 0.5f, thickness * 0.5f, Parent.Width - thickness, Parent.Height - thickness);
|
|
||||||
Render2D.DrawRectangle(rect, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void OnDestroy()
|
|
||||||
{
|
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
if (_window != null)
|
|
||||||
{
|
|
||||||
_window.Closed -= OnWindowClosed;
|
|
||||||
OnWindowClosed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ namespace FlaxEditor.Gizmo
|
|||||||
public abstract class GizmoBase
|
public abstract class GizmoBase
|
||||||
{
|
{
|
||||||
private IGizmoOwner _owner;
|
private IGizmoOwner _owner;
|
||||||
private bool _visible = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the gizmo owner.
|
/// Gets the gizmo owner.
|
||||||
@@ -35,11 +34,6 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual BoundingSphere FocusBounds => BoundingSphere.Empty;
|
public virtual BoundingSphere FocusBounds => BoundingSphere.Empty;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether this gizmo is visible.
|
|
||||||
/// </summary>
|
|
||||||
public bool Visible { get { return _visible; } set { _visible = value; } }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="GizmoBase"/> class.
|
/// Initializes a new instance of the <see cref="GizmoBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -36,12 +36,11 @@ public sealed class ViewportRubberBandSelector
|
|||||||
/// Triggers the start of a rubber band selection.
|
/// Triggers the start of a rubber band selection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if selection started, otherwise false.</returns>
|
/// <returns>True if selection started, otherwise false.</returns>
|
||||||
public bool TryStartingRubberBandSelection(Float2 mousePosition)
|
public bool TryStartingRubberBandSelection()
|
||||||
{
|
{
|
||||||
if (!_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
if (!_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
||||||
{
|
{
|
||||||
_tryStartRubberBand = true;
|
_tryStartRubberBand = true;
|
||||||
_cachedStartingMousePosition = mousePosition;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -83,15 +82,12 @@ public sealed class ViewportRubberBandSelector
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_tryStartRubberBand && canStart)
|
if (_tryStartRubberBand && (Mathf.Abs(_owner.MouseDelta.X) > 0.1f || Mathf.Abs(_owner.MouseDelta.Y) > 0.1f) && canStart)
|
||||||
{
|
{
|
||||||
var delta = mousePosition - _cachedStartingMousePosition;
|
_isRubberBandSpanning = true;
|
||||||
if (Mathf.Abs(delta.X) > 0.1f || Mathf.Abs(delta.Y) > 0.1f)
|
_cachedStartingMousePosition = mousePosition;
|
||||||
{
|
_rubberBandRect = new Rectangle(_cachedStartingMousePosition, Float2.Zero);
|
||||||
_isRubberBandSpanning = true;
|
_tryStartRubberBand = false;
|
||||||
_rubberBandRect = new Rectangle(_cachedStartingMousePosition, Float2.Zero);
|
|
||||||
_tryStartRubberBand = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
else if (_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -402,11 +402,10 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowsManager::WindowsLocker.Unlock();
|
|
||||||
for (const auto& e : inputEvents)
|
for (const auto& e : inputEvents)
|
||||||
{
|
{
|
||||||
auto window = e.Target ? e.Target : defaultWindow;
|
auto window = e.Target ? e.Target : defaultWindow;
|
||||||
if (!window || window->IsClosed())
|
if (!window)
|
||||||
continue;
|
continue;
|
||||||
switch (e.Type)
|
switch (e.Type)
|
||||||
{
|
{
|
||||||
@@ -436,14 +435,12 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa
|
|||||||
case InputDevice::EventType::MouseMove:
|
case InputDevice::EventType::MouseMove:
|
||||||
window->OnMouseMove(window->ScreenToClient(e.MouseData.Position));
|
window->OnMouseMove(window->ScreenToClient(e.MouseData.Position));
|
||||||
break;
|
break;
|
||||||
case InputDevice::EventType::MouseMoveRelative:
|
|
||||||
window->OnMouseMoveRelative(e.MouseMovementData.PositionRelative);
|
|
||||||
break;
|
|
||||||
case InputDevice::EventType::MouseLeave:
|
case InputDevice::EventType::MouseLeave:
|
||||||
window->OnMouseLeave();
|
window->OnMouseLeave();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WindowsManager::WindowsLocker.Unlock();
|
||||||
}
|
}
|
||||||
WindowsManager::WindowsLocker.Lock();
|
WindowsManager::WindowsLocker.Lock();
|
||||||
Array<Window*, InlinedAllocation<32>> windows;
|
Array<Window*, InlinedAllocation<32>> windows;
|
||||||
|
|||||||
@@ -1013,7 +1013,7 @@ namespace FlaxEditor.Modules
|
|||||||
ContentItem item;
|
ContentItem item;
|
||||||
if (path.EndsWith(".cs"))
|
if (path.EndsWith(".cs"))
|
||||||
item = new CSharpScriptItem(path);
|
item = new CSharpScriptItem(path);
|
||||||
else if (path.EndsWith(".cpp") || path.EndsWith(".h") || path.EndsWith(".c") || path.EndsWith(".hpp"))
|
else if (path.EndsWith(".cpp") || path.EndsWith(".h"))
|
||||||
item = new CppScriptItem(path);
|
item = new CppScriptItem(path);
|
||||||
else if (path.EndsWith(".shader") || path.EndsWith(".hlsl"))
|
else if (path.EndsWith(".shader") || path.EndsWith(".hlsl"))
|
||||||
item = new ShaderSourceItem(path);
|
item = new ShaderSourceItem(path);
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ namespace FlaxEditor.Modules
|
|||||||
outputExtension = extension;
|
outputExtension = extension;
|
||||||
|
|
||||||
// Check if can place source files here
|
// Check if can place source files here
|
||||||
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h" || extension == ".c" || extension == ".hpp"))
|
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h"))
|
||||||
{
|
{
|
||||||
// Error
|
// Error
|
||||||
Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path));
|
Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path));
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ namespace FlaxEditor.Modules
|
|||||||
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
||||||
public sealed class SceneEditingModule : EditorModule
|
public sealed class SceneEditingModule : EditorModule
|
||||||
{
|
{
|
||||||
private int _lastSelectionStatus = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The selected objects.
|
/// The selected objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -195,20 +193,6 @@ namespace FlaxEditor.Modules
|
|||||||
Undo.AddAction(new SelectionChangeAction(before, Selection.ToArray(), OnSelectionUndo));
|
Undo.AddAction(new SelectionChangeAction(before, Selection.ToArray(), OnSelectionUndo));
|
||||||
|
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
|
|
||||||
// Display amount of selected actors on the status bar
|
|
||||||
Editor.UI.RemoveStatusMessage(_lastSelectionStatus);
|
|
||||||
var objects = Selection.Count;
|
|
||||||
var actors = CountActors(Selection);
|
|
||||||
_lastSelectionStatus = Editor.UI.AddStatusMessage($"Selected {objects} {(objects > 1 ? "objects" : "object")} (total {actors} {(actors > 1 ? "actors" : "actor")})");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int CountActors(List<SceneGraphNode> nodes)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
foreach (var node in nodes)
|
|
||||||
result += 1 + CountActors(node.ChildNodes);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectionUndo(SceneGraphNode[] toSelect)
|
private void OnSelectionUndo(SceneGraphNode[] toSelect)
|
||||||
@@ -245,7 +229,7 @@ namespace FlaxEditor.Modules
|
|||||||
if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && node.AffectsNavigationWithChildren)
|
if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && node.AffectsNavigationWithChildren)
|
||||||
{
|
{
|
||||||
var bounds = actor.BoxWithChildren;
|
var bounds = actor.BoxWithChildren;
|
||||||
Navigation.BuildNavMesh(bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
Navigation.BuildNavMesh(actor.Scene, bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ namespace FlaxEditor.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnPlayBeginning()
|
public override void OnPlayBegin()
|
||||||
{
|
{
|
||||||
Editor.Windows.FlashMainWindow();
|
Editor.Windows.FlashMainWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using FlaxEditor.Windows;
|
|||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
|
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
|
||||||
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
|
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
|
||||||
using FlaxEditor.Content.Settings;
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEditor.Options;
|
using FlaxEditor.Options;
|
||||||
@@ -28,52 +29,10 @@ namespace FlaxEditor.Modules
|
|||||||
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
||||||
public sealed class UIModule : EditorModule
|
public sealed class UIModule : EditorModule
|
||||||
{
|
{
|
||||||
private class MainWindowDecorations : WindowDecorations
|
|
||||||
{
|
|
||||||
public MainWindowDecorations(RootControl window, bool iconOnly)
|
|
||||||
: base(window, iconOnly)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool OnKeyDown(KeyboardKeys key)
|
|
||||||
{
|
|
||||||
if (base.OnKeyDown(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Fallback to the edit window for shortcuts
|
|
||||||
var editor = Editor.Instance;
|
|
||||||
return editor.Windows.EditWin.InputActions.Process(editor, this, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void DrawBorders()
|
|
||||||
{
|
|
||||||
// Draw main window borders if using a custom style
|
|
||||||
var win = RootWindow.Window;
|
|
||||||
if (win.IsMaximized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var color = Editor.Instance.UI.StatusBar.StatusColor;
|
|
||||||
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
|
|
||||||
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
|
|
||||||
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
|
|
||||||
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct Status
|
|
||||||
{
|
|
||||||
public int ID;
|
|
||||||
public string Text;
|
|
||||||
public DateTime EndTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Label _progressLabel;
|
private Label _progressLabel;
|
||||||
private ProgressBar _progressBar;
|
private ProgressBar _progressBar;
|
||||||
private Button _outputLogButton;
|
private Button _outputLogButton;
|
||||||
private List<Status> _statusMessages;
|
private List<KeyValuePair<string, DateTime>> _statusMessages;
|
||||||
private int _statusID = 1;
|
|
||||||
private ContentStats _contentStats;
|
private ContentStats _contentStats;
|
||||||
private bool _progressFailed;
|
private bool _progressFailed;
|
||||||
|
|
||||||
@@ -166,7 +125,6 @@ namespace FlaxEditor.Modules
|
|||||||
private ContextMenuButton _menuToolsProfilerWindow;
|
private ContextMenuButton _menuToolsProfilerWindow;
|
||||||
private ContextMenuButton _menuToolsSetTheCurrentSceneViewAsDefault;
|
private ContextMenuButton _menuToolsSetTheCurrentSceneViewAsDefault;
|
||||||
private ContextMenuButton _menuToolsTakeScreenshot;
|
private ContextMenuButton _menuToolsTakeScreenshot;
|
||||||
private ContextMenuButton _menuToolsOpenLocalFolder;
|
|
||||||
private ContextMenuChildMenu _menuWindowApplyWindowLayout;
|
private ContextMenuChildMenu _menuWindowApplyWindowLayout;
|
||||||
|
|
||||||
private ToolStripButton _toolStripSaveAll;
|
private ToolStripButton _toolStripSaveAll;
|
||||||
@@ -186,11 +144,6 @@ namespace FlaxEditor.Modules
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public MainMenu MainMenu;
|
public MainMenu MainMenu;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The window decorations (title bar with buttons)
|
|
||||||
/// </summary>
|
|
||||||
public WindowDecorations WindowDecorations;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tool strip control.
|
/// The tool strip control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -387,7 +340,7 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
string text;
|
string text;
|
||||||
if (_statusMessages != null && _statusMessages.Count != 0)
|
if (_statusMessages != null && _statusMessages.Count != 0)
|
||||||
text = _statusMessages[0].Text;
|
text = _statusMessages[0].Key;
|
||||||
else if (Editor.StateMachine.CurrentState.Status != null)
|
else if (Editor.StateMachine.CurrentState.Status != null)
|
||||||
text = Editor.StateMachine.CurrentState.Status;
|
text = Editor.StateMachine.CurrentState.Status;
|
||||||
else if (contentStats.LoadingAssetsCount != 0)
|
else if (contentStats.LoadingAssetsCount != 0)
|
||||||
@@ -409,34 +362,13 @@ namespace FlaxEditor.Modules
|
|||||||
/// Adds the status bar message text to be displayed as a notification.
|
/// Adds the status bar message text to be displayed as a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message to display.</param>
|
/// <param name="message">The message to display.</param>
|
||||||
/// <returns>The ID of that status message (unique). Can be used to hide it manually.</returns>
|
public void AddStatusMessage(string message)
|
||||||
public int AddStatusMessage(string message)
|
|
||||||
{
|
{
|
||||||
if (_statusMessages == null)
|
if (_statusMessages == null)
|
||||||
_statusMessages = new List<Status>();
|
_statusMessages = new List<KeyValuePair<string, DateTime>>();
|
||||||
var status = new Status { ID = _statusID++, Text = message, EndTime = DateTime.Now + TimeSpan.FromSeconds(3.0f) };
|
_statusMessages.Add(new KeyValuePair<string, DateTime>(message, DateTime.Now + TimeSpan.FromSeconds(3.0f)));
|
||||||
_statusMessages.Add(status);
|
|
||||||
if (_statusMessages.Count == 1)
|
if (_statusMessages.Count == 1)
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
return status.ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a specific status message once it's not needed anymore,
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The ID of the message returned by <see cref="AddStatusMessage"/>.</param>
|
|
||||||
public void RemoveStatusMessage(int id)
|
|
||||||
{
|
|
||||||
if (_statusMessages == null || id == 0)
|
|
||||||
return;
|
|
||||||
for (var i = 0; i < _statusMessages.Count; i++)
|
|
||||||
{
|
|
||||||
if (_statusMessages[i].ID == id)
|
|
||||||
{
|
|
||||||
_statusMessages.RemoveAt(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool ProgressVisible
|
internal bool ProgressVisible
|
||||||
@@ -494,11 +426,19 @@ namespace FlaxEditor.Modules
|
|||||||
InitToolstrip(mainWindow);
|
InitToolstrip(mainWindow);
|
||||||
InitStatusBar(mainWindow);
|
InitStatusBar(mainWindow);
|
||||||
InitDockPanel(mainWindow);
|
InitDockPanel(mainWindow);
|
||||||
InitWindowDecorations(mainWindow);
|
|
||||||
|
|
||||||
Editor.Options.OptionsChanged += OnOptionsChanged;
|
Editor.Options.OptionsChanged += OnOptionsChanged;
|
||||||
|
|
||||||
mainWindow.PerformLayout(true);
|
// Add dummy control for drawing the main window borders if using a custom style
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
if (!Editor.Options.Options.Interface.UseNativeWindowSystem)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
mainWindow.AddChild(new CustomWindowBorderControl
|
||||||
|
{
|
||||||
|
Size = Float2.Zero,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitViewportScaleOptions()
|
private void InitViewportScaleOptions()
|
||||||
@@ -549,13 +489,13 @@ namespace FlaxEditor.Modules
|
|||||||
public void SaveCustomViewportScalingOptions()
|
public void SaveCustomViewportScalingOptions()
|
||||||
{
|
{
|
||||||
var customOptions = JsonSerializer.Serialize(CustomViewportScaleOptions);
|
var customOptions = JsonSerializer.Serialize(CustomViewportScaleOptions);
|
||||||
Editor.Instance.ProjectCache.SetCustomData("CustomViewportScalingOptions", customOptions);
|
Editor.Instance.ProjectCache.SetCustomData("CustomViewportScalingOptions", customOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnUpdate()
|
public override void OnUpdate()
|
||||||
{
|
{
|
||||||
if (_statusMessages != null && _statusMessages.Count > 0 && _statusMessages[0].EndTime - DateTime.Now < TimeSpan.Zero)
|
if (_statusMessages != null && _statusMessages.Count > 0 && _statusMessages[0].Value - DateTime.Now < TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
_statusMessages.RemoveAt(0);
|
_statusMessages.RemoveAt(0);
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
@@ -570,6 +510,23 @@ namespace FlaxEditor.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CustomWindowBorderControl : Control
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
var win = RootWindow.Window;
|
||||||
|
if (win.IsMaximized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var color = Editor.Instance.UI.StatusBar.StatusColor;
|
||||||
|
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
|
||||||
|
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
|
||||||
|
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
|
||||||
|
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnEndInit()
|
public override void OnEndInit()
|
||||||
{
|
{
|
||||||
@@ -601,6 +558,13 @@ namespace FlaxEditor.Modules
|
|||||||
UpdateToolstrip();
|
UpdateToolstrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnExit()
|
||||||
|
{
|
||||||
|
// Cleanup dock panel hint proxy windows (Flax will destroy them by var but it's better to clear them earlier)
|
||||||
|
DockHintWindow.Proxy.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing)
|
private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing)
|
||||||
{
|
{
|
||||||
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);
|
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);
|
||||||
@@ -654,12 +618,10 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
private void InitMainMenu(RootControl mainWindow)
|
private void InitMainMenu(RootControl mainWindow)
|
||||||
{
|
{
|
||||||
MainMenu = new MainMenu()
|
MainMenu = new MainMenu(mainWindow)
|
||||||
{
|
{
|
||||||
Parent = mainWindow
|
Parent = mainWindow
|
||||||
};
|
};
|
||||||
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
|
|
||||||
MainMenu.Height = 28;
|
|
||||||
|
|
||||||
var inputOptions = Editor.Options.Options.Input;
|
var inputOptions = Editor.Options.Options.Input;
|
||||||
|
|
||||||
@@ -763,22 +725,12 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
||||||
cm.AddSeparator();
|
cm.AddSeparator();
|
||||||
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
||||||
cm.AddSeparator();
|
|
||||||
var childMenu = cm.AddChildMenu("Open Product Local folder");
|
|
||||||
childMenu.ContextMenu.AddButton("Editor", () => FileSystem.ShowFileExplorer(Globals.ProductLocalFolder));
|
|
||||||
_menuToolsOpenLocalFolder = childMenu.ContextMenu.AddButton("Game", () =>
|
|
||||||
{
|
|
||||||
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
||||||
GameSettings settings = GameSettings.Load<GameSettings>();
|
|
||||||
string path = Path.Combine(localAppData, settings.CompanyName, settings.ProductName);
|
|
||||||
FileSystem.ShowFileExplorer(path);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
MenuWindow = MainMenu.AddButton("Window");
|
MenuWindow = MainMenu.AddButton("Window");
|
||||||
cm = MenuWindow.ContextMenu;
|
cm = MenuWindow.ContextMenu;
|
||||||
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
||||||
cm.AddButton("Content", inputOptions.ContentWindow, Editor.Windows.ContentWin.FocusOrShow);
|
cm.AddButton("Content", inputOptions.ContentWindow,Editor.Windows.ContentWin.FocusOrShow);
|
||||||
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
|
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
|
||||||
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
|
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
|
||||||
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
|
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
|
||||||
@@ -811,23 +763,6 @@ namespace FlaxEditor.Modules
|
|||||||
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
|
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitWindowDecorations(RootControl mainWindow)
|
|
||||||
{
|
|
||||||
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
|
|
||||||
string driver = string.Empty;
|
|
||||||
#if PLATFORM_LINUX
|
|
||||||
driver = LinuxPlatform.DisplayServer;
|
|
||||||
if (!string.IsNullOrEmpty(driver))
|
|
||||||
driver = $" ({driver})";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WindowDecorations = new MainWindowDecorations(mainWindow, !Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
|
|
||||||
{
|
|
||||||
Parent = mainWindow,
|
|
||||||
IconTooltipText = $"{mainWindow.RootWindow.Title}\nVersion {Globals.EngineVersion}\nConfiguration {configuration}\nGraphics {GPUDevice.Instance.RendererType}{driver}",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnOptionsChanged(EditorOptions options)
|
private void OnOptionsChanged(EditorOptions options)
|
||||||
{
|
{
|
||||||
var inputOptions = options.Input;
|
var inputOptions = options.Input;
|
||||||
@@ -1127,10 +1062,6 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsBuildNavMesh.Enabled = canEdit;
|
_menuToolsBuildNavMesh.Enabled = canEdit;
|
||||||
_menuToolsCancelBuilding.Enabled = GameCooker.IsRunning;
|
_menuToolsCancelBuilding.Enabled = GameCooker.IsRunning;
|
||||||
_menuToolsSetTheCurrentSceneViewAsDefault.Enabled = Level.ScenesCount > 0;
|
_menuToolsSetTheCurrentSceneViewAsDefault.Enabled = Level.ScenesCount > 0;
|
||||||
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
||||||
GameSettings settings = GameSettings.Load<GameSettings>();
|
|
||||||
string path = Path.Combine(localAppData, settings.CompanyName, settings.ProductName);
|
|
||||||
_menuToolsOpenLocalFolder.Enabled = Directory.Exists(path);
|
|
||||||
|
|
||||||
c.PerformLayout();
|
c.PerformLayout();
|
||||||
}
|
}
|
||||||
@@ -1252,7 +1183,6 @@ namespace FlaxEditor.Modules
|
|||||||
{
|
{
|
||||||
// Clear UI references (GUI cannot be used after window closing)
|
// Clear UI references (GUI cannot be used after window closing)
|
||||||
MainMenu = null;
|
MainMenu = null;
|
||||||
WindowDecorations = null;
|
|
||||||
ToolStrip = null;
|
ToolStrip = null;
|
||||||
MasterPanel = null;
|
MasterPanel = null;
|
||||||
StatusBar = null;
|
StatusBar = null;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Text;
|
|||||||
using System.Xml;
|
using System.Xml;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI.Dialogs;
|
using FlaxEditor.GUI.Dialogs;
|
||||||
|
using FlaxEditor.GUI.Docking;
|
||||||
using FlaxEditor.Windows;
|
using FlaxEditor.Windows;
|
||||||
using FlaxEditor.Windows.Assets;
|
using FlaxEditor.Windows.Assets;
|
||||||
using FlaxEditor.Windows.Profiler;
|
using FlaxEditor.Windows.Profiler;
|
||||||
@@ -490,15 +491,10 @@ namespace FlaxEditor.Modules
|
|||||||
Editor.LogWarning("Empty panel inside layout.");
|
Editor.LogWarning("Empty panel inside layout.");
|
||||||
p.RemoveIt();
|
p.RemoveIt();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
p.CollapseEmptyTabsProxy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.SelectTab(selectedTab);
|
panel.SelectTab(selectedTab);
|
||||||
panel.CollapseEmptyTabsProxy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SaveBounds(XmlWriter writer, Window win)
|
private static void SaveBounds(XmlWriter writer, Window win)
|
||||||
@@ -762,19 +758,17 @@ namespace FlaxEditor.Modules
|
|||||||
var settings = CreateWindowSettings.Default;
|
var settings = CreateWindowSettings.Default;
|
||||||
settings.Title = "Flax Editor";
|
settings.Title = "Flax Editor";
|
||||||
settings.Size = Platform.DesktopSize * 0.75f;
|
settings.Size = Platform.DesktopSize * 0.75f;
|
||||||
settings.MinimumSize = new Float2(200, 150);
|
|
||||||
settings.StartPosition = WindowStartPosition.CenterScreen;
|
settings.StartPosition = WindowStartPosition.CenterScreen;
|
||||||
settings.ShowAfterFirstPaint = true;
|
settings.ShowAfterFirstPaint = true;
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
|
if (!Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
|
||||||
{
|
{
|
||||||
settings.HasBorder = false;
|
settings.HasBorder = false;
|
||||||
#if PLATFORM_WINDOWS && !PLATFORM_SDL
|
|
||||||
// Skip OS sizing frame and implement it using LeftButtonHit
|
// Skip OS sizing frame and implement it using LeftButtonHit
|
||||||
settings.HasSizingFrame = false;
|
settings.HasSizingFrame = false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if PLATFORM_LINUX && !PLATFORM_SDL
|
#elif PLATFORM_LINUX
|
||||||
settings.HasBorder = false;
|
settings.HasBorder = false;
|
||||||
#endif
|
#endif
|
||||||
MainWindow = Platform.CreateWindow(ref settings);
|
MainWindow = Platform.CreateWindow(ref settings);
|
||||||
|
|||||||
@@ -387,14 +387,6 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Viewport"), EditorOrder(1760)]
|
[EditorDisplay("Viewport"), EditorOrder(1760)]
|
||||||
public InputBinding ToggleOrthographic = new InputBinding(KeyboardKeys.NumpadDecimal);
|
public InputBinding ToggleOrthographic = new InputBinding(KeyboardKeys.NumpadDecimal);
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "G")]
|
|
||||||
[EditorDisplay("Viewport"), EditorOrder(1770)]
|
|
||||||
public InputBinding ToggleGameView = new InputBinding(KeyboardKeys.G);
|
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "P")]
|
|
||||||
[EditorDisplay("Viewport"), EditorOrder(1770)]
|
|
||||||
public InputBinding ToggleNavMeshVisibility = new InputBinding(KeyboardKeys.P);
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Debug Views
|
#region Debug Views
|
||||||
@@ -579,10 +571,6 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("View Flags"), EditorOrder(3260)]
|
[EditorDisplay("View Flags"), EditorOrder(3260)]
|
||||||
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
|
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "None")]
|
|
||||||
[EditorDisplay("View Flags"), EditorOrder(3270)]
|
|
||||||
public InputBinding Particles = new InputBinding(KeyboardKeys.None);
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Interface
|
#region Interface
|
||||||
|
|||||||
@@ -85,12 +85,10 @@ namespace FlaxEditor.Options
|
|||||||
/// Never show the close button.
|
/// Never show the close button.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Never,
|
Never,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show the close button on tabs that are currently selected.
|
/// Show the close button on tabs that are currently selected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SelectedTab,
|
SelectedTab,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show the close button on all tabs that can be closed.
|
/// Show the close button on all tabs that can be closed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -181,34 +179,6 @@ namespace FlaxEditor.Options
|
|||||||
GameWindowThenRestore,
|
GameWindowThenRestore,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Options for type of window decorations to use.
|
|
||||||
/// </summary>
|
|
||||||
public enum WindowDecorationsType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Determined automatically based on the system and any known compatibility issues with native decorations.
|
|
||||||
/// </summary>
|
|
||||||
Auto,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Automatically choose most compatible window decorations for child windows, prefer custom decorations on main window.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay(Name = "Auto (Child Only)")]
|
|
||||||
AutoChildOnly,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use native system window decorations on all windows.
|
|
||||||
/// </summary>
|
|
||||||
Native,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use custom client-side window decorations on all windows.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay(Name = "Client-side")]
|
|
||||||
ClientSide,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.
|
/// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -298,14 +268,7 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Interface"), EditorOrder(322)]
|
[EditorDisplay("Interface"), EditorOrder(322)]
|
||||||
public bool ScrollToScriptOnAdd { get; set; } = true;
|
public bool ScrollToScriptOnAdd { get; set; } = true;
|
||||||
|
|
||||||
#if PLATFORM_SDL
|
#if PLATFORM_WINDOWS
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
|
|
||||||
/// </summary>
|
|
||||||
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
|
|
||||||
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
|
|
||||||
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
|
|
||||||
#elif PLATFORM_WINDOWS
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
|
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -314,7 +277,7 @@ namespace FlaxEditor.Options
|
|||||||
public bool UseNativeWindowSystem { get; set; } = false;
|
public bool UseNativeWindowSystem { get; set; } = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_SDL || PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
|
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -324,7 +287,7 @@ namespace FlaxEditor.Options
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether the minimum tab width should be used. Editor restart required.
|
/// Gets or sets a value indicating wether the minum tab width should be used. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
|
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
|
||||||
@@ -535,7 +498,7 @@ namespace FlaxEditor.Options
|
|||||||
public float ConnectionCurvature { get; set; } = 1.0f;
|
public float ConnectionCurvature { get; set; } = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value that indicates whether the context menu description panel is shown or not.
|
/// Gets or sets a value that indicates wether the context menu description panel is shown or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(true)]
|
[DefaultValue(true)]
|
||||||
[EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in visual scripting context menu.")]
|
[EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in visual scripting context menu.")]
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user