Compare commits
493 Commits
mac_change
...
work
| Author | SHA1 | Date | |
|---|---|---|---|
| c1f6bcb83f | |||
| eca4f6d9bc | |||
| 802074fca3 | |||
| 0bb13e1d91 | |||
| db47531a6d | |||
|
|
48c6339ebb | ||
|
|
2dd34b288c | ||
|
|
0bc595f16f | ||
|
|
7abed93972 | ||
| 51feaa0730 | |||
| 8e69aa8bd6 | |||
| 90b2fded48 | |||
| 9125ffeb9e | |||
| 28980e5fbf | |||
| aab0d772a4 | |||
|
|
4b10d7057a | ||
|
|
85aed8c4d7 | ||
|
|
da08be42b4 | ||
|
|
056fea9a8c | ||
|
|
bf345f13ce | ||
|
|
a138c6b062 | ||
|
|
33e58c12cb | ||
|
|
094a6562b8 | ||
|
|
7f783bb7da | ||
|
|
b08f218f30 | ||
|
|
c6640be04a | ||
|
|
eff3c50d9c | ||
|
|
3fa099ad06 | ||
|
|
5e47a861f3 | ||
|
|
37b4b25ead | ||
|
|
edfd145226 | ||
|
|
763ede4bd9 | ||
|
|
284da341e1 | ||
|
|
53ed2431b5 | ||
|
|
b4ab39b3bf | ||
|
|
de61e3efb5 | ||
|
|
29fb36fcd6 | ||
|
|
78f0ff75f2 | ||
|
|
6efd456eaf | ||
|
|
e0c96c0cde | ||
|
|
ada269568a | ||
|
|
dd256ad518 | ||
|
|
12c8bb4f31 | ||
|
|
4e4d380267 | ||
|
|
448eb48c23 | ||
|
|
78d519cb9a | ||
|
|
43d11264f8 | ||
|
|
f126a83b79 | ||
|
|
bdd7bae459 | ||
|
|
3dc7546dd4 | ||
|
|
185151b025 | ||
|
|
8cdec15fa6 | ||
|
|
1b40775d62 | ||
|
|
45e82d21f4 | ||
|
|
5c37584eca | ||
|
|
674fda7375 | ||
| 6296e1a9eb | |||
| 1586bb0702 | |||
|
|
bf10d0949e | ||
|
|
d1c43ec1fe | ||
| edeaf6af09 | |||
|
|
dbd8297612 | ||
|
|
8d62a13cbc | ||
| 951edd95db | |||
| 9951211596 | |||
| 6d337464f7 | |||
|
|
5a05038a9b | ||
|
|
109d4423bb | ||
| d0b552d74a | |||
|
|
6c1e380a3e | ||
| 83512822b1 | |||
| ccb78103ec | |||
| 6e79ffea34 | |||
| 4f03d37a17 | |||
|
|
c57a1a7205 | ||
|
|
867ae2ceaa | ||
|
|
ef5d45874a | ||
|
|
169db79b2a | ||
|
|
9e4c1da032 | ||
|
|
d7df403e5e | ||
|
|
d3a50cdacb | ||
|
|
3cb74d48ca | ||
|
|
8633ed2124 | ||
|
|
2e10d776e9 | ||
|
|
4ac870f701 | ||
|
|
6144f6c74e | ||
|
|
edb6884942 | ||
|
|
62e329ac6e | ||
|
|
68dce7e4dd | ||
|
|
6479a3d3c6 | ||
|
|
e41c48f9e5 | ||
|
|
9cfcbfa9d2 | ||
|
|
bcd2b1f0f2 | ||
| 6fb8419b3c | |||
| a4272d6ca9 | |||
|
|
eb6010cba7 | ||
|
|
bd2add7edd | ||
|
|
986693757c | ||
|
|
5a23060e05 | ||
|
|
b92c18cf25 | ||
|
|
6a82eb114d | ||
|
|
97b37b3ce4 | ||
|
|
bbe54969b0 | ||
| 4654117d5e | |||
|
|
8164ce924f | ||
|
|
22911bbc45 | ||
|
|
cae2720585 | ||
|
|
90b6293bc2 | ||
|
|
d110237423 | ||
|
|
117f890612 | ||
|
|
a6a2fd2c66 | ||
|
|
a05ca12770 | ||
|
|
abe7785e94 | ||
|
|
2cedac8d96 | ||
|
|
ea854a0f7b | ||
|
|
d0817809ff | ||
|
|
95f2216f97 | ||
|
|
7e5edf1b33 | ||
|
|
c649a4f4b2 | ||
|
|
cd7233d559 | ||
| 6ff260d052 | |||
| 88d2b72822 | |||
|
|
3c74b315a8 | ||
|
|
f841575378 | ||
|
|
d90377ed62 | ||
|
|
c8d622bda9 | ||
|
|
fbf2d8f567 | ||
|
|
42687a792c | ||
|
|
5c43d35146 | ||
|
|
c1e1dee975 | ||
|
|
742d74a2d0 | ||
|
|
614ffa70a0 | ||
|
|
4b4331fd70 | ||
|
|
e221f7204b | ||
|
|
18fa8e1c47 | ||
|
|
2f02ec52ed | ||
|
|
9464f97e16 | ||
|
|
54467a4a5e | ||
|
|
3a9e175043 | ||
|
|
9dff048cb5 | ||
|
|
f376fd50a9 | ||
|
|
e27cf04f91 | ||
|
|
648504ceb1 | ||
|
|
e2f741cab9 | ||
|
|
766091045b | ||
|
|
47e1547d29 | ||
|
|
e2d9452994 | ||
|
|
eadb4411ff | ||
|
|
bdc87c7bc6 | ||
|
|
7606c9ac12 | ||
|
|
4240646ec7 | ||
|
|
214ec9f2b1 | ||
|
|
0fa53f860a | ||
|
|
27ac755bbe | ||
|
|
8ec138399a | ||
|
|
5b6859a66f | ||
|
|
bed1f6e9cc | ||
|
|
00055ef663 | ||
|
|
aa59a6faf7 | ||
|
|
e9835766bc | ||
|
|
d6eb647d59 | ||
|
|
b50f3fcb64 | ||
|
|
d6b4992991 | ||
|
|
fc561b5ec5 | ||
|
|
dacc0068e0 | ||
|
|
e7d2025010 | ||
|
|
b418ab5275 | ||
|
|
c1e782bb32 | ||
|
|
cfd2f42b0c | ||
|
|
e1a2a36978 | ||
|
|
793bc33b2f | ||
|
|
2109a2d261 | ||
|
|
89c7f4b0a3 | ||
|
|
d7ff9fdade | ||
|
|
9e50a39ebf | ||
|
|
7fc564a0ac | ||
|
|
8dfb564fb3 | ||
|
|
f8daff273a | ||
|
|
112e728465 | ||
|
|
057ec9d41e | ||
|
|
7fa4efcac5 | ||
|
|
6547e7ee9c | ||
|
|
907c593671 | ||
| 29868531ad | |||
| 95dfb6fdc6 | |||
|
|
9c9d560ce5 | ||
|
|
f1945552ab | ||
|
|
65ab42158d | ||
|
|
99841e2e8d | ||
|
|
73c30d3d89 | ||
|
|
ecd5559aad | ||
|
|
1fa83639c2 | ||
|
|
568719b615 | ||
|
|
74000fa766 | ||
|
|
1d63067614 | ||
|
|
85fd1389db | ||
|
|
cce042045e | ||
|
|
53e3cee196 | ||
|
|
6ee3b23261 | ||
|
|
1a77ba4552 | ||
|
|
bffb175a9b | ||
|
|
125a973ff2 | ||
|
|
462f75abd0 | ||
|
|
d95cd2f0be | ||
|
|
091f76bbf2 | ||
|
|
e8b60060ab | ||
|
|
cd637e8a7a | ||
|
|
9d8e75caa3 | ||
|
|
eee4e55cf0 | ||
|
|
0670c0bbd3 | ||
|
|
f462a2187f | ||
|
|
c2cbaeed30 | ||
|
|
e982a23ed3 | ||
|
|
f6feae5cf2 | ||
|
|
ba75fd5882 | ||
|
|
1eaf40f2f7 | ||
|
|
fe98a23cb4 | ||
|
|
77bf03128e | ||
|
|
8f49a492d8 | ||
| 8df3999f85 | |||
|
|
dd4bb2f7f1 | ||
|
|
496856d12e | ||
|
|
e97d683545 | ||
|
|
ae44d47043 | ||
|
|
8b88def9d0 | ||
|
|
fa97229830 | ||
|
|
1946caac6e | ||
|
|
6f5308126b | ||
|
|
6a0c734cec | ||
|
|
13b8863f0c | ||
|
|
f2aaad0048 | ||
|
|
55b441e9fa | ||
|
|
6fece4ca38 | ||
|
|
2fd9b4a62a | ||
|
|
077f7a3cd1 | ||
|
|
7da69f18d4 | ||
| 6c63c2f650 | |||
| 149b189629 | |||
|
|
fd8a8b5a4d | ||
| b1fd86e6b5 | |||
| 5e8fdf879d | |||
|
|
fa89e710d8 | ||
|
|
b51ba58063 | ||
|
|
057489e5b9 | ||
|
|
5bae695ae9 | ||
|
|
5b3ed1fbc3 | ||
|
|
f5092e5262 | ||
|
|
3bd6160c3b | ||
|
|
1d0a0a409d | ||
|
|
eb90ab84f2 | ||
|
|
6f37525674 | ||
|
|
eeb8a7ea41 | ||
|
|
df0b571c50 | ||
|
|
ec22427acd | ||
|
|
6c499e877f | ||
|
|
4d9407e4e9 | ||
|
|
28c70f5078 | ||
|
|
14806a1ac7 | ||
|
|
1ebb3e67d6 | ||
|
|
991cdbb9a0 | ||
|
|
278b177c46 | ||
|
|
0630b6257a | ||
|
|
f86d9c47b7 | ||
|
|
ae2088bb9d | ||
|
|
9340c42f2b | ||
|
|
8d7dfd5946 | ||
|
|
894cb273aa | ||
|
|
2996e0c53c | ||
|
|
79ce82d8a0 | ||
|
|
3c8e59c114 | ||
|
|
1493571810 | ||
|
|
a613d89f47 | ||
|
|
5471c59d5f | ||
|
|
ac42223f9e | ||
|
|
c21c9c13ad | ||
|
|
8251509607 | ||
|
|
3083e3f611 | ||
|
|
66add1f3bd | ||
|
|
b8a680df57 | ||
|
|
e969b7fffb | ||
|
|
5d9657781a | ||
|
|
2cd03787cd | ||
|
|
619c5ac3b0 | ||
|
|
89baa91552 | ||
|
|
83b3b1af76 | ||
|
|
19148f21ac | ||
|
|
2da8e392db | ||
|
|
a812b8b108 | ||
|
|
3dc96352e6 | ||
|
|
c2b590d2cf | ||
|
|
842d6969fe | ||
|
|
0f3044ae72 | ||
|
|
11dec8e868 | ||
|
|
d6b1f06721 | ||
|
|
14fcc593c7 | ||
|
|
08ed5ae483 | ||
|
|
b065e6c989 | ||
|
|
372a23cf3a | ||
|
|
4721e8109f | ||
|
|
b58aaccc53 | ||
|
|
294dd3d363 | ||
|
|
e00f552baf | ||
|
|
8eff098850 | ||
|
|
4fe9fdded6 | ||
|
|
03d52d4eb9 | ||
|
|
ab61ed5a37 | ||
|
|
72ee80242d | ||
|
|
9dc4dbc6d7 | ||
|
|
a74c5e7943 | ||
|
|
8f9fa6995e | ||
|
|
98e59450f1 | ||
|
|
8c62f1120f | ||
|
|
9aaba955d0 | ||
|
|
410ec0465c | ||
|
|
ae9ded504d | ||
|
|
f9cb4ddae2 | ||
|
|
9753e579c1 | ||
|
|
2e996c8e91 | ||
|
|
545a43de32 | ||
|
|
e606c35093 | ||
|
|
21ae2d5d40 | ||
|
|
4649298605 | ||
|
|
ae9622d271 | ||
|
|
4366976015 | ||
|
|
5b2a966ac6 | ||
|
|
bb855e2663 | ||
|
|
d24f9d1e1e | ||
|
|
c1b1f4afc4 | ||
|
|
c639a3103c | ||
|
|
32bc73610f | ||
|
|
66dcfafa2e | ||
|
|
9215f2662f | ||
|
|
2dc404cbd3 | ||
|
|
59308df250 | ||
|
|
9ba1c4c338 | ||
|
|
ec2957bf38 | ||
|
|
8bb5655b2f | ||
|
|
c24ecaaab1 | ||
|
|
483a33996f | ||
|
|
6be8158209 | ||
|
|
8e7fcd3cad | ||
|
|
a792a8a533 | ||
|
|
25d8c4645e | ||
|
|
64c552d69d | ||
|
|
fafa400db0 | ||
|
|
0b20a5342e | ||
|
|
fa4e56a32a | ||
|
|
212bd7a011 | ||
|
|
943864004f | ||
|
|
8ce4d94a96 | ||
|
|
6be193bfbf | ||
|
|
5d3947f117 | ||
|
|
c7bb7be20f | ||
|
|
f74b96bcb6 | ||
|
|
cecfea1ecf | ||
|
|
09ce2b5a6d | ||
|
|
2f9cdadb11 | ||
|
|
e218ce2d85 | ||
|
|
5ec6993342 | ||
|
|
87787cb5bf | ||
|
|
5b618b4f31 | ||
|
|
08a86066d0 | ||
|
|
388eb654a5 | ||
|
|
d8059c3db3 | ||
| 559d17e6c3 | |||
|
|
dfe177447c | ||
|
|
2a5aed6c15 | ||
|
|
f5ad8566eb | ||
| 7c5628d47e | |||
| 9645008460 | |||
| 12dbf09164 | |||
| f09fd7ad34 | |||
| 8986290b12 | |||
| 9a4d3a56a3 | |||
|
|
b0048d6540 | ||
|
|
b1b36ea1a3 | ||
|
|
e568e6e17b | ||
|
|
af955ba418 | ||
|
|
a56e2e7b1e | ||
|
|
a0cdb08893 | ||
|
|
fbb829a915 | ||
|
|
5790da6167 | ||
|
|
c6e4fbd966 | ||
|
|
101ea44051 | ||
|
|
d6c6936f6d | ||
|
|
4929e8172c | ||
|
|
8c83156133 | ||
|
|
d587921a83 | ||
|
|
6fe6ba20fb | ||
|
|
2ea3cde203 | ||
|
|
059fe98c67 | ||
|
|
1ab05b620a | ||
|
|
4b387d040d | ||
|
|
9d527ab4a6 | ||
|
|
bbc221086a | ||
|
|
e5b7e58a07 | ||
|
|
cfef93134e | ||
| 84ada18299 | |||
| 635fe8017e | |||
| 834380ff05 | |||
| dd65fc2289 | |||
| 86125bb625 | |||
| 09a9d8b380 | |||
| 86b223ec93 | |||
| 78f6080321 | |||
| c7be6f6e0e | |||
| c40c31fbb7 | |||
| f5fbc1e32d | |||
| 0a20378acd | |||
| d4e87877b6 | |||
| 7eb7236b8a | |||
| dc0e4ffce2 | |||
| 86fe93943d | |||
| 3258113ef8 | |||
| ebf3999cfe | |||
| a1ccbbb5b9 | |||
| 35072c40d8 | |||
| 5c51021388 | |||
| 95fd527515 | |||
| 113d851cea | |||
| 72f0c460f9 | |||
| 13ddd15b44 | |||
| c9e24aaf5f | |||
| 68c0ac0ffc | |||
| bebda275a9 | |||
| 287eaae850 | |||
| 7e59c3b9a7 | |||
| 38658a5b8c | |||
| 88c75b8672 | |||
| 17ab1e6830 | |||
| 1f45110e5f | |||
| 5401166a07 | |||
| bfa8188782 | |||
| e777a71784 | |||
| c13e91a0d0 | |||
| aac5d57352 | |||
| ceca13c7b6 | |||
| 2905470330 | |||
| 2c17033822 | |||
| 0a4cb9e9b1 | |||
| 096651f4c1 | |||
| 275a08506b | |||
| 4cd61cb381 | |||
| 9ad1147581 | |||
| 35e09def1b | |||
| 0469607a71 | |||
| d115d22ee6 | |||
| 8120ae621d | |||
| f873c2fa9f | |||
| c3ffbe2f42 | |||
| 55a0a39881 | |||
| 592215dd30 | |||
| ef0c2a2785 | |||
| 37979e452a | |||
| e9671bb727 | |||
| aa328bd591 | |||
| 188e4313f9 | |||
| df02c70e31 | |||
| 257f54b323 | |||
| fb4b5b2575 | |||
| 4e1251276d | |||
| a7b200dc57 | |||
| 8cadbae80e | |||
| c3bae49aae | |||
|
|
6fa4fc6149 | ||
| f1ffe1acaa | |||
| 5c9ddf7f00 | |||
| 431767a150 | |||
| 8ba4e442a6 | |||
| 2f8d19c267 | |||
| f2fd98f742 | |||
| 3ce35d6e81 | |||
| 796dbaa836 | |||
| 84b209ec7f | |||
| fa976b34dc | |||
| e7cda362b7 | |||
| a41a09c162 | |||
| e82f84f0ab | |||
| f1d387ceea | |||
| 3893d4d1f8 | |||
| cf7ac50faf | |||
| 3f6bf15554 | |||
| dac74829b4 | |||
| 94d6f213a0 | |||
| 8f2550ef61 | |||
| b622a1cc5e | |||
| c83a3c32c7 | |||
| e7dcf7f7e7 | |||
| 398785a2be | |||
| 05dba0f1f5 | |||
| 39dbd32b2e | |||
| 23a34a455a | |||
| 4308328b48 |
4
.github/workflows/build_linux.yml
vendored
4
.github/workflows/build_linux.yml
vendored
@@ -16,7 +16,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 build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install 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
|
||||||
@@ -44,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
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev libwayland-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
|
|||||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install 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
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ 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__);
|
||||||
@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.
|
||||||
|
LightData GetDirectionalLight() { return DirectionalLight; }
|
||||||
|
LightData GetSkyLight() { return SkyLight; }
|
||||||
|
ProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
|
||||||
|
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
|
||||||
|
uint GetLocalLightsCount() { return LocalLightsCount; }
|
||||||
|
LightData GetLocalLight(uint i) { return LocalLights[i]; }
|
||||||
@5// Forward Shading: Shaders
|
@5// Forward Shading: Shaders
|
||||||
|
|
||||||
// Pixel Shader function for Forward Pass
|
// Pixel Shader function for Forward Pass
|
||||||
@@ -76,9 +83,8 @@ void PS_Forward(
|
|||||||
gBuffer.ShadingModel = MATERIAL_SHADING_MODEL;
|
gBuffer.ShadingModel = MATERIAL_SHADING_MODEL;
|
||||||
|
|
||||||
// Calculate lighting from a single directional light
|
// Calculate lighting from a single directional light
|
||||||
float4 shadowMask = 1.0f;
|
|
||||||
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
|
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
|
||||||
shadowMask = GetShadowMask(shadow);
|
float4 shadowMask = GetShadowMask(shadow);
|
||||||
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
||||||
|
|
||||||
// Calculate lighting from sky light
|
// Calculate lighting from sky light
|
||||||
@@ -143,9 +149,9 @@ void PS_Forward(
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_FOG
|
#if USE_FOG && MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT
|
||||||
// Calculate exponential height fog
|
// Calculate exponential height fog
|
||||||
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0);
|
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z);
|
||||||
|
|
||||||
// Apply fog to the output color
|
// Apply fog to the output color
|
||||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#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/TerrainCommon.hlsl"
|
||||||
@7
|
@7
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
META_CB_BEGIN(0, Data)
|
META_CB_BEGIN(0, Data)
|
||||||
@@ -334,7 +335,7 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
float lodValue = CurrentLOD;
|
float lodValue = CurrentLOD;
|
||||||
float morphAlpha = lodCalculated - CurrentLOD;
|
float morphAlpha = lodCalculated - CurrentLOD;
|
||||||
|
|
||||||
// Sample heightmap
|
// Sample heightmap and splatmaps
|
||||||
float2 heightmapUVs = input.TexCoord * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
|
float2 heightmapUVs = input.TexCoord * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
|
||||||
#if USE_SMOOTH_LOD_TRANSITION
|
#if USE_SMOOTH_LOD_TRANSITION
|
||||||
float4 heightmapValueThisLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
float4 heightmapValueThisLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
||||||
@@ -342,7 +343,6 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
float2 heightmapUVsNextLOD = nextLODPos * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
|
float2 heightmapUVsNextLOD = nextLODPos * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
|
||||||
float4 heightmapValueNextLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
|
float4 heightmapValueNextLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
|
||||||
float4 heightmapValue = lerp(heightmapValueThisLOD, heightmapValueNextLOD, morphAlpha);
|
float4 heightmapValue = lerp(heightmapValueThisLOD, heightmapValueNextLOD, morphAlpha);
|
||||||
bool isHole = max(heightmapValueThisLOD.b + heightmapValueThisLOD.a, heightmapValueNextLOD.b + heightmapValueNextLOD.a) >= 1.9f;
|
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
float4 splatmapValueThisLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
float4 splatmapValueThisLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
||||||
float4 splatmapValueNextLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
|
float4 splatmapValueNextLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
|
||||||
@@ -355,7 +355,6 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
float4 heightmapValue = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
float4 heightmapValue = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
||||||
bool isHole = (heightmapValue.b + heightmapValue.a) >= 1.9f;
|
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
float4 splatmap0Value = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
float4 splatmap0Value = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
|
||||||
#if TERRAIN_LAYERS_DATA_SIZE > 1
|
#if TERRAIN_LAYERS_DATA_SIZE > 1
|
||||||
@@ -363,12 +362,11 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
float height = (float)((int)(heightmapValue.x * 255.0) + ((int)(heightmapValue.y * 255) << 8)) / 65535.0;
|
float height = DecodeHeightmapHeight(heightmapValue);
|
||||||
|
|
||||||
// Extract normal and the holes mask
|
// Extract normal and the holes mask
|
||||||
float2 normalTemp = float2(heightmapValue.b, heightmapValue.a) * 2.0f - 1.0f;
|
bool isHole;
|
||||||
float3 normal = float3(normalTemp.x, sqrt(1.0 - saturate(dot(normalTemp, normalTemp))), normalTemp.y);
|
float3 normal = DecodeHeightmapNormal(heightmapValue, isHole);
|
||||||
normal = normalize(normal);
|
|
||||||
output.Geometry.HolesMask = isHole ? 0 : 1;
|
output.Geometry.HolesMask = isHole ? 0 : 1;
|
||||||
if (isHole)
|
if (isHole)
|
||||||
{
|
{
|
||||||
@@ -438,7 +436,6 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
// Apply world position offset per-vertex
|
// Apply world position offset per-vertex
|
||||||
#if USE_POSITION_OFFSET
|
#if USE_POSITION_OFFSET
|
||||||
output.Geometry.WorldPosition += material.PositionOffset;
|
output.Geometry.WorldPosition += material.PositionOffset;
|
||||||
output.Geometry.PrevWorldPosition += material.PositionOffset;
|
|
||||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
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/Shaders/Editor/Grid.flax
(Stored with Git LFS)
BIN
Content/Shaders/Editor/Grid.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/ProbesFilter.flax
(Stored with Git LFS)
BIN
Content/Shaders/ProbesFilter.flax
(Stored with Git LFS)
Binary file not shown.
@@ -2,9 +2,9 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 10,
|
"Minor": 11,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6705
|
"Build": 6800
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"Configuration": {
|
"Configuration": {
|
||||||
"UseCSharp": true,
|
"UseCSharp": true,
|
||||||
"UseLargeWorlds": false,
|
"UseLargeWorlds": false,
|
||||||
"UseDotNet": true
|
"UseDotNet": true,
|
||||||
|
"UseSDL": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,6 +267,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=comperand/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=comperand/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=coord/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=coord/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=cubemap/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=cubemap/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDGI/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Deformer/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Deformer/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=deformers/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=deformers/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=defragmentation/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=defragmentation/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -14,4 +14,4 @@ bash ./Development/Scripts/Linux/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=x64 -platform=Linux --buildTargets=FlaxEditor
|
#Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -6,7 +6,7 @@
|
|||||||
Flax Engine is a high quality modern 3D game engine written in C++ and C#.
|
Flax Engine is a high quality modern 3D game engine written in C++ and C#.
|
||||||
From stunning graphics to powerful scripts, it's designed for fast workflow with many ready-to-use features waiting for you right now. To learn more see the website ([www.flaxengine.com](https://flaxengine.com)).
|
From stunning graphics to powerful scripts, it's designed for fast workflow with many ready-to-use features waiting for you right now. To learn more see the website ([www.flaxengine.com](https://flaxengine.com)).
|
||||||
|
|
||||||
This repository contains full source code of the Flax Engine (excluding NDA-protected platforms support). Anyone is welcome to contribute or use the modified source in Flax-based games.
|
This repository contains full source code of the Flax Engine (excluding NDA-protected platforms support). Documentation source is also available in a separate repository. Anyone is welcome to contribute or use the modified source in Flax-based games.
|
||||||
|
|
||||||
# Development
|
# Development
|
||||||
|
|
||||||
@@ -46,21 +46,26 @@ Follow the instructions below to compile and run the engine from source.
|
|||||||
* Install Visual Studio Code
|
* Install Visual Studio Code
|
||||||
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||||
* Ubuntu: `sudo apt install dotnet-sdk-8.0`
|
* Ubuntu: `sudo apt install dotnet-sdk-8.0`
|
||||||
|
* Fedora: `sudo dnf install dotnet-sdk-8.0`
|
||||||
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
|
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
|
||||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||||
* Ubuntu: `sudo apt install vulkan-sdk`
|
* Ubuntu: `sudo apt install vulkan-sdk`
|
||||||
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
|
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
|
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
* Install Git with LFS
|
* Install Git with LFS
|
||||||
* Ubuntu: `sudo apt-get install git git-lfs`
|
* Ubuntu: `sudo apt-get install git git-lfs`
|
||||||
* Arch: `sudo pacman -S git git-lfs`
|
* Arch: `sudo pacman -S git git-lfs`
|
||||||
* `git-lfs install`
|
* `git-lfs install`
|
||||||
* Install the required packages:
|
* Install the required packages:
|
||||||
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
|
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev zenity wayland-protocols libportal-dev`
|
||||||
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
|
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel zenity wayland-protocols-devel libportal`
|
||||||
|
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib zenity wayland-protocols libportal`
|
||||||
* Install Clang compiler (version 6 or later):
|
* Install Clang compiler (version 6 or later):
|
||||||
* Ubuntu: `sudo apt-get install clang lldb lld`
|
* Ubuntu: `sudo apt-get install clang lldb lld`
|
||||||
|
* Fedora: `sudo dnf install clang llvm lldb lld`
|
||||||
* Arch: `sudo pacman -S clang lldb lld`
|
* Arch: `sudo pacman -S clang lldb lld`
|
||||||
* Clone the repository (with LFS)
|
* Clone the repository (with LFS)
|
||||||
|
* git-lfs clone https://github.com/FlaxEngine/FlaxEngine.git
|
||||||
* Run `./GenerateProjectFiles.sh`
|
* Run `./GenerateProjectFiles.sh`
|
||||||
* Open workspace with Visual Code
|
* Open workspace with Visual Code
|
||||||
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)
|
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)
|
||||||
|
|||||||
@@ -174,7 +174,9 @@ void EditorAnalytics::StartSession()
|
|||||||
// Bind events
|
// Bind events
|
||||||
GameCooker::OnEvent.Bind<RegisterGameCookingStart>();
|
GameCooker::OnEvent.Bind<RegisterGameCookingStart>();
|
||||||
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Bind<RegisterLightmapsBuildingStart>();
|
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Bind<RegisterLightmapsBuildingStart>();
|
||||||
|
#if LOG_ENABLE
|
||||||
Log::Logger::OnError.Bind<RegisterError>();
|
Log::Logger::OnError.Bind<RegisterError>();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorAnalytics::EndSession()
|
void EditorAnalytics::EndSession()
|
||||||
@@ -187,7 +189,9 @@ void EditorAnalytics::EndSession()
|
|||||||
// Unbind events
|
// Unbind events
|
||||||
GameCooker::OnEvent.Unbind<RegisterGameCookingStart>();
|
GameCooker::OnEvent.Unbind<RegisterGameCookingStart>();
|
||||||
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Unbind<RegisterLightmapsBuildingStart>();
|
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Unbind<RegisterLightmapsBuildingStart>();
|
||||||
|
#if LOG_ENABLE
|
||||||
Log::Logger::OnError.Unbind<RegisterError>();
|
Log::Logger::OnError.Unbind<RegisterError>();
|
||||||
|
#endif
|
||||||
|
|
||||||
// End session
|
// End session
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string ResultUrl { get; }
|
public string ResultUrl { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating wether a file can be created based on the current settings.
|
||||||
|
/// </summary>
|
||||||
|
public abstract bool CanBeCreated { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this entry has settings to modify.
|
/// Gets a value indicating whether this entry has settings to modify.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ namespace FlaxEditor.Content.Create
|
|||||||
Text = "Create",
|
Text = "Create",
|
||||||
AnchorPreset = AnchorPresets.BottomRight,
|
AnchorPreset = AnchorPresets.BottomRight,
|
||||||
Offsets = new Margin(-ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
|
Offsets = new Margin(-ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
|
||||||
Parent = this
|
Parent = this,
|
||||||
|
Enabled = entry.CanBeCreated,
|
||||||
};
|
};
|
||||||
createButton.Clicked += OnSubmit;
|
createButton.Clicked += OnSubmit;
|
||||||
var cancelButton = new Button
|
var cancelButton = new Button
|
||||||
@@ -68,7 +69,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
Text = "Cancel",
|
Text = "Cancel",
|
||||||
AnchorPreset = AnchorPresets.BottomRight,
|
AnchorPreset = AnchorPresets.BottomRight,
|
||||||
Offsets = new Margin(-ButtonsWidth - ButtonsMargin - ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
|
Offsets = new Margin(-ButtonsWidth - ButtonsMargin - ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
|
||||||
Parent = this
|
Parent = this,
|
||||||
};
|
};
|
||||||
cancelButton.Clicked += OnCancel;
|
cancelButton.Clicked += OnCancel;
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
{
|
{
|
||||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||||
Offsets = new Margin(2, 2, infoLabel.Bottom + 2, EditorHeight),
|
Offsets = new Margin(2, 2, infoLabel.Bottom + 2, EditorHeight),
|
||||||
Parent = this
|
Parent = this,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings editor
|
// Settings editor
|
||||||
@@ -87,6 +88,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
_dialogSize = new Float2(TotalWidth, panel.Bottom);
|
_dialogSize = new Float2(TotalWidth, panel.Bottom);
|
||||||
|
|
||||||
_settingsEditor.Select(_entry.Settings);
|
_settingsEditor.Select(_entry.Settings);
|
||||||
|
_settingsEditor.Modified += () => createButton.Enabled = _entry.CanBeCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
public class ParticleEmitterCreateEntry : CreateFileEntry
|
public class ParticleEmitterCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool CanBeCreated => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Types of the emitter templates that can be created.
|
/// Types of the emitter templates that can be created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
public class PrefabCreateEntry : CreateFileEntry
|
public class PrefabCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanBeCreated => _options.RootActorType != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The create options.
|
/// The create options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -73,6 +76,9 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
public class WidgetCreateEntry : CreateFileEntry
|
public class WidgetCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool CanBeCreated => _options.RootControlType != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The create options.
|
/// The create options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
internal class SettingsCreateEntry : CreateFileEntry
|
internal class SettingsCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
public override bool CanBeCreated => _options.Type != null;
|
||||||
|
|
||||||
internal class Options
|
internal class Options
|
||||||
{
|
{
|
||||||
[Tooltip("The settings type.")]
|
[Tooltip("The settings type.")]
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
public class VisualScriptCreateEntry : CreateFileEntry
|
public class VisualScriptCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool CanBeCreated => _options.BaseClass != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The create options.
|
/// The create options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ namespace FlaxEditor.Content.GUI
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
value = Mathf.Clamp(value, 0.3f, 3.0f);
|
value = Mathf.Clamp(value, 0.3f, 3.0f);
|
||||||
if (!Mathf.NearEqual(value, _viewScale))
|
if (value != _viewScale)
|
||||||
{
|
{
|
||||||
_viewScale = value;
|
_viewScale = value;
|
||||||
ViewScaleChanged?.Invoke();
|
ViewScaleChanged?.Invoke();
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
if (data is DragDataFiles)
|
if (data is DragDataFiles)
|
||||||
return DragDropEffect.Copy;
|
return DragDropEffect.Copy;
|
||||||
return _dragOverItems.Effect;
|
return _dragOverItems?.Effect ?? DragDropEffect.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace FlaxEditor.Content
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string TypeDescription => Path.EndsWith(".h") ? "C++ Header File" : "C++ Source Code";
|
public override string TypeDescription => Path.EndsWith(".h") || Path.EndsWith(".hpp") ? "C++ Header File" : "C++ Source Code";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
|
||||||
public class GenericJsonCreateEntry : CreateFileEntry
|
public class GenericJsonCreateEntry : CreateFileEntry
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool CanBeCreated => _options.Type != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The create options.
|
/// The create options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ using FlaxEngine;
|
|||||||
namespace FlaxEditor.Content
|
namespace FlaxEditor.Content
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
|
/// Base class for shader source files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
|
public abstract class ShaderBaseProxy : ContentProxy
|
||||||
[ContentContextMenu("New/Shader Source")]
|
|
||||||
public class ShaderSourceProxy : ContentProxy
|
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanCreate(ContentFolder targetLocation)
|
public override bool CanCreate(ContentFolder targetLocation)
|
||||||
@@ -29,6 +27,21 @@ namespace FlaxEditor.Content
|
|||||||
return targetLocation.ShortName == "Source" && prevTargetLocation.ShortName == "Shaders";
|
return targetLocation.ShortName == "Source" && prevTargetLocation.ShortName == "Shaders";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override EditorWindow Open(Editor editor, ContentItem item)
|
||||||
|
{
|
||||||
|
Editor.Instance.CodeEditing.OpenFile(item.Path);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
|
||||||
|
[ContentContextMenu("New/Shader Source (.shader)")]
|
||||||
|
public class ShaderSourceProxy : ShaderBaseProxy
|
||||||
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Create(string outputPath, object arg)
|
public override void Create(string outputPath, object arg)
|
||||||
{
|
{
|
||||||
@@ -44,13 +57,6 @@ namespace FlaxEditor.Content
|
|||||||
File.WriteAllText(outputPath, shaderTemplate, Encoding.UTF8);
|
File.WriteAllText(outputPath, shaderTemplate, Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override EditorWindow Open(Editor editor, ContentItem item)
|
|
||||||
{
|
|
||||||
Editor.Instance.CodeEditing.OpenFile(item.Path);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Color AccentColor => Color.FromRGB(0x7542f5);
|
public override Color AccentColor => Color.FromRGB(0x7542f5);
|
||||||
|
|
||||||
@@ -66,4 +72,33 @@ namespace FlaxEditor.Content
|
|||||||
return item is ShaderSourceItem;
|
return item is ShaderSourceItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Context proxy object for shader header files.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
|
||||||
|
[ContentContextMenu("New/Shader Header (.hlsl)")]
|
||||||
|
public class ShaderHeaderProxy : ShaderBaseProxy
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Create(string outputPath, object arg)
|
||||||
|
{
|
||||||
|
File.WriteAllText(outputPath, "\n", Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Color AccentColor => Color.FromRGB(0x2545a5);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string FileExtension => "hlsl";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Name => "Shader Header";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IsProxyFor(ContentItem item)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
||||||
#include "Engine/Content/JsonAsset.h"
|
#include "Engine/Content/JsonAsset.h"
|
||||||
#include "Engine/Content/AssetReference.h"
|
#include "Engine/Content/AssetReference.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
#include "Platform/Windows/WindowsPlatformTools.h"
|
#include "Platform/Windows/WindowsPlatformTools.h"
|
||||||
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
||||||
@@ -380,6 +381,7 @@ bool GameCooker::IsCancelRequested()
|
|||||||
|
|
||||||
PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
PlatformTools* result = nullptr;
|
PlatformTools* result = nullptr;
|
||||||
if (!Tools.TryGet(platform, result))
|
if (!Tools.TryGet(platform, result))
|
||||||
{
|
{
|
||||||
@@ -471,6 +473,7 @@ bool GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
|
|||||||
LOG(Error, "Build platform {0} is not supported.", ::ToString(platform));
|
LOG(Error, "Build platform {0} is not supported.", ::ToString(platform));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
CancelFlag = 0;
|
CancelFlag = 0;
|
||||||
@@ -624,6 +627,7 @@ void GameCookerImpl::ReportProgress(const String& info, float totalProgress)
|
|||||||
|
|
||||||
void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
|
void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
if (Internal_OnCollectAssets == nullptr)
|
if (Internal_OnCollectAssets == nullptr)
|
||||||
{
|
{
|
||||||
auto c = GameCooker::GetStaticClass();
|
auto c = GameCooker::GetStaticClass();
|
||||||
@@ -651,6 +655,7 @@ void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
|
|||||||
|
|
||||||
bool GameCookerImpl::Build()
|
bool GameCookerImpl::Build()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
CookingData& data = *Data;
|
CookingData& data = *Data;
|
||||||
LOG(Info, "Starting Game Cooker...");
|
LOG(Info, "Starting Game Cooker...");
|
||||||
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
|
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
|
||||||
@@ -778,6 +783,8 @@ int32 GameCookerImpl::ThreadFunction()
|
|||||||
|
|
||||||
bool GameCookerService::Init()
|
bool GameCookerService::Init()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
|
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
|
||||||
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
|
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
|
||||||
GameCooker::OnCollectAssets.Bind(OnCollectAssets);
|
GameCooker::OnCollectAssets.Bind(OnCollectAssets);
|
||||||
@@ -789,6 +796,7 @@ void GameCookerService::Update()
|
|||||||
{
|
{
|
||||||
if (IsRunning)
|
if (IsRunning)
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
ScopeLock lock(ProgressLocker);
|
ScopeLock lock(ProgressLocker);
|
||||||
|
|
||||||
if (ProgressMsg.HasChars())
|
if (ProgressMsg.HasChars())
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
ADD_ENTRY("CFBundlePackageType", "APPL");
|
ADD_ENTRY("CFBundlePackageType", "APPL");
|
||||||
ADD_ENTRY("NSPrincipalClass", "NSApplication");
|
ADD_ENTRY("NSPrincipalClass", "NSApplication");
|
||||||
ADD_ENTRY("LSApplicationCategoryType", "public.app-category.games");
|
ADD_ENTRY("LSApplicationCategoryType", "public.app-category.games");
|
||||||
ADD_ENTRY("LSMinimumSystemVersion", "10.15");
|
ADD_ENTRY("LSMinimumSystemVersion", "13");
|
||||||
ADD_ENTRY("CFBundleIconFile", "icon.icns");
|
ADD_ENTRY("CFBundleIconFile", "icon.icns");
|
||||||
ADD_ENTRY_STR("CFBundleExecutable", executableName);
|
ADD_ENTRY_STR("CFBundleExecutable", executableName);
|
||||||
ADD_ENTRY_STR("CFBundleIdentifier", appIdentifier);
|
ADD_ENTRY_STR("CFBundleIdentifier", appIdentifier);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "Engine/Engine/Base/GameBase.h"
|
#include "Engine/Engine/Base/GameBase.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||||
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Scripting/Enums.h"
|
#include "Engine/Scripting/Enums.h"
|
||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using FlaxEditor.SceneGraph;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -52,6 +53,16 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodes">The nodes to select</param>
|
/// <param name="nodes">The nodes to select</param>
|
||||||
public void Select(List<SceneGraph.SceneGraphNode> nodes);
|
public void Select(List<SceneGraph.SceneGraphNode> nodes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current selection.
|
||||||
|
/// </summary>
|
||||||
|
public List<SceneGraphNode> Selection { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indication of if the properties window is locked on specific objects.
|
||||||
|
/// </summary>
|
||||||
|
public bool LockSelection { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -81,6 +92,8 @@ namespace FlaxEditor.CustomEditors
|
|||||||
Offsets = Margin.Zero;
|
Offsets = Margin.Zero;
|
||||||
Pivot = Float2.Zero;
|
Pivot = Float2.Zero;
|
||||||
IsScrollable = true;
|
IsScrollable = true;
|
||||||
|
Spacing = Utilities.Constants.UIMargin;
|
||||||
|
Margin = new Margin(Utilities.Constants.UIMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -95,7 +108,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
{
|
{
|
||||||
FlaxEditor.Editor.LogWarning(ex);
|
FlaxEditor.Editor.LogWarning(ex);
|
||||||
|
|
||||||
// Refresh layout on errors to reduce lgo spam
|
// Refresh layout on errors to reduce log spam
|
||||||
_presenter.BuildLayout();
|
_presenter.BuildLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "Engine/Core/Types/TimeSpan.h"
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
#include "Engine/Core/Types/Stopwatch.h"
|
#include "Engine/Core/Types/Stopwatch.h"
|
||||||
#include "Engine/Core/Collections/Dictionary.h"
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Scripting/Scripting.h"
|
#include "Engine/Scripting/Scripting.h"
|
||||||
#include "Engine/Scripting/BinaryModule.h"
|
#include "Engine/Scripting/BinaryModule.h"
|
||||||
@@ -69,6 +71,7 @@ MTypeObject* CustomEditorsUtil::GetCustomEditor(MTypeObject* refType)
|
|||||||
|
|
||||||
bool CustomEditorsUtilService::Init()
|
bool CustomEditorsUtilService::Init()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
TRACK_ASSEMBLY(((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly);
|
TRACK_ASSEMBLY(((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly);
|
||||||
Scripting::BinaryModuleLoaded.Bind(&OnBinaryModuleLoaded);
|
Scripting::BinaryModuleLoaded.Bind(&OnBinaryModuleLoaded);
|
||||||
|
|
||||||
@@ -77,6 +80,8 @@ bool CustomEditorsUtilService::Init()
|
|||||||
|
|
||||||
void OnAssemblyLoaded(MAssembly* assembly)
|
void OnAssemblyLoaded(MAssembly* assembly)
|
||||||
{
|
{
|
||||||
|
PROFILE_CPU_NAMED("CustomEditors.OnAssemblyLoaded");
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
Stopwatch stopwatch;
|
Stopwatch stopwatch;
|
||||||
|
|
||||||
// Prepare FlaxEngine
|
// Prepare FlaxEngine
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ using FlaxEditor.CustomEditors.Elements;
|
|||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Tree;
|
using FlaxEditor.GUI.Tree;
|
||||||
using FlaxEditor.Modules;
|
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Windows;
|
using FlaxEditor.Windows;
|
||||||
using FlaxEditor.Windows.Assets;
|
using FlaxEditor.Windows.Assets;
|
||||||
@@ -71,7 +70,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
|
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
|
||||||
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
|
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
|
||||||
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
|
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
|
||||||
var panel = layout.CustomContainer<UniformGridPanel>();
|
var panel = layout.UniformGrid();
|
||||||
panel.CustomControl.Height = 20.0f;
|
panel.CustomControl.Height = 20.0f;
|
||||||
panel.CustomControl.SlotsVertically = 1;
|
panel.CustomControl.SlotsVertically = 1;
|
||||||
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter || nestedPrefab)
|
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter || nestedPrefab)
|
||||||
@@ -133,35 +132,22 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var actor = (Actor)Values[0];
|
var actor = (Actor)Values[0];
|
||||||
var scriptType = TypeUtils.GetType(actor.TypeName);
|
var scriptType = TypeUtils.GetType(actor.TypeName);
|
||||||
var item = scriptType.ContentItem;
|
var item = scriptType.ContentItem;
|
||||||
if (Presenter.Owner is PropertiesWindow propertiesWindow)
|
if (Presenter.Owner != null)
|
||||||
{
|
{
|
||||||
var lockButton = cm.AddButton(propertiesWindow.LockObjects ? "Unlock" : "Lock");
|
var lockButton = cm.AddButton(Presenter.Owner.LockSelection ? "Unlock" : "Lock");
|
||||||
lockButton.ButtonClicked += button =>
|
lockButton.ButtonClicked += button =>
|
||||||
{
|
{
|
||||||
propertiesWindow.LockObjects = !propertiesWindow.LockObjects;
|
var owner = Presenter?.Owner;
|
||||||
|
if (owner == null)
|
||||||
|
return;
|
||||||
|
owner.LockSelection = !owner.LockSelection;
|
||||||
|
|
||||||
// Reselect current selection
|
// Reselect current selection
|
||||||
if (!propertiesWindow.LockObjects && Editor.Instance.SceneEditing.SelectionCount > 0)
|
if (!owner.LockSelection && owner.Selection.Count > 0)
|
||||||
{
|
{
|
||||||
var cachedSelection = Editor.Instance.SceneEditing.Selection.ToArray();
|
var cachedSelection = owner.Selection.ToList();
|
||||||
Editor.Instance.SceneEditing.Select(null);
|
owner.Select(null);
|
||||||
Editor.Instance.SceneEditing.Select(cachedSelection);
|
owner.Select(cachedSelection);
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (Presenter.Owner is PrefabWindow prefabWindow)
|
|
||||||
{
|
|
||||||
var lockButton = cm.AddButton(prefabWindow.LockSelectedObjects ? "Unlock" : "Lock");
|
|
||||||
lockButton.ButtonClicked += button =>
|
|
||||||
{
|
|
||||||
prefabWindow.LockSelectedObjects = !prefabWindow.LockSelectedObjects;
|
|
||||||
|
|
||||||
// Reselect current selection
|
|
||||||
if (!prefabWindow.LockSelectedObjects && prefabWindow.Selection.Count > 0)
|
|
||||||
{
|
|
||||||
var cachedSelection = prefabWindow.Selection.ToList();
|
|
||||||
prefabWindow.Select(null);
|
|
||||||
prefabWindow.Select(cachedSelection);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -258,7 +244,17 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
else if (editor.Values[0] is SceneObject sceneObject)
|
else if (editor.Values[0] is SceneObject sceneObject)
|
||||||
{
|
{
|
||||||
node.TextColor = sceneObject.HasPrefabLink ? FlaxEngine.GUI.Style.Current.ProgressNormal : FlaxEngine.GUI.Style.Current.BackgroundSelected;
|
node.TextColor = sceneObject.HasPrefabLink ? FlaxEngine.GUI.Style.Current.ProgressNormal : FlaxEngine.GUI.Style.Current.BackgroundSelected;
|
||||||
node.Text = Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name);
|
if (editor.Values.Info != ScriptMemberInfo.Null)
|
||||||
|
{
|
||||||
|
if (editor.Values.GetAttributes().FirstOrDefault(x => x is EditorDisplayAttribute) is EditorDisplayAttribute editorDisplayAttribute && !string.IsNullOrEmpty(editorDisplayAttribute.Name))
|
||||||
|
node.Text = $"{Utilities.Utils.GetPropertyNameUI(editorDisplayAttribute.Name)} ({Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name)})";
|
||||||
|
else
|
||||||
|
node.Text = Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name);
|
||||||
|
}
|
||||||
|
else if (sceneObject is Actor actor)
|
||||||
|
node.Text = $"{actor.Name} ({Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name)})";
|
||||||
|
else
|
||||||
|
node.Text = Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name);
|
||||||
}
|
}
|
||||||
// Array Item
|
// Array Item
|
||||||
else if (editor.ParentEditor is CollectionEditor)
|
else if (editor.ParentEditor is CollectionEditor)
|
||||||
@@ -268,7 +264,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Common type
|
// Common type
|
||||||
else if (editor.Values.Info != ScriptMemberInfo.Null)
|
else if (editor.Values.Info != ScriptMemberInfo.Null)
|
||||||
{
|
{
|
||||||
node.Text = Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name);
|
if (editor.Values.GetAttributes().FirstOrDefault(x => x is EditorDisplayAttribute) is EditorDisplayAttribute editorDisplayAttribute
|
||||||
|
&& !string.IsNullOrEmpty(editorDisplayAttribute.Name)
|
||||||
|
&& !editorDisplayAttribute.Name.Contains("_inline"))
|
||||||
|
node.Text = $"{Utilities.Utils.GetPropertyNameUI(editorDisplayAttribute.Name)} ({Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name)})";
|
||||||
|
else
|
||||||
|
node.Text = Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name);
|
||||||
}
|
}
|
||||||
// Custom type
|
// Custom type
|
||||||
else if (editor.Values[0] != null)
|
else if (editor.Values[0] != null)
|
||||||
@@ -316,7 +317,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var childEditor = editor.ChildrenEditors[i];
|
var childEditor = editor.ChildrenEditors[i];
|
||||||
|
|
||||||
// Special case for root actor transformation (can be applied only in Prefab editor, not in Level)
|
// Special case for root actor transformation (can be applied only in Prefab editor, not in Level)
|
||||||
if (isActorEditorInLevel && childEditor.Values.Info.Name is "LocalPosition" or "LocalOrientation" or "LocalScale")
|
if (isActorEditorInLevel && childEditor.Values.Info.Name is "LocalPosition" or "LocalOrientation" or "LocalScale" or "Name")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var child = ProcessDiff(childEditor, !isScriptEditorWithRefValue);
|
var child = ProcessDiff(childEditor, !isScriptEditorWithRefValue);
|
||||||
@@ -361,13 +362,39 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TreeNode CreateDiffTree(Actor actor, CustomEditorPresenter presenter, LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
var actorNode = Editor.Instance.Scene.GetActorNode(actor);
|
||||||
|
ValueContainer vc = new ValueContainer(ScriptMemberInfo.Null);
|
||||||
|
vc.SetType(new ScriptType(actorNode.EditableObject.GetType()));
|
||||||
|
vc.Add(actorNode.EditableObject);
|
||||||
|
var editor = CustomEditorsUtil.CreateEditor(vc, null, false);
|
||||||
|
editor.Initialize(presenter, layout, vc);
|
||||||
|
var node = ProcessDiff(editor, false);
|
||||||
|
layout.ClearLayout();
|
||||||
|
foreach (var child in actor.Children)
|
||||||
|
{
|
||||||
|
var childNode = CreateDiffTree(child, presenter, layout);
|
||||||
|
if (childNode == null)
|
||||||
|
continue;
|
||||||
|
if (node == null)
|
||||||
|
node = CreateDiffNode(editor);
|
||||||
|
node.AddChild(childNode);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
private void ViewChanges(Control target, Float2 targetLocation)
|
private void ViewChanges(Control target, Float2 targetLocation)
|
||||||
{
|
{
|
||||||
// Build a tree out of modified properties
|
// Build a tree out of modified properties
|
||||||
var rootNode = ProcessDiff(this, false);
|
var thisActor = (Actor)Values[0];
|
||||||
|
var rootActor = thisActor.IsPrefabRoot ? thisActor : thisActor.GetPrefabRoot();
|
||||||
|
var presenter = new CustomEditorPresenter(null);
|
||||||
|
var layout = new CustomElementsContainer<ContainerControl>();
|
||||||
|
var rootNode = CreateDiffTree(rootActor, presenter, layout);
|
||||||
|
|
||||||
// Skip if no changes detected
|
// Skip if no changes detected
|
||||||
if (rootNode == null || rootNode.ChildrenCount == 0)
|
if (rootNode == null)
|
||||||
{
|
{
|
||||||
var cm1 = new ContextMenu();
|
var cm1 = new ContextMenu();
|
||||||
cm1.AddButton("No changes detected");
|
cm1.AddButton("No changes detected");
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
_infoLabel.AutoHeight = true;
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
var grid = playbackGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var paintValue = new ReadOnlyValueContainer(new ScriptType(typeof(ClothPaintingGizmoMode)), _gizmoMode);
|
var paintValue = new ReadOnlyValueContainer(new ScriptType(typeof(ClothPaintingGizmoMode)), _gizmoMode);
|
||||||
paintGroup.Object(paintValue);
|
paintGroup.Object(paintValue);
|
||||||
{
|
{
|
||||||
var grid = paintGroup.CustomContainer<UniformGridPanel>();
|
var grid = paintGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FlaxEditor.Content.Settings;
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -16,6 +15,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
private int _layersCount;
|
private int _layersCount;
|
||||||
private List<CheckBox> _checkBoxes;
|
private List<CheckBox> _checkBoxes;
|
||||||
|
private VerticalPanel _upperRightCell;
|
||||||
|
private VerticalPanel _bottomLeftCell;
|
||||||
|
private UniformGridPanel _grid;
|
||||||
|
private Border _horizontalHighlight;
|
||||||
|
private Border _verticalHighlight;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DisplayStyle Style => DisplayStyle.InlineIntoParent;
|
public override DisplayStyle Style => DisplayStyle.InlineIntoParent;
|
||||||
@@ -37,12 +41,29 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
Parent = panel,
|
Parent = panel,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var style = FlaxEngine.GUI.Style.Current;
|
||||||
|
_horizontalHighlight = new Border()
|
||||||
|
{
|
||||||
|
Parent = panel,
|
||||||
|
BorderColor = style.Foreground,
|
||||||
|
BorderWidth = 1.0f,
|
||||||
|
Visible = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
_verticalHighlight = new Border()
|
||||||
|
{
|
||||||
|
Parent = panel,
|
||||||
|
BorderColor = style.Foreground,
|
||||||
|
BorderWidth = 1.0f,
|
||||||
|
Visible = false,
|
||||||
|
};
|
||||||
|
|
||||||
var upperLeftCell = new Label
|
var upperLeftCell = new Label
|
||||||
{
|
{
|
||||||
Parent = gridPanel,
|
Parent = gridPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
var upperRightCell = new VerticalPanel
|
_upperRightCell = new VerticalPanel
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
Pivot = new Float2(0.00001f, 0.0f),
|
Pivot = new Float2(0.00001f, 0.0f),
|
||||||
@@ -54,7 +75,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
Parent = gridPanel,
|
Parent = gridPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
var bottomLeftCell = new VerticalPanel
|
_bottomLeftCell = new VerticalPanel
|
||||||
{
|
{
|
||||||
Pivot = Float2.Zero,
|
Pivot = Float2.Zero,
|
||||||
Spacing = 0,
|
Spacing = 0,
|
||||||
@@ -63,7 +84,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
Parent = gridPanel,
|
Parent = gridPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
var grid = new UniformGridPanel(0)
|
_grid = new UniformGridPanel(0)
|
||||||
{
|
{
|
||||||
SlotsHorizontally = layersCount,
|
SlotsHorizontally = layersCount,
|
||||||
SlotsVertically = layersCount,
|
SlotsVertically = layersCount,
|
||||||
@@ -74,13 +95,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
int layerIndex = 0;
|
int layerIndex = 0;
|
||||||
for (; layerIndex < layerNames.Length; layerIndex++)
|
for (; layerIndex < layerNames.Length; layerIndex++)
|
||||||
{
|
{
|
||||||
upperRightCell.AddChild(new Label
|
_upperRightCell.AddChild(new Label
|
||||||
{
|
{
|
||||||
Height = labelsHeight,
|
Height = labelsHeight,
|
||||||
Text = layerNames[layerNames.Length - layerIndex - 1],
|
Text = layerNames[layerNames.Length - layerIndex - 1],
|
||||||
HorizontalAlignment = TextAlignment.Near,
|
HorizontalAlignment = TextAlignment.Near,
|
||||||
});
|
});
|
||||||
bottomLeftCell.AddChild(new Label
|
_bottomLeftCell.AddChild(new Label
|
||||||
{
|
{
|
||||||
Height = labelsHeight,
|
Height = labelsHeight,
|
||||||
Text = layerNames[layerIndex],
|
Text = layerNames[layerIndex],
|
||||||
@@ -90,13 +111,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
for (; layerIndex < layersCount; layerIndex++)
|
for (; layerIndex < layersCount; layerIndex++)
|
||||||
{
|
{
|
||||||
string name = "Layer " + layerIndex;
|
string name = "Layer " + layerIndex;
|
||||||
upperRightCell.AddChild(new Label
|
_upperRightCell.AddChild(new Label
|
||||||
{
|
{
|
||||||
Height = labelsHeight,
|
Height = labelsHeight,
|
||||||
Text = name,
|
Text = name,
|
||||||
HorizontalAlignment = TextAlignment.Near,
|
HorizontalAlignment = TextAlignment.Near,
|
||||||
});
|
});
|
||||||
bottomLeftCell.AddChild(new Label
|
_bottomLeftCell.AddChild(new Label
|
||||||
{
|
{
|
||||||
Height = labelsHeight,
|
Height = labelsHeight,
|
||||||
Text = name,
|
Text = name,
|
||||||
@@ -118,7 +139,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var box = new CheckBox(0, 0, true)
|
var box = new CheckBox(0, 0, true)
|
||||||
{
|
{
|
||||||
Tag = new Float2(_layersCount - column - 1, row),
|
Tag = new Float2(_layersCount - column - 1, row),
|
||||||
Parent = grid,
|
Parent = _grid,
|
||||||
Checked = GetBit(column, row),
|
Checked = GetBit(column, row),
|
||||||
};
|
};
|
||||||
box.StateChanged += OnCheckBoxChanged;
|
box.StateChanged += OnCheckBoxChanged;
|
||||||
@@ -126,7 +147,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
for (; column < layersCount; column++)
|
for (; column < layersCount; column++)
|
||||||
{
|
{
|
||||||
grid.AddChild(new Label());
|
_grid.AddChild(new Label());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,6 +162,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Refresh()
|
public override void Refresh()
|
||||||
{
|
{
|
||||||
|
int selectedColumn = -1;
|
||||||
|
int selectedRow = -1;
|
||||||
|
var style = FlaxEngine.GUI.Style.Current;
|
||||||
|
bool mouseOverGrid = _grid.IsMouseOver;
|
||||||
|
|
||||||
|
// Only hide highlights if mouse is not over the grid to reduce flickering
|
||||||
|
if (!mouseOverGrid)
|
||||||
|
{
|
||||||
|
_horizontalHighlight.Visible = false;
|
||||||
|
_verticalHighlight.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Sync check boxes
|
// Sync check boxes
|
||||||
for (int i = 0; i < _checkBoxes.Count; i++)
|
for (int i = 0; i < _checkBoxes.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -148,6 +181,39 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
int column = (int)((Float2)box.Tag).X;
|
int column = (int)((Float2)box.Tag).X;
|
||||||
int row = (int)((Float2)box.Tag).Y;
|
int row = (int)((Float2)box.Tag).Y;
|
||||||
box.Checked = GetBit(column, row);
|
box.Checked = GetBit(column, row);
|
||||||
|
|
||||||
|
if (box.IsMouseOver)
|
||||||
|
{
|
||||||
|
selectedColumn = column;
|
||||||
|
selectedRow = row;
|
||||||
|
|
||||||
|
_horizontalHighlight.X = _grid.X - _bottomLeftCell.Width;
|
||||||
|
_horizontalHighlight.Y = _grid.Y + box.Y;
|
||||||
|
_horizontalHighlight.Width = _bottomLeftCell.Width + box.Width + box.X;
|
||||||
|
_horizontalHighlight.Height = box.Height;
|
||||||
|
_horizontalHighlight.Visible = true;
|
||||||
|
|
||||||
|
_verticalHighlight.X = _grid.X + box.X;
|
||||||
|
_verticalHighlight.Y = _grid.Y - _upperRightCell.Height;
|
||||||
|
_verticalHighlight.Width = box.Width;
|
||||||
|
_verticalHighlight.Height = _upperRightCell.Height + box.Height + box.Y;
|
||||||
|
_verticalHighlight.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _checkBoxes.Count; i++)
|
||||||
|
{
|
||||||
|
var box = _checkBoxes[i];
|
||||||
|
int column = (int)((Float2)box.Tag).X;
|
||||||
|
int row = (int)((Float2)box.Tag).Y;
|
||||||
|
|
||||||
|
if (!mouseOverGrid)
|
||||||
|
box.ImageColor = style.BorderSelected;
|
||||||
|
else if (selectedColumn > -1 && selectedRow > -1)
|
||||||
|
{
|
||||||
|
bool isRowOrColumn = column == selectedColumn || row == selectedRow;
|
||||||
|
box.ImageColor = style.BorderSelected * (isRowOrColumn ? 1.2f : 0.75f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,12 +92,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
// Update add button
|
// Update add button
|
||||||
var update = group.Button("Update").Button;
|
var update = group.Button("Update").Button;
|
||||||
|
group.Space(0);
|
||||||
update.TooltipText = "Refreshes the dashboard statistics";
|
update.TooltipText = "Refreshes the dashboard statistics";
|
||||||
update.Height = 16.0f;
|
update.Height = 16.0f;
|
||||||
update.Clicked += RebuildLayout;
|
update.Clicked += RebuildLayout;
|
||||||
|
|
||||||
// New locale add button
|
// New locale add button
|
||||||
var addLocale = group.Button("Add Locale...").Button;
|
var addLocale = group.Button("Add Locale...").Button;
|
||||||
|
group.Space(0);
|
||||||
addLocale.TooltipText = "Shows a locale picker and creates new localization for it with not translated string tables";
|
addLocale.TooltipText = "Shows a locale picker and creates new localization for it with not translated string tables";
|
||||||
addLocale.Height = 16.0f;
|
addLocale.Height = 16.0f;
|
||||||
addLocale.ButtonClicked += delegate(Button button)
|
addLocale.ButtonClicked += delegate(Button button)
|
||||||
@@ -167,12 +169,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
// Export button
|
// Export button
|
||||||
var exportLocalization = group.Button("Export...").Button;
|
var exportLocalization = group.Button("Export...").Button;
|
||||||
|
group.Space(0);
|
||||||
exportLocalization.TooltipText = "Exports the localization strings into .pot file for translation";
|
exportLocalization.TooltipText = "Exports the localization strings into .pot file for translation";
|
||||||
exportLocalization.Height = 16.0f;
|
exportLocalization.Height = 16.0f;
|
||||||
exportLocalization.Clicked += () => Export(tableEntries, allKeys);
|
exportLocalization.Clicked += () => Export(tableEntries, allKeys);
|
||||||
|
|
||||||
// Find localized strings in code button
|
// Find localized strings in code button
|
||||||
var findStringsCode = group.Button("Find localized strings in code").Button;
|
var findStringsCode = group.Button("Find localized strings in code").Button;
|
||||||
|
group.Space(0);
|
||||||
findStringsCode.TooltipText = "Searches for localized string usage in inside a project source files";
|
findStringsCode.TooltipText = "Searches for localized string usage in inside a project source files";
|
||||||
findStringsCode.Height = 16.0f;
|
findStringsCode.Height = 16.0f;
|
||||||
findStringsCode.Clicked += delegate
|
findStringsCode.Clicked += delegate
|
||||||
@@ -186,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);
|
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.c", SearchOption.AllDirectories)).ToArray();
|
||||||
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);
|
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray();;
|
||||||
filesCount += files.Length;
|
filesCount += files.Length;
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
FindNewKeysCpp(file, newKeys, allKeys);
|
FindNewKeysCpp(file, newKeys, allKeys);
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ public class ModelPrefabEditor : GenericEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates the import path UI
|
// Creates the import path UI
|
||||||
Utilities.Utils.CreateImportPathUI(layout, modelPrefab.ImportPath, false);
|
var group = layout.Group("Import Path");
|
||||||
|
Utilities.Utils.CreateImportPathUI(group, modelPrefab.ImportPath);
|
||||||
|
|
||||||
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
|
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
|
||||||
_reimportButton = button.Button;
|
_reimportButton = button.Button;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
_infoLabel.AutoHeight = true;
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
var grid = playbackGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
if (ragdoll.Parent is AnimatedModel animatedModel && animatedModel.SkinnedModel)
|
if (ragdoll.Parent is AnimatedModel animatedModel && animatedModel.SkinnedModel)
|
||||||
{
|
{
|
||||||
// Builder
|
// Builder
|
||||||
var grid = editorGroup.CustomContainer<UniformGridPanel>();
|
var grid = editorGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
@@ -53,7 +53,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
if (Presenter.Owner != null)
|
if (Presenter.Owner != null)
|
||||||
{
|
{
|
||||||
// Selection
|
// Selection
|
||||||
var grid = editorGroup.CustomContainer<UniformGridPanel>();
|
var grid = editorGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -93,8 +94,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Add info box
|
// Add info box
|
||||||
if (IsSingleObject && Values[0] is RigidBody && Editor.IsPlayMode)
|
if (IsSingleObject && Values[0] is RigidBody && Editor.IsPlayMode)
|
||||||
{
|
{
|
||||||
_infoLabel = layout.Label(string.Empty).Label;
|
var group = layout.Group("Info");
|
||||||
|
_infoLabel = group.Label(string.Empty).Label;
|
||||||
_infoLabel.AutoHeight = true;
|
_infoLabel.AutoHeight = true;
|
||||||
|
_infoLabel.Margin = new Margin(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
_infoLabel.AutoHeight = true;
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
var grid = playbackGroup.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
private CustomElementsContainer<UniformGridPanel> UniformGridTwoByOne(LayoutElementsContainer cont)
|
private CustomElementsContainer<UniformGridPanel> UniformGridTwoByOne(LayoutElementsContainer cont)
|
||||||
{
|
{
|
||||||
var grid = cont.CustomContainer<UniformGridPanel>();
|
var grid = cont.UniformGrid();
|
||||||
grid.CustomControl.SlotsHorizontally = 2;
|
grid.CustomControl.SlotsHorizontally = 2;
|
||||||
grid.CustomControl.SlotsVertically = 1;
|
grid.CustomControl.SlotsVertically = 1;
|
||||||
grid.CustomControl.SlotPadding = Margin.Zero;
|
grid.CustomControl.SlotPadding = Margin.Zero;
|
||||||
|
|||||||
@@ -43,11 +43,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
base.Initialize(layout);
|
base.Initialize(layout);
|
||||||
|
|
||||||
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
||||||
{
|
CheckLayout(ug);
|
||||||
ug.Height += 2;
|
|
||||||
ug.SlotSpacing = new Float2(4);
|
|
||||||
ug.SlotPadding = new Margin(0, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override colors
|
// Override colors
|
||||||
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
||||||
@@ -75,11 +71,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
base.Initialize(layout);
|
base.Initialize(layout);
|
||||||
|
|
||||||
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
||||||
{
|
CheckLayout(ug);
|
||||||
ug.Height += 2;
|
|
||||||
ug.SlotSpacing = new Float2(4);
|
|
||||||
ug.SlotPadding = new Margin(0, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override colors
|
// Override colors
|
||||||
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
||||||
@@ -138,11 +130,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
if (XElement.ValueBox.Parent is UniformGridPanel ug)
|
||||||
{
|
CheckLayout(ug);
|
||||||
ug.Height += 2;
|
|
||||||
ug.SlotSpacing = new Float2(4);
|
|
||||||
ug.SlotPadding = new Margin(0, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override colors
|
// Override colors
|
||||||
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
|
||||||
@@ -203,5 +191,13 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
_linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling";
|
_linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CheckLayout(UniformGridPanel ug)
|
||||||
|
{
|
||||||
|
// Enlarge to fix border visibility
|
||||||
|
ug.Height += 2;
|
||||||
|
ug.SlotSpacing += new Float2(2);
|
||||||
|
ug.SlotPadding += new Margin(0, 0, 1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -642,10 +642,10 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (_canResize && !_readOnly)
|
if (_canResize && !_readOnly)
|
||||||
{
|
{
|
||||||
var panel = dragArea.HorizontalPanel();
|
var panel = dragArea.HorizontalPanel();
|
||||||
panel.Panel.Size = new Float2(0, 20);
|
panel.Panel.Size = new Float2(0, 18);
|
||||||
panel.Panel.Margin = new Margin(2);
|
panel.Panel.Margin = new Margin(0, 0, Utilities.Constants.UIMargin, 0);
|
||||||
|
|
||||||
var removeButton = panel.Button("-", "Remove last item");
|
var removeButton = panel.Button("-", "Remove the last item");
|
||||||
removeButton.Button.Size = new Float2(16, 16);
|
removeButton.Button.Size = new Float2(16, 16);
|
||||||
removeButton.Button.Enabled = size > _minCount;
|
removeButton.Button.Enabled = size > _minCount;
|
||||||
removeButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
removeButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
||||||
@@ -656,7 +656,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Resize(Count - 1);
|
Resize(Count - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
var addButton = panel.Button("+", "Add new item");
|
var addButton = panel.Button("+", "Add a new item");
|
||||||
addButton.Button.Size = new Float2(16, 16);
|
addButton.Button.Size = new Float2(16, 16);
|
||||||
addButton.Button.Enabled = (!NotNullItems || size > 0) && size < _maxCount;
|
addButton.Button.Enabled = (!NotNullItems || size > 0) && size < _maxCount;
|
||||||
addButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
addButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
float trackBallSize = 80.0f;
|
float trackBallSize = 100f;
|
||||||
float margin = 4.0f;
|
float margin = 4.0f;
|
||||||
|
|
||||||
// Panel
|
// Panel
|
||||||
@@ -50,7 +50,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
// Scale editor
|
// Scale editor
|
||||||
{
|
{
|
||||||
var grid = masterPanel.CustomContainer<UniformGridPanel>();
|
var grid = masterPanel.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.SlotPadding = new Margin(4, 2, 2, 2);
|
gridControl.SlotPadding = new Margin(4, 2, 2, 2);
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
||||||
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
||||||
new OptionType("Video", typeof(VideoBrush)),
|
new OptionType("Video", typeof(VideoBrush)),
|
||||||
|
new OptionType("UI Brush", typeof(UIBrush)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
public sealed class LocalizedStringEditor : GenericEditor
|
public sealed class LocalizedStringEditor : GenericEditor
|
||||||
{
|
{
|
||||||
private TextBoxElement _idElement, _valueElement;
|
private TextBoxElement _idElement, _valueElement;
|
||||||
|
private Button _viewStringButton;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DisplayStyle Style => DisplayStyle.Inline;
|
public override DisplayStyle Style => DisplayStyle.Inline;
|
||||||
@@ -70,6 +71,21 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
};
|
};
|
||||||
addString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
|
addString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
|
||||||
addString.ButtonClicked += OnAddStringClicked;
|
addString.ButtonClicked += OnAddStringClicked;
|
||||||
|
|
||||||
|
var viewString = new Button
|
||||||
|
{
|
||||||
|
Visible = false,
|
||||||
|
Width = 16.0f,
|
||||||
|
BackgroundColor = Color.White,
|
||||||
|
BackgroundColorHighlighted = Color.Gray,
|
||||||
|
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Search12),
|
||||||
|
TooltipText = "Find localized text in Localized String Table asset for the current locale...",
|
||||||
|
Parent = valueElement.TextBox,
|
||||||
|
};
|
||||||
|
viewString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
|
||||||
|
viewString.LocalX -= 16.0f;
|
||||||
|
viewString.ButtonClicked += OnViewStringClicked;
|
||||||
|
_viewStringButton = viewString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -80,6 +96,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (_valueElement != null)
|
if (_valueElement != null)
|
||||||
{
|
{
|
||||||
_valueElement.TextBox.WatermarkText = Localization.GetString(_idElement.Text);
|
_valueElement.TextBox.WatermarkText = Localization.GetString(_idElement.Text);
|
||||||
|
_viewStringButton.Visible = !string.IsNullOrEmpty(_valueElement.TextBox.WatermarkText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,14 +109,21 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
_valueElement = null;
|
_valueElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectStringClicked(Button button)
|
private bool GetSettings(out LocalizationSettings settings)
|
||||||
{
|
{
|
||||||
var settings = GameSettings.Load<LocalizationSettings>();
|
settings = GameSettings.Load<LocalizationSettings>();
|
||||||
if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
|
if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
|
||||||
{
|
{
|
||||||
MessageBox.Show("No valid localization settings setup.");
|
MessageBox.Show("No valid localization settings setup.");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectStringClicked(Button button)
|
||||||
|
{
|
||||||
|
if (GetSettings(out var settings))
|
||||||
|
return;
|
||||||
Profiler.BeginEvent("LocalizedStringEditor.OnSelectStringClicked");
|
Profiler.BeginEvent("LocalizedStringEditor.OnSelectStringClicked");
|
||||||
var allKeys = new HashSet<string>();
|
var allKeys = new HashSet<string>();
|
||||||
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
|
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
|
||||||
@@ -136,6 +160,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
{
|
{
|
||||||
menu.Hide();
|
menu.Hide();
|
||||||
_idElement.TextBox.SetTextAsUser(after[0].Text);
|
_idElement.TextBox.SetTextAsUser(after[0].Text);
|
||||||
|
_valueElement.TextBox.SetTextAsUser(string.Empty);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
searchBox.TextChanged += delegate
|
searchBox.TextChanged += delegate
|
||||||
@@ -158,12 +183,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
private void OnAddStringClicked(Button button)
|
private void OnAddStringClicked(Button button)
|
||||||
{
|
{
|
||||||
var settings = GameSettings.Load<LocalizationSettings>();
|
if (GetSettings(out var settings))
|
||||||
if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
|
|
||||||
{
|
|
||||||
MessageBox.Show("No valid localization settings setup.");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
Profiler.BeginEvent("LocalizedStringEditor.OnAddStringClicked");
|
Profiler.BeginEvent("LocalizedStringEditor.OnAddStringClicked");
|
||||||
var allKeys = new HashSet<string>();
|
var allKeys = new HashSet<string>();
|
||||||
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
|
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
|
||||||
@@ -231,5 +252,30 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
_idElement.TextBox.SetTextAsUser(newKey);
|
_idElement.TextBox.SetTextAsUser(newKey);
|
||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnViewStringClicked(Button button)
|
||||||
|
{
|
||||||
|
if (GetSettings(out var settings))
|
||||||
|
return;
|
||||||
|
var id = _idElement.TextBox.Text;
|
||||||
|
var value = _valueElement.TextBox.WatermarkText;
|
||||||
|
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
|
||||||
|
{
|
||||||
|
var table = settings.LocalizedStringTables[i];
|
||||||
|
if (table && !table.WaitForLoaded())
|
||||||
|
{
|
||||||
|
var entries = table.Entries;
|
||||||
|
if (entries.TryGetValue(id, out var messages))
|
||||||
|
{
|
||||||
|
if (messages.Length != 0 && messages[0] == value)
|
||||||
|
{
|
||||||
|
Editor.Instance.ContentEditing.Open(table);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageBox.Show("Unable to find localized string table.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
}
|
}
|
||||||
|
|
||||||
_element = layout.TextBox(isMultiLine);
|
_element = layout.TextBox(isMultiLine);
|
||||||
_defaultWatermarkColor = _element.TextBox.WatermarkTextColor;
|
_watermarkColor = _defaultWatermarkColor = _element.TextBox.WatermarkTextColor;
|
||||||
if (watermarkAttribute is WatermarkAttribute watermark)
|
if (watermarkAttribute is WatermarkAttribute watermark)
|
||||||
{
|
{
|
||||||
_watermarkText = watermark.WatermarkText;
|
_watermarkText = watermark.WatermarkText;
|
||||||
|
|||||||
@@ -604,6 +604,9 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
root.SortChildrenRecursive();
|
root.SortChildrenRecursive();
|
||||||
root.Expand(true);
|
root.Expand(true);
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyboardKeys.Shift))
|
||||||
|
root.ExpandAll(true);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -131,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -220,7 +220,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -469,7 +469,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -783,7 +783,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -163,7 +163,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
@@ -274,7 +274,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
var grid = layout.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = TextBox.DefaultHeight;
|
gridControl.Height = TextBox.DefaultHeight;
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ namespace FlaxEditor.CustomEditors.Elements
|
|||||||
ArrowImageClosed = new SpriteBrush(Style.Current.ArrowRight),
|
ArrowImageClosed = new SpriteBrush(Style.Current.ArrowRight),
|
||||||
ArrowImageOpened = new SpriteBrush(Style.Current.ArrowDown),
|
ArrowImageOpened = new SpriteBrush(Style.Current.ArrowDown),
|
||||||
EnableDropDownIcon = true,
|
EnableDropDownIcon = true,
|
||||||
ItemsMargin = new Margin(7, 7, 3, 3),
|
ItemsMargin = new Margin(Utilities.Constants.UIMargin),
|
||||||
|
ItemsSpacing = Utilities.Constants.UIMargin,
|
||||||
HeaderHeight = 18.0f,
|
HeaderHeight = 18.0f,
|
||||||
EnableContainmentLines = true,
|
EnableContainmentLines = true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,13 +20,6 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const int SplitterSize = 2;
|
public const int SplitterSize = 2;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The splitter margin (in pixels).
|
|
||||||
/// </summary>
|
|
||||||
public const int SplitterMargin = 4;
|
|
||||||
|
|
||||||
private const int SplitterSizeHalf = SplitterSize / 2;
|
|
||||||
|
|
||||||
private PropertiesListElement _element;
|
private PropertiesListElement _element;
|
||||||
private float _splitterValue;
|
private float _splitterValue;
|
||||||
private Rectangle _splitterRect;
|
private Rectangle _splitterRect;
|
||||||
@@ -65,16 +58,18 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
/// <param name="element">The element.</param>
|
/// <param name="element">The element.</param>
|
||||||
public PropertiesList(PropertiesListElement element)
|
public PropertiesList(PropertiesListElement element)
|
||||||
{
|
{
|
||||||
|
ClipChildren = false;
|
||||||
_element = element;
|
_element = element;
|
||||||
_splitterValue = 0.4f;
|
_splitterValue = 0.4f;
|
||||||
BottomMargin = TopMargin = RightMargin = SplitterMargin;
|
Margin = new Margin();
|
||||||
|
Spacing = Utilities.Constants.UIMargin;
|
||||||
UpdateSplitRect();
|
UpdateSplitRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSplitRect()
|
private void UpdateSplitRect()
|
||||||
{
|
{
|
||||||
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSizeHalf, 0.0f, Width), 0, SplitterSize, Height);
|
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSize * 0.5f, 0.0f, Width), 0, SplitterSize, Height);
|
||||||
LeftMargin = _splitterValue * Width + SplitterMargin;
|
LeftMargin = _splitterValue * Width + _spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartTracking()
|
private void StartTracking()
|
||||||
@@ -222,23 +217,33 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void PerformLayoutAfterChildren()
|
protected override void PerformLayoutAfterChildren()
|
||||||
{
|
{
|
||||||
// Sort controls from up to down into two columns: one for labels and one for the rest of the stuff
|
// Place non-label controls from top to down
|
||||||
|
|
||||||
float y = _margin.Top;
|
float y = _margin.Top;
|
||||||
float w = Width - _margin.Width;
|
float w = Width - _margin.Width;
|
||||||
|
bool firstItem = true;
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = 0; i < _children.Count; i++)
|
||||||
{
|
{
|
||||||
Control c = _children[i];
|
Control c = _children[i];
|
||||||
if (!(c is PropertyNameLabel))
|
if (!(c is PropertyNameLabel))
|
||||||
{
|
{
|
||||||
var h = c.Height;
|
var rect = new Rectangle(_margin.Left, y, w, c.Height);
|
||||||
c.Bounds = new Rectangle(_margin.Left, y + _spacing, w, h);
|
if (c.Visible)
|
||||||
|
{
|
||||||
|
if (firstItem)
|
||||||
|
firstItem = false;
|
||||||
|
else
|
||||||
|
rect.Y += _spacing;
|
||||||
|
}
|
||||||
|
else if (!firstItem)
|
||||||
|
rect.Y += _spacing;
|
||||||
|
c.Bounds = rect;
|
||||||
if (c.Visible)
|
if (c.Visible)
|
||||||
y = c.Bottom;
|
y = c.Bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y += _margin.Bottom;
|
y += _margin.Bottom;
|
||||||
|
|
||||||
|
// Place labels accordingly to their respective controls placement
|
||||||
float namesWidth = _splitterValue * Width;
|
float namesWidth = _splitterValue * Width;
|
||||||
int count = _element.Labels.Count;
|
int count = _element.Labels.Count;
|
||||||
float[] yStarts = new float[count + 1];
|
float[] yStarts = new float[count + 1];
|
||||||
@@ -271,7 +276,9 @@ namespace FlaxEditor.CustomEditors.GUI
|
|||||||
{
|
{
|
||||||
var label = _element.Labels[i];
|
var label = _element.Labels[i];
|
||||||
|
|
||||||
var rect = new Rectangle(0, yStarts[i] + 1, namesWidth, yStarts[i + 1] - yStarts[i] - 2);
|
var rect = new Rectangle(0, yStarts[i], namesWidth, yStarts[i + 1] - yStarts[i]);
|
||||||
|
if (i != count - 1)
|
||||||
|
rect.Height -= _spacing;
|
||||||
//label.Parent = this;
|
//label.Parent = this;
|
||||||
label.Bounds = rect;
|
label.Bounds = rect;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,17 @@ namespace FlaxEditor.CustomEditors
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds new uniform grid control.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The created element.</returns>
|
||||||
|
public CustomElementsContainer<UniformGridPanel> UniformGrid()
|
||||||
|
{
|
||||||
|
var grid = CustomContainer<UniformGridPanel>();
|
||||||
|
grid.CustomControl.SlotSpacing = new Float2(Utilities.Constants.UIMargin);
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds new custom element.
|
/// Adds new custom element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -276,10 +287,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(SpriteHandle sprite)
|
public ImageElement Image(SpriteHandle sprite)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
return Image(new SpriteBrush(sprite));
|
||||||
element.Image.Brush = new SpriteBrush(sprite);
|
|
||||||
OnAddElement(element);
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -289,10 +297,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(Texture texture)
|
public ImageElement Image(Texture texture)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
return Image(new TextureBrush(texture));
|
||||||
element.Image.Brush = new TextureBrush(texture);
|
|
||||||
OnAddElement(element);
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -301,9 +306,19 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <param name="texture">The GPU texture.</param>
|
/// <param name="texture">The GPU texture.</param>
|
||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(GPUTexture texture)
|
public ImageElement Image(GPUTexture texture)
|
||||||
|
{
|
||||||
|
return Image(new GPUTextureBrush(texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds brush image to the layout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="brush">The brush.</param>
|
||||||
|
/// <returns>The created element.</returns>
|
||||||
|
public ImageElement Image(IBrush brush)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
var element = new ImageElement();
|
||||||
element.Image.Brush = new GPUTextureBrush(texture);
|
element.Image.Brush = brush;
|
||||||
OnAddElement(element);
|
OnAddElement(element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
#include "Engine/ShadowsOfMordor/Builder.h"
|
#include "Engine/ShadowsOfMordor/Builder.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "FlaxEngine.Gen.h"
|
#include "FlaxEngine.Gen.h"
|
||||||
#if PLATFORM_LINUX
|
#if PLATFORM_LINUX
|
||||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||||
@@ -47,6 +48,7 @@ void Editor::CloseSplashScreen()
|
|||||||
|
|
||||||
bool Editor::CheckProjectUpgrade()
|
bool Editor::CheckProjectUpgrade()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
const auto versionFilePath = Globals::ProjectCacheFolder / TEXT("version");
|
const auto versionFilePath = Globals::ProjectCacheFolder / TEXT("version");
|
||||||
|
|
||||||
// Load version cache file
|
// Load version cache file
|
||||||
@@ -366,6 +368,8 @@ bool Editor::BackupProject()
|
|||||||
|
|
||||||
int32 Editor::LoadProduct()
|
int32 Editor::LoadProduct()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Flax Editor product
|
// Flax Editor product
|
||||||
Globals::ProductName = TEXT("Flax Editor");
|
Globals::ProductName = TEXT("Flax Editor");
|
||||||
Globals::CompanyName = TEXT("Flax");
|
Globals::CompanyName = TEXT("Flax");
|
||||||
@@ -626,6 +630,7 @@ int32 Editor::LoadProduct()
|
|||||||
|
|
||||||
Window* Editor::CreateMainWindow()
|
Window* Editor::CreateMainWindow()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
Window* window = Managed->GetMainWindow();
|
Window* window = Managed->GetMainWindow();
|
||||||
|
|
||||||
#if PLATFORM_LINUX
|
#if PLATFORM_LINUX
|
||||||
@@ -662,6 +667,7 @@ bool Editor::Init()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
PROFILE_CPU();
|
PROFILE_CPU();
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// If during last lightmaps baking engine crashed we could try to restore the progress
|
// If during last lightmaps baking engine crashed we could try to restore the progress
|
||||||
ShadowsOfMordor::Builder::Instance()->CheckIfRestoreState();
|
ShadowsOfMordor::Builder::Instance()->CheckIfRestoreState();
|
||||||
@@ -693,11 +699,13 @@ bool Editor::Init()
|
|||||||
|
|
||||||
void Editor::BeforeRun()
|
void Editor::BeforeRun()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
Managed->BeforeRun();
|
Managed->BeforeRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::BeforeExit()
|
void Editor::BeforeExit()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
CloseSplashScreen();
|
CloseSplashScreen();
|
||||||
|
|
||||||
Managed->Exit();
|
Managed->Exit();
|
||||||
@@ -708,6 +716,8 @@ void Editor::BeforeExit()
|
|||||||
|
|
||||||
void EditorImpl::OnUpdate()
|
void EditorImpl::OnUpdate()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Update c# editor
|
// Update c# editor
|
||||||
Editor::Managed->Update();
|
Editor::Managed->Update();
|
||||||
|
|
||||||
|
|||||||
@@ -670,6 +670,8 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
FlaxEngine.Networking.NetworkManager.Stop(); // Shutdown any multiplayer from playmode
|
FlaxEngine.Networking.NetworkManager.Stop(); // Shutdown any multiplayer from playmode
|
||||||
PlayModeEnding?.Invoke();
|
PlayModeEnding?.Invoke();
|
||||||
|
for (int i = 0; i < _modules.Count; i++)
|
||||||
|
_modules[i].OnPlayEnding();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnPlayEnd()
|
internal void OnPlayEnd()
|
||||||
@@ -1031,6 +1033,8 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
Internal_GetEditorBoxWithChildren(FlaxEngine.Object.GetUnmanagedPtr(actor), out var box);
|
Internal_GetEditorBoxWithChildren(FlaxEngine.Object.GetUnmanagedPtr(actor), out var box);
|
||||||
BoundingSphere.FromBox(ref box, out sphere);
|
BoundingSphere.FromBox(ref box, out sphere);
|
||||||
|
if (sphere == BoundingSphere.Empty)
|
||||||
|
sphere = new BoundingSphere(actor.Position, sphere.Radius);
|
||||||
sphere.Radius = Math.Max(sphere.Radius, 15.0f);
|
sphere.Radius = Math.Max(sphere.Radius, 15.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
// Select asset
|
// Select asset
|
||||||
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
||||||
|
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Button1Rect.Contains(location))
|
else if (Button1Rect.Contains(location))
|
||||||
@@ -312,6 +313,7 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
// Select asset
|
// Select asset
|
||||||
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
||||||
|
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||||
}
|
}
|
||||||
else if (Button3Rect.Contains(location))
|
else if (Button3Rect.Contains(location))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The column title horizontal text alignment
|
/// The column title horizontal text alignment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TextAlignment TitleAlignment = TextAlignment.Near;
|
public TextAlignment TitleAlignment = TextAlignment.Center;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The column title margin.
|
/// The column title margin.
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS || PLATFORM_SDL
|
||||||
#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;
|
||||||
@@ -121,7 +124,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shows the empty menu popup o na screen.
|
/// Shows the empty menu popup on a 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>
|
||||||
@@ -256,7 +259,9 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
desc.AllowMaximize = false;
|
desc.AllowMaximize = false;
|
||||||
desc.AllowDragAndDrop = false;
|
desc.AllowDragAndDrop = false;
|
||||||
desc.IsTopmost = true;
|
desc.IsTopmost = true;
|
||||||
desc.IsRegularWindow = false;
|
desc.Type = WindowType.Popup;
|
||||||
|
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);
|
||||||
@@ -266,6 +271,12 @@ 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;
|
||||||
@@ -285,6 +296,17 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ForceDefocus(ContainerControl c)
|
||||||
|
{
|
||||||
|
foreach (var cc in c.Children)
|
||||||
|
{
|
||||||
|
if (cc.ContainsFocus)
|
||||||
|
cc.Defocus();
|
||||||
|
if (cc is ContainerControl ccc)
|
||||||
|
ForceDefocus(ccc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hide popup menu and all child menus.
|
/// Hide popup menu and all child menus.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -299,6 +321,9 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
// Close child
|
// Close child
|
||||||
HideChild();
|
HideChild();
|
||||||
|
|
||||||
|
// Force defocus
|
||||||
|
ForceDefocus(this);
|
||||||
|
|
||||||
// Unlink from window
|
// Unlink from window
|
||||||
Parent = null;
|
Parent = null;
|
||||||
|
|
||||||
@@ -426,6 +451,17 @@ 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;
|
||||||
@@ -439,6 +475,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private void OnWindowLostFocus()
|
private void OnWindowLostFocus()
|
||||||
{
|
{
|
||||||
@@ -537,7 +574,12 @@ 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
|
||||||
|
|||||||
@@ -326,8 +326,11 @@ 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;
|
||||||
SelectedColor = ScreenUtilities.GetColorAt(mousePosition);
|
Color color = ScreenUtilities.GetColorAt(mousePosition);
|
||||||
|
if (color != Color.Transparent)
|
||||||
|
SelectedColor = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,545 +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 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 += DockPanel.DefaultHeaderHeight;
|
|
||||||
result.Size.Y -= DockPanel.DefaultHeaderHeight;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,6 +50,11 @@ 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>
|
||||||
@@ -165,7 +170,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
|
||||||
DockHintWindow.Create(_panel as FloatWindowDockPanel);
|
WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -176,7 +181,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
_panel.SelectTab(index - 1);
|
_panel.SelectTab(index - 1);
|
||||||
|
|
||||||
// Create docking hint window
|
// Create docking hint window
|
||||||
DockHintWindow.Create(win);
|
WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,6 +360,7 @@ 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)
|
||||||
@@ -441,6 +447,20 @@ 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,6 +182,25 @@ 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();
|
||||||
|
|
||||||
@@ -199,14 +218,17 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
windowGUI.UnlockChildrenRecursive();
|
windowGUI.UnlockChildrenRecursive();
|
||||||
windowGUI.PerformLayout();
|
windowGUI.PerformLayout();
|
||||||
|
|
||||||
// Show
|
if (showWindow)
|
||||||
window.Show();
|
{
|
||||||
window.BringToFront();
|
// Show
|
||||||
window.Focus();
|
window.Show();
|
||||||
OnShow();
|
window.BringToFront();
|
||||||
|
window.Focus();
|
||||||
|
OnShow();
|
||||||
|
|
||||||
// Perform layout again
|
// Perform layout again
|
||||||
windowGUI.PerformLayout();
|
windowGUI.PerformLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,6 +11,42 @@ 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;
|
||||||
|
|
||||||
@@ -40,6 +76,26 @@ 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>
|
||||||
@@ -52,7 +108,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Create docking hint window
|
// Create docking hint window
|
||||||
DockHintWindow.Create(this);
|
WindowDragHelper.StartDragging(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -71,23 +127,29 @@ 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(1);
|
settings.MinimumSize = new Float2(200, 150);
|
||||||
settings.MaximumSize = Float2.Zero; // Unlimited size
|
settings.MaximumSize = Float2.Zero; // Unlimited size
|
||||||
settings.Fullscreen = false;
|
settings.Fullscreen = false;
|
||||||
settings.HasBorder = true;
|
settings.HasBorder = true;
|
||||||
settings.SupportsTransparency = false;
|
settings.SupportsTransparency = true;
|
||||||
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.IsRegularWindow = true;
|
settings.Type = WindowType.Regular;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ 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];
|
||||||
@@ -94,9 +93,44 @@ 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
|
||||||
|
|||||||
458
Source/Editor/GUI/Docking/WindowDragHelper.cs
Normal file
458
Source/Editor/GUI/Docking/WindowDragHelper.cs
Normal file
@@ -0,0 +1,458 @@
|
|||||||
|
// 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 = 32.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;
|
||||||
|
|
||||||
|
// Bind events
|
||||||
|
FlaxEngine.Scripting.Update += OnUpdate;
|
||||||
|
window.MouseUp += OnMouseUp;
|
||||||
|
|
||||||
|
// Update rectangles
|
||||||
|
UpdateRects(Platform.MousePosition);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
|
||||||
|
|
||||||
|
_dragSourceWindow.MouseUp += OnMouseUp; // The mouse up event is sent to the source window on Windows
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
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 (_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>
|
||||||
|
/// <returns>The window drag helper object.</returns>
|
||||||
|
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove)
|
||||||
|
{
|
||||||
|
if (toMove == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
return new WindowDragHelper(toMove, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
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
|
||||||
|
_toDock?.RootWindow.Window.BringToFront();
|
||||||
|
//_toDock?.RootWindow.Window.Focus();
|
||||||
|
|
||||||
|
// Make the dragged window transparent when dock hints are visible
|
||||||
|
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check dock state to use
|
||||||
|
bool showProxyHints = _toDock != null;
|
||||||
|
bool showBorderHints = showProxyHints;
|
||||||
|
bool showCenterHint = showProxyHints;
|
||||||
|
Control hoveredHintControl = null;
|
||||||
|
Float2 hoveredSizeOverride = Float2.Zero;
|
||||||
|
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 = 4.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
|
||||||
|
DockState toSet = DockState.Float;
|
||||||
|
if (showBorderHints)
|
||||||
|
{
|
||||||
|
if (_rUpper.Contains(_toDock.PointFromScreen(_mouse)))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockTop;
|
||||||
|
hoveredHintControl = _dockHintUp;
|
||||||
|
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
|
||||||
|
}
|
||||||
|
else if (_rBottom.Contains(_toDock.PointFromScreen(_mouse)))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockBottom;
|
||||||
|
hoveredHintControl = _dockHintDown;
|
||||||
|
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
|
||||||
|
}
|
||||||
|
else if (_rLeft.Contains(_toDock.PointFromScreen(_mouse)))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockLeft;
|
||||||
|
hoveredHintControl = _dockHintLeft;
|
||||||
|
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
|
||||||
|
}
|
||||||
|
else if (_rRight.Contains(_toDock.PointFromScreen(_mouse)))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockRight;
|
||||||
|
hoveredHintControl = _dockHintRight;
|
||||||
|
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (showCenterHint && _rCenter.Contains(_toDock.PointFromScreen(_mouse)))
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (hoveredHintControl != _dockHintDown)
|
||||||
|
{
|
||||||
|
_dockHintDown.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintDown.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintLeft)
|
||||||
|
{
|
||||||
|
_dockHintLeft.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintLeft.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintRight)
|
||||||
|
{
|
||||||
|
_dockHintRight.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintRight.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintUp)
|
||||||
|
{
|
||||||
|
_dockHintUp.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintUp.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintCenter)
|
||||||
|
{
|
||||||
|
_dockHintCenter.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintCenter.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_toSet != DockState.Float)
|
||||||
|
{
|
||||||
|
if (hoveredHintControl != null)
|
||||||
|
{
|
||||||
|
hoveredHintControl.BackgroundColor = Style.Current.Selection.AlphaMultiplied(1.0f);
|
||||||
|
hoveredHintControl.Size = hoveredSizeOverride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
{
|
||||||
|
var mousePos = Platform.MousePosition;
|
||||||
|
|
||||||
|
if (_mouse != mousePos)
|
||||||
|
OnMouseMove(mousePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMouseMove(Float2 mousePos)
|
||||||
|
{
|
||||||
|
if (_dragSourceWindow != null)
|
||||||
|
_toMove.Window.Window.Position = mousePos - _dragOffset;
|
||||||
|
|
||||||
|
UpdateRects(mousePos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _min;
|
get => _min;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathd.NearEqual(_min, value))
|
if (_min != value)
|
||||||
{
|
{
|
||||||
if (value > _max)
|
if (value > _max)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
@@ -58,7 +58,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _max;
|
get => _max;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathd.NearEqual(_max, value))
|
if (_max != value)
|
||||||
{
|
{
|
||||||
if (value < _min)
|
if (value < _min)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _min;
|
get => _min;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathf.NearEqual(_min, value))
|
if (_min != value)
|
||||||
{
|
{
|
||||||
if (value > _max)
|
if (value > _max)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
@@ -54,7 +54,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _max;
|
get => _max;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathf.NearEqual(_max, value))
|
if (_max != value)
|
||||||
{
|
{
|
||||||
if (value < _min)
|
if (value < _min)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
value = Mathf.Clamp(value, Minimum, Maximum);
|
value = Mathf.Clamp(value, Minimum, Maximum);
|
||||||
if (!Mathf.NearEqual(value, _value))
|
if (value != _value)
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _min;
|
get => _min;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathf.NearEqual(_min, value))
|
if (_min != value)
|
||||||
{
|
{
|
||||||
if (value > _max)
|
if (value > _max)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
@@ -330,7 +330,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
get => _max;
|
get => _max;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!Mathf.NearEqual(_max, value))
|
if (_max != value)
|
||||||
{
|
{
|
||||||
if (value < _min)
|
if (value < _min)
|
||||||
throw new ArgumentException();
|
throw new ArgumentException();
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -292,13 +293,45 @@ namespace FlaxEditor.GUI.Input
|
|||||||
base.OnMouseMove(location);
|
base.OnMouseMove(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnMouseMoveRelative(Float2 mouseMotion)
|
||||||
|
{
|
||||||
|
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(mouseMotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,9 +227,8 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
int order = -1 * SortScore.CompareTo(otherItem.SortScore);
|
int order = -1 * SortScore.CompareTo(otherItem.SortScore);
|
||||||
if (order == 0)
|
if (order == 0)
|
||||||
{
|
|
||||||
order = string.Compare(Name, otherItem.Name, StringComparison.Ordinal);
|
order = string.Compare(Name, otherItem.Name, StringComparison.Ordinal);
|
||||||
}
|
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
return base.Compare(other);
|
return base.Compare(other);
|
||||||
@@ -509,7 +508,7 @@ namespace FlaxEditor.GUI
|
|||||||
OnSearchFilterChanged();
|
OnSearchFilterChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Item> GetVisibleItems()
|
private List<Item> GetVisibleItems(bool ignoreFoldedCategories)
|
||||||
{
|
{
|
||||||
var result = new List<Item>();
|
var result = new List<Item>();
|
||||||
var items = ItemsPanel.Children;
|
var items = ItemsPanel.Children;
|
||||||
@@ -523,7 +522,7 @@ namespace FlaxEditor.GUI
|
|||||||
for (int i = 0; i < _categoryPanels.Count; i++)
|
for (int i = 0; i < _categoryPanels.Count; i++)
|
||||||
{
|
{
|
||||||
var category = _categoryPanels[i];
|
var category = _categoryPanels[i];
|
||||||
if (!category.Visible)
|
if (!category.Visible || (ignoreFoldedCategories && category is DropPanel panel && panel.IsClosed))
|
||||||
continue;
|
continue;
|
||||||
for (int j = 0; j < category.Children.Count; j++)
|
for (int j = 0; j < category.Children.Count; j++)
|
||||||
{
|
{
|
||||||
@@ -535,6 +534,12 @@ namespace FlaxEditor.GUI
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExpandToItem(Item item)
|
||||||
|
{
|
||||||
|
if (item.Parent is DropPanel dropPanel)
|
||||||
|
dropPanel.Open(false);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnShow()
|
protected override void OnShow()
|
||||||
{
|
{
|
||||||
@@ -563,8 +568,17 @@ namespace FlaxEditor.GUI
|
|||||||
case KeyboardKeys.Escape:
|
case KeyboardKeys.Escape:
|
||||||
Hide();
|
Hide();
|
||||||
return true;
|
return true;
|
||||||
|
case KeyboardKeys.Backspace:
|
||||||
|
// Allow the user to quickly focus the searchbar
|
||||||
|
if (_searchBox != null && !_searchBox.IsFocused)
|
||||||
|
{
|
||||||
|
_searchBox.Focus();
|
||||||
|
_searchBox.SelectAll();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case KeyboardKeys.ArrowDown:
|
case KeyboardKeys.ArrowDown:
|
||||||
{
|
case KeyboardKeys.ArrowUp:
|
||||||
if (RootWindow.FocusedControl == null)
|
if (RootWindow.FocusedControl == null)
|
||||||
{
|
{
|
||||||
// Focus search box if nothing is focused
|
// Focus search box if nothing is focused
|
||||||
@@ -572,45 +586,44 @@ namespace FlaxEditor.GUI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus the first visible item or then next one
|
// Get the next item
|
||||||
var items = GetVisibleItems();
|
bool controlDown = Root.GetKey(KeyboardKeys.Control);
|
||||||
|
var items = GetVisibleItems(!controlDown);
|
||||||
var focusedIndex = items.IndexOf(focusedItem);
|
var focusedIndex = items.IndexOf(focusedItem);
|
||||||
if (focusedIndex == -1)
|
|
||||||
focusedIndex = -1;
|
// If the user hasn't selected anything yet and is holding control, focus first folded item
|
||||||
if (focusedIndex + 1 < items.Count)
|
if (focusedIndex == -1 && controlDown)
|
||||||
{
|
focusedIndex = GetVisibleItems(true).Count - 1;
|
||||||
var item = items[focusedIndex + 1];
|
|
||||||
item.Focus();
|
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
|
||||||
_scrollPanel.ScrollViewTo(item);
|
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, items.Count - 1);
|
||||||
return true;
|
var nextItem = items[nextIndex];
|
||||||
}
|
|
||||||
break;
|
// Focus the next item
|
||||||
}
|
nextItem.Focus();
|
||||||
case KeyboardKeys.ArrowUp:
|
|
||||||
if (focusedItem != null)
|
// Allow the user to expand groups while scrolling
|
||||||
{
|
if (controlDown)
|
||||||
// Focus the previous visible item or the search box
|
ExpandToItem(nextItem);
|
||||||
var items = GetVisibleItems();
|
|
||||||
var focusedIndex = items.IndexOf(focusedItem);
|
_scrollPanel.ScrollViewTo(nextItem);
|
||||||
if (focusedIndex == 0)
|
return true;
|
||||||
{
|
|
||||||
_searchBox?.Focus();
|
|
||||||
}
|
|
||||||
else if (focusedIndex > 0)
|
|
||||||
{
|
|
||||||
var item = items[focusedIndex - 1];
|
|
||||||
item.Focus();
|
|
||||||
_scrollPanel.ScrollViewTo(item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KeyboardKeys.Return:
|
case KeyboardKeys.Return:
|
||||||
if (focusedItem != null)
|
if (focusedItem != null)
|
||||||
{
|
{
|
||||||
OnClickItem(focusedItem);
|
OnClickItem(focusedItem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Select first item if no item is focused (most likely to be the best result), saves the user from pressing arrow down first
|
||||||
|
var visibleItems = GetVisibleItems(true);
|
||||||
|
if (visibleItems.Count > 0)
|
||||||
|
{
|
||||||
|
OnClickItem(visibleItems[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,16 +12,6 @@ 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>
|
||||||
@@ -60,200 +50,12 @@ 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>
|
||||||
/// <param name="mainWindow">The main window.</param>
|
public MainMenu()
|
||||||
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>
|
||||||
@@ -266,6 +68,19 @@ namespace FlaxEditor.GUI
|
|||||||
return AddChild(new MainMenuButton(text));
|
return AddChild(new MainMenuButton(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or adds a button.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The button text</param>
|
||||||
|
/// <returns>The existing or created button control.</returns>
|
||||||
|
public MainMenuButton GetOrAddButton(string text)
|
||||||
|
{
|
||||||
|
MainMenuButton result = GetButton(text);
|
||||||
|
if (result == null)
|
||||||
|
result = AddButton(text);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the button.
|
/// Gets the button.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -285,26 +100,6 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -320,16 +115,8 @@ namespace FlaxEditor.GUI
|
|||||||
protected override void PerformLayoutAfterChildren()
|
protected override void PerformLayoutAfterChildren()
|
||||||
{
|
{
|
||||||
float x = 0;
|
float x = 0;
|
||||||
|
WindowDecorations decorations = Parent.GetChild<WindowDecorations>();
|
||||||
#if PLATFORM_WINDOWS
|
x += decorations?.Icon?.Width ?? 0;
|
||||||
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;
|
||||||
@@ -349,36 +136,20 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
// Fill the right side if title and buttons are not present
|
||||||
if (_useCustomWindowSystem)
|
if (decorations?.Title == null)
|
||||||
{
|
Width = Parent.Width;
|
||||||
// Buttons
|
else
|
||||||
_closeButton.Height = Height;
|
Width = x;
|
||||||
_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 (_window != null)
|
if (_selected != null)
|
||||||
{
|
Selected = null;
|
||||||
_window.Closed -= OnWindowClosed;
|
|
||||||
OnWindowClosed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,14 +42,12 @@ namespace FlaxEditor.GUI
|
|||||||
Text = text;
|
Text = text;
|
||||||
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
#if PLATFORM_WINDOWS
|
if (!Utilities.Utils.UseCustomWindowDecorations())
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace FlaxEditor.GUI.Tabs
|
|||||||
if (EnabledInHierarchy && Tab.Enabled)
|
if (EnabledInHierarchy && Tab.Enabled)
|
||||||
{
|
{
|
||||||
Tabs.SelectedTab = Tab;
|
Tabs.SelectedTab = Tab;
|
||||||
|
Tab.PerformLayout(true);
|
||||||
Tabs.Focus();
|
Tabs.Focus();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -122,6 +122,14 @@ namespace FlaxEditor.GUI
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClicked()
|
||||||
|
{
|
||||||
|
if (AutoCheck)
|
||||||
|
Checked = !Checked;
|
||||||
|
Clicked?.Invoke();
|
||||||
|
(Parent as ToolStrip)?.OnButtonClicked(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
@@ -196,11 +204,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (button == MouseButton.Left && _primaryMouseDown)
|
if (button == MouseButton.Left && _primaryMouseDown)
|
||||||
{
|
{
|
||||||
_primaryMouseDown = false;
|
_primaryMouseDown = false;
|
||||||
if (AutoCheck)
|
OnClicked();
|
||||||
Checked = !Checked;
|
|
||||||
Clicked?.Invoke();
|
|
||||||
(Parent as ToolStrip)?.OnButtonClicked(this);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (button == MouseButton.Right && _secondaryMouseDown)
|
if (button == MouseButton.Right && _secondaryMouseDown)
|
||||||
@@ -215,6 +219,18 @@ namespace FlaxEditor.GUI
|
|||||||
return base.OnMouseUp(location, button);
|
return base.OnMouseUp(location, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
|
{
|
||||||
|
if (button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
OnClicked();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnMouseLeave()
|
public override void OnMouseLeave()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
private readonly bool _supportMultiSelect;
|
private readonly bool _supportMultiSelect;
|
||||||
private Margin _margin;
|
private Margin _margin;
|
||||||
private bool _autoSize = true;
|
private bool _autoSize = true;
|
||||||
|
private bool _deferLayoutUpdate = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The TreeNode that is being dragged over. This could have a value when not dragging.
|
/// The TreeNode that is being dragged over. This could have a value when not dragging.
|
||||||
@@ -67,6 +68,16 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
|
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allow nodes to Draw the root tree line.
|
||||||
|
/// </summary>
|
||||||
|
public bool DrawRootTreeLine = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the deferred layout operation was performed.
|
||||||
|
/// </summary>
|
||||||
|
public event Action AfterDeferredLayout;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the margin for the child tree nodes.
|
/// Gets or sets the margin for the child tree nodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -353,9 +364,26 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
BulkSelectUpdateExpanded(false);
|
BulkSelectUpdateExpanded(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void PerformLayout(bool force = false)
|
||||||
|
{
|
||||||
|
if (_isLayoutLocked && !force)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// In case the tree was fully expanded or collapsed along its children, avoid calculating the layout multiple times for each child
|
||||||
|
_deferLayoutUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Update(float deltaTime)
|
public override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (_deferLayoutUpdate)
|
||||||
|
{
|
||||||
|
base.PerformLayout();
|
||||||
|
AfterDeferredLayout?.Invoke();
|
||||||
|
_deferLayoutUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
var node = SelectedNode;
|
var node = SelectedNode;
|
||||||
|
|
||||||
// Check if has focus and if any node is focused and it isn't a root
|
// Check if has focus and if any node is focused and it isn't a root
|
||||||
|
|||||||
@@ -760,20 +760,21 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
// Show tree guidelines
|
// Show tree guidelines
|
||||||
if (Editor.Instance.Options.Options.Interface.ShowTreeLines)
|
if (Editor.Instance.Options.Options.Interface.ShowTreeLines)
|
||||||
{
|
{
|
||||||
TreeNode parentNode = Parent as TreeNode;
|
ContainerControl parent = Parent;
|
||||||
|
TreeNode parentNode = parent as TreeNode;
|
||||||
bool thisNodeIsLast = false;
|
bool thisNodeIsLast = false;
|
||||||
while (parentNode != null && parentNode != ParentTree.Children[0])
|
while (parentNode != null && (parentNode != tree.Children[0] || tree.DrawRootTreeLine))
|
||||||
{
|
{
|
||||||
float bottomOffset = 0;
|
float bottomOffset = 0;
|
||||||
float topOffset = 0;
|
float topOffset = 0;
|
||||||
|
|
||||||
if (Parent == parentNode && this == Parent.Children[0])
|
if (parent == parentNode && this == parent.Children[0])
|
||||||
topOffset = 2;
|
topOffset = 2;
|
||||||
|
|
||||||
if (thisNodeIsLast && parentNode.Children.Count == 1)
|
if (thisNodeIsLast && parentNode.Children.Count == 1)
|
||||||
bottomOffset = topOffset != 0 ? 4 : 2;
|
bottomOffset = topOffset != 0 ? 4 : 2;
|
||||||
|
|
||||||
if (Parent == parentNode && this == Parent.Children[Parent.Children.Count - 1] && !_opened)
|
if (parent == parentNode && this == parent.Children[^1] && !_opened)
|
||||||
{
|
{
|
||||||
thisNodeIsLast = true;
|
thisNodeIsLast = true;
|
||||||
bottomOffset = topOffset != 0 ? 4 : 2;
|
bottomOffset = topOffset != 0 ? 4 : 2;
|
||||||
@@ -784,6 +785,8 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
if (_iconCollaped.IsValid)
|
if (_iconCollaped.IsValid)
|
||||||
leftOffset += 18;
|
leftOffset += 18;
|
||||||
var lineRect1 = new Rectangle(parentNode.TextRect.Left - leftOffset, parentNode.HeaderRect.Top + topOffset, 1, parentNode.HeaderRect.Height - bottomOffset);
|
var lineRect1 = new Rectangle(parentNode.TextRect.Left - leftOffset, parentNode.HeaderRect.Top + topOffset, 1, parentNode.HeaderRect.Height - bottomOffset);
|
||||||
|
if (HasAnyVisibleChild && CustomArrowRect.HasValue && CustomArrowRect.Value.Intersects(lineRect1))
|
||||||
|
lineRect1 = Rectangle.Empty; // Skip drawing line if it's overlapping the arrow rectangle
|
||||||
Render2D.FillRectangle(lineRect1, isSelected ? style.ForegroundGrey : style.LightBackground);
|
Render2D.FillRectangle(lineRect1, isSelected ? style.ForegroundGrey : style.LightBackground);
|
||||||
parentNode = parentNode.Parent as TreeNode;
|
parentNode = parentNode.Parent as TreeNode;
|
||||||
}
|
}
|
||||||
|
|||||||
342
Source/Editor/GUI/WindowDecorations.cs
Normal file
342
Source/Editor/GUI/WindowDecorations.cs
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEditor.GUI.Docking;
|
||||||
|
using FlaxEditor.Options;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -402,10 +402,11 @@ 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)
|
if (!window || window->IsClosed())
|
||||||
continue;
|
continue;
|
||||||
switch (e.Type)
|
switch (e.Type)
|
||||||
{
|
{
|
||||||
@@ -435,12 +436,14 @@ 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;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
|
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
|
||||||
#include "Engine/Content/Assets/VisualScript.h"
|
#include "Engine/Content/Assets/VisualScript.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
|
#include "Engine/Level/Actor.h"
|
||||||
#include "Engine/CSG/CSGBuilder.h"
|
#include "Engine/CSG/CSGBuilder.h"
|
||||||
#include "Engine/Engine/CommandLine.h"
|
#include "Engine/Engine/CommandLine.h"
|
||||||
#include "Engine/Renderer/ProbesRenderer.h"
|
#include "Engine/Renderer/ProbesRenderer.h"
|
||||||
@@ -74,7 +75,7 @@ void OnLightmapsBuildFinished(bool failed)
|
|||||||
OnLightmapsBake(ShadowsOfMordor::BuildProgressStep::GenerateLightmapCharts, 0, 0, false);
|
OnLightmapsBake(ShadowsOfMordor::BuildProgressStep::GenerateLightmapCharts, 0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
|
void OnBakeEvent(bool started, Actor* e)
|
||||||
{
|
{
|
||||||
if (Internal_EnvProbeBake == nullptr)
|
if (Internal_EnvProbeBake == nullptr)
|
||||||
{
|
{
|
||||||
@@ -82,7 +83,7 @@ void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
|
|||||||
ASSERT(Internal_EnvProbeBake);
|
ASSERT(Internal_EnvProbeBake);
|
||||||
}
|
}
|
||||||
|
|
||||||
MObject* probeObj = e.Actor ? e.Actor->GetManagedInstance() : nullptr;
|
MObject* probeObj = e ? e->GetManagedInstance() : nullptr;
|
||||||
|
|
||||||
MainThreadManagedInvokeAction::ParamsBuilder params;
|
MainThreadManagedInvokeAction::ParamsBuilder params;
|
||||||
params.AddParam(started);
|
params.AddParam(started);
|
||||||
@@ -90,12 +91,12 @@ void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
|
|||||||
MainThreadManagedInvokeAction::Invoke(Internal_EnvProbeBake, params);
|
MainThreadManagedInvokeAction::Invoke(Internal_EnvProbeBake, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnRegisterBake(const ProbesRenderer::Entry& e)
|
void OnRegisterBake(Actor* e)
|
||||||
{
|
{
|
||||||
OnBakeEvent(true, e);
|
OnBakeEvent(true, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnFinishBake(const ProbesRenderer::Entry& e)
|
void OnFinishBake(Actor* e)
|
||||||
{
|
{
|
||||||
OnBakeEvent(false, e);
|
OnBakeEvent(false, e);
|
||||||
}
|
}
|
||||||
@@ -156,7 +157,9 @@ ManagedEditor::ManagedEditor()
|
|||||||
lightmapsBuilder->OnBuildProgress.Bind<OnLightmapsBuildProgress>();
|
lightmapsBuilder->OnBuildProgress.Bind<OnLightmapsBuildProgress>();
|
||||||
lightmapsBuilder->OnBuildFinished.Bind<OnLightmapsBuildFinished>();
|
lightmapsBuilder->OnBuildFinished.Bind<OnLightmapsBuildFinished>();
|
||||||
CSG::Builder::OnBrushModified.Bind<OnBrushModified>();
|
CSG::Builder::OnBrushModified.Bind<OnBrushModified>();
|
||||||
|
#if LOG_ENABLE
|
||||||
Log::Logger::OnMessage.Bind<OnLogMessage>();
|
Log::Logger::OnMessage.Bind<OnLogMessage>();
|
||||||
|
#endif
|
||||||
VisualScripting::DebugFlow.Bind<OnVisualScriptingDebugFlow>();
|
VisualScripting::DebugFlow.Bind<OnVisualScriptingDebugFlow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,9 @@ ManagedEditor::~ManagedEditor()
|
|||||||
lightmapsBuilder->OnBuildProgress.Unbind<OnLightmapsBuildProgress>();
|
lightmapsBuilder->OnBuildProgress.Unbind<OnLightmapsBuildProgress>();
|
||||||
lightmapsBuilder->OnBuildFinished.Unbind<OnLightmapsBuildFinished>();
|
lightmapsBuilder->OnBuildFinished.Unbind<OnLightmapsBuildFinished>();
|
||||||
CSG::Builder::OnBrushModified.Unbind<OnBrushModified>();
|
CSG::Builder::OnBrushModified.Unbind<OnBrushModified>();
|
||||||
|
#if LOG_ENABLE
|
||||||
Log::Logger::OnMessage.Unbind<OnLogMessage>();
|
Log::Logger::OnMessage.Unbind<OnLogMessage>();
|
||||||
|
#endif
|
||||||
VisualScripting::DebugFlow.Unbind<OnVisualScriptingDebugFlow>();
|
VisualScripting::DebugFlow.Unbind<OnVisualScriptingDebugFlow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"))
|
else if (path.EndsWith(".cpp") || path.EndsWith(".h") || path.EndsWith(".c") || path.EndsWith(".hpp"))
|
||||||
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);
|
||||||
@@ -1135,6 +1135,7 @@ namespace FlaxEditor.Modules
|
|||||||
Proxy.Add(new FontProxy());
|
Proxy.Add(new FontProxy());
|
||||||
Proxy.Add(new ShaderProxy());
|
Proxy.Add(new ShaderProxy());
|
||||||
Proxy.Add(new ShaderSourceProxy());
|
Proxy.Add(new ShaderSourceProxy());
|
||||||
|
Proxy.Add(new ShaderHeaderProxy());
|
||||||
Proxy.Add(new ParticleEmitterProxy());
|
Proxy.Add(new ParticleEmitterProxy());
|
||||||
Proxy.Add(new ParticleEmitterFunctionProxy());
|
Proxy.Add(new ParticleEmitterFunctionProxy());
|
||||||
Proxy.Add(new ParticleSystemProxy());
|
Proxy.Add(new ParticleSystemProxy());
|
||||||
|
|||||||
@@ -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"))
|
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h" || extension == ".c" || extension == ".hpp"))
|
||||||
{
|
{
|
||||||
// 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));
|
||||||
|
|||||||
@@ -76,6 +76,13 @@ namespace FlaxEditor.Modules
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when Editor will leave the play mode.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnPlayEnding()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when Editor leaves the play mode.
|
/// Called when Editor leaves the play mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -255,12 +255,17 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
// When applying changes to prefab from actor in level ignore it's root transformation (see ActorEditor.ProcessDiff)
|
// When applying changes to prefab from actor in level ignore it's root transformation (see ActorEditor.ProcessDiff)
|
||||||
var originalTransform = instance.LocalTransform;
|
var originalTransform = instance.LocalTransform;
|
||||||
|
var originalName = instance.Name;
|
||||||
if (instance.IsPrefabRoot && instance.HasScene)
|
if (instance.IsPrefabRoot && instance.HasScene)
|
||||||
|
{
|
||||||
instance.LocalTransform = prefab.GetDefaultInstance().Transform;
|
instance.LocalTransform = prefab.GetDefaultInstance().Transform;
|
||||||
|
instance.Name = prefab.GetDefaultInstance().Name;
|
||||||
|
}
|
||||||
|
|
||||||
// Call backend
|
// Call backend
|
||||||
var failed = PrefabManager.Internal_ApplyAll(FlaxEngine.Object.GetUnmanagedPtr(instance));
|
var failed = PrefabManager.Internal_ApplyAll(FlaxEngine.Object.GetUnmanagedPtr(instance));
|
||||||
instance.LocalTransform = originalTransform;
|
instance.LocalTransform = originalTransform;
|
||||||
|
instance.Name = originalName;
|
||||||
if (failed)
|
if (failed)
|
||||||
throw new Exception("Failed to apply the prefab. See log to learn more.");
|
throw new Exception("Failed to apply the prefab. See log to learn more.");
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FlaxEditor.Actions;
|
using FlaxEditor.Actions;
|
||||||
using FlaxEditor.SceneGraph;
|
using FlaxEditor.SceneGraph;
|
||||||
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
namespace FlaxEditor.Modules
|
namespace FlaxEditor.Modules
|
||||||
@@ -561,7 +562,8 @@ namespace FlaxEditor.Modules
|
|||||||
public void CreateParentForSelectedActors()
|
public void CreateParentForSelectedActors()
|
||||||
{
|
{
|
||||||
List<SceneGraphNode> selection = Editor.SceneEditing.Selection;
|
List<SceneGraphNode> selection = Editor.SceneEditing.Selection;
|
||||||
var actors = selection.Where(x => x is ActorNode).Select(x => ((ActorNode)x).Actor);
|
// Get Actors but skip scene node
|
||||||
|
var actors = selection.Where(x => x is ActorNode and not SceneNode).Select(x => ((ActorNode)x).Actor);
|
||||||
var actorsCount = actors.Count();
|
var actorsCount = actors.Count();
|
||||||
if (actorsCount == 0)
|
if (actorsCount == 0)
|
||||||
return;
|
return;
|
||||||
@@ -709,7 +711,11 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
private void OnActorChildNodesDispose(ActorNode node)
|
private void OnActorChildNodesDispose(ActorNode node)
|
||||||
{
|
{
|
||||||
|
if (Selection.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// TODO: cache if selection contains any actor child node and skip this loop if no need to iterate
|
// TODO: cache if selection contains any actor child node and skip this loop if no need to iterate
|
||||||
|
// TODO: or build a hash set with selected nodes for quick O(1) checks (cached until selection changes)
|
||||||
|
|
||||||
// Deselect child nodes
|
// Deselect child nodes
|
||||||
for (int i = 0; i < node.ChildNodes.Count; i++)
|
for (int i = 0; i < node.ChildNodes.Count; i++)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.SceneGraph;
|
using FlaxEditor.SceneGraph;
|
||||||
using FlaxEditor.SceneGraph.Actors;
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -658,6 +659,48 @@ namespace FlaxEditor.Modules
|
|||||||
//node?.TreeNode.OnActiveChanged();
|
//node?.TreeNode.OnActiveChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnActorDestroyChildren(Actor actor)
|
||||||
|
{
|
||||||
|
// Instead of doing OnActorParentChanged for every child lets remove all of them at once from that actor
|
||||||
|
ActorNode node = GetActorNode(actor);
|
||||||
|
if (node != null)
|
||||||
|
{
|
||||||
|
if (Editor.SceneEditing.HasSthSelected)
|
||||||
|
{
|
||||||
|
// Clear selection if one of the removed actors is selected
|
||||||
|
var selection = new HashSet<Actor>();
|
||||||
|
foreach (var e in Editor.SceneEditing.Selection)
|
||||||
|
{
|
||||||
|
if (e is ActorNode q && q.Actor)
|
||||||
|
selection.Add(q.Actor);
|
||||||
|
}
|
||||||
|
var count = actor.ChildrenCount;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var child = actor.GetChild(i);
|
||||||
|
if (selection.Contains(child))
|
||||||
|
{
|
||||||
|
Editor.SceneEditing.Deselect();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all child nodes (upfront remove all nodes to run faster)
|
||||||
|
for (int i = 0; i < node.ChildNodes.Count; i++)
|
||||||
|
{
|
||||||
|
if (node.ChildNodes[i] is ActorNode child)
|
||||||
|
child.parentNode = null;
|
||||||
|
}
|
||||||
|
node.TreeNode.DisposeChildren();
|
||||||
|
for (int i = 0; i < node.ChildNodes.Count; i++)
|
||||||
|
{
|
||||||
|
node.ChildNodes[i].Dispose();
|
||||||
|
}
|
||||||
|
node.ChildNodes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the actor node.
|
/// Gets the actor node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -709,6 +752,7 @@ namespace FlaxEditor.Modules
|
|||||||
Level.ActorOrderInParentChanged += OnActorOrderInParentChanged;
|
Level.ActorOrderInParentChanged += OnActorOrderInParentChanged;
|
||||||
Level.ActorNameChanged += OnActorNameChanged;
|
Level.ActorNameChanged += OnActorNameChanged;
|
||||||
Level.ActorActiveChanged += OnActorActiveChanged;
|
Level.ActorActiveChanged += OnActorActiveChanged;
|
||||||
|
Level.ActorDestroyChildren += OnActorDestroyChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -726,6 +770,7 @@ namespace FlaxEditor.Modules
|
|||||||
Level.ActorOrderInParentChanged -= OnActorOrderInParentChanged;
|
Level.ActorOrderInParentChanged -= OnActorOrderInParentChanged;
|
||||||
Level.ActorNameChanged -= OnActorNameChanged;
|
Level.ActorNameChanged -= OnActorNameChanged;
|
||||||
Level.ActorActiveChanged -= OnActorActiveChanged;
|
Level.ActorActiveChanged -= OnActorActiveChanged;
|
||||||
|
Level.ActorDestroyChildren -= OnActorDestroyChildren;
|
||||||
|
|
||||||
// Cleanup graph
|
// Cleanup graph
|
||||||
Root.Dispose();
|
Root.Dispose();
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ namespace FlaxEditor.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnPlayBegin()
|
public override void OnPlayBeginning()
|
||||||
{
|
{
|
||||||
Editor.Windows.FlashMainWindow();
|
Editor.Windows.FlashMainWindow();
|
||||||
|
|
||||||
@@ -306,19 +306,21 @@ namespace FlaxEditor.Modules
|
|||||||
public override void OnPlayEnd()
|
public override void OnPlayEnd()
|
||||||
{
|
{
|
||||||
var gameWin = Editor.Windows.GameWin;
|
var gameWin = Editor.Windows.GameWin;
|
||||||
|
if (gameWin != null)
|
||||||
switch (gameWin.FocusOnPlayOption)
|
|
||||||
{
|
{
|
||||||
case Options.InterfaceOptions.PlayModeFocus.None: break;
|
switch (gameWin.FocusOnPlayOption)
|
||||||
case Options.InterfaceOptions.PlayModeFocus.GameWindow: break;
|
|
||||||
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore:
|
|
||||||
if (_previousWindow != null && !_previousWindow.IsDisposing)
|
|
||||||
{
|
{
|
||||||
if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow))
|
case Options.InterfaceOptions.PlayModeFocus.None: break;
|
||||||
break;
|
case Options.InterfaceOptions.PlayModeFocus.GameWindow: break;
|
||||||
_previousWindow.Focus();
|
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore:
|
||||||
|
if (_previousWindow != null && !_previousWindow.IsDisposing)
|
||||||
|
{
|
||||||
|
if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow))
|
||||||
|
break;
|
||||||
|
_previousWindow.Focus();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor.UI.UncheckPauseButton();
|
Editor.UI.UncheckPauseButton();
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ 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;
|
||||||
@@ -29,6 +28,40 @@ 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 Label _progressLabel;
|
private Label _progressLabel;
|
||||||
private ProgressBar _progressBar;
|
private ProgressBar _progressBar;
|
||||||
private Button _outputLogButton;
|
private Button _outputLogButton;
|
||||||
@@ -97,6 +130,11 @@ 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>
|
||||||
@@ -377,19 +415,11 @@ 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;
|
||||||
|
|
||||||
// Add dummy control for drawing the main window borders if using a custom style
|
mainWindow.PerformLayout(true);
|
||||||
#if PLATFORM_WINDOWS
|
|
||||||
if (!Editor.Options.Options.Interface.UseNativeWindowSystem)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
mainWindow.AddChild(new CustomWindowBorderControl
|
|
||||||
{
|
|
||||||
Size = Float2.Zero,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -410,23 +440,6 @@ 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()
|
||||||
{
|
{
|
||||||
@@ -458,13 +471,6 @@ 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);
|
||||||
@@ -518,10 +524,12 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
private void InitMainMenu(RootControl mainWindow)
|
private void InitMainMenu(RootControl mainWindow)
|
||||||
{
|
{
|
||||||
MainMenu = new MainMenu(mainWindow)
|
MainMenu = new MainMenu()
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
@@ -628,19 +636,19 @@ namespace FlaxEditor.Modules
|
|||||||
MenuWindow = MainMenu.AddButton("Window");
|
MenuWindow = MainMenu.AddButton("Window");
|
||||||
cm = MenuWindow.ContextMenu;
|
cm = MenuWindow.ContextMenu;
|
||||||
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
||||||
cm.AddButton("Content", Editor.Windows.ContentWin.FocusOrShow);
|
cm.AddButton("Content", inputOptions.ContentWindow,Editor.Windows.ContentWin.FocusOrShow);
|
||||||
cm.AddButton("Scene", Editor.Windows.SceneWin.FocusOrShow);
|
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
|
||||||
cm.AddButton("Toolbox", Editor.Windows.ToolboxWin.FocusOrShow);
|
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
|
||||||
cm.AddButton("Properties", Editor.Windows.PropertiesWin.FocusOrShow);
|
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
|
||||||
cm.AddButton("Game", Editor.Windows.GameWin.FocusOrShow);
|
cm.AddButton("Game", inputOptions.GameWindow, Editor.Windows.GameWin.FocusOrShow);
|
||||||
cm.AddButton("Editor", Editor.Windows.EditWin.FocusOrShow);
|
cm.AddButton("Editor", inputOptions.EditorWindow, Editor.Windows.EditWin.FocusOrShow);
|
||||||
cm.AddButton("Debug Log", Editor.Windows.DebugLogWin.FocusOrShow);
|
cm.AddButton("Debug Log", inputOptions.DebugLogWindow, Editor.Windows.DebugLogWin.FocusOrShow);
|
||||||
cm.AddButton("Output Log", Editor.Windows.OutputLogWin.FocusOrShow);
|
cm.AddButton("Output Log", inputOptions.OutputLogWindow, Editor.Windows.OutputLogWin.FocusOrShow);
|
||||||
cm.AddButton("Graphics Quality", Editor.Windows.GraphicsQualityWin.FocusOrShow);
|
cm.AddButton("Graphics Quality", inputOptions.GraphicsQualityWindow, Editor.Windows.GraphicsQualityWin.FocusOrShow);
|
||||||
cm.AddButton("Game Cooker", Editor.Windows.GameCookerWin.FocusOrShow);
|
cm.AddButton("Game Cooker", inputOptions.GameCookerWindow, Editor.Windows.GameCookerWin.FocusOrShow);
|
||||||
cm.AddButton("Profiler", inputOptions.ProfilerWindow, Editor.Windows.ProfilerWin.FocusOrShow);
|
cm.AddButton("Profiler", inputOptions.ProfilerWindow, Editor.Windows.ProfilerWin.FocusOrShow);
|
||||||
cm.AddButton("Content Search", Editor.ContentFinding.ShowSearch);
|
cm.AddButton("Content Search", inputOptions.ContentSearchWindow, Editor.ContentFinding.ShowSearch);
|
||||||
cm.AddButton("Visual Script Debugger", Editor.Windows.VisualScriptDebuggerWin.FocusOrShow);
|
cm.AddButton("Visual Script Debugger", inputOptions.VisualScriptDebuggerWindow, Editor.Windows.VisualScriptDebuggerWin.FocusOrShow);
|
||||||
cm.AddSeparator();
|
cm.AddSeparator();
|
||||||
cm.AddButton("Save window layout", Editor.Windows.SaveLayout);
|
cm.AddButton("Save window layout", Editor.Windows.SaveLayout);
|
||||||
_menuWindowApplyWindowLayout = cm.AddChildMenu("Window layouts");
|
_menuWindowApplyWindowLayout = cm.AddChildMenu("Window layouts");
|
||||||
@@ -661,6 +669,20 @@ 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);
|
||||||
|
var driver = Platform.DisplayServer;
|
||||||
|
if (!string.IsNullOrEmpty(driver))
|
||||||
|
driver = $" ({driver})";
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -1070,6 +1092,7 @@ 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,7 +10,6 @@ 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;
|
||||||
@@ -758,17 +757,19 @@ 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 (!Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
|
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
|
||||||
{
|
{
|
||||||
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
|
||||||
}
|
}
|
||||||
#elif PLATFORM_LINUX
|
#if PLATFORM_LINUX && !PLATFORM_SDL
|
||||||
settings.HasBorder = false;
|
settings.HasBorder = false;
|
||||||
#endif
|
#endif
|
||||||
MainWindow = Platform.CreateWindow(ref settings);
|
MainWindow = Platform.CreateWindow(ref settings);
|
||||||
@@ -1223,6 +1224,13 @@ namespace FlaxEditor.Modules
|
|||||||
Windows[i].OnPlayBegin();
|
Windows[i].OnPlayBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnPlayEnding()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Windows.Count; i++)
|
||||||
|
Windows[i].OnPlayEnding();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnPlayEnd()
|
public override void OnPlayEnd()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,25 @@ namespace FlaxEditor.Options
|
|||||||
OpenPrefab,
|
OpenPrefab,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shortcut availability in play mode.
|
||||||
|
/// </summary>
|
||||||
|
public enum PlayModeShortcutAvailability
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// None of the window shortcuts will be available in play mode.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
/// <summary>
|
||||||
|
/// Only the profiler window shortcut will be available in play mode.
|
||||||
|
/// </summary>
|
||||||
|
ProfilerOnly,
|
||||||
|
/// <summary>
|
||||||
|
/// All window shortcuts will be available in play mode.
|
||||||
|
/// </summary>
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Input editor options data container.
|
/// Input editor options data container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -40,6 +59,16 @@ namespace FlaxEditor.Options
|
|||||||
[HideInEditor]
|
[HideInEditor]
|
||||||
public sealed class InputOptions
|
public sealed class InputOptions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value based on the current settings that indicates wether window shortcuts will be avaliable during play mode.
|
||||||
|
/// </summary>
|
||||||
|
public static bool WindowShortcutsAvaliable => !Editor.IsPlayMode || Editor.Instance.Options.Options.Input.PlayModeWindowShortcutAvaliability == PlayModeShortcutAvailability.All;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value based on the current settings that indicates wether the profiler window shortcut will be avaliable during play mode.
|
||||||
|
/// </summary>
|
||||||
|
public static bool ProfilerShortcutAvaliable => WindowShortcutsAvaliable || Editor.Instance.Options.Options.Input.PlayModeWindowShortcutAvaliability == PlayModeShortcutAvailability.ProfilerOnly;
|
||||||
|
|
||||||
#region Common
|
#region Common
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "Ctrl+S")]
|
[DefaultValue(typeof(InputBinding), "Ctrl+S")]
|
||||||
@@ -110,6 +139,10 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Common"), EditorOrder(240)]
|
[EditorDisplay("Common"), EditorOrder(240)]
|
||||||
public InputBinding ToggleFullscreen = new InputBinding(KeyboardKeys.F11);
|
public InputBinding ToggleFullscreen = new InputBinding(KeyboardKeys.F11);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+BackQuote")]
|
||||||
|
[EditorDisplay("Common"), EditorOrder(250)]
|
||||||
|
public InputBinding FocusConsoleCommand = new InputBinding(KeyboardKeys.BackQuote, KeyboardKeys.Control);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region File
|
#region File
|
||||||
@@ -230,9 +263,9 @@ namespace FlaxEditor.Options
|
|||||||
|
|
||||||
#region Profiler
|
#region Profiler
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "None")]
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha7")]
|
||||||
[EditorDisplay("Profiler", "Open Profiler Window"), EditorOrder(630)]
|
[EditorDisplay("Profiler", "Open Profiler Window"), EditorOrder(630)]
|
||||||
public InputBinding ProfilerWindow = new InputBinding(KeyboardKeys.None);
|
public InputBinding ProfilerWindow = new InputBinding(KeyboardKeys.Alpha7, KeyboardKeys.Control);
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "None")]
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
[EditorDisplay("Profiler", "Start/Stop Profiler"), EditorOrder(631)]
|
[EditorDisplay("Profiler", "Start/Stop Profiler"), EditorOrder(631)]
|
||||||
@@ -356,24 +389,307 @@ namespace FlaxEditor.Options
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Debug Views
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Alpha4")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2000)]
|
||||||
|
public InputBinding Default = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Alpha3")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2010)]
|
||||||
|
public InputBinding Unlit = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2020)]
|
||||||
|
public InputBinding NoPostFX = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Alpha2")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2030)]
|
||||||
|
public InputBinding Wireframe = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Alpha5")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2040)]
|
||||||
|
public InputBinding LightBuffer = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2050)]
|
||||||
|
public InputBinding ReflectionsBuffer = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2060)]
|
||||||
|
public InputBinding DepthBuffer = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2070)]
|
||||||
|
public InputBinding MotionVectors = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2080)]
|
||||||
|
public InputBinding LightmapUVDensity = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2090)]
|
||||||
|
public InputBinding VertexColors = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Alpha1")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2100)]
|
||||||
|
public InputBinding PhysicsColliders = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2110)]
|
||||||
|
public InputBinding LODPreview = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2120)]
|
||||||
|
public InputBinding MaterialComplexity = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2130)]
|
||||||
|
public InputBinding QuadOverdraw = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2140)]
|
||||||
|
public InputBinding GloablSDF = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2150)]
|
||||||
|
public InputBinding GlobalSurfaceAtlas = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Debug Views"), EditorOrder(2160)]
|
||||||
|
public InputBinding GlobalIllumination = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region View Flags
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3000)]
|
||||||
|
public InputBinding AntiAliasing = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3010)]
|
||||||
|
public InputBinding Shadows = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha7")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3020)]
|
||||||
|
public InputBinding EditorSprites = new InputBinding(KeyboardKeys.Alpha7, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3030)]
|
||||||
|
public InputBinding Reflections = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3040)]
|
||||||
|
public InputBinding ScreenSpaceReflections = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3050)]
|
||||||
|
public InputBinding AmbientOcclusion = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha6")]
|
||||||
|
[EditorDisplay("View Flags", "Global Illumination"), EditorOrder(3060)]
|
||||||
|
public InputBinding GlobalIlluminationViewFlag = new InputBinding(KeyboardKeys.Alpha6, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3070)]
|
||||||
|
public InputBinding DirectionalLights = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3080)]
|
||||||
|
public InputBinding PointLights = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3090)]
|
||||||
|
public InputBinding SpotLights = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3100)]
|
||||||
|
public InputBinding SkyLights = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3110)]
|
||||||
|
public InputBinding Sky = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3120)]
|
||||||
|
public InputBinding Fog = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3130)]
|
||||||
|
public InputBinding SpecularLight = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3140)]
|
||||||
|
public InputBinding Decals = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha3")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3150)]
|
||||||
|
public InputBinding CustomPostProcess = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3160)]
|
||||||
|
public InputBinding Bloom = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3170)]
|
||||||
|
public InputBinding ToneMapping = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha2")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3180)]
|
||||||
|
public InputBinding EyeAdaptation = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3190)]
|
||||||
|
public InputBinding CameraArtifacts = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3200)]
|
||||||
|
public InputBinding LensFlares = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3210)]
|
||||||
|
public InputBinding DepthOfField = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3220)]
|
||||||
|
public InputBinding MotionBlur = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3230)]
|
||||||
|
public InputBinding ContactShadows = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha1")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3240)]
|
||||||
|
public InputBinding PhysicsDebug = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha5")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3250)]
|
||||||
|
public InputBinding LightsDebug = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha4")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3260)]
|
||||||
|
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Interface
|
#region Interface
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "Ctrl+W")]
|
[DefaultValue(typeof(InputBinding), "Ctrl+W")]
|
||||||
[EditorDisplay("Interface"), EditorOrder(2000)]
|
[EditorDisplay("Interface"), EditorOrder(3500)]
|
||||||
public InputBinding CloseTab = new InputBinding(KeyboardKeys.W, KeyboardKeys.Control);
|
public InputBinding CloseTab = new InputBinding(KeyboardKeys.W, KeyboardKeys.Control);
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "Ctrl+Tab")]
|
[DefaultValue(typeof(InputBinding), "Ctrl+Tab")]
|
||||||
[EditorDisplay("Interface"), EditorOrder(2010)]
|
[EditorDisplay("Interface"), EditorOrder(3510)]
|
||||||
public InputBinding NextTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control);
|
public InputBinding NextTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control);
|
||||||
|
|
||||||
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Tab")]
|
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Tab")]
|
||||||
[EditorDisplay("Interface"), EditorOrder(2020)]
|
[EditorDisplay("Interface"), EditorOrder(3520)]
|
||||||
public InputBinding PreviousTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control, KeyboardKeys.Shift);
|
public InputBinding PreviousTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
[DefaultValue(SceneNodeDoubleClick.Expand)]
|
[DefaultValue(SceneNodeDoubleClick.Expand)]
|
||||||
[EditorDisplay("Interface"), EditorOrder(2030)]
|
[EditorDisplay("Interface"), EditorOrder(3530)]
|
||||||
public SceneNodeDoubleClick DoubleClickSceneNode = SceneNodeDoubleClick.Expand;
|
public SceneNodeDoubleClick DoubleClickSceneNode = SceneNodeDoubleClick.Expand;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Windows
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating what window shortcuts will be available during play mode.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(PlayModeShortcutAvailability.ProfilerOnly)]
|
||||||
|
[EditorDisplay("Windows", "Avaliability in Play Mode"), EditorOrder(3000)]
|
||||||
|
public PlayModeShortcutAvailability PlayModeWindowShortcutAvaliability { get; set; } = PlayModeShortcutAvailability.ProfilerOnly;
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha5")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3010)]
|
||||||
|
public InputBinding ContentWindow = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Control);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha4")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3020)]
|
||||||
|
public InputBinding SceneWindow = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3030)]
|
||||||
|
public InputBinding ToolboxWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha3")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3040)]
|
||||||
|
public InputBinding PropertiesWindow = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Control);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha2")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3050)]
|
||||||
|
public InputBinding GameWindow = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Control);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha1")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3060)]
|
||||||
|
public InputBinding EditorWindow = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Control);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3070)]
|
||||||
|
public InputBinding DebugLogWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3080)]
|
||||||
|
public InputBinding OutputLogWindow = new InputBinding(KeyboardKeys.C, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(3090)]
|
||||||
|
public InputBinding GraphicsQualityWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(4000)]
|
||||||
|
public InputBinding GameCookerWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(4010)]
|
||||||
|
public InputBinding ContentSearchWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Windows"), EditorOrder(4020)]
|
||||||
|
public InputBinding VisualScriptDebuggerWindow = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Node editors
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+W")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4500)]
|
||||||
|
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+A")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4510)]
|
||||||
|
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+S")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4520)]
|
||||||
|
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Shift+D")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4530)]
|
||||||
|
public InputBinding NodesAlignRight = new InputBinding(KeyboardKeys.D, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Shift+W")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4540)]
|
||||||
|
public InputBinding NodesAlignMiddle = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Alt+Shift+S")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4550)]
|
||||||
|
public InputBinding NodesAlignCenter = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "Q")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4560)]
|
||||||
|
public InputBinding NodesAutoFormat = new InputBinding(KeyboardKeys.Q);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4570)]
|
||||||
|
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("Node editors"), EditorOrder(4580)]
|
||||||
|
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,34 @@ 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>
|
||||||
@@ -167,14 +195,12 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Interface"), EditorOrder(10), Tooltip("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.")]
|
[EditorDisplay("Interface"), EditorOrder(10), Tooltip("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.")]
|
||||||
public float InterfaceScale { get; set; } = 1.0f;
|
public float InterfaceScale { get; set; } = 1.0f;
|
||||||
|
|
||||||
#if 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 decorations in child windows. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
|
||||||
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar. Editor restart required.")]
|
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
|
||||||
public bool UseNativeWindowSystem { get; set; } = false;
|
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether show selected camera preview in the editor window.
|
/// Gets or sets a value indicating whether show selected camera preview in the editor window.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Engine/Core/Math/Quaternion.h"
|
#include "Engine/Core/Math/Quaternion.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "Engine/Serialization/JsonWriters.h"
|
#include "Engine/Serialization/JsonWriters.h"
|
||||||
#include "Engine/Serialization/JsonTools.h"
|
#include "Engine/Serialization/JsonTools.h"
|
||||||
#include <ThirdParty/pugixml/pugixml.hpp>
|
#include <ThirdParty/pugixml/pugixml.hpp>
|
||||||
@@ -327,6 +328,7 @@ ProjectInfo* ProjectInfo::Load(const String& path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
auto project = New<ProjectInfo>();
|
auto project = New<ProjectInfo>();
|
||||||
if (project->LoadProject(path))
|
if (project->LoadProject(path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ namespace FlaxEditor.SceneGraph
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingSphere sphere = new BoundingSphere(Transform.Translation, 7.0f);
|
var center = _actor.Transform.Translation;
|
||||||
|
ViewportIconsRenderer.GetBounds(ref center, ref ray.Ray.Position, out var sphere);
|
||||||
return CollisionsHelper.RayIntersectsSphere(ref ray.Ray, ref sphere, out distance);
|
return CollisionsHelper.RayIntersectsSphere(ref ray.Ray, ref sphere, out distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,9 +76,13 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
// Skip removing this terrain file sif it's still referenced
|
// Skip removing this terrain file sif it's still referenced
|
||||||
var sceneReferences = Editor.GetAssetReferences(e.SceneId);
|
var sceneReferences = Editor.GetAssetReferences(e.SceneId);
|
||||||
if (sceneReferences != null && sceneReferences.Contains(e.TerrainId))
|
if (sceneReferences != null && sceneReferences.Contains(e.TerrainId))
|
||||||
|
{
|
||||||
|
Debug.Log($"Skip removing files used by terrain {e.TerrainId} on scene {e.SceneId} as it's still in use");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Delete files
|
// Delete files
|
||||||
|
Debug.Log($"Removing files used by removed terrain {e.TerrainId} on scene {e.SceneId}");
|
||||||
foreach (var file in e.Files)
|
foreach (var file in e.Files)
|
||||||
{
|
{
|
||||||
if (file != null && File.Exists(file))
|
if (file != null && File.Exists(file))
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
_infoLabel.AutoHeight = true;
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
var grid = layout.UniformGrid();
|
||||||
var gridControl = grid.CustomControl;
|
var gridControl = grid.CustomControl;
|
||||||
gridControl.ClipChildren = false;
|
gridControl.ClipChildren = false;
|
||||||
gridControl.Height = Button.DefaultHeight;
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
if (noFilter && actor != null)
|
if (noFilter && actor != null)
|
||||||
{
|
{
|
||||||
// Pick the correct id when inside a prefab window.
|
// Pick the correct id when inside a prefab window.
|
||||||
var id = actor.HasPrefabLink && actor.Scene.Scene == null ? actor.PrefabObjectID : actor.ID;
|
var id = actor.HasPrefabLink && actor.Scene == null ? actor.PrefabObjectID : actor.ID;
|
||||||
isExpanded = Editor.Instance.ProjectCache.IsExpandedActor(ref id);
|
isExpanded = Editor.Instance.ProjectCache.IsExpandedActor(ref id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace FlaxEditor.SceneGraph
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parent node.
|
/// The parent node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected SceneGraphNode parentNode;
|
internal SceneGraphNode parentNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the children list.
|
/// Gets the children list.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Platform/Thread.h"
|
#include "Engine/Platform/Thread.h"
|
||||||
#include "Engine/Threading/IRunnable.h"
|
#include "Engine/Threading/IRunnable.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
|
|
||||||
void OnAsyncBegin(Thread* thread);
|
void OnAsyncBegin(Thread* thread);
|
||||||
void OnAsyncEnd();
|
void OnAsyncEnd();
|
||||||
@@ -232,6 +233,8 @@ void OnAsyncEnd()
|
|||||||
|
|
||||||
bool CodeEditingManagerService::Init()
|
bool CodeEditingManagerService::Init()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Try get editors
|
// Try get editors
|
||||||
#if USE_VISUAL_STUDIO_DTE
|
#if USE_VISUAL_STUDIO_DTE
|
||||||
VisualStudioEditor::FindEditors(&CodeEditors);
|
VisualStudioEditor::FindEditors(&CodeEditors);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "Engine/Scripting/Scripting.h"
|
#include "Engine/Scripting/Scripting.h"
|
||||||
#include "Engine/Scripting/Script.h"
|
#include "Engine/Scripting/Script.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "Engine/Level/Level.h"
|
#include "Engine/Level/Level.h"
|
||||||
#include "FlaxEngine.Gen.h"
|
#include "FlaxEngine.Gen.h"
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ namespace ScriptsBuilderImpl
|
|||||||
void onScriptsReloadEnd();
|
void onScriptsReloadEnd();
|
||||||
void onScriptsLoaded();
|
void onScriptsLoaded();
|
||||||
|
|
||||||
void GetClassName(const StringAnsi& fullname, StringAnsi& className);
|
void GetClassName(const StringAnsiView fullname, StringAnsi& className);
|
||||||
|
|
||||||
void onCodeEditorAsyncOpenBegin()
|
void onCodeEditorAsyncOpenBegin()
|
||||||
{
|
{
|
||||||
@@ -120,9 +121,13 @@ void ScriptsBuilderImpl::sourceDirEvent(const String& path, FileSystemAction act
|
|||||||
// Discard non-source files or generated files
|
// Discard non-source files or generated files
|
||||||
if ((!path.EndsWith(TEXT(".cs")) &&
|
if ((!path.EndsWith(TEXT(".cs")) &&
|
||||||
!path.EndsWith(TEXT(".cpp")) &&
|
!path.EndsWith(TEXT(".cpp")) &&
|
||||||
|
!path.EndsWith(TEXT(".c")) &&
|
||||||
|
!path.EndsWith(TEXT(".hpp")) &&
|
||||||
!path.EndsWith(TEXT(".h"))) ||
|
!path.EndsWith(TEXT(".h"))) ||
|
||||||
path.EndsWith(TEXT(".Gen.cs")))
|
path.EndsWith(TEXT(".Gen.cs")))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ScopeLock scopeLock(_locker);
|
ScopeLock scopeLock(_locker);
|
||||||
_lastSourceCodeEdited = DateTime::Now();
|
_lastSourceCodeEdited = DateTime::Now();
|
||||||
@@ -272,7 +277,7 @@ bool ScriptsBuilder::GenerateProject(const StringView& customArgs)
|
|||||||
return RunBuildTool(args);
|
return RunBuildTool(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptsBuilderImpl::GetClassName(const StringAnsi& fullname, StringAnsi& className)
|
void ScriptsBuilderImpl::GetClassName(const StringAnsiView fullname, StringAnsi& className)
|
||||||
{
|
{
|
||||||
const auto lastDotIndex = fullname.FindLast('.');
|
const auto lastDotIndex = fullname.FindLast('.');
|
||||||
if (lastDotIndex != -1)
|
if (lastDotIndex != -1)
|
||||||
@@ -413,6 +418,7 @@ void ScriptsBuilder::GetBinariesConfiguration(const Char*& target, const Char*&
|
|||||||
|
|
||||||
bool ScriptsBuilderImpl::compileGameScriptsAsyncInner()
|
bool ScriptsBuilderImpl::compileGameScriptsAsyncInner()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
LOG(Info, "Starting scripts compilation...");
|
LOG(Info, "Starting scripts compilation...");
|
||||||
CallEvent(EventType::CompileStarted);
|
CallEvent(EventType::CompileStarted);
|
||||||
|
|
||||||
@@ -519,6 +525,8 @@ void ScriptsBuilderImpl::onEditorAssemblyUnloading(MAssembly* assembly)
|
|||||||
|
|
||||||
bool ScriptsBuilderImpl::compileGameScriptsAsync()
|
bool ScriptsBuilderImpl::compileGameScriptsAsync()
|
||||||
{
|
{
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
{
|
{
|
||||||
ScopeLock scopeLock(_locker);
|
ScopeLock scopeLock(_locker);
|
||||||
@@ -562,6 +570,7 @@ bool ScriptsBuilderService::Init()
|
|||||||
// Check flag
|
// Check flag
|
||||||
if (_isInited)
|
if (_isInited)
|
||||||
return false;
|
return false;
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
_isInited = true;
|
_isInited = true;
|
||||||
|
|
||||||
// Link for Editor assembly unload event to clear cached Internal_OnCompilationEnd to prevent errors
|
// Link for Editor assembly unload event to clear cached Internal_OnCompilationEnd to prevent errors
|
||||||
@@ -659,6 +668,9 @@ bool ScriptsBuilderService::Init()
|
|||||||
|
|
||||||
void ScriptsBuilderService::Update()
|
void ScriptsBuilderService::Update()
|
||||||
{
|
{
|
||||||
|
PROFILE_CPU();
|
||||||
|
PROFILE_MEM(Editor);
|
||||||
|
|
||||||
// Send compilation events
|
// Send compilation events
|
||||||
{
|
{
|
||||||
ScopeLock scopeLock(_compileEventsLocker);
|
ScopeLock scopeLock(_compileEventsLocker);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user