Compare commits
508 Commits
master_fix
...
mac_change
| Author | SHA1 | Date | |
|---|---|---|---|
| fd5c50635c | |||
|
|
07f031e4c5 | ||
|
|
06c31a39f2 | ||
|
|
2a6e38e020 | ||
|
|
cc69e5d966 | ||
|
|
d68969dbe2 | ||
|
|
c4d20f06ee | ||
|
|
3c5c6f9883 | ||
|
|
8e7dc2a91e | ||
|
|
4ddbc8ba5c | ||
|
|
15f379e87f | ||
|
|
d4a7b3074e | ||
|
|
a3492e59ef | ||
|
|
515ad56fa2 | ||
|
|
ebd20dd816 | ||
|
|
019a9f6089 | ||
|
|
273b110db4 | ||
|
|
0bea701a83 | ||
|
|
ee22b9dc25 | ||
|
|
a1096aaf92 | ||
|
|
885ee15767 | ||
|
|
c978ab2b84 | ||
|
|
f045b5b6b6 | ||
|
|
c51a023e61 | ||
|
|
645df4fb06 | ||
|
|
b53028782f | ||
|
|
ef551c36ae | ||
|
|
e851efa0a8 | ||
| 0084bc051c | |||
|
|
9c8023d64f | ||
|
|
6d02f5d9da | ||
|
|
1f9f281c31 | ||
|
|
846b64048f | ||
|
|
55f73b6cf7 | ||
|
|
0f6c1aea62 | ||
|
|
d2ee61ef8d | ||
|
|
a1399c5157 | ||
|
|
7b7a92758f | ||
|
|
bd300651ec | ||
|
|
a2b0d0714e | ||
|
|
3d66316716 | ||
|
|
9c32f978fb | ||
|
|
ed5ad91a32 | ||
|
|
ecddb8aae5 | ||
|
|
a855b17cc0 | ||
|
|
27dd1bda25 | ||
|
|
4afd9fd8df | ||
|
|
73c19b278f | ||
|
|
b4cb1028ed | ||
|
|
4a7f1a5fde | ||
|
|
5d0fdc8313 | ||
|
|
70b324cdec | ||
|
|
20516bb8bc | ||
|
|
c18b9163ca | ||
|
|
db5b65beac | ||
|
|
78e5baf6a5 | ||
|
|
4833c19366 | ||
|
|
65fd22f5b6 | ||
|
|
f57df83d26 | ||
|
|
66894b71fa | ||
|
|
7e9ee0610a | ||
|
|
f733611213 | ||
|
|
780e78f056 | ||
|
|
4d447b7544 | ||
|
|
9a44902949 | ||
|
|
e84b5410ec | ||
|
|
9ac19cbd2f | ||
|
|
39a2bc2535 | ||
|
|
15771355cb | ||
|
|
f3111e855d | ||
|
|
3c6838ee35 | ||
|
|
36ab08e60d | ||
|
|
834c4553b2 | ||
|
|
5a95336601 | ||
|
|
f26fae2daf | ||
|
|
20df4289c2 | ||
|
|
217701ae05 | ||
|
|
f1509bab28 | ||
|
|
30fdd7336e | ||
|
|
3b120cc5a4 | ||
|
|
4cf0c38940 | ||
|
|
0f383d2fc6 | ||
| 483df22929 | |||
|
|
07f21a1520 | ||
| f870fc3ae2 | |||
|
|
bbb5354e9c | ||
|
|
21e2c830e5 | ||
|
|
c828c90161 | ||
|
|
f725f4c0b9 | ||
|
|
1535f95cf1 | ||
|
|
b1f85b7462 | ||
|
|
3a0af54f48 | ||
|
|
4e3e9386cc | ||
|
|
449fc597b5 | ||
|
|
0e91a2d25b | ||
|
|
aba995a42f | ||
|
|
bf0c7fe0dc | ||
|
|
2ab8b9dd55 | ||
|
|
e1ffdee57a | ||
|
|
7c44767d4d | ||
|
|
87ccaa9dd8 | ||
|
|
e8c2f18a4d | ||
|
|
6b36543717 | ||
|
|
bb2a883dc7 | ||
|
|
be7e88de36 | ||
|
|
4a1490f0b1 | ||
|
|
e0d0acc33c | ||
|
|
e2f2d3e6f6 | ||
|
|
afc04dc41c | ||
|
|
bdfa503c05 | ||
|
|
205a8b2ebe | ||
|
|
d18c245730 | ||
|
|
e4eb064562 | ||
|
|
9fc9382e58 | ||
|
|
2bf9efaf30 | ||
|
|
528b4c89ce | ||
|
|
277dabc8b4 | ||
|
|
9a5bc444ba | ||
|
|
e834fc5a42 | ||
|
|
6b87985a44 | ||
|
|
a65a74b866 | ||
|
|
b2124201d5 | ||
|
|
29b8326042 | ||
|
|
81bfa6edc9 | ||
|
|
8ed6a92022 | ||
|
|
c9d16e16cc | ||
|
|
d9f9401c5a | ||
|
|
1e9918b9cc | ||
|
|
6c84b7a259 | ||
|
|
43b337e163 | ||
|
|
45306ca20e | ||
|
|
259d93f95c | ||
|
|
61b6aeb252 | ||
|
|
d694c35db4 | ||
|
|
f105d6f84f | ||
|
|
b1b6953200 | ||
|
|
fa428e343b | ||
|
|
dbbb67f398 | ||
|
|
a9bddfa784 | ||
|
|
f9b784a42a | ||
|
|
d47bd5d6e7 | ||
|
|
e1013aec94 | ||
|
|
1c294059df | ||
|
|
305296883d | ||
|
|
a7016d1186 | ||
|
|
004e02af73 | ||
|
|
143d714037 | ||
|
|
da8376bba1 | ||
|
|
f773a0755d | ||
|
|
d8343dae8e | ||
|
|
b09fbe2d9b | ||
|
|
6dbfd25bdb | ||
|
|
ecfd03f79c | ||
|
|
66a295d5af | ||
|
|
d7458d81a5 | ||
|
|
cc5e4c19e1 | ||
|
|
0c5cb59875 | ||
|
|
85ed0ecb06 | ||
|
|
95b9392f51 | ||
|
|
c7c1bbe35f | ||
|
|
192d3d1a8e | ||
|
|
877d57681d | ||
|
|
0a9bc084f4 | ||
|
|
ec4f8ce239 | ||
|
|
d049a16882 | ||
|
|
ee75cab73e | ||
|
|
0072e21ffa | ||
|
|
f44dde89db | ||
|
|
e6fd761b80 | ||
|
|
62a378e01a | ||
|
|
e67b705397 | ||
|
|
847f6411e7 | ||
|
|
0d7c04682d | ||
|
|
baf068330c | ||
|
|
593646061e | ||
|
|
9ac231c403 | ||
|
|
d2d7a871ce | ||
|
|
b172b08782 | ||
|
|
18778aa511 | ||
|
|
b7e32e13ab | ||
|
|
610c76578b | ||
|
|
e721fbd89f | ||
|
|
ff2c5290b5 | ||
|
|
2b4dc97a97 | ||
|
|
14842183f2 | ||
|
|
b4b13d8dd4 | ||
|
|
e3d1e8a5ea | ||
|
|
d9f90f726b | ||
|
|
e0062a6ff1 | ||
|
|
e494c9ec76 | ||
|
|
2501095500 | ||
|
|
3cfc5db54a | ||
|
|
840835fad2 | ||
|
|
41f136ce0f | ||
|
|
32cae3aacd | ||
|
|
832c524c3c | ||
|
|
a18ca9a4ad | ||
|
|
05e7e6630c | ||
|
|
788d8660b8 | ||
|
|
ab806b2a9b | ||
|
|
610ba00915 | ||
|
|
e60bd165f4 | ||
|
|
223d4f64eb | ||
|
|
827ad85651 | ||
|
|
69c5d65318 | ||
|
|
b834dddb11 | ||
|
|
baddfec6d1 | ||
|
|
fc2f56aca6 | ||
|
|
0364fd629b | ||
|
|
5dbaf3f94e | ||
|
|
c5b7ea9c44 | ||
|
|
7b856fdc95 | ||
|
|
890df65970 | ||
|
|
ab6dfca36e | ||
|
|
72bb2dd932 | ||
|
|
ca09852898 | ||
|
|
e21cb9154a | ||
|
|
af124ce163 | ||
|
|
c28381fb09 | ||
|
|
973ff0efa0 | ||
|
|
27896b6410 | ||
|
|
4bb9de21b4 | ||
|
|
890538c667 | ||
|
|
4b9fa0dcf5 | ||
|
|
14d1b7dd24 | ||
|
|
6788844270 | ||
|
|
b2f2537338 | ||
|
|
450b998a29 | ||
|
|
688d9c77cb | ||
|
|
d71ea5a72b | ||
|
|
01e3ece2af | ||
|
|
afc65f7557 | ||
|
|
d60484b917 | ||
| feceb4e00f | |||
| 67b33a575a | |||
|
|
76b869146d | ||
|
|
32e725392b | ||
|
|
0975ac2a25 | ||
|
|
cf3bcc4549 | ||
|
|
11ea889fa9 | ||
|
|
c5a28a5734 | ||
|
|
6c79a17c7a | ||
|
|
b24d98df9e | ||
|
|
400e2f1b0e | ||
|
|
22e6139ca3 | ||
|
|
859fa16a74 | ||
|
|
8facb46def | ||
|
|
b87f8b96e1 | ||
|
|
37df16a3e4 | ||
|
|
ce45fa3d54 | ||
|
|
7f56d9456b | ||
|
|
1cad2489a3 | ||
|
|
7cdc2456cd | ||
|
|
6b0ee3eeed | ||
|
|
57330e39ca | ||
|
|
af29f2f3dc | ||
|
|
1bdb577b60 | ||
|
|
329ea1c9b4 | ||
|
|
728da6354f | ||
|
|
d5456d6eb3 | ||
|
|
e65714988f | ||
|
|
4e4df736f9 | ||
|
|
5bfe5b0035 | ||
|
|
b30553ea65 | ||
|
|
2550763808 | ||
|
|
6f6dd2f4a3 | ||
|
|
c30d457b1c | ||
|
|
b786fa1c22 | ||
|
|
bbcbe305a8 | ||
|
|
222df16f11 | ||
|
|
8b924d13c1 | ||
|
|
66e25c81b0 | ||
|
|
e12f99ee53 | ||
|
|
387f0cf457 | ||
|
|
f11acdf5db | ||
|
|
3af7dddcc2 | ||
|
|
543e2ecd13 | ||
| 35f8051a62 | |||
| 4453453d46 | |||
|
|
23f5f4d85f | ||
|
|
90a21696f6 | ||
|
|
fa38f0ac91 | ||
|
|
38d8832468 | ||
|
|
c68aa3b371 | ||
| d031649bbd | |||
| 21b8d1838d | |||
| c8ee2fc155 | |||
|
|
dc22fa4061 | ||
| 3eb690fe58 | |||
| 52e2327527 | |||
| f95cbb0e52 | |||
| 518a19c857 | |||
| c0b54be692 | |||
|
|
c2c92eba82 | ||
| d64c28f672 | |||
| 2a959d0531 | |||
|
|
4504d0ae96 | ||
| f14ba6ace6 | |||
| 518f9dc9dc | |||
| 8db29a30e0 | |||
|
|
0e76585709 | ||
|
|
8bf51512ac | ||
|
|
779e8e7169 | ||
|
|
3c8b80152b | ||
|
|
f280412ef4 | ||
| 1327fa40cb | |||
| b70ab01308 | |||
| 46fd5a5855 | |||
| 74c1e200ce | |||
| 31945a53a2 | |||
| 3e91ba3fb2 | |||
| ae03bc2dd2 | |||
| 5cd27032b4 | |||
| 7445064d97 | |||
|
|
e47fc5a54a | ||
|
|
26e24769be | ||
| 092beb6ae9 | |||
| eb69186271 | |||
|
|
394860656a | ||
|
|
b07d74d28d | ||
|
|
dacb3b0891 | ||
|
|
a8db0086b1 | ||
|
|
e46b6d5b06 | ||
|
|
dfc8c1fac2 | ||
|
|
f8de118288 | ||
| 0ac3ab2329 | |||
|
|
887311d1f1 | ||
| 466f9a4797 | |||
|
|
f8e4f54c77 | ||
| ea20dc6da0 | |||
| 9becddd84f | |||
| b08c765400 | |||
| afd59d7eb3 | |||
| 47cdd0582c | |||
| af54d04f9d | |||
| 1d2b3bc858 | |||
| 4b552563be | |||
| ebd929176c | |||
| 430e685a7c | |||
| d5bd857c45 | |||
| b8b9ba3069 | |||
| 84c79d5192 | |||
| 028f3a7871 | |||
| 0c462315f0 | |||
| 26261a2090 | |||
| c61ecc0545 | |||
|
|
b5de4d78ad | ||
|
|
0913e6f738 | ||
| 22ba7f2ee5 | |||
|
|
99c26ff9af | ||
|
|
a2d91d989d | ||
|
|
881154e9f4 | ||
| f52f3920cb | |||
| f99a244b8e | |||
|
|
5ec2476aec | ||
|
|
79351f0c4d | ||
|
|
25744986a3 | ||
| 668a4dbb4d | |||
|
|
48100cf9fc | ||
|
|
76f0768b99 | ||
|
|
b2b855200f | ||
|
|
241a8bc764 | ||
|
|
13dd80d429 | ||
|
|
6e9902a966 | ||
|
|
fd1e0a4e80 | ||
|
|
b130b81863 | ||
|
|
b38a7e6eb2 | ||
|
|
4f3f1cd163 | ||
|
|
4d77646f26 | ||
|
|
187592b673 | ||
|
|
215467ae42 | ||
|
|
facd7d39dc | ||
|
|
6810e5f2a4 | ||
|
|
ee6fae8956 | ||
|
|
bb6c3233d2 | ||
|
|
499228cc98 | ||
| 1d8f221f1b | |||
| d70a003617 | |||
| b443b74d18 | |||
| fc341a86e7 | |||
|
|
f2699892e0 | ||
| 68da28ffe8 | |||
|
|
427e76e76e | ||
| b183b5bcfc | |||
| 51feaa0730 | |||
| 8e69aa8bd6 | |||
| 90b2fded48 | |||
| 9125ffeb9e | |||
| 28980e5fbf | |||
| aab0d772a4 | |||
| 6296e1a9eb | |||
| 1586bb0702 | |||
| edeaf6af09 | |||
| 951edd95db | |||
| 9951211596 | |||
| 6d337464f7 | |||
| d0b552d74a | |||
| 83512822b1 | |||
| ccb78103ec | |||
| 6e79ffea34 | |||
| 4f03d37a17 | |||
| 6fb8419b3c | |||
| a4272d6ca9 | |||
| 4654117d5e | |||
| 6ff260d052 | |||
| 88d2b72822 | |||
| 29868531ad | |||
| 95dfb6fdc6 | |||
| 8df3999f85 | |||
| 149b189629 | |||
| b1fd86e6b5 | |||
| 5e8fdf879d | |||
| 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 |
5
.github/workflows/build_linux.yml
vendored
5
.github/workflows/build_linux.yml
vendored
@@ -16,7 +16,8 @@ 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 update
|
||||||
|
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
@@ -44,7 +45,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
|
||||||
|
|||||||
6
.github/workflows/cd.yml
vendored
6
.github/workflows/cd.yml
vendored
@@ -87,7 +87,8 @@ jobs:
|
|||||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
@@ -118,7 +119,8 @@ jobs:
|
|||||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
|
|||||||
3
.github/workflows/tests.yml
vendored
3
.github/workflows/tests.yml
vendored
@@ -28,7 +28,8 @@ 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 update
|
||||||
|
sudo apt-get install -y --fix-missing libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8
|
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8
|
||||||
|
|||||||
BIN
Content/Editor/Camera/M_Camera.flax
(Stored with Git LFS)
BIN
Content/Editor/Camera/M_Camera.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/CubeTexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Decal.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Particle.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Surface.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/SingleColor/Terrain.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/DefaultFontMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/FoliageBrushMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialWire.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/SelectionOutlineMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Highlight Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/Icons/IconsMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/IesProfilePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
@@ -4,8 +4,8 @@
|
|||||||
#define MAX_LOCAL_LIGHTS 4
|
#define MAX_LOCAL_LIGHTS 4
|
||||||
@1// Forward Shading: Includes
|
@1// Forward Shading: Includes
|
||||||
#include "./Flax/LightingCommon.hlsl"
|
#include "./Flax/LightingCommon.hlsl"
|
||||||
#if USE_REFLECTIONS
|
|
||||||
#include "./Flax/ReflectionsCommon.hlsl"
|
#include "./Flax/ReflectionsCommon.hlsl"
|
||||||
|
#if USE_REFLECTIONS
|
||||||
#define MATERIAL_REFLECTIONS_SSR 1
|
#define MATERIAL_REFLECTIONS_SSR 1
|
||||||
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
||||||
#include "./Flax/SSR.hlsl"
|
#include "./Flax/SSR.hlsl"
|
||||||
@@ -14,11 +14,13 @@
|
|||||||
#include "./Flax/Lighting.hlsl"
|
#include "./Flax/Lighting.hlsl"
|
||||||
#include "./Flax/ShadowsSampling.hlsl"
|
#include "./Flax/ShadowsSampling.hlsl"
|
||||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||||
|
#include "./Flax/VolumetricFog.hlsl"
|
||||||
@2// Forward Shading: Constants
|
@2// Forward Shading: Constants
|
||||||
LightData DirectionalLight;
|
LightData DirectionalLight;
|
||||||
LightData SkyLight;
|
LightData SkyLight;
|
||||||
ProbeData EnvironmentProbe;
|
EnvProbeData EnvironmentProbe;
|
||||||
ExponentialHeightFogData ExponentialHeightFog;
|
ExponentialHeightFogData ExponentialHeightFog;
|
||||||
|
VolumetricFogData VolumetricFog;
|
||||||
float3 Dummy2;
|
float3 Dummy2;
|
||||||
uint LocalLightsCount;
|
uint LocalLightsCount;
|
||||||
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
||||||
@@ -28,12 +30,14 @@ TextureCube SkyLightTexture : register(t__SRV__);
|
|||||||
Buffer<float4> ShadowsBuffer : register(t__SRV__);
|
Buffer<float4> ShadowsBuffer : register(t__SRV__);
|
||||||
Texture2D<float> ShadowMap : register(t__SRV__);
|
Texture2D<float> ShadowMap : register(t__SRV__);
|
||||||
Texture3D VolumetricFogTexture : register(t__SRV__);
|
Texture3D VolumetricFogTexture : register(t__SRV__);
|
||||||
|
Texture2D PreIntegratedGF : register(t__SRV__);
|
||||||
@4// Forward Shading: Utilities
|
@4// Forward Shading: Utilities
|
||||||
// Public accessors for lighting data, use them as data binding might change but those methods will remain.
|
// Public accessors for lighting data, use them as data binding might change but those methods will remain.
|
||||||
LightData GetDirectionalLight() { return DirectionalLight; }
|
LightData GetDirectionalLight() { return DirectionalLight; }
|
||||||
LightData GetSkyLight() { return SkyLight; }
|
LightData GetSkyLight() { return SkyLight; }
|
||||||
ProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
|
EnvProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
|
||||||
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
|
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
|
||||||
|
VolumetricFogData GetVolumetricFog() { return VolumetricFog; }
|
||||||
uint GetLocalLightsCount() { return LocalLightsCount; }
|
uint GetLocalLightsCount() { return LocalLightsCount; }
|
||||||
LightData GetLocalLight(uint i) { return LocalLights[i]; }
|
LightData GetLocalLight(uint i) { return LocalLights[i]; }
|
||||||
@5// Forward Shading: Shaders
|
@5// Forward Shading: Shaders
|
||||||
@@ -108,7 +112,8 @@ void PS_Forward(
|
|||||||
|
|
||||||
// Calculate reflections
|
// Calculate reflections
|
||||||
#if USE_REFLECTIONS
|
#if USE_REFLECTIONS
|
||||||
float3 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness).rgb;
|
float4 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness);
|
||||||
|
reflections.rgb *= reflections.a;
|
||||||
|
|
||||||
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
#if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR
|
||||||
// Screen Space Reflections
|
// Screen Space Reflections
|
||||||
@@ -116,7 +121,7 @@ void PS_Forward(
|
|||||||
Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR;
|
Texture2D sceneColorTexture = MATERIAL_REFLECTIONS_SSR_COLOR;
|
||||||
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
||||||
float stepSize = ScreenSize.z; // 1 / screenWidth
|
float stepSize = ScreenSize.z; // 1 / screenWidth
|
||||||
float maxSamples = 48;
|
float maxSamples = 50;
|
||||||
float worldAntiSelfOcclusionBias = 0.1f;
|
float worldAntiSelfOcclusionBias = 0.1f;
|
||||||
float brdfBias = 0.82f;
|
float brdfBias = 0.82f;
|
||||||
float drawDistance = 5000.0f;
|
float drawDistance = 5000.0f;
|
||||||
@@ -124,7 +129,7 @@ void PS_Forward(
|
|||||||
if (hit.z > 0)
|
if (hit.z > 0)
|
||||||
{
|
{
|
||||||
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
||||||
reflections = lerp(reflections, screenColor, hit.z);
|
reflections.rgb = lerp(reflections.rgb, screenColor, hit.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to software tracing if possible
|
// Fallback to software tracing if possible
|
||||||
@@ -136,17 +141,17 @@ void PS_Forward(
|
|||||||
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
|
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
|
||||||
{
|
{
|
||||||
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb;
|
||||||
reflections = lerp(surfaceAtlas, float4(screenColor, 1), hit.z);
|
reflections.rgb = lerp(surfaceAtlas, float4(screenColor, 1), hit.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
light.rgb += reflections * GetReflectionSpecularLighting(ViewPos, gBuffer) * light.a;
|
light.rgb += reflections.rgb * GetReflectionSpecularLighting(PreIntegratedGF, ViewPos, gBuffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add lighting (apply ambient occlusion)
|
// Add lighting
|
||||||
output.rgb += light.rgb * gBuffer.AO;
|
output.rgb += light.rgb;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -158,17 +163,13 @@ void PS_Forward(
|
|||||||
#else
|
#else
|
||||||
float fogSceneDistance = gBuffer.ViewPos.z;
|
float fogSceneDistance = gBuffer.ViewPos.z;
|
||||||
#endif
|
#endif
|
||||||
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, fogSceneDistance);
|
float fogSkipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
|
||||||
|
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, fogSkipDistance, fogSceneDistance);
|
||||||
if (ExponentialHeightFog.VolumetricFogMaxDistance > 0)
|
if (ExponentialHeightFog.VolumetricFogMaxDistance > 0)
|
||||||
{
|
{
|
||||||
// Sample volumetric fog and mix it in
|
// Sample volumetric fog and mix it in
|
||||||
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
float2 screenUV = materialInput.SvPosition.xy * ScreenSize.zw;
|
||||||
float3 viewVector = materialInput.WorldPosition - ViewPos;
|
float4 volumetricFog = SampleVolumetricFog(VolumetricFogTexture, VolumetricFog, materialInput.WorldPosition - ViewPos, screenUV, TemporalAAJitter);
|
||||||
float sceneDepth = length(viewVector);
|
|
||||||
float depthSlice = sceneDepth / ExponentialHeightFog.VolumetricFogMaxDistance;
|
|
||||||
float3 volumeUV = float3(screenUV, depthSlice);
|
|
||||||
float4 volumetricFog = VolumetricFogTexture.SampleLevel(SamplerLinearClamp, volumeUV, 0);
|
|
||||||
fog = CombineVolumetricFog(fog, volumetricFog);
|
fog = CombineVolumetricFog(fog, volumetricFog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ struct VertexOutput
|
|||||||
#endif
|
#endif
|
||||||
float4 ClipExtents : TEXCOORD3;
|
float4 ClipExtents : TEXCOORD3;
|
||||||
float2 ClipOrigin : TEXCOORD4;
|
float2 ClipOrigin : TEXCOORD4;
|
||||||
|
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
@@ -55,6 +56,7 @@ struct PixelInput
|
|||||||
#endif
|
#endif
|
||||||
float4 ClipExtents : TEXCOORD3;
|
float4 ClipExtents : TEXCOORD3;
|
||||||
float2 ClipOrigin : TEXCOORD4;
|
float2 ClipOrigin : TEXCOORD4;
|
||||||
|
float2 CustomData : TEXCOORD5; // x-per-geometry type, y-features mask
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
@@ -67,6 +69,7 @@ struct MaterialInput
|
|||||||
float3 WorldPosition;
|
float3 WorldPosition;
|
||||||
float TwoSidedSign;
|
float TwoSidedSign;
|
||||||
float2 TexCoord;
|
float2 TexCoord;
|
||||||
|
float2 CustomData; // x-per-geometry type, y-features mask
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
half4 VertexColor;
|
half4 VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -84,6 +87,7 @@ MaterialInput GetMaterialInput(Render2DVertex input, VertexOutput output)
|
|||||||
MaterialInput result;
|
MaterialInput result;
|
||||||
result.WorldPosition = output.WorldPosition;
|
result.WorldPosition = output.WorldPosition;
|
||||||
result.TexCoord = output.TexCoord;
|
result.TexCoord = output.TexCoord;
|
||||||
|
result.CustomData = input.CustomDataAndClipOrigin.xy;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = output.VertexColor;
|
result.VertexColor = output.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -103,6 +107,7 @@ MaterialInput GetMaterialInput(PixelInput input)
|
|||||||
MaterialInput result;
|
MaterialInput result;
|
||||||
result.WorldPosition = input.WorldPosition;
|
result.WorldPosition = input.WorldPosition;
|
||||||
result.TexCoord = input.TexCoord;
|
result.TexCoord = input.TexCoord;
|
||||||
|
result.CustomData = input.CustomData;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = input.VertexColor;
|
result.VertexColor = input.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
@@ -229,6 +234,7 @@ VertexOutput VS_GUI(Render2DVertex input)
|
|||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = input.Color;
|
output.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
|
output.CustomData = input.CustomDataAndClipOrigin.xy;
|
||||||
output.ClipOrigin = input.CustomDataAndClipOrigin.zw;
|
output.ClipOrigin = input.CustomDataAndClipOrigin.zw;
|
||||||
output.ClipExtents = input.ClipExtents;
|
output.ClipExtents = input.ClipExtents;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,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/VolumetricFog.hlsl"
|
||||||
@7
|
@7
|
||||||
|
|
||||||
// Primary constant buffer (with additional material parameters)
|
// Primary constant buffer (with additional material parameters)
|
||||||
@@ -21,6 +22,7 @@ float Dummy0;
|
|||||||
float VolumetricFogMaxDistance;
|
float VolumetricFogMaxDistance;
|
||||||
int ParticleStride;
|
int ParticleStride;
|
||||||
int ParticleIndex;
|
int ParticleIndex;
|
||||||
|
float4 GridSliceParameters;
|
||||||
@1META_CB_END
|
@1META_CB_END
|
||||||
|
|
||||||
// Particles attributes buffer
|
// Particles attributes buffer
|
||||||
@@ -202,19 +204,19 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
META_PS(true, FEATURE_LEVEL_SM5)
|
META_PS(true, FEATURE_LEVEL_SM5)
|
||||||
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
|
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
|
||||||
{
|
{
|
||||||
|
// Reproject grid position back to the screen and world space
|
||||||
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
|
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
|
||||||
float3 cellOffset = 0.5f;
|
float3 cellOffset = 0.5f;
|
||||||
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
|
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
|
||||||
float zSlice = gridCoordinate.z + cellOffset.z;
|
float sceneDepth = GetDepthFromSlice(GridSliceParameters, gridCoordinate.z + cellOffset.z) / ViewFar;
|
||||||
float sceneDepth = (zSlice / GridSize.z) * VolumetricFogMaxDistance / ViewFar;
|
|
||||||
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
|
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
|
||||||
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
||||||
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
||||||
float3 positionWS = wsPos.xyz / wsPos.w;
|
wsPos.xyz /= wsPos.w;
|
||||||
|
|
||||||
// Get material parameters
|
// Get material parameters
|
||||||
MaterialInput materialInput = (MaterialInput)0;
|
MaterialInput materialInput = (MaterialInput)0;
|
||||||
materialInput.WorldPosition = positionWS;
|
materialInput.WorldPosition = wsPos.xyz;
|
||||||
materialInput.TexCoord = input.Vertex.TexCoord;
|
materialInput.TexCoord = input.Vertex.TexCoord;
|
||||||
materialInput.ParticleIndex = ParticleIndex;
|
materialInput.ParticleIndex = ParticleIndex;
|
||||||
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
||||||
@@ -225,9 +227,10 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
|
|||||||
Material material = GetMaterialPS(materialInput);
|
Material material = GetMaterialPS(materialInput);
|
||||||
|
|
||||||
// Compute fog properties
|
// Compute fog properties
|
||||||
|
material.Opacity *= material.Mask;
|
||||||
float3 albedo = material.Color;
|
float3 albedo = material.Color;
|
||||||
float extinction = material.Opacity * material.Mask * 0.001f;
|
float extinction = material.Opacity * 0.001f;
|
||||||
float3 emission = material.Emissive;
|
float3 emission = material.Emissive * material.Opacity;
|
||||||
float3 scattering = albedo * extinction;
|
float3 scattering = albedo * extinction;
|
||||||
float absorption = max(0.0f, extinction - Luminance(scattering));
|
float absorption = max(0.0f, extinction - Luminance(scattering));
|
||||||
|
|
||||||
|
|||||||
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Particle Material Color.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Smoke Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/SpriteMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Circle Brush Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Terrain/Highlight Terrain Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
BIN
Content/Editor/TexturePreviewMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
BIN
Content/Editor/Wires Debug Material.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultDeformableMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultRadialMenu.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/DefaultTerrainMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SingleColorMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
BIN
Content/Engine/SkyboxMaterial.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/ColorGrading.flax
(Stored with Git LFS)
BIN
Content/Shaders/ColorGrading.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Fog.flax
(Stored with Git LFS)
BIN
Content/Shaders/Fog.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:0f34bf867df5f4296ca66ac691c2bca4efa168fb9e21ca4e613e8086669575cf
|
oid sha256:615dff65b01507be6c4de722e126324aba20fc197f8e12dafaa94a05e46cba6e
|
||||||
size 13296
|
size 13222
|
||||||
|
|||||||
BIN
Content/Shaders/GUI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GUI.flax
(Stored with Git LFS)
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:064f54786958f109222c49cbc0358ff4f345b30010fcd5e8cc1fab7bdc68c4fe
|
oid sha256:1f07ebb16820897e8598ae7a0627cb75b3d28e9dceea3ad4bd9ff543d5cdd01c
|
||||||
size 13349
|
size 13979
|
||||||
|
|||||||
BIN
Content/Shaders/Histogram.flax
(Stored with Git LFS)
BIN
Content/Shaders/Histogram.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Lights.flax
(Stored with Git LFS)
BIN
Content/Shaders/Lights.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/MultiScaler.flax
(Stored with Git LFS)
BIN
Content/Shaders/MultiScaler.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
BIN
Content/Shaders/PostProcessing.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Reflections.flax
(Stored with Git LFS)
BIN
Content/Shaders/Reflections.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/SSAO.flax
(Stored with Git LFS)
BIN
Content/Shaders/SSAO.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/SSR.flax
(Stored with Git LFS)
BIN
Content/Shaders/SSR.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/TAA.flax
(Stored with Git LFS)
BIN
Content/Shaders/TAA.flax
(Stored with Git LFS)
Binary file not shown.
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:872ac3560279bfd0aeb989ebac1b49750dd142b985bc40058888dfd2b63fe9b2
|
oid sha256:706adde844360c2b0e65ecabaf1d2e2cc4eb4ac7ca9d483d0dd04ec8163b3d97
|
||||||
size 13214
|
size 13081
|
||||||
|
|||||||
@@ -2,17 +2,18 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 11,
|
"Minor": 12,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6805
|
"Build": 6905
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
|
||||||
"GameTarget": "FlaxGame",
|
"GameTarget": "FlaxGame",
|
||||||
"EditorTarget": "FlaxEditor",
|
"EditorTarget": "FlaxEditor",
|
||||||
"Configuration": {
|
"Configuration": {
|
||||||
"UseCSharp": true,
|
"UseCSharp": true,
|
||||||
"UseLargeWorlds": false,
|
"UseLargeWorlds": false,
|
||||||
"UseDotNet": true
|
"UseDotNet": true,
|
||||||
|
"UseSDL": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">ALWAYS</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_STATEMENT_ON_SAME_LINE/@EntryValue">NEVER</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">ON_SINGLE_LINE</s:String>
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ cd "`dirname "$0"`"
|
|||||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --genproject "$@"
|
bash ./Development/Scripts/Mac/CallBuildTool.sh --genproject "$@"
|
||||||
|
|
||||||
# Build bindings for all editor configurations
|
# Build bindings for all editor configurations
|
||||||
echo Building C# bindings...
|
#echo Building C# bindings...
|
||||||
# TODO: Detect the correct architecture here
|
# TODO: Detect the correct architecture here
|
||||||
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor
|
#Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor
|
||||||
|
|||||||
@@ -187,6 +187,11 @@ namespace FlaxEditor.Content.Import
|
|||||||
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
||||||
_settings.Settings.Type = TextureFormatType.GrayScale;
|
_settings.Settings.Type = TextureFormatType.GrayScale;
|
||||||
}
|
}
|
||||||
|
else if (_settings.Settings.Type == TextureFormatType.ColorRGB)
|
||||||
|
{
|
||||||
|
// Blind guess that common color texture is sRGB
|
||||||
|
_settings.Settings.sRGB = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to restore target asset texture import options (useful for fast reimport)
|
// Try to restore target asset texture import options (useful for fast reimport)
|
||||||
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
if (data is DragDataFiles)
|
if (data is DragDataFiles)
|
||||||
return DragDropEffect.Copy;
|
return DragDropEffect.Copy;
|
||||||
return _dragOverItems.Effect;
|
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;
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
if (Values.HasDifferentTypes == false)
|
if (Values.HasDifferentTypes == false)
|
||||||
{
|
{
|
||||||
var group = layout.Group("Bake");
|
var group = layout.Group("Probe");
|
||||||
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
||||||
_bake = group.Button("Bake").Button;
|
_bake = group.Button("Bake").Button;
|
||||||
_bake.Clicked += BakeButtonClicked;
|
_bake.Clicked += BakeButtonClicked;
|
||||||
|
var view = group.Button("View", "Opens the probe texture viewer");
|
||||||
|
view.Button.Clicked += OnViewButtonClicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,5 +52,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnViewButtonClicked()
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is EnvironmentProbe probe && probe.ProbeAsset)
|
||||||
|
Editor.Instance.ContentEditing.Open(probe.ProbeAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,12 +190,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
FindNewKeysCSharp(file, newKeys, allKeys);
|
FindNewKeysCSharp(file, newKeys, allKeys);
|
||||||
|
|
||||||
// C++
|
// C/C++
|
||||||
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories);
|
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);
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEngine;
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="NavMeshBoundsVolume"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ActorEditor" />
|
||||||
|
[CustomEditor(typeof(NavMeshBoundsVolume)), DefaultEditor]
|
||||||
|
internal class NavMeshBoundsVolumeEditor : ActorEditor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
base.Initialize(layout);
|
||||||
|
|
||||||
|
if (Values.HasDifferentTypes == false)
|
||||||
|
{
|
||||||
|
var button = layout.Button("Build");
|
||||||
|
button.Button.Clicked += OnBuildClicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBuildClicked()
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is NavMeshBoundsVolume volume)
|
||||||
|
{
|
||||||
|
Navigation.BuildNavMesh(volume.Box, volume.Scene);
|
||||||
|
Editor.Instance.Scene.MarkSceneEdited(volume.Scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection.Emit;
|
|
||||||
using FlaxEditor.CustomEditors.GUI;
|
using FlaxEditor.CustomEditors.GUI;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|||||||
@@ -909,7 +909,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
settingsButton.Tag = script;
|
settingsButton.Tag = script;
|
||||||
settingsButton.Clicked += OnSettingsButtonClicked;
|
settingsButton.Clicked += OnSettingsButtonClicked;
|
||||||
|
|
||||||
group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2);
|
// Adjust margin to not overlap with other ui elements in the header
|
||||||
|
group.Panel.HeaderTextMargin = group.Panel.HeaderTextMargin with { Left = scriptDrag.Right - 12, Right = settingsButton.Width + Utilities.Constants.UIMargin };
|
||||||
group.Object(values, editor);
|
group.Object(values, editor);
|
||||||
// Remove drop down arrows and containment lines if no objects in the group
|
// Remove drop down arrows and containment lines if no objects in the group
|
||||||
if (group.Children.Count == 0)
|
if (group.Children.Count == 0)
|
||||||
|
|||||||
@@ -450,6 +450,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
protected bool NotNullItems;
|
protected bool NotNullItems;
|
||||||
|
|
||||||
private IntValueBox _sizeBox;
|
private IntValueBox _sizeBox;
|
||||||
|
private Label _label;
|
||||||
private Color _background;
|
private Color _background;
|
||||||
private int _elementsCount, _minCount, _maxCount;
|
private int _elementsCount, _minCount, _maxCount;
|
||||||
private bool _readOnly;
|
private bool _readOnly;
|
||||||
@@ -566,7 +567,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Parent = dropPanel,
|
Parent = dropPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
var label = new Label
|
_label = new Label
|
||||||
{
|
{
|
||||||
Text = "Size",
|
Text = "Size",
|
||||||
AnchorPreset = AnchorPresets.TopRight,
|
AnchorPreset = AnchorPresets.TopRight,
|
||||||
@@ -592,11 +593,12 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
panel.Panel.Offsets = new Margin(7, 7, 0, 0);
|
panel.Panel.Offsets = new Margin(7, 7, 0, 0);
|
||||||
panel.Panel.BackgroundColor = _background;
|
panel.Panel.BackgroundColor = _background;
|
||||||
var elementType = ElementType;
|
var elementType = ElementType;
|
||||||
|
var bindingAttr = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public;
|
||||||
bool single = elementType.IsPrimitive ||
|
bool single = elementType.IsPrimitive ||
|
||||||
elementType.Equals(new ScriptType(typeof(string))) ||
|
elementType.Equals(new ScriptType(typeof(string))) ||
|
||||||
elementType.IsEnum ||
|
elementType.IsEnum ||
|
||||||
(elementType.GetFields().Length == 1 && elementType.GetProperties().Length == 0) ||
|
(elementType.GetFields(bindingAttr).Length == 1 && elementType.GetProperties(bindingAttr).Length == 0) ||
|
||||||
(elementType.GetProperties().Length == 1 && elementType.GetFields().Length == 0) ||
|
(elementType.GetProperties(bindingAttr).Length == 1 && elementType.GetFields(bindingAttr).Length == 0) ||
|
||||||
elementType.Equals(new ScriptType(typeof(JsonAsset))) ||
|
elementType.Equals(new ScriptType(typeof(JsonAsset))) ||
|
||||||
elementType.Equals(new ScriptType(typeof(SettingsBase)));
|
elementType.Equals(new ScriptType(typeof(SettingsBase)));
|
||||||
if (_cachedDropPanels == null)
|
if (_cachedDropPanels == null)
|
||||||
@@ -672,6 +674,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Resize(Count + 1);
|
Resize(Count + 1);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Layout.ContainerControl.SizeChanged += OnLayoutSizeChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSetupContextMenu(ContextMenu menu, DropPanel panel)
|
private void OnSetupContextMenu(ContextMenu menu, DropPanel panel)
|
||||||
@@ -696,10 +700,24 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLayoutSizeChanged(Control control)
|
||||||
|
{
|
||||||
|
if (Layout.ContainerControl is DropPanel dropPanel)
|
||||||
|
{
|
||||||
|
// Hide "Size" text when array editor title overlaps
|
||||||
|
var headerTextSize = dropPanel.HeaderTextFont.GetFont().MeasureText(dropPanel.HeaderText);
|
||||||
|
if (headerTextSize.X + DropPanel.DropDownIconSize >= _label.Left)
|
||||||
|
_label.TextColor = _label.TextColorHighlighted = Color.Transparent;
|
||||||
|
else
|
||||||
|
_label.TextColor = _label.TextColorHighlighted = FlaxEngine.GUI.Style.Current.Foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Deinitialize()
|
protected override void Deinitialize()
|
||||||
{
|
{
|
||||||
_sizeBox = null;
|
_sizeBox = null;
|
||||||
|
Layout.ContainerControl.SizeChanged -= OnLayoutSizeChanged;
|
||||||
|
|
||||||
base.Deinitialize();
|
base.Deinitialize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
return inputEvent;
|
return inputEvent;
|
||||||
if (Values[0] is string str)
|
if (Values[0] is string str)
|
||||||
return str;
|
return str;
|
||||||
|
if (Values.Type.Type == typeof(InputEvent))
|
||||||
|
return new InputEvent();
|
||||||
if (Values.Type.Type == typeof(string))
|
if (Values.Type.Type == typeof(string))
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ namespace FlaxEditor.CustomEditors.Elements
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var settingsButtonSize = Panel.HeaderHeight;
|
var settingsButtonSize = Panel.HeaderHeight;
|
||||||
return new Image
|
Panel.HeaderTextMargin = Panel.HeaderTextMargin with { Right = settingsButtonSize + Utilities.Constants.UIMargin };
|
||||||
|
; return new Image
|
||||||
{
|
{
|
||||||
TooltipText = "Settings",
|
TooltipText = "Settings",
|
||||||
AutoFocus = true,
|
AutoFocus = true,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ using FlaxEngine.Assertions;
|
|||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Interop;
|
using FlaxEngine.Interop;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
@@ -1370,7 +1371,7 @@ namespace FlaxEditor
|
|||||||
public void BuildCSG()
|
public void BuildCSG()
|
||||||
{
|
{
|
||||||
var scenes = Level.Scenes;
|
var scenes = Level.Scenes;
|
||||||
scenes.ToList().ForEach(x => x.BuildCSG(0));
|
scenes.ForEach(x => x.BuildCSG(0));
|
||||||
Scene.MarkSceneEdited(scenes);
|
Scene.MarkSceneEdited(scenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1380,7 +1381,7 @@ namespace FlaxEditor
|
|||||||
public void BuildNavMesh()
|
public void BuildNavMesh()
|
||||||
{
|
{
|
||||||
var scenes = Level.Scenes;
|
var scenes = Level.Scenes;
|
||||||
scenes.ToList().ForEach(x => Navigation.BuildNavMesh(x, 0));
|
Navigation.BuildNavMesh();
|
||||||
Scene.MarkSceneEdited(scenes);
|
Scene.MarkSceneEdited(scenes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -502,6 +502,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
if (base.OnKeyDown(key))
|
if (base.OnKeyDown(key))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Keyboard navigation around the menu
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case KeyboardKeys.ArrowDown:
|
case KeyboardKeys.ArrowDown:
|
||||||
@@ -526,6 +527,20 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case KeyboardKeys.ArrowRight:
|
||||||
|
for (int i = 0; i < _panel.Children.Count; i++)
|
||||||
|
{
|
||||||
|
if (_panel.Children[i] is ContextMenuChildMenu item && item.Visible && item.IsFocused && !item.ContextMenu.IsOpened)
|
||||||
|
{
|
||||||
|
item.ShowChild(this);
|
||||||
|
item.ContextMenu._panel.Children.FirstOrDefault(x => x is ContextMenuButton && x.Visible)?.Focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyboardKeys.ArrowLeft:
|
||||||
|
ParentCM?.RootWindow.Focus();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,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;
|
||||||
@@ -72,6 +75,11 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasChildCMOpened => _childCM != null;
|
public bool HasChildCMOpened => _childCM != null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the parent context menu (if exists).
|
||||||
|
/// </summary>
|
||||||
|
public ContextMenuBase ParentCM => _parentCM;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the topmost context menu.
|
/// Gets the topmost context menu.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -81,9 +89,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
{
|
{
|
||||||
var cm = this;
|
var cm = this;
|
||||||
while (cm._parentCM != null && cm._isSubMenu)
|
while (cm._parentCM != null && cm._isSubMenu)
|
||||||
{
|
|
||||||
cm = cm._parentCM;
|
cm = cm._parentCM;
|
||||||
}
|
|
||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,6 +114,11 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseInput = true;
|
public bool UseInput = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional flag that can disable UI navigation (tab/enter).
|
||||||
|
/// </summary>
|
||||||
|
public bool UseNavigation = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
/// Initializes a new instance of the <see cref="ContextMenuBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -122,7 +133,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>
|
||||||
@@ -257,7 +268,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);
|
||||||
@@ -267,6 +280,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;
|
||||||
@@ -441,6 +460,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;
|
||||||
@@ -454,6 +484,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private void OnWindowLostFocus()
|
private void OnWindowLostFocus()
|
||||||
{
|
{
|
||||||
@@ -552,7 +583,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
|
||||||
@@ -594,6 +630,21 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
case KeyboardKeys.Escape:
|
case KeyboardKeys.Escape:
|
||||||
Hide();
|
Hide();
|
||||||
return true;
|
return true;
|
||||||
|
case KeyboardKeys.Return:
|
||||||
|
if (UseNavigation && Root?.FocusedControl != null)
|
||||||
|
{
|
||||||
|
Root.SubmitFocused();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyboardKeys.Tab:
|
||||||
|
if (UseNavigation && Root != null)
|
||||||
|
{
|
||||||
|
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||||
|
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
CloseMenuOnClick = false;
|
CloseMenuOnClick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowChild(ContextMenu parentContextMenu)
|
internal void ShowChild(ContextMenu parentContextMenu)
|
||||||
{
|
{
|
||||||
// Hide parent CM popups and set itself as child
|
// Hide parent CM popups and set itself as child
|
||||||
var vAlign = parentContextMenu.ItemsAreaMargin.Top;
|
var vAlign = parentContextMenu.ItemsAreaMargin.Top;
|
||||||
|
|||||||
@@ -522,6 +522,16 @@ namespace FlaxEditor.GUI
|
|||||||
cm.AddButton("Show whole curve", _editor.ShowWholeCurve);
|
cm.AddButton("Show whole curve", _editor.ShowWholeCurve);
|
||||||
cm.AddButton("Reset view", _editor.ResetView);
|
cm.AddButton("Reset view", _editor.ResetView);
|
||||||
}
|
}
|
||||||
|
cm.AddSeparator();
|
||||||
|
var presetCm = cm.AddChildMenu("Apply preset");
|
||||||
|
foreach (var value in Enum.GetValues(typeof(CurvePreset)))
|
||||||
|
{
|
||||||
|
CurvePreset preset = (CurvePreset)value;
|
||||||
|
string name = Utilities.Utils.GetPropertyNameUI(preset.ToString());
|
||||||
|
var b = presetCm.ContextMenu.AddButton(name, () => _editor.ApplyPreset(preset));
|
||||||
|
b.Enabled = !(_editor is LinearCurveEditor<T> && (preset != CurvePreset.Constant && preset != CurvePreset.Linear));
|
||||||
|
}
|
||||||
|
|
||||||
_editor.OnShowContextMenu(cm, selectionCount);
|
_editor.OnShowContextMenu(cm, selectionCount);
|
||||||
cm.Show(this, location);
|
cm.Show(this, location);
|
||||||
}
|
}
|
||||||
@@ -619,6 +629,33 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of avaliable curve presets for the <see cref="CurveEditor{T}"/>.
|
||||||
|
/// </summary>
|
||||||
|
public enum CurvePreset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A curve where every point has the same value.
|
||||||
|
/// </summary>
|
||||||
|
Constant,
|
||||||
|
/// <summary>
|
||||||
|
/// A curve linear curve.
|
||||||
|
/// </summary>
|
||||||
|
Linear,
|
||||||
|
/// <summary>
|
||||||
|
/// A curve that starts a slowly and then accelerates until the end.
|
||||||
|
/// </summary>
|
||||||
|
EaseIn,
|
||||||
|
/// <summary>
|
||||||
|
/// A curve that starts a steep and then flattens until the end.
|
||||||
|
/// </summary>
|
||||||
|
EaseOut,
|
||||||
|
/// <summary>
|
||||||
|
/// A combination of the <see cref="CurvePreset.EaseIn"/> and <see cref="CurvePreset.EaseOut"/> preset.
|
||||||
|
/// </summary>
|
||||||
|
Smoothstep
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnKeyframesDeselect(IKeyframesEditor editor)
|
public override void OnKeyframesDeselect(IKeyframesEditor editor)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,48 @@ namespace FlaxEditor.GUI
|
|||||||
/// <seealso cref="CurveEditorBase" />
|
/// <seealso cref="CurveEditorBase" />
|
||||||
public abstract partial class CurveEditor<T> : CurveEditorBase where T : new()
|
public abstract partial class CurveEditor<T> : CurveEditorBase where T : new()
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a single point in a <see cref="CurveEditorPreset"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected struct CurvePresetPoint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The time.
|
||||||
|
/// </summary>
|
||||||
|
public float Time;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value.
|
||||||
|
/// </summary>
|
||||||
|
public float Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The in tangent. Will be ignored in <see cref="LinearCurveEditor{T}"/>
|
||||||
|
/// </summary>
|
||||||
|
public float TangentIn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The out tangent. Will be ignored in <see cref="LinearCurveEditor{T}"/>
|
||||||
|
/// </summary>
|
||||||
|
public float TangentOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A curve preset.
|
||||||
|
/// </summary>
|
||||||
|
protected struct CurveEditorPreset()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// If the tangents will be linear or smooth.
|
||||||
|
/// </summary>
|
||||||
|
public bool LinearTangents;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The points of the preset.
|
||||||
|
/// </summary>
|
||||||
|
public List<CurvePresetPoint> Points;
|
||||||
|
}
|
||||||
|
|
||||||
private class Popup : ContextMenuBase
|
private class Popup : ContextMenuBase
|
||||||
{
|
{
|
||||||
private CustomEditorPresenter _presenter;
|
private CustomEditorPresenter _presenter;
|
||||||
@@ -26,11 +68,12 @@ namespace FlaxEditor.GUI
|
|||||||
private List<int> _keyframeIndices;
|
private List<int> _keyframeIndices;
|
||||||
private bool _isDirty;
|
private bool _isDirty;
|
||||||
|
|
||||||
public Popup(CurveEditor<T> editor, object[] selection, List<int> keyframeIndices = null, float height = 140.0f)
|
public Popup(CurveEditor<T> editor, object[] selection, List<int> keyframeIndices = null, float maxHeight = 140.0f)
|
||||||
: this(editor, height)
|
: this(editor, maxHeight)
|
||||||
{
|
{
|
||||||
_presenter.Select(selection);
|
_presenter.Select(selection);
|
||||||
_presenter.OpenAllGroups();
|
_presenter.OpenAllGroups();
|
||||||
|
Size = new Float2(Size.X, Mathf.Min(_presenter.ContainerControl.Size.Y, maxHeight));
|
||||||
_keyframeIndices = keyframeIndices;
|
_keyframeIndices = keyframeIndices;
|
||||||
if (keyframeIndices != null && selection.Length != keyframeIndices.Count)
|
if (keyframeIndices != null && selection.Length != keyframeIndices.Count)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
@@ -169,7 +212,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (IsSelected)
|
if (IsSelected)
|
||||||
color = Editor.ContainsFocus ? style.SelectionBorder : Color.Lerp(style.ForegroundDisabled, style.SelectionBorder, 0.4f);
|
color = Editor.ContainsFocus ? style.SelectionBorder : Color.Lerp(style.ForegroundDisabled, style.SelectionBorder, 0.4f);
|
||||||
if (IsMouseOver)
|
if (IsMouseOver)
|
||||||
color *= 1.1f;
|
color *= 1.5f;
|
||||||
Render2D.FillRectangle(rect, color);
|
Render2D.FillRectangle(rect, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +328,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The keyframes size.
|
/// The keyframes size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected static readonly Float2 KeyframesSize = new Float2(7.0f);
|
protected static readonly Float2 KeyframesSize = new Float2(8.0f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The colors for the keyframe points.
|
/// The colors for the keyframe points.
|
||||||
@@ -326,6 +369,63 @@ namespace FlaxEditor.GUI
|
|||||||
private Color _labelsColor;
|
private Color _labelsColor;
|
||||||
private Font _labelsFont;
|
private Font _labelsFont;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preset values for <see cref="CurvePreset"/> to be applied to a <see cref="CurveEditor{T}"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected Dictionary<CurvePreset, CurveEditorPreset> Presets = new Dictionary<CurvePreset, CurveEditorPreset>
|
||||||
|
{
|
||||||
|
{ CurvePreset.Constant, new CurveEditorPreset
|
||||||
|
{
|
||||||
|
LinearTangents = true,
|
||||||
|
Points = new List<CurvePresetPoint>
|
||||||
|
{
|
||||||
|
new CurvePresetPoint { Time = 0f, Value = 0.5f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
new CurvePresetPoint { Time = 1f, Value = 0.5f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ CurvePreset.EaseIn, new CurveEditorPreset
|
||||||
|
{
|
||||||
|
LinearTangents = false,
|
||||||
|
Points = new List<CurvePresetPoint>
|
||||||
|
{
|
||||||
|
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = -1.4f, TangentOut = 0f },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ CurvePreset.EaseOut, new CurveEditorPreset
|
||||||
|
{
|
||||||
|
LinearTangents = false,
|
||||||
|
Points = new List<CurvePresetPoint>
|
||||||
|
{
|
||||||
|
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 1.4f },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ CurvePreset.Linear, new CurveEditorPreset
|
||||||
|
{
|
||||||
|
LinearTangents = true,
|
||||||
|
Points = new List<CurvePresetPoint>
|
||||||
|
{
|
||||||
|
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ CurvePreset.Smoothstep, new CurveEditorPreset
|
||||||
|
{
|
||||||
|
LinearTangents = false,
|
||||||
|
Points = new List<CurvePresetPoint>
|
||||||
|
{
|
||||||
|
new CurvePresetPoint { Time = 0f, Value = 0f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
new CurvePresetPoint { Time = 1f, Value = 1f, TangentIn = 0f, TangentOut = 0f },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The keyframe UI points.
|
/// The keyframe UI points.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -568,6 +668,28 @@ namespace FlaxEditor.GUI
|
|||||||
/// <param name="indicesToRemove">The list of indices of the keyframes to remove.</param>
|
/// <param name="indicesToRemove">The list of indices of the keyframes to remove.</param>
|
||||||
protected abstract void RemoveKeyframesInternal(HashSet<int> indicesToRemove);
|
protected abstract void RemoveKeyframesInternal(HashSet<int> indicesToRemove);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to convert a float to the type of the type wildcard of the curve editor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The float.</param>
|
||||||
|
/// <returns>The converted value.</returns>
|
||||||
|
public static object ConvertCurvePresetValueToCurveEditorType(float value)
|
||||||
|
{
|
||||||
|
if (typeof(T) == typeof(Float2))
|
||||||
|
return new Float2(value);
|
||||||
|
if (typeof(T) == typeof(Float3))
|
||||||
|
return new Float3(value);
|
||||||
|
if (typeof(T) == typeof(Float4))
|
||||||
|
return new Float4(value);
|
||||||
|
if (typeof(T) == typeof(Vector2))
|
||||||
|
return new Vector2(value);
|
||||||
|
if (typeof(T) == typeof(Vector3))
|
||||||
|
return new Vector3(value);
|
||||||
|
if (typeof(T) == typeof(Vector4))
|
||||||
|
return new Vector4(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when showing a context menu. Can be used to add custom buttons with actions.
|
/// Called when showing a context menu. Can be used to add custom buttons with actions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -752,6 +874,17 @@ namespace FlaxEditor.GUI
|
|||||||
ShowCurve(false);
|
ShowCurve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies a <see cref="CurvePreset"/> to the curve editor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset">The preset.</param>
|
||||||
|
public virtual void ApplyPreset(CurvePreset preset)
|
||||||
|
{
|
||||||
|
// Remove existing keyframes
|
||||||
|
SelectAll();
|
||||||
|
RemoveKeyframes();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Evaluate(out object result, float time, bool loop = false)
|
public override void Evaluate(out object result, float time, bool loop = false)
|
||||||
{
|
{
|
||||||
@@ -1028,6 +1161,31 @@ namespace FlaxEditor.GUI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool left = key == KeyboardKeys.ArrowLeft;
|
||||||
|
bool right = key == KeyboardKeys.ArrowRight;
|
||||||
|
bool up = key == KeyboardKeys.ArrowUp;
|
||||||
|
bool down = key == KeyboardKeys.ArrowDown;
|
||||||
|
|
||||||
|
if (left || right || up || down)
|
||||||
|
{
|
||||||
|
bool shift = Root.GetKey(KeyboardKeys.Shift);
|
||||||
|
bool alt = Root.GetKey(KeyboardKeys.Alt);
|
||||||
|
float deltaValue = 10f;
|
||||||
|
if (shift || alt)
|
||||||
|
deltaValue = shift ? 2.5f : 5f;
|
||||||
|
|
||||||
|
Float2 moveDelta = Float2.Zero;
|
||||||
|
if (left || right)
|
||||||
|
moveDelta.X = left ? -deltaValue : deltaValue;
|
||||||
|
if (up || down)
|
||||||
|
moveDelta.Y = up ? -deltaValue : deltaValue;
|
||||||
|
|
||||||
|
_contents.OnMoveStart(Float2.Zero);
|
||||||
|
_contents.OnMove(moveDelta);
|
||||||
|
_contents.OnMoveEnd(Float2.Zero);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1526,6 +1684,22 @@ namespace FlaxEditor.GUI
|
|||||||
_tangents[i].Visible = false;
|
_tangents[i].Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ApplyPreset(CurvePreset preset)
|
||||||
|
{
|
||||||
|
base.ApplyPreset(preset);
|
||||||
|
|
||||||
|
CurveEditorPreset data = Presets[preset];
|
||||||
|
foreach (var point in data.Points)
|
||||||
|
{
|
||||||
|
float time = point.Time;
|
||||||
|
object value = ConvertCurvePresetValueToCurveEditorType((float)point.Value);
|
||||||
|
AddKeyframe(time, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWholeCurve();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void DrawCurve(ref Rectangle viewRect)
|
protected override void DrawCurve(ref Rectangle viewRect)
|
||||||
{
|
{
|
||||||
@@ -2312,6 +2486,30 @@ namespace FlaxEditor.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ApplyPreset(CurvePreset preset)
|
||||||
|
{
|
||||||
|
base.ApplyPreset(preset);
|
||||||
|
|
||||||
|
CurveEditorPreset data = Presets[preset];
|
||||||
|
|
||||||
|
foreach (var point in data.Points)
|
||||||
|
{
|
||||||
|
float time = point.Time;
|
||||||
|
object value = ConvertCurvePresetValueToCurveEditorType((float)point.Value);
|
||||||
|
object tangentIn = ConvertCurvePresetValueToCurveEditorType((float)point.TangentIn);
|
||||||
|
object tangentOut = ConvertCurvePresetValueToCurveEditorType((float)point.TangentOut);
|
||||||
|
|
||||||
|
AddKeyframe(time, value, tangentIn, tangentOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectAll();
|
||||||
|
if (data.LinearTangents)
|
||||||
|
SetTangentsLinear();
|
||||||
|
|
||||||
|
ShowWholeCurve();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void SetScaleInternal(ref Float2 scale)
|
protected override void SetScaleInternal(ref Float2 scale)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
private bool _useDynamicEditing;
|
private bool _useDynamicEditing;
|
||||||
private bool _activeEyedropper;
|
private bool _activeEyedropper;
|
||||||
private bool _canPassLastChangeEvent = true;
|
private bool _canPassLastChangeEvent = true;
|
||||||
|
private bool _linear;
|
||||||
private ColorValueBox.ColorPickerEvent _onChanged;
|
private ColorValueBox.ColorPickerEvent _onChanged;
|
||||||
private ColorValueBox.ColorPickerClosedEvent _onClosed;
|
private ColorValueBox.ColorPickerClosedEvent _onClosed;
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
private Button _cCancel;
|
private Button _cCancel;
|
||||||
private Button _cOK;
|
private Button _cOK;
|
||||||
private Button _cEyedropper;
|
private Button _cEyedropper;
|
||||||
|
private Button _cLinearSRGB;
|
||||||
|
|
||||||
private List<Color> _savedColors = new List<Color>();
|
private List<Color> _savedColors = new List<Color>();
|
||||||
private List<Button> _savedColorButtons = new List<Button>();
|
private List<Button> _savedColorButtons = new List<Button>();
|
||||||
@@ -118,6 +120,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
_value = Color.Transparent;
|
_value = Color.Transparent;
|
||||||
_onChanged = colorChanged;
|
_onChanged = colorChanged;
|
||||||
_onClosed = pickerClosed;
|
_onClosed = pickerClosed;
|
||||||
|
_linear = !Graphics.GammaColorSpace;
|
||||||
|
|
||||||
// Get saved colors if they exist
|
// Get saved colors if they exist
|
||||||
if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out string savedColors))
|
if (Editor.Instance.ProjectCache.TryGetCustomData("ColorPickerSavedColors", out string savedColors))
|
||||||
@@ -227,6 +230,25 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
_cEyedropper.Width = _cEyedropper.Height;
|
_cEyedropper.Width = _cEyedropper.Height;
|
||||||
_cEyedropper.X -= _cEyedropper.Width;
|
_cEyedropper.X -= _cEyedropper.Width;
|
||||||
|
|
||||||
|
// Linear/sRGB toggle button
|
||||||
|
_cLinearSRGB = new Button(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin)
|
||||||
|
{
|
||||||
|
TooltipText = "Toggles between color preview in Linear and sRGB",
|
||||||
|
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.SplineAligned64),
|
||||||
|
BackgroundColor = _cEyedropper.BackgroundColor,
|
||||||
|
BackgroundColorHighlighted = _cEyedropper.BackgroundColorHighlighted,
|
||||||
|
BorderColor = _linear ? Color.Transparent : style.Foreground,
|
||||||
|
BorderColorHighlighted = _cEyedropper.BorderColorHighlighted,
|
||||||
|
Size = _cEyedropper.Size,
|
||||||
|
Parent = this,
|
||||||
|
Location = _cEyedropper.BottomLeft + new Float2(0, 4),
|
||||||
|
};
|
||||||
|
_cLinearSRGB.Clicked += () =>
|
||||||
|
{
|
||||||
|
_linear = !_linear;
|
||||||
|
_cLinearSRGB.BorderColor = _linear ? Color.Transparent : style.Foreground;
|
||||||
|
};
|
||||||
|
|
||||||
// Set initial color
|
// Set initial color
|
||||||
SelectedColor = initialValue;
|
SelectedColor = initialValue;
|
||||||
}
|
}
|
||||||
@@ -281,16 +303,22 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
if (_activeEyedropper)
|
if (_activeEyedropper)
|
||||||
{
|
{
|
||||||
_activeEyedropper = false;
|
_activeEyedropper = false;
|
||||||
SelectedColor = colorPicked;
|
if (colorPicked != Color.Transparent)
|
||||||
ScreenUtilities.PickColorDone -= OnColorPicked;
|
{
|
||||||
|
Color color = colorPicked;
|
||||||
|
if (_linear)
|
||||||
|
color = color.ToLinear();
|
||||||
|
SelectedColor = color;
|
||||||
|
}
|
||||||
|
Platform.PickScreenColorDone -= OnColorPicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEyedropStart()
|
private void OnEyedropStart()
|
||||||
{
|
{
|
||||||
_activeEyedropper = true;
|
_activeEyedropper = true;
|
||||||
ScreenUtilities.PickColor();
|
Platform.PickScreenColor();
|
||||||
ScreenUtilities.PickColorDone += OnColorPicked;
|
Platform.PickScreenColorDone += OnColorPicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRGBAChanged()
|
private void OnRGBAChanged()
|
||||||
@@ -326,8 +354,15 @@ 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 = Platform.GetScreenColorAt(mousePosition);
|
||||||
|
if (color != Color.Transparent)
|
||||||
|
{
|
||||||
|
if (_linear)
|
||||||
|
color = color.ToLinear();
|
||||||
|
SelectedColor = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +423,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Render2D.FillRectangle(newRect, _value);
|
Render2D.FillRectangle(newRect, _linear ? _value.ToSRgb() : _value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -409,7 +444,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
{
|
{
|
||||||
// Cancel eye dropping
|
// Cancel eye dropping
|
||||||
_activeEyedropper = false;
|
_activeEyedropper = false;
|
||||||
ScreenUtilities.PickColorDone -= OnColorPicked;
|
Platform.PickScreenColorDone -= OnColorPicked;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -310,6 +310,26 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
Render2D.DrawRectangle(_slider1Rect, _isMouseDownSlider1 ? style.BackgroundSelected : Color.Black);
|
Render2D.DrawRectangle(_slider1Rect, _isMouseDownSlider1 ? style.BackgroundSelected : Color.Black);
|
||||||
Render2D.DrawRectangle(valueR, _isMouseDownSlider1 ? Color.White : Color.Gray);
|
Render2D.DrawRectangle(valueR, _isMouseDownSlider1 ? Color.White : Color.Gray);
|
||||||
|
|
||||||
|
// Draw checkerboard pattern to part of the alpha slider background
|
||||||
|
var alphaRect = _slider2Rect;
|
||||||
|
Render2D.FillRectangle(alphaRect, Color.White);
|
||||||
|
var smallRectSize = alphaRect.Width * 0.5f;
|
||||||
|
var numHor = Mathf.CeilToInt(alphaRect.Width / smallRectSize);
|
||||||
|
var numVer = Mathf.CeilToInt(alphaRect.Height / smallRectSize);
|
||||||
|
for (int i = 0; i < numHor; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < numVer; j++)
|
||||||
|
{
|
||||||
|
if ((i + j) % 2 == 0)
|
||||||
|
{
|
||||||
|
var rect = new Rectangle(alphaRect.X + smallRectSize * i, alphaRect.Y + smallRectSize * j, new Float2(smallRectSize));
|
||||||
|
Render2D.PushClip(alphaRect);
|
||||||
|
Render2D.FillRectangle(rect, Color.Gray);
|
||||||
|
Render2D.PopClip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Alpha
|
// Alpha
|
||||||
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
float alphaY = _slider2Rect.Height * (1 - _color.A);
|
||||||
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
|
||||||
|
|||||||
@@ -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 += Editor.Instance.Options.Options.Interface.TabHeight;
|
|
||||||
result.Size.Y -= Editor.Instance.Options.Options.Interface.TabHeight;
|
|
||||||
break;
|
|
||||||
case DockState.DockTop:
|
|
||||||
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
|
||||||
break;
|
|
||||||
case DockState.DockLeft:
|
|
||||||
result.Size.X *= DockPanel.DefaultSplitterValue;
|
|
||||||
break;
|
|
||||||
case DockState.DockBottom:
|
|
||||||
result.Location.Y += result.Size.Y * (1 - DockPanel.DefaultSplitterValue);
|
|
||||||
result.Size.Y *= DockPanel.DefaultSplitterValue;
|
|
||||||
break;
|
|
||||||
case DockState.DockRight:
|
|
||||||
result.Location.X += result.Size.X * (1 - DockPanel.DefaultSplitterValue);
|
|
||||||
result.Size.X *= DockPanel.DefaultSplitterValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CalculateDragOffset(Float2 mouseScreenPosition)
|
|
||||||
{
|
|
||||||
var baseWinPos = _toMove.Window.Window.Position;
|
|
||||||
_dragOffset = mouseScreenPosition - baseWinPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateRects()
|
|
||||||
{
|
|
||||||
// Cache mouse position
|
|
||||||
_mouse = Platform.MousePosition;
|
|
||||||
|
|
||||||
// Check intersection with any dock panel
|
|
||||||
var uiMouse = _mouse;
|
|
||||||
_toDock = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
|
|
||||||
|
|
||||||
// Check dock state to use
|
|
||||||
bool showProxyHints = _toDock != null;
|
|
||||||
bool showBorderHints = showProxyHints;
|
|
||||||
bool showCenterHint = showProxyHints;
|
|
||||||
if (showProxyHints)
|
|
||||||
{
|
|
||||||
// If moved window has not only tabs but also child panels disable docking as tab
|
|
||||||
if (_toMove.ChildPanelsCount > 0)
|
|
||||||
showCenterHint = false;
|
|
||||||
|
|
||||||
// Disable docking windows with one or more dock panels inside
|
|
||||||
if (_toMove.ChildPanelsCount > 0)
|
|
||||||
showBorderHints = false;
|
|
||||||
|
|
||||||
// Get dock area
|
|
||||||
_rectDock = _toDock.DockAreaBounds;
|
|
||||||
|
|
||||||
// Cache dock rectangles
|
|
||||||
var size = _rectDock.Size;
|
|
||||||
var offset = _rectDock.Location;
|
|
||||||
var borderMargin = 4.0f;
|
|
||||||
var hintWindowsSize = Proxy.HintWindowsSize * Platform.DpiScale;
|
|
||||||
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
|
||||||
var centerX = size.X * 0.5f;
|
|
||||||
var centerY = size.Y * 0.5f;
|
|
||||||
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
|
||||||
|
|
||||||
// Hit test
|
|
||||||
DockState toSet = DockState.Float;
|
|
||||||
if (showBorderHints)
|
|
||||||
{
|
|
||||||
if (_rUpper.Contains(_mouse))
|
|
||||||
toSet = DockState.DockTop;
|
|
||||||
else if (_rBottom.Contains(_mouse))
|
|
||||||
toSet = DockState.DockBottom;
|
|
||||||
else if (_rLeft.Contains(_mouse))
|
|
||||||
toSet = DockState.DockLeft;
|
|
||||||
else if (_rRight.Contains(_mouse))
|
|
||||||
toSet = DockState.DockRight;
|
|
||||||
}
|
|
||||||
if (showCenterHint && _rCenter.Contains(_mouse))
|
|
||||||
toSet = DockState.DockFill;
|
|
||||||
_toSet = toSet;
|
|
||||||
|
|
||||||
// Show proxy hint windows
|
|
||||||
Proxy.Down.Position = _rBottom.Location;
|
|
||||||
Proxy.Left.Position = _rLeft.Location;
|
|
||||||
Proxy.Right.Position = _rRight.Location;
|
|
||||||
Proxy.Up.Position = _rUpper.Location;
|
|
||||||
Proxy.Center.Position = _rCenter.Location;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_toSet = DockState.Float;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update proxy hint windows visibility
|
|
||||||
Proxy.Down.IsVisible = showProxyHints & showBorderHints;
|
|
||||||
Proxy.Left.IsVisible = showProxyHints & showBorderHints;
|
|
||||||
Proxy.Right.IsVisible = showProxyHints & showBorderHints;
|
|
||||||
Proxy.Up.IsVisible = showProxyHints & showBorderHints;
|
|
||||||
Proxy.Center.IsVisible = showProxyHints & showCenterHint;
|
|
||||||
|
|
||||||
// Calculate proxy/dock/window rectangles
|
|
||||||
if (_toDock == null)
|
|
||||||
{
|
|
||||||
// Floating window over nothing
|
|
||||||
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_toSet == DockState.Float)
|
|
||||||
{
|
|
||||||
// Floating window over dock panel
|
|
||||||
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use only part of the dock panel to show hint
|
|
||||||
_rectWindow = CalculateDockRect(_toSet, ref _rectDock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update proxy window
|
|
||||||
Proxy.Window.ClientBounds = _rectWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
|
||||||
{
|
|
||||||
if (button == MouseButton.Left)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMouseMove(ref Float2 mousePos)
|
|
||||||
{
|
|
||||||
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
|
|
||||||
if (_lateDragOffsetUpdate)
|
|
||||||
{
|
|
||||||
// Calculate dragging offset and move window to the destination position
|
|
||||||
CalculateDragOffset(mousePos);
|
|
||||||
|
|
||||||
// Reset state
|
|
||||||
_lateDragOffsetUpdate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateRects();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnLostFocus()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
|
|
||||||
/// </summary>
|
|
||||||
public static class Proxy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The drag proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Window;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The left hint proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Left;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The right hint proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Right;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The up hint proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Up;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The down hint proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Down;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The center hint proxy window.
|
|
||||||
/// </summary>
|
|
||||||
public static Window Center;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The hint windows size.
|
|
||||||
/// </summary>
|
|
||||||
public const float HintWindowsSize = 32.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes the hit proxy windows. Those windows are used to indicate drag target areas (left, right, top, bottom, etc.).
|
|
||||||
/// </summary>
|
|
||||||
public static void InitHitProxy()
|
|
||||||
{
|
|
||||||
CreateProxy(ref Left, "DockHint.Left");
|
|
||||||
CreateProxy(ref Right, "DockHint.Right");
|
|
||||||
CreateProxy(ref Up, "DockHint.Up");
|
|
||||||
CreateProxy(ref Down, "DockHint.Down");
|
|
||||||
CreateProxy(ref Center, "DockHint.Center");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes the hint window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="initSize">Initial size of the proxy window.</param>
|
|
||||||
public static void Init(ref Float2 initSize)
|
|
||||||
{
|
|
||||||
if (Window == null)
|
|
||||||
{
|
|
||||||
var settings = CreateWindowSettings.Default;
|
|
||||||
settings.Title = "DockHint.Window";
|
|
||||||
settings.Size = initSize;
|
|
||||||
settings.AllowInput = true;
|
|
||||||
settings.AllowMaximize = false;
|
|
||||||
settings.AllowMinimize = false;
|
|
||||||
settings.HasBorder = false;
|
|
||||||
settings.HasSizingFrame = false;
|
|
||||||
settings.IsRegularWindow = false;
|
|
||||||
settings.SupportsTransparency = true;
|
|
||||||
settings.ShowInTaskbar = false;
|
|
||||||
settings.ShowAfterFirstPaint = false;
|
|
||||||
settings.IsTopmost = true;
|
|
||||||
|
|
||||||
Window = Platform.CreateWindow(ref settings);
|
|
||||||
Window.Opacity = 0.6f;
|
|
||||||
Window.GUI.BackgroundColor = Style.Current.Selection;
|
|
||||||
Window.GUI.AddChild<DragVisuals>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Resize proxy
|
|
||||||
Window.ClientSize = initSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitHitProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DragVisuals : Control
|
|
||||||
{
|
|
||||||
public DragVisuals()
|
|
||||||
{
|
|
||||||
AnchorPreset = AnchorPresets.StretchAll;
|
|
||||||
Offsets = Margin.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw()
|
|
||||||
{
|
|
||||||
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreateProxy(ref Window win, string name)
|
|
||||||
{
|
|
||||||
if (win != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var settings = CreateWindowSettings.Default;
|
|
||||||
settings.Title = name;
|
|
||||||
settings.Size = new Float2(HintWindowsSize * Platform.DpiScale);
|
|
||||||
settings.AllowInput = false;
|
|
||||||
settings.AllowMaximize = false;
|
|
||||||
settings.AllowMinimize = false;
|
|
||||||
settings.HasBorder = false;
|
|
||||||
settings.HasSizingFrame = false;
|
|
||||||
settings.IsRegularWindow = false;
|
|
||||||
settings.SupportsTransparency = true;
|
|
||||||
settings.ShowInTaskbar = false;
|
|
||||||
settings.ActivateWhenFirstShown = false;
|
|
||||||
settings.IsTopmost = true;
|
|
||||||
settings.ShowAfterFirstPaint = false;
|
|
||||||
|
|
||||||
win = Platform.CreateWindow(ref settings);
|
|
||||||
win.Opacity = 0.6f;
|
|
||||||
win.GUI.BackgroundColor = Style.Current.Selection;
|
|
||||||
win.GUI.AddChild<DragVisuals>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hides proxy windows.
|
|
||||||
/// </summary>
|
|
||||||
public static void Hide()
|
|
||||||
{
|
|
||||||
HideProxy(ref Window);
|
|
||||||
HideProxy(ref Left);
|
|
||||||
HideProxy(ref Right);
|
|
||||||
HideProxy(ref Up);
|
|
||||||
HideProxy(ref Down);
|
|
||||||
HideProxy(ref Center);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void HideProxy(ref Window win)
|
|
||||||
{
|
|
||||||
if (win)
|
|
||||||
{
|
|
||||||
win.Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases proxy data and windows.
|
|
||||||
/// </summary>
|
|
||||||
public static void Dispose()
|
|
||||||
{
|
|
||||||
DisposeProxy(ref Window);
|
|
||||||
DisposeProxy(ref Left);
|
|
||||||
DisposeProxy(ref Right);
|
|
||||||
DisposeProxy(ref Up);
|
|
||||||
DisposeProxy(ref Down);
|
|
||||||
DisposeProxy(ref Center);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DisposeProxy(ref Window win)
|
|
||||||
{
|
|
||||||
if (win)
|
|
||||||
{
|
|
||||||
win.Close(ClosingReason.User);
|
|
||||||
win = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -469,7 +469,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
var childPanels = _childPanels.ToArray();
|
var childPanels = _childPanels.ToArray();
|
||||||
if (childPanels.Length != 0)
|
if (childPanels.Length != 0)
|
||||||
{
|
{
|
||||||
// Move tabs from child panels into this one
|
// Fallback: move tabs from child panels into this one.
|
||||||
DockWindow selectedTab = null;
|
DockWindow selectedTab = null;
|
||||||
foreach (var childPanel in childPanels)
|
foreach (var childPanel in childPanels)
|
||||||
{
|
{
|
||||||
@@ -490,7 +490,8 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
{
|
{
|
||||||
// Unlink splitter
|
// Unlink splitter
|
||||||
var splitterParent = splitter.Parent;
|
var splitterParent = splitter.Parent;
|
||||||
Assert.IsNotNull(splitterParent);
|
if (splitterParent == null)
|
||||||
|
return;
|
||||||
splitter.Parent = null;
|
splitter.Parent = null;
|
||||||
|
|
||||||
// Move controls from second split panel to the split panel parent
|
// Move controls from second split panel to the split panel parent
|
||||||
@@ -507,17 +508,63 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
splitter.Dispose();
|
splitter.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (IsMaster && _childPanels.Count != 0)
|
||||||
|
{
|
||||||
|
if (TryCollapseSplitter(_tabsProxy?.Parent as Panel))
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (!IsMaster)
|
else if (!IsMaster)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (_childPanels.Count != 0)
|
||||||
|
{
|
||||||
|
if (TryCollapseSplitter(_tabsProxy?.Parent as Panel))
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (!IsMaster)
|
else if (!IsMaster)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool CollapseEmptyTabsProxy()
|
||||||
|
{
|
||||||
|
if (TabsCount == 0 && ChildPanelsCount > 0)
|
||||||
|
{
|
||||||
|
return TryCollapseSplitter(_tabsProxy?.Parent as Panel);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryCollapseSplitter(Panel removedPanelParent)
|
||||||
|
{
|
||||||
|
if (removedPanelParent == null)
|
||||||
|
return false;
|
||||||
|
if (!(removedPanelParent.Parent is SplitPanel tabsSplitter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var splitterParent = tabsSplitter.Parent;
|
||||||
|
if (splitterParent == null)
|
||||||
|
return false;
|
||||||
|
tabsSplitter.Parent = null;
|
||||||
|
|
||||||
|
var scrPanel = removedPanelParent == tabsSplitter.Panel2 ? tabsSplitter.Panel1 : tabsSplitter.Panel2;
|
||||||
|
var srcPanelChildrenCount = scrPanel.ChildrenCount;
|
||||||
|
for (int i = srcPanelChildrenCount - 1; i >= 0 && scrPanel.ChildrenCount > 0; i--)
|
||||||
|
{
|
||||||
|
scrPanel.GetChild(i).Parent = splitterParent;
|
||||||
|
}
|
||||||
|
Assert.IsTrue(scrPanel.ChildrenCount == 0);
|
||||||
|
Assert.IsTrue(splitterParent.ChildrenCount == srcPanelChildrenCount);
|
||||||
|
|
||||||
|
tabsSplitter.Dispose();
|
||||||
|
if (_tabsProxy != null && _tabsProxy.Parent == removedPanelParent)
|
||||||
|
_tabsProxy = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
internal virtual void DockWindowInternal(DockState state, DockWindow window, bool autoSelect = true, float? splitterValue = null)
|
internal virtual void DockWindowInternal(DockState state, DockWindow window, bool autoSelect = true, float? splitterValue = null)
|
||||||
{
|
{
|
||||||
DockWindow(state, window, autoSelect, splitterValue);
|
DockWindow(state, window, autoSelect, splitterValue);
|
||||||
|
|||||||
@@ -19,11 +19,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
|
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
|
||||||
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
|
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
|
||||||
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
|
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
|
||||||
#if PLATFORM_WINDOWS
|
private readonly bool _hideTabForSingleTab = Utilities.Utils.HideSingleTabWindowTabBars();
|
||||||
private readonly bool _hideTabForSingleTab = Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
|
|
||||||
#else
|
|
||||||
private readonly bool _hideTabForSingleTab = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The is mouse down flag (left button).
|
/// The is mouse down flag (left button).
|
||||||
@@ -55,6 +51,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>
|
||||||
@@ -196,7 +197,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
|
||||||
{
|
{
|
||||||
@@ -207,7 +208,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,6 +394,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)
|
||||||
@@ -479,6 +481,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,26 @@ 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 +219,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,11 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Create docking hint window
|
// Create docking hint window
|
||||||
DockHintWindow.Create(this);
|
Window dragSourceWindow = null;
|
||||||
|
#if !PLATFORM_SDL
|
||||||
|
dragSourceWindow = _window?.Window;
|
||||||
|
#endif
|
||||||
|
WindowDragHelper.StartDragging(this, dragSourceWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -71,23 +131,33 @@ 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(100, 100);
|
||||||
settings.MaximumSize = Float2.Zero; // Unlimited size
|
settings.MaximumSize = Float2.Zero; // Unlimited size
|
||||||
settings.Fullscreen = false;
|
settings.Fullscreen = false;
|
||||||
settings.HasBorder = true;
|
settings.HasBorder = true;
|
||||||
|
#if PLATFORM_SDL
|
||||||
|
settings.SupportsTransparency = true;
|
||||||
|
#else
|
||||||
settings.SupportsTransparency = false;
|
settings.SupportsTransparency = false;
|
||||||
|
#endif
|
||||||
settings.ActivateWhenFirstShown = true;
|
settings.ActivateWhenFirstShown = true;
|
||||||
settings.AllowInput = true;
|
settings.AllowInput = true;
|
||||||
settings.AllowMinimize = true;
|
settings.AllowMinimize = true;
|
||||||
settings.AllowMaximize = true;
|
settings.AllowMaximize = true;
|
||||||
settings.AllowDragAndDrop = true;
|
settings.AllowDragAndDrop = true;
|
||||||
settings.IsTopmost = false;
|
settings.IsTopmost = false;
|
||||||
settings.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);
|
||||||
}
|
}
|
||||||
@@ -151,7 +221,12 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
base.OnSelectedTabChanged();
|
base.OnSelectedTabChanged();
|
||||||
|
|
||||||
if (_window != null && SelectedTab != null)
|
if (_window != null && SelectedTab != null)
|
||||||
|
{
|
||||||
_window.Title = SelectedTab.Title;
|
_window.Title = SelectedTab.Title;
|
||||||
|
var decorations = Parent.GetChild<FloatWindowDecorations>();
|
||||||
|
if (decorations != null)
|
||||||
|
decorations.PerformLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -81,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
|
||||||
|
|||||||
514
Source/Editor/GUI/Docking/WindowDragHelper.cs
Normal file
514
Source/Editor/GUI/Docking/WindowDragHelper.cs
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.GUI.Docking
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class used to handle docking windows dragging and docking.
|
||||||
|
/// </summary>
|
||||||
|
public class WindowDragHelper
|
||||||
|
{
|
||||||
|
private FloatWindowDockPanel _toMove;
|
||||||
|
|
||||||
|
private Float2 _dragOffset;
|
||||||
|
private Rectangle _rectDock;
|
||||||
|
private Float2 _mouse;
|
||||||
|
private DockState _toSet;
|
||||||
|
private DockPanel _toDock;
|
||||||
|
private Window _dragSourceWindow;
|
||||||
|
|
||||||
|
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
|
||||||
|
private Control _dockHintDown, _dockHintUp, _dockHintLeft, _dockHintRight, _dockHintCenter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hint control size.
|
||||||
|
/// </summary>
|
||||||
|
public const float HintControlSize = 48.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The opacity of the dragged window when hint controls are shown.
|
||||||
|
/// </summary>
|
||||||
|
public const float DragWindowOpacity = 0.4f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if any windows are being dragged.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsDragActive { get; private set; }
|
||||||
|
|
||||||
|
private WindowDragHelper(FloatWindowDockPanel toMove, Window dragSourceWindow)
|
||||||
|
{
|
||||||
|
IsDragActive = true;
|
||||||
|
_toMove = toMove;
|
||||||
|
_toSet = DockState.Float;
|
||||||
|
var window = toMove.Window.Window;
|
||||||
|
var mousePos = Platform.MousePosition;
|
||||||
|
|
||||||
|
// Check if window is maximized and restore window for correct dragging
|
||||||
|
if (window.IsMaximized)
|
||||||
|
{
|
||||||
|
var windowMousePos = mousePos - window.Position;
|
||||||
|
var previousSize = window.Size;
|
||||||
|
window.Restore();
|
||||||
|
window.Position = mousePos - windowMousePos * window.Size / previousSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When drag starts from a tabs the window might not be shown yet
|
||||||
|
if (!window.IsVisible)
|
||||||
|
{
|
||||||
|
window.Show();
|
||||||
|
window.Position = mousePos - new Float2(40, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind events
|
||||||
|
FlaxEngine.Scripting.Update += OnUpdate;
|
||||||
|
window.MouseUp += OnMouseUp;
|
||||||
|
#if !PLATFORM_SDL
|
||||||
|
window.StartTrackingMouse(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Update rectangles
|
||||||
|
UpdateRects(mousePos);
|
||||||
|
|
||||||
|
// Ensure the dragged window stays on top of every other window
|
||||||
|
window.IsAlwaysOnTop = true;
|
||||||
|
|
||||||
|
_dragSourceWindow = dragSourceWindow;
|
||||||
|
if (_dragSourceWindow != null) // Detaching a tab from existing window
|
||||||
|
{
|
||||||
|
#if PLATFORM_SDL
|
||||||
|
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
|
||||||
|
#else
|
||||||
|
_dragOffset = mousePos - window.Position;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The mouse up event is sent to the source window on Windows
|
||||||
|
_dragSourceWindow.MouseUp += OnMouseUp;
|
||||||
|
|
||||||
|
// TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
|
||||||
|
var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
|
||||||
|
window.DoDragDrop(window.Title, _dragOffset, dragSourceWindowWayland);
|
||||||
|
#if !PLATFORM_SDL
|
||||||
|
_dragSourceWindow.BringToFront();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dragOffset = window.MousePosition;
|
||||||
|
window.DoDragDrop(window.Title, _dragOffset, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases unmanaged and - optionally - managed resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
IsDragActive = false;
|
||||||
|
var window = _toMove?.Window?.Window;
|
||||||
|
|
||||||
|
// Unbind events
|
||||||
|
FlaxEngine.Scripting.Update -= OnUpdate;
|
||||||
|
if (window != null)
|
||||||
|
{
|
||||||
|
window.MouseUp -= OnMouseUp;
|
||||||
|
#if !PLATFORM_SDL
|
||||||
|
window.EndTrackingMouse();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (_dragSourceWindow != null)
|
||||||
|
_dragSourceWindow.MouseUp -= OnMouseUp;
|
||||||
|
|
||||||
|
RemoveDockHints();
|
||||||
|
|
||||||
|
if (_toMove == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window != null)
|
||||||
|
{
|
||||||
|
window.Opacity = 1.0f;
|
||||||
|
window.IsAlwaysOnTop = false;
|
||||||
|
window.BringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if window won't be docked
|
||||||
|
if (_toSet == DockState.Float)
|
||||||
|
{
|
||||||
|
if (window == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Show base window
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
|
||||||
|
|
||||||
|
// Check if window has only single tab
|
||||||
|
if (hasNoChildPanels && _toMove.TabsCount == 1)
|
||||||
|
{
|
||||||
|
// Dock window
|
||||||
|
_toMove.GetTab(0).Show(_toSet, _toDock);
|
||||||
|
}
|
||||||
|
// Check if dock as tab and has no child panels
|
||||||
|
else if (hasNoChildPanels && _toSet == DockState.DockFill)
|
||||||
|
{
|
||||||
|
// Dock all tabs
|
||||||
|
while (_toMove.TabsCount > 0)
|
||||||
|
{
|
||||||
|
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var selectedTab = _toMove.SelectedTab;
|
||||||
|
|
||||||
|
// Dock the first tab into the target location
|
||||||
|
if (_toMove.TabsCount > 0)
|
||||||
|
{
|
||||||
|
var firstTab = _toMove.GetTab(0);
|
||||||
|
firstTab.Show(_toSet, _toDock);
|
||||||
|
|
||||||
|
// Dock rest of the tabs
|
||||||
|
while (_toMove.TabsCount > 0)
|
||||||
|
{
|
||||||
|
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep selected tab being selected
|
||||||
|
selectedTab?.SelectTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus target window
|
||||||
|
_toDock.Root.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
_toMove = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start dragging a floating dock panel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toMove">Floating dock panel to move.</param>
|
||||||
|
/// <param name="dragSourceWindow">The window where dragging started from.</param>
|
||||||
|
/// <returns>The window drag helper object.</returns>
|
||||||
|
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove, Window dragSourceWindow = null)
|
||||||
|
{
|
||||||
|
if (toMove == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
return new WindowDragHelper(toMove, dragSourceWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start dragging a docked panel into a floating window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toMove">Dock window to move.</param>
|
||||||
|
/// <param name="dragSourceWindow">The window where dragging started from.</param>
|
||||||
|
/// <returns>The window drag helper object.</returns>
|
||||||
|
public static WindowDragHelper StartDragging(DockWindow toMove, Window dragSourceWindow)
|
||||||
|
{
|
||||||
|
if (toMove == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
// Create floating window
|
||||||
|
toMove.CreateFloating();
|
||||||
|
|
||||||
|
// Get floating panel
|
||||||
|
var window = (WindowRootControl)toMove.Root;
|
||||||
|
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
|
||||||
|
|
||||||
|
return new WindowDragHelper(floatingPanelToMove, dragSourceWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class DragVisuals : Control
|
||||||
|
{
|
||||||
|
public DragVisuals()
|
||||||
|
{
|
||||||
|
AnchorPreset = AnchorPresets.StretchAll;
|
||||||
|
Offsets = Margin.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
base.Draw();
|
||||||
|
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddDockHints()
|
||||||
|
{
|
||||||
|
if (_toDock == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_toDock.RootWindow.Window != _dragSourceWindow)
|
||||||
|
_toDock.RootWindow.Window.MouseUp += OnMouseUp;
|
||||||
|
|
||||||
|
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
|
||||||
|
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
|
||||||
|
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
|
||||||
|
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
|
||||||
|
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
|
||||||
|
|
||||||
|
Control AddHintControl(Float2 pivot)
|
||||||
|
{
|
||||||
|
DragVisuals hintControl = _toDock.AddChild<DragVisuals>();
|
||||||
|
hintControl.Size = new Float2(HintControlSize);
|
||||||
|
hintControl.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
|
||||||
|
hintControl.Pivot = pivot;
|
||||||
|
hintControl.PivotRelative = true;
|
||||||
|
return hintControl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveDockHints()
|
||||||
|
{
|
||||||
|
if (_toDock == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_toDock.RootWindow.Window != _dragSourceWindow)
|
||||||
|
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
|
||||||
|
|
||||||
|
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
|
||||||
|
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
|
||||||
|
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
|
||||||
|
_dockHintRight?.Parent.RemoveChild(_dockHintRight);
|
||||||
|
_dockHintCenter?.Parent.RemoveChild(_dockHintCenter);
|
||||||
|
_dockHintDown = _dockHintUp = _dockHintLeft = _dockHintRight = _dockHintCenter = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRects(Float2 mousePos)
|
||||||
|
{
|
||||||
|
// Cache mouse position
|
||||||
|
_mouse = mousePos;
|
||||||
|
|
||||||
|
// Check intersection with any dock panel
|
||||||
|
DockPanel dockPanel = null;
|
||||||
|
if (_toMove.MasterPanel.HitTest(ref _mouse, _toMove, out var hitResults))
|
||||||
|
{
|
||||||
|
dockPanel = hitResults[0];
|
||||||
|
|
||||||
|
// Prefer panel which currently has focus
|
||||||
|
foreach (var hit in hitResults)
|
||||||
|
{
|
||||||
|
if (hit.RootWindow.Window.IsFocused)
|
||||||
|
{
|
||||||
|
dockPanel = hit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefer panel in the same window we hit earlier
|
||||||
|
// TODO: this doesn't allow docking window into another floating window over the main window
|
||||||
|
/*if (dockPanel?.RootWindow != _toDock?.RootWindow)
|
||||||
|
{
|
||||||
|
foreach (var hit in hitResults)
|
||||||
|
{
|
||||||
|
if (hit.RootWindow == _toDock?.RootWindow)
|
||||||
|
{
|
||||||
|
dockPanel = _toDock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dockPanel != _toDock)
|
||||||
|
{
|
||||||
|
RemoveDockHints();
|
||||||
|
_toDock = dockPanel;
|
||||||
|
AddDockHints();
|
||||||
|
|
||||||
|
// Make sure the all the dock hint areas are not under other windows
|
||||||
|
if (_toDock != Editor.Instance.UI.MasterPanel)
|
||||||
|
_toDock?.RootWindow.Window.BringToFront();
|
||||||
|
//_toDock?.RootWindow.Window.Focus();
|
||||||
|
|
||||||
|
#if PLATFORM_SDL
|
||||||
|
// Make the dragged window transparent when dock hints are visible
|
||||||
|
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
|
||||||
|
#else
|
||||||
|
// Bring the drop source always to the top
|
||||||
|
if (_dragSourceWindow != null)
|
||||||
|
_dragSourceWindow.BringToFront();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check dock state to use
|
||||||
|
bool showProxyHints = _toDock != null;
|
||||||
|
bool showBorderHints = showProxyHints;
|
||||||
|
bool showCenterHint = showProxyHints;
|
||||||
|
Control hoveredHintControl = null;
|
||||||
|
Float2 hoveredLocationOffset = Float2.Zero;
|
||||||
|
Float2 hoveredSizeOverride = Float2.Zero;
|
||||||
|
DockState prevToSet = _toSet;
|
||||||
|
float hoveredMargin = 1.0f;
|
||||||
|
if (showProxyHints)
|
||||||
|
{
|
||||||
|
// If moved window has not only tabs but also child panels disable docking as tab
|
||||||
|
if (_toMove.ChildPanelsCount > 0)
|
||||||
|
showCenterHint = false;
|
||||||
|
|
||||||
|
// Disable docking windows with one or more dock panels inside
|
||||||
|
if (_toMove.ChildPanelsCount > 0)
|
||||||
|
showBorderHints = false;
|
||||||
|
|
||||||
|
// Get dock area
|
||||||
|
_rectDock = _toDock.DockAreaBounds;
|
||||||
|
|
||||||
|
// Cache dock rectangles
|
||||||
|
var size = _rectDock.Size / Platform.DpiScale;
|
||||||
|
var offset = _toDock.PointFromScreen(_rectDock.Location);
|
||||||
|
var borderMargin = 10.0f;
|
||||||
|
var hintWindowsSize = HintControlSize;
|
||||||
|
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
||||||
|
var hintPreviewSize = new Float2(Math.Max(HintControlSize * 2, size.X * 0.5f), Math.Max(HintControlSize * 2, size.Y * 0.5f));
|
||||||
|
var centerX = size.X * 0.5f;
|
||||||
|
var centerY = size.Y * 0.5f;
|
||||||
|
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
|
||||||
|
|
||||||
|
// Hit test, and calculate the approximation for filled area when hovered over the hint
|
||||||
|
var toSet = DockState.Float;
|
||||||
|
var hintTestPoint = _toDock.PointFromScreen(_mouse);
|
||||||
|
if (showBorderHints)
|
||||||
|
{
|
||||||
|
if (_rUpper.Contains(ref hintTestPoint))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockTop;
|
||||||
|
hoveredHintControl = _dockHintUp;
|
||||||
|
hoveredSizeOverride = new Float2(size.X, size.Y * DockPanel.DefaultSplitterValue);
|
||||||
|
hoveredLocationOffset.Y -= borderMargin - hoveredMargin;
|
||||||
|
}
|
||||||
|
else if (_rBottom.Contains(ref hintTestPoint))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockBottom;
|
||||||
|
hoveredHintControl = _dockHintDown;
|
||||||
|
hoveredSizeOverride = new Float2(size.X, size.Y * DockPanel.DefaultSplitterValue);
|
||||||
|
hoveredLocationOffset.Y += borderMargin - hoveredMargin;
|
||||||
|
}
|
||||||
|
else if (_rLeft.Contains(ref hintTestPoint))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockLeft;
|
||||||
|
hoveredHintControl = _dockHintLeft;
|
||||||
|
hoveredSizeOverride = new Float2(size.X * DockPanel.DefaultSplitterValue, size.Y);
|
||||||
|
hoveredLocationOffset.X -= borderMargin - hoveredMargin;
|
||||||
|
}
|
||||||
|
else if (_rRight.Contains(ref hintTestPoint))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockRight;
|
||||||
|
hoveredHintControl = _dockHintRight;
|
||||||
|
hoveredSizeOverride = new Float2(size.X * DockPanel.DefaultSplitterValue, size.Y);
|
||||||
|
hoveredLocationOffset.X += borderMargin - hoveredMargin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (showCenterHint && _rCenter.Contains(ref hintTestPoint))
|
||||||
|
{
|
||||||
|
toSet = DockState.DockFill;
|
||||||
|
hoveredHintControl = _dockHintCenter;
|
||||||
|
hoveredSizeOverride = new Float2(size.X, size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toSet = toSet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_toSet = DockState.Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update sizes and opacity of hint controls
|
||||||
|
if (_toDock != null)
|
||||||
|
{
|
||||||
|
var mainColor = Style.Current.Selection;
|
||||||
|
if (hoveredHintControl != _dockHintDown)
|
||||||
|
{
|
||||||
|
_dockHintDown.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintDown.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintLeft)
|
||||||
|
{
|
||||||
|
_dockHintLeft.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintLeft.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintRight)
|
||||||
|
{
|
||||||
|
_dockHintRight.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintRight.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintUp)
|
||||||
|
{
|
||||||
|
_dockHintUp.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintUp.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
if (hoveredHintControl != _dockHintCenter)
|
||||||
|
{
|
||||||
|
_dockHintCenter.Size = new Float2(HintControlSize);
|
||||||
|
_dockHintCenter.BackgroundColor = mainColor.AlphaMultiplied(0.6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_toSet != DockState.Float)
|
||||||
|
{
|
||||||
|
if (hoveredHintControl != null)
|
||||||
|
{
|
||||||
|
hoveredHintControl.BackgroundColor = mainColor;
|
||||||
|
if (_toSet != prevToSet)
|
||||||
|
hoveredHintControl.Location += hoveredLocationOffset;
|
||||||
|
hoveredHintControl.Size = hoveredSizeOverride - hoveredMargin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update hint controls visibility and location
|
||||||
|
if (showProxyHints)
|
||||||
|
{
|
||||||
|
if (hoveredHintControl != _dockHintDown)
|
||||||
|
_dockHintDown.Location = _rBottom.Location;
|
||||||
|
if (hoveredHintControl != _dockHintLeft)
|
||||||
|
_dockHintLeft.Location = _rLeft.Location;
|
||||||
|
if (hoveredHintControl != _dockHintRight)
|
||||||
|
_dockHintRight.Location = _rRight.Location;
|
||||||
|
if (hoveredHintControl != _dockHintUp)
|
||||||
|
_dockHintUp.Location = _rUpper.Location;
|
||||||
|
if (hoveredHintControl != _dockHintCenter)
|
||||||
|
_dockHintCenter.Location = _rCenter.Location;
|
||||||
|
|
||||||
|
_dockHintDown.Visible = showProxyHints & showBorderHints;
|
||||||
|
_dockHintLeft.Visible = showProxyHints & showBorderHints;
|
||||||
|
_dockHintRight.Visible = showProxyHints & showBorderHints;
|
||||||
|
_dockHintUp.Visible = showProxyHints & showBorderHints;
|
||||||
|
_dockHintCenter.Visible = showProxyHints & showCenterHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
||||||
|
{
|
||||||
|
if (button == MouseButton.Left)
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUpdate()
|
||||||
|
{
|
||||||
|
// If the engine lost focus during dragging, end the action
|
||||||
|
if (!Engine.HasFocus)
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mousePos = Platform.MousePosition;
|
||||||
|
if (_mouse != mousePos)
|
||||||
|
{
|
||||||
|
if (_dragSourceWindow != null)
|
||||||
|
_toMove.Window.Window.Position = mousePos - _dragOffset;
|
||||||
|
|
||||||
|
UpdateRects(mousePos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -242,6 +242,15 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
FieldInfo[] fields = type.GetFields();
|
FieldInfo[] fields = type.GetFields();
|
||||||
entries.Capacity = Mathf.Max(fields.Length - 1, entries.Capacity);
|
entries.Capacity = Mathf.Max(fields.Length - 1, entries.Capacity);
|
||||||
|
if (formatMode == EnumDisplayAttribute.FormatMode.Default)
|
||||||
|
{
|
||||||
|
// Override display mode from enum itself
|
||||||
|
var attr = type.GetCustomAttribute<EnumDisplayAttribute>();
|
||||||
|
if (attr != null)
|
||||||
|
{
|
||||||
|
formatMode = attr.Mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i = 0; i < fields.Length; i++)
|
for (int i = 0; i < fields.Length; i++)
|
||||||
{
|
{
|
||||||
var field = fields[i];
|
var field = fields[i];
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
public class ColorValueBox : Control
|
public class ColorValueBox : Control
|
||||||
{
|
{
|
||||||
private bool _isMouseDown;
|
private bool _isMouseDown;
|
||||||
|
private bool _linear;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delegate function used for the color picker events handling.
|
/// Delegate function used for the color picker events handling.
|
||||||
@@ -101,6 +102,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
public ColorValueBox()
|
public ColorValueBox()
|
||||||
: base(0, 0, 32, 18)
|
: base(0, 0, 32, 18)
|
||||||
{
|
{
|
||||||
|
_linear = !Graphics.GammaColorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -113,6 +115,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
: base(x, y, 32, 18)
|
: base(x, y, 32, 18)
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
|
_linear = !Graphics.GammaColorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -129,8 +132,10 @@ namespace FlaxEditor.GUI.Input
|
|||||||
{
|
{
|
||||||
base.Draw();
|
base.Draw();
|
||||||
|
|
||||||
bool isTransparent = _value.A < 1;
|
var value = _value;
|
||||||
|
if (_linear)
|
||||||
|
value = value.ToSRgb();
|
||||||
|
var isTransparent = value.A < 1;
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var fullRect = new Rectangle(0, 0, Width, Height);
|
var fullRect = new Rectangle(0, 0, Width, Height);
|
||||||
var colorRect = new Rectangle(0, 0, isTransparent ? Width * 0.7f : Width, Height);
|
var colorRect = new Rectangle(0, 0, isTransparent ? Width * 0.7f : Width, Height);
|
||||||
@@ -157,10 +162,10 @@ namespace FlaxEditor.GUI.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Render2D.FillRectangle(alphaRect, _value);
|
Render2D.FillRectangle(alphaRect, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Render2D.FillRectangle(colorRect, _value with { A = 1 });
|
Render2D.FillRectangle(colorRect, value with { A = 1 });
|
||||||
Render2D.DrawRectangle(fullRect, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black);
|
Render2D.DrawRectangle(fullRect, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ namespace FlaxEditor.GUI.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action SlidingEnd;
|
public event Action SlidingEnd;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If enabled, pressing the arrow up or down key increments/ decrements the value.
|
||||||
|
/// </summary>
|
||||||
|
public bool ArrowKeysIncrement = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the slider speed. Use value 0 to disable and hide slider UI.
|
/// Gets or sets the slider speed. Use value 0 to disable and hide slider UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -239,6 +244,27 @@ namespace FlaxEditor.GUI.Input
|
|||||||
ResetViewOffset();
|
ResetViewOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
|
{
|
||||||
|
if (ArrowKeysIncrement && (key == KeyboardKeys.ArrowUp || key == KeyboardKeys.ArrowDown))
|
||||||
|
{
|
||||||
|
bool altDown = Root.GetKey(KeyboardKeys.Alt);
|
||||||
|
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||||
|
bool controlDown = Root.GetKey(KeyboardKeys.Control);
|
||||||
|
float deltaValue = altDown ? 0.1f : (shiftDown ? 10f : (controlDown ? 100f : 1f));
|
||||||
|
float slideDelta = key == KeyboardKeys.ArrowUp ? deltaValue : -deltaValue;
|
||||||
|
|
||||||
|
_startSlideValue = Value;
|
||||||
|
ApplySliding(slideDelta);
|
||||||
|
EndSliding();
|
||||||
|
Focus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnKeyDown(key);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
@@ -266,6 +292,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 +319,45 @@ namespace FlaxEditor.GUI.Input
|
|||||||
base.OnMouseMove(location);
|
base.OnMouseMove(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnMouseMoveRelative(Float2 motion)
|
||||||
|
{
|
||||||
|
var location = Root.TrackingMouseOffset;
|
||||||
|
if (_isSliding)
|
||||||
|
{
|
||||||
|
// Update sliding
|
||||||
|
ApplySliding(Root.TrackingMouseOffset.X * _slideSpeed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cursor type so user knows they can slide value
|
||||||
|
if (CanUseSliding && SlideRect.Contains(location) && !_isSliding)
|
||||||
|
{
|
||||||
|
Cursor = CursorType.SizeWE;
|
||||||
|
_cursorChanged = true;
|
||||||
|
}
|
||||||
|
else if (_cursorChanged && !_isSliding)
|
||||||
|
{
|
||||||
|
Cursor = CursorType.Default;
|
||||||
|
_cursorChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnMouseMoveRelative(motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
if (button == MouseButton.Left && _isSliding)
|
if (button == MouseButton.Left && _isSliding)
|
||||||
{
|
{
|
||||||
|
#if !PLATFORM_SDL
|
||||||
// End sliding and return mouse to original location
|
// End sliding and return mouse to original location
|
||||||
RootWindow.MousePosition = _mouseClickedPosition;
|
RootWindow.MousePosition = _mouseClickedPosition;
|
||||||
|
#endif
|
||||||
EndSliding();
|
EndSliding();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,12 +59,12 @@ namespace FlaxEditor.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when items gets clicked by the user.
|
/// Occurs when items gets clicked by the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Item> Clicked;
|
public event Action<Item> ItemClicked;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when items gets focused.
|
/// Occurs when items gets focused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<Item> Focused;
|
public event Action<Item> ItemFocused;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tint color of the text.
|
/// The tint color of the text.
|
||||||
@@ -203,7 +203,7 @@ namespace FlaxEditor.GUI
|
|||||||
if (button == MouseButton.Left && _isMouseDown)
|
if (button == MouseButton.Left && _isMouseDown)
|
||||||
{
|
{
|
||||||
_isMouseDown = false;
|
_isMouseDown = false;
|
||||||
Clicked?.Invoke(this);
|
ItemClicked?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.OnMouseUp(location, button);
|
return base.OnMouseUp(location, button);
|
||||||
@@ -222,7 +222,7 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
base.OnGotFocus();
|
base.OnGotFocus();
|
||||||
|
|
||||||
Focused?.Invoke(this);
|
ItemFocused?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -434,7 +434,7 @@ namespace FlaxEditor.GUI
|
|||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
public void AddItem(Item item)
|
public void AddItem(Item item)
|
||||||
{
|
{
|
||||||
item.Clicked += OnClickItem;
|
item.ItemClicked += OnClickItem;
|
||||||
ContainerControl parent = ItemsPanel;
|
ContainerControl parent = ItemsPanel;
|
||||||
if (!string.IsNullOrEmpty(item.Category))
|
if (!string.IsNullOrEmpty(item.Category))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -298,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)
|
||||||
{
|
{
|
||||||
@@ -333,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;
|
||||||
@@ -362,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1140,8 +1140,11 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
ParentTree.DraggedOverNode = this;
|
ParentTree.DraggedOverNode = this;
|
||||||
|
|
||||||
// Expand node if mouse goes over arrow
|
// Expand node if mouse goes over arrow
|
||||||
if (ArrowRect.Contains(location) && HasAnyVisibleChild)
|
if (ArrowRect.Contains(location) && HasAnyVisibleChild && IsCollapsed)
|
||||||
|
{
|
||||||
Expand(true);
|
Expand(true);
|
||||||
|
ParentTree?.FlushPendingPerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
result = OnDragEnterHeader(data);
|
result = OnDragEnterHeader(data);
|
||||||
}
|
}
|
||||||
@@ -1172,8 +1175,11 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
ParentTree.DraggedOverNode = this;
|
ParentTree.DraggedOverNode = this;
|
||||||
|
|
||||||
// Expand node if mouse goes over arrow
|
// Expand node if mouse goes over arrow
|
||||||
if (ArrowRect.Contains(location) && HasAnyVisibleChild)
|
if (ArrowRect.Contains(location) && HasAnyVisibleChild && IsCollapsed)
|
||||||
|
{
|
||||||
Expand(true);
|
Expand(true);
|
||||||
|
ParentTree?.FlushPendingPerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
if (!_isDragOverHeader)
|
if (!_isDragOverHeader)
|
||||||
result = OnDragEnterHeader(data);
|
result = OnDragEnterHeader(data);
|
||||||
|
|||||||
339
Source/Editor/GUI/WindowDecorations.cs
Normal file
339
Source/Editor/GUI/WindowDecorations.cs
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.GUI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the title bar of the window with buttons.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
|
||||||
|
public class WindowDecorations : ContainerControl
|
||||||
|
{
|
||||||
|
private Image _icon;
|
||||||
|
private Label _title;
|
||||||
|
private Button _closeButton;
|
||||||
|
private Button _minimizeButton;
|
||||||
|
private Button _maximizeButton;
|
||||||
|
private LocalizedString _charChromeRestore, _charChromeMaximize;
|
||||||
|
private Window _window;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The title label in the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public Label Title => _title;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The icon used in the title bar.
|
||||||
|
/// </summary>
|
||||||
|
public Image Icon => _icon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The tooltip shown when hovering over the icon.
|
||||||
|
/// </summary>
|
||||||
|
public string IconTooltipText
|
||||||
|
{
|
||||||
|
get => _icon?.TooltipText ?? null;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_icon != null)
|
||||||
|
_icon.TooltipText = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="WindowDecorations"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window">The window.</param>
|
||||||
|
/// <param name="iconOnly">When set, omit drawing title and buttons.</param>
|
||||||
|
public WindowDecorations(RootControl window, bool iconOnly = false)
|
||||||
|
: base(0, 0, 0, 20)
|
||||||
|
{
|
||||||
|
_window = window.RootWindow.Window;
|
||||||
|
|
||||||
|
AutoFocus = false;
|
||||||
|
AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
||||||
|
BackgroundColor = Color.Transparent;
|
||||||
|
|
||||||
|
var windowIcon = FlaxEngine.Content.LoadAsyncInternal<Texture>(EditorAssets.WindowIcon);
|
||||||
|
|
||||||
|
_icon = new Image
|
||||||
|
{
|
||||||
|
Margin = new Margin(4, 4, 4, 4),
|
||||||
|
Brush = new TextureBrush(windowIcon),
|
||||||
|
Color = Style.Current.Foreground,
|
||||||
|
BackgroundColor = Style.Current.LightBackground,
|
||||||
|
KeepAspectRatio = false,
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!iconOnly)
|
||||||
|
{
|
||||||
|
_icon.Margin = new Margin(6, 6, 6, 6);
|
||||||
|
Height = 28;
|
||||||
|
|
||||||
|
_window.HitTest += OnHitTest;
|
||||||
|
_window.Closed += OnWindowClosed;
|
||||||
|
|
||||||
|
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.WindowIconsFont);
|
||||||
|
Font iconFont = windowIconsFont?.CreateFont(9);
|
||||||
|
|
||||||
|
_title = new Label(0, 0, Width, Height)
|
||||||
|
{
|
||||||
|
Text = _window.Title,
|
||||||
|
HorizontalAlignment = TextAlignment.Center,
|
||||||
|
VerticalAlignment = TextAlignment.Center,
|
||||||
|
ClipText = true,
|
||||||
|
TextColor = Style.Current.ForegroundGrey,
|
||||||
|
TextColorHighlighted = Style.Current.ForegroundGrey,
|
||||||
|
BackgroundColor = Style.Current.LightBackground,
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
_closeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Style.Current.LightBackground,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Color.Red,
|
||||||
|
BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_closeButton.Clicked += () => _window.Close(ClosingReason.User);
|
||||||
|
|
||||||
|
_minimizeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Style.Current.LightBackground,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_minimizeButton.Clicked += () => _window.Minimize();
|
||||||
|
|
||||||
|
_maximizeButton = new Button
|
||||||
|
{
|
||||||
|
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
|
||||||
|
Font = new FontReference(iconFont),
|
||||||
|
BackgroundColor = Style.Current.LightBackground,
|
||||||
|
BorderColor = Color.Transparent,
|
||||||
|
BorderColorHighlighted = Color.Transparent,
|
||||||
|
BorderColorSelected = Color.Transparent,
|
||||||
|
TextColor = Style.Current.Foreground,
|
||||||
|
Width = 46,
|
||||||
|
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
|
||||||
|
Parent = this,
|
||||||
|
};
|
||||||
|
_maximizeButton.Clicked += () =>
|
||||||
|
{
|
||||||
|
if (_window.IsMaximized)
|
||||||
|
_window.Restore();
|
||||||
|
else
|
||||||
|
_window.Maximize();
|
||||||
|
};
|
||||||
|
|
||||||
|
_charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
|
||||||
|
_charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (_maximizeButton != null)
|
||||||
|
{
|
||||||
|
var maximizeText = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
|
||||||
|
if (_maximizeButton.Text != maximizeText)
|
||||||
|
_maximizeButton.Text = maximizeText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWindowClosed()
|
||||||
|
{
|
||||||
|
if (_window != null)
|
||||||
|
{
|
||||||
|
_window.HitTest -= OnHitTest;
|
||||||
|
_window = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform hit test on the window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mouse">The mouse position</param>
|
||||||
|
/// <returns>The hit code for given position.</returns>
|
||||||
|
protected virtual WindowHitCodes OnHitTest(ref Float2 mouse)
|
||||||
|
{
|
||||||
|
if (_window.IsMinimized)
|
||||||
|
return WindowHitCodes.NoWhere;
|
||||||
|
|
||||||
|
var dpiScale = _window.DpiScale;
|
||||||
|
var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
|
||||||
|
if (!_window.IsMaximized)
|
||||||
|
{
|
||||||
|
var winSize = _window.Size;
|
||||||
|
|
||||||
|
// Distance from which the mouse is considered to be on the border/corner
|
||||||
|
float distance = 5.0f * dpiScale;
|
||||||
|
|
||||||
|
if (pos.Y > winSize.Y - distance && pos.X < distance)
|
||||||
|
return WindowHitCodes.BottomLeft;
|
||||||
|
|
||||||
|
if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
|
||||||
|
return WindowHitCodes.BottomRight;
|
||||||
|
|
||||||
|
if (pos.Y < distance && pos.X < distance)
|
||||||
|
return WindowHitCodes.TopLeft;
|
||||||
|
|
||||||
|
if (pos.Y < distance && pos.X > winSize.X - distance)
|
||||||
|
return WindowHitCodes.TopRight;
|
||||||
|
|
||||||
|
if (pos.X > winSize.X - distance)
|
||||||
|
return WindowHitCodes.Right;
|
||||||
|
|
||||||
|
if (pos.X < distance)
|
||||||
|
return WindowHitCodes.Left;
|
||||||
|
|
||||||
|
if (pos.Y < distance)
|
||||||
|
return WindowHitCodes.Top;
|
||||||
|
|
||||||
|
if (pos.Y > winSize.Y - distance)
|
||||||
|
return WindowHitCodes.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
var controlUnderMouse = GetChildAt(pos, control => control != _title);
|
||||||
|
if (_title.Bounds.Contains(pos) && controlUnderMouse == null)
|
||||||
|
return WindowHitCodes.Caption;
|
||||||
|
|
||||||
|
return WindowHitCodes.Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
|
{
|
||||||
|
// These may not work with main window due to SDL not passing mouse events
|
||||||
|
// when interacting with hit tests on caption area...
|
||||||
|
|
||||||
|
if (Title.Bounds.Contains(location) && button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
if (_window.IsMaximized)
|
||||||
|
_window.Restore();
|
||||||
|
else
|
||||||
|
_window.Maximize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (Icon.Bounds.Contains(location) && button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
_window.Close(ClosingReason.User);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.OnMouseDoubleClick(location, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void PerformLayoutAfterChildren()
|
||||||
|
{
|
||||||
|
// Calculate extents for title bounds area excluding the icon and main menu area
|
||||||
|
float x = 0;
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
if (_icon != null)
|
||||||
|
{
|
||||||
|
_icon.X = x;
|
||||||
|
_icon.Size = new Float2(Height);
|
||||||
|
x += _icon.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main menu if present
|
||||||
|
if (Parent.GetChild<MainMenu>() is MainMenu mainMenu)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mainMenu.Children.Count; i++)
|
||||||
|
{
|
||||||
|
var c = mainMenu.Children[i];
|
||||||
|
if (c is MainMenuButton b && c.Visible)
|
||||||
|
{
|
||||||
|
b.Bounds = new Rectangle(x, 0, b.Width, Height);
|
||||||
|
x += b.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
float rightMostButtonX = Width;
|
||||||
|
if (_closeButton != null)
|
||||||
|
{
|
||||||
|
_closeButton.Height = Height;
|
||||||
|
_closeButton.X = rightMostButtonX - _closeButton.Width;
|
||||||
|
rightMostButtonX = _closeButton.X;
|
||||||
|
}
|
||||||
|
if (_maximizeButton != null)
|
||||||
|
{
|
||||||
|
_maximizeButton.Height = Height;
|
||||||
|
_maximizeButton.X = rightMostButtonX - _maximizeButton.Width;
|
||||||
|
rightMostButtonX = _maximizeButton.X;
|
||||||
|
}
|
||||||
|
if (_minimizeButton != null)
|
||||||
|
{
|
||||||
|
_minimizeButton.Height = Height;
|
||||||
|
_minimizeButton.X = rightMostButtonX - _minimizeButton.Width;
|
||||||
|
rightMostButtonX = _minimizeButton.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Title
|
||||||
|
if (_title != null)
|
||||||
|
{
|
||||||
|
_title.Text = _window.Title;
|
||||||
|
_title.Bounds = new Rectangle(x, 0, rightMostButtonX - x, Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
base.Draw();
|
||||||
|
DrawBorders();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw borders around the window.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void DrawBorders()
|
||||||
|
{
|
||||||
|
var win = RootWindow.Window;
|
||||||
|
if (win.IsMaximized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Editor.Instance.UI.StatusBar == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float thickness = 1.0f;
|
||||||
|
Color color = Editor.Instance.UI.StatusBar.StatusColor;
|
||||||
|
Rectangle rect = new Rectangle(thickness * 0.5f, thickness * 0.5f, Parent.Width - thickness, Parent.Height - thickness);
|
||||||
|
Render2D.DrawRectangle(rect, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnDestroy()
|
||||||
|
{
|
||||||
|
base.OnDestroy();
|
||||||
|
|
||||||
|
if (_window != null)
|
||||||
|
{
|
||||||
|
_window.Closed -= OnWindowClosed;
|
||||||
|
OnWindowClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
public abstract class GizmoBase
|
public abstract class GizmoBase
|
||||||
{
|
{
|
||||||
private IGizmoOwner _owner;
|
private IGizmoOwner _owner;
|
||||||
|
private bool _visible = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the gizmo owner.
|
/// Gets the gizmo owner.
|
||||||
@@ -34,6 +35,11 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual BoundingSphere FocusBounds => BoundingSphere.Empty;
|
public virtual BoundingSphere FocusBounds => BoundingSphere.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this gizmo is visible.
|
||||||
|
/// </summary>
|
||||||
|
public bool Visible { get { return _visible; } set { _visible = value; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="GizmoBase"/> class.
|
/// Initializes a new instance of the <see cref="GizmoBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ public sealed class ViewportRubberBandSelector
|
|||||||
/// Triggers the start of a rubber band selection.
|
/// Triggers the start of a rubber band selection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if selection started, otherwise false.</returns>
|
/// <returns>True if selection started, otherwise false.</returns>
|
||||||
public bool TryStartingRubberBandSelection()
|
public bool TryStartingRubberBandSelection(Float2 mousePosition)
|
||||||
{
|
{
|
||||||
if (!_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
if (!_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
||||||
{
|
{
|
||||||
_tryStartRubberBand = true;
|
_tryStartRubberBand = true;
|
||||||
|
_cachedStartingMousePosition = mousePosition;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -82,12 +83,15 @@ public sealed class ViewportRubberBandSelector
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_tryStartRubberBand && (Mathf.Abs(_owner.MouseDelta.X) > 0.1f || Mathf.Abs(_owner.MouseDelta.Y) > 0.1f) && canStart)
|
if (_tryStartRubberBand && canStart)
|
||||||
{
|
{
|
||||||
_isRubberBandSpanning = true;
|
var delta = mousePosition - _cachedStartingMousePosition;
|
||||||
_cachedStartingMousePosition = mousePosition;
|
if (Mathf.Abs(delta.X) > 0.1f || Mathf.Abs(delta.Y) > 0.1f)
|
||||||
_rubberBandRect = new Rectangle(_cachedStartingMousePosition, Float2.Zero);
|
{
|
||||||
_tryStartRubberBand = false;
|
_isRubberBandSpanning = true;
|
||||||
|
_rubberBandRect = new Rectangle(_cachedStartingMousePosition, Float2.Zero);
|
||||||
|
_tryStartRubberBand = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
else if (_isRubberBandSpanning && _owner.Gizmos.Active != null && !_owner.Gizmos.Active.IsControllingMouse && !_owner.IsRightMouseButtonDown)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -402,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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace FlaxEditor.Modules
|
|||||||
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
||||||
public sealed class SceneEditingModule : EditorModule
|
public sealed class SceneEditingModule : EditorModule
|
||||||
{
|
{
|
||||||
|
private int _lastSelectionStatus = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The selected objects.
|
/// The selected objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -193,6 +195,20 @@ namespace FlaxEditor.Modules
|
|||||||
Undo.AddAction(new SelectionChangeAction(before, Selection.ToArray(), OnSelectionUndo));
|
Undo.AddAction(new SelectionChangeAction(before, Selection.ToArray(), OnSelectionUndo));
|
||||||
|
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
|
|
||||||
|
// Display amount of selected actors on the status bar
|
||||||
|
Editor.UI.RemoveStatusMessage(_lastSelectionStatus);
|
||||||
|
var objects = Selection.Count;
|
||||||
|
var actors = CountActors(Selection);
|
||||||
|
_lastSelectionStatus = Editor.UI.AddStatusMessage($"Selected {objects} {(objects > 1 ? "objects" : "object")} (total {actors} {(actors > 1 ? "actors" : "actor")})");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountActors(List<SceneGraphNode> nodes)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
foreach (var node in nodes)
|
||||||
|
result += 1 + CountActors(node.ChildNodes);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectionUndo(SceneGraphNode[] toSelect)
|
private void OnSelectionUndo(SceneGraphNode[] toSelect)
|
||||||
@@ -229,7 +245,7 @@ namespace FlaxEditor.Modules
|
|||||||
if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && node.AffectsNavigationWithChildren)
|
if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && node.AffectsNavigationWithChildren)
|
||||||
{
|
{
|
||||||
var bounds = actor.BoxWithChildren;
|
var bounds = actor.BoxWithChildren;
|
||||||
Navigation.BuildNavMesh(actor.Scene, bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
Navigation.BuildNavMesh(bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ namespace FlaxEditor.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnPlayBegin()
|
public override void OnPlayBeginning()
|
||||||
{
|
{
|
||||||
Editor.Windows.FlashMainWindow();
|
Editor.Windows.FlashMainWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -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,10 +28,52 @@ namespace FlaxEditor.Modules
|
|||||||
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
|
||||||
public sealed class UIModule : EditorModule
|
public sealed class UIModule : EditorModule
|
||||||
{
|
{
|
||||||
|
private class MainWindowDecorations : WindowDecorations
|
||||||
|
{
|
||||||
|
public MainWindowDecorations(RootControl window, bool iconOnly)
|
||||||
|
: base(window, iconOnly)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
|
{
|
||||||
|
if (base.OnKeyDown(key))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Fallback to the edit window for shortcuts
|
||||||
|
var editor = Editor.Instance;
|
||||||
|
return editor.Windows.EditWin.InputActions.Process(editor, this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void DrawBorders()
|
||||||
|
{
|
||||||
|
// Draw main window borders if using a custom style
|
||||||
|
var win = RootWindow.Window;
|
||||||
|
if (win.IsMaximized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var color = Editor.Instance.UI.StatusBar.StatusColor;
|
||||||
|
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
|
||||||
|
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
|
||||||
|
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
|
||||||
|
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Status
|
||||||
|
{
|
||||||
|
public int ID;
|
||||||
|
public string Text;
|
||||||
|
public DateTime EndTime;
|
||||||
|
}
|
||||||
|
|
||||||
private Label _progressLabel;
|
private Label _progressLabel;
|
||||||
private ProgressBar _progressBar;
|
private ProgressBar _progressBar;
|
||||||
private Button _outputLogButton;
|
private Button _outputLogButton;
|
||||||
private List<KeyValuePair<string, DateTime>> _statusMessages;
|
private List<Status> _statusMessages;
|
||||||
|
private int _statusID = 1;
|
||||||
private ContentStats _contentStats;
|
private ContentStats _contentStats;
|
||||||
private bool _progressFailed;
|
private bool _progressFailed;
|
||||||
|
|
||||||
@@ -125,6 +166,7 @@ namespace FlaxEditor.Modules
|
|||||||
private ContextMenuButton _menuToolsProfilerWindow;
|
private ContextMenuButton _menuToolsProfilerWindow;
|
||||||
private ContextMenuButton _menuToolsSetTheCurrentSceneViewAsDefault;
|
private ContextMenuButton _menuToolsSetTheCurrentSceneViewAsDefault;
|
||||||
private ContextMenuButton _menuToolsTakeScreenshot;
|
private ContextMenuButton _menuToolsTakeScreenshot;
|
||||||
|
private ContextMenuButton _menuToolsOpenLocalFolder;
|
||||||
private ContextMenuChildMenu _menuWindowApplyWindowLayout;
|
private ContextMenuChildMenu _menuWindowApplyWindowLayout;
|
||||||
|
|
||||||
private ToolStripButton _toolStripSaveAll;
|
private ToolStripButton _toolStripSaveAll;
|
||||||
@@ -144,6 +186,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>
|
||||||
@@ -340,7 +387,7 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
string text;
|
string text;
|
||||||
if (_statusMessages != null && _statusMessages.Count != 0)
|
if (_statusMessages != null && _statusMessages.Count != 0)
|
||||||
text = _statusMessages[0].Key;
|
text = _statusMessages[0].Text;
|
||||||
else if (Editor.StateMachine.CurrentState.Status != null)
|
else if (Editor.StateMachine.CurrentState.Status != null)
|
||||||
text = Editor.StateMachine.CurrentState.Status;
|
text = Editor.StateMachine.CurrentState.Status;
|
||||||
else if (contentStats.LoadingAssetsCount != 0)
|
else if (contentStats.LoadingAssetsCount != 0)
|
||||||
@@ -362,13 +409,34 @@ namespace FlaxEditor.Modules
|
|||||||
/// Adds the status bar message text to be displayed as a notification.
|
/// Adds the status bar message text to be displayed as a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message to display.</param>
|
/// <param name="message">The message to display.</param>
|
||||||
public void AddStatusMessage(string message)
|
/// <returns>The ID of that status message (unique). Can be used to hide it manually.</returns>
|
||||||
|
public int AddStatusMessage(string message)
|
||||||
{
|
{
|
||||||
if (_statusMessages == null)
|
if (_statusMessages == null)
|
||||||
_statusMessages = new List<KeyValuePair<string, DateTime>>();
|
_statusMessages = new List<Status>();
|
||||||
_statusMessages.Add(new KeyValuePair<string, DateTime>(message, DateTime.Now + TimeSpan.FromSeconds(3.0f)));
|
var status = new Status { ID = _statusID++, Text = message, EndTime = DateTime.Now + TimeSpan.FromSeconds(3.0f) };
|
||||||
|
_statusMessages.Add(status);
|
||||||
if (_statusMessages.Count == 1)
|
if (_statusMessages.Count == 1)
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
|
return status.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a specific status message once it's not needed anymore,
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of the message returned by <see cref="AddStatusMessage"/>.</param>
|
||||||
|
public void RemoveStatusMessage(int id)
|
||||||
|
{
|
||||||
|
if (_statusMessages == null || id == 0)
|
||||||
|
return;
|
||||||
|
for (var i = 0; i < _statusMessages.Count; i++)
|
||||||
|
{
|
||||||
|
if (_statusMessages[i].ID == id)
|
||||||
|
{
|
||||||
|
_statusMessages.RemoveAt(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool ProgressVisible
|
internal bool ProgressVisible
|
||||||
@@ -426,19 +494,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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitViewportScaleOptions()
|
private void InitViewportScaleOptions()
|
||||||
@@ -489,13 +549,13 @@ namespace FlaxEditor.Modules
|
|||||||
public void SaveCustomViewportScalingOptions()
|
public void SaveCustomViewportScalingOptions()
|
||||||
{
|
{
|
||||||
var customOptions = JsonSerializer.Serialize(CustomViewportScaleOptions);
|
var customOptions = JsonSerializer.Serialize(CustomViewportScaleOptions);
|
||||||
Editor.Instance.ProjectCache.SetCustomData("CustomViewportScalingOptions", customOptions);
|
Editor.Instance.ProjectCache.SetCustomData("CustomViewportScalingOptions", customOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnUpdate()
|
public override void OnUpdate()
|
||||||
{
|
{
|
||||||
if (_statusMessages != null && _statusMessages.Count > 0 && _statusMessages[0].Value - DateTime.Now < TimeSpan.Zero)
|
if (_statusMessages != null && _statusMessages.Count > 0 && _statusMessages[0].EndTime - DateTime.Now < TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
_statusMessages.RemoveAt(0);
|
_statusMessages.RemoveAt(0);
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
@@ -510,23 +570,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()
|
||||||
{
|
{
|
||||||
@@ -558,13 +601,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);
|
||||||
@@ -618,10 +654,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;
|
||||||
|
|
||||||
@@ -725,12 +763,22 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
||||||
cm.AddSeparator();
|
cm.AddSeparator();
|
||||||
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
||||||
|
cm.AddSeparator();
|
||||||
|
var childMenu = cm.AddChildMenu("Open Product Local folder");
|
||||||
|
childMenu.ContextMenu.AddButton("Editor", () => FileSystem.ShowFileExplorer(Globals.ProductLocalFolder));
|
||||||
|
_menuToolsOpenLocalFolder = childMenu.ContextMenu.AddButton("Game", () =>
|
||||||
|
{
|
||||||
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
GameSettings settings = GameSettings.Load<GameSettings>();
|
||||||
|
string path = Path.Combine(localAppData, settings.CompanyName, settings.ProductName);
|
||||||
|
FileSystem.ShowFileExplorer(path);
|
||||||
|
});
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
MenuWindow = MainMenu.AddButton("Window");
|
MenuWindow = MainMenu.AddButton("Window");
|
||||||
cm = MenuWindow.ContextMenu;
|
cm = MenuWindow.ContextMenu;
|
||||||
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
cm.VisibleChanged += OnMenuWindowVisibleChanged;
|
||||||
cm.AddButton("Content", inputOptions.ContentWindow,Editor.Windows.ContentWin.FocusOrShow);
|
cm.AddButton("Content", inputOptions.ContentWindow, Editor.Windows.ContentWin.FocusOrShow);
|
||||||
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
|
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
|
||||||
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
|
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
|
||||||
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
|
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
|
||||||
@@ -763,6 +811,23 @@ namespace FlaxEditor.Modules
|
|||||||
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
|
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitWindowDecorations(RootControl mainWindow)
|
||||||
|
{
|
||||||
|
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
|
||||||
|
string driver = string.Empty;
|
||||||
|
#if PLATFORM_LINUX
|
||||||
|
driver = LinuxPlatform.DisplayServer;
|
||||||
|
if (!string.IsNullOrEmpty(driver))
|
||||||
|
driver = $" ({driver})";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WindowDecorations = new MainWindowDecorations(mainWindow, !Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
|
||||||
|
{
|
||||||
|
Parent = mainWindow,
|
||||||
|
IconTooltipText = $"{mainWindow.RootWindow.Title}\nVersion {Globals.EngineVersion}\nConfiguration {configuration}\nGraphics {GPUDevice.Instance.RendererType}{driver}",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void OnOptionsChanged(EditorOptions options)
|
private void OnOptionsChanged(EditorOptions options)
|
||||||
{
|
{
|
||||||
var inputOptions = options.Input;
|
var inputOptions = options.Input;
|
||||||
@@ -1062,6 +1127,10 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsBuildNavMesh.Enabled = canEdit;
|
_menuToolsBuildNavMesh.Enabled = canEdit;
|
||||||
_menuToolsCancelBuilding.Enabled = GameCooker.IsRunning;
|
_menuToolsCancelBuilding.Enabled = GameCooker.IsRunning;
|
||||||
_menuToolsSetTheCurrentSceneViewAsDefault.Enabled = Level.ScenesCount > 0;
|
_menuToolsSetTheCurrentSceneViewAsDefault.Enabled = Level.ScenesCount > 0;
|
||||||
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
GameSettings settings = GameSettings.Load<GameSettings>();
|
||||||
|
string path = Path.Combine(localAppData, settings.CompanyName, settings.ProductName);
|
||||||
|
_menuToolsOpenLocalFolder.Enabled = Directory.Exists(path);
|
||||||
|
|
||||||
c.PerformLayout();
|
c.PerformLayout();
|
||||||
}
|
}
|
||||||
@@ -1183,6 +1252,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;
|
||||||
@@ -491,10 +490,15 @@ namespace FlaxEditor.Modules
|
|||||||
Editor.LogWarning("Empty panel inside layout.");
|
Editor.LogWarning("Empty panel inside layout.");
|
||||||
p.RemoveIt();
|
p.RemoveIt();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.CollapseEmptyTabsProxy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.SelectTab(selectedTab);
|
panel.SelectTab(selectedTab);
|
||||||
|
panel.CollapseEmptyTabsProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SaveBounds(XmlWriter writer, Window win)
|
private static void SaveBounds(XmlWriter writer, Window win)
|
||||||
@@ -758,17 +762,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);
|
||||||
|
|||||||
@@ -387,6 +387,14 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Viewport"), EditorOrder(1760)]
|
[EditorDisplay("Viewport"), EditorOrder(1760)]
|
||||||
public InputBinding ToggleOrthographic = new InputBinding(KeyboardKeys.NumpadDecimal);
|
public InputBinding ToggleOrthographic = new InputBinding(KeyboardKeys.NumpadDecimal);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "G")]
|
||||||
|
[EditorDisplay("Viewport"), EditorOrder(1770)]
|
||||||
|
public InputBinding ToggleGameView = new InputBinding(KeyboardKeys.G);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "P")]
|
||||||
|
[EditorDisplay("Viewport"), EditorOrder(1770)]
|
||||||
|
public InputBinding ToggleNavMeshVisibility = new InputBinding(KeyboardKeys.P);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Debug Views
|
#region Debug Views
|
||||||
@@ -571,6 +579,10 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("View Flags"), EditorOrder(3260)]
|
[EditorDisplay("View Flags"), EditorOrder(3260)]
|
||||||
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
|
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
|
||||||
|
|
||||||
|
[DefaultValue(typeof(InputBinding), "None")]
|
||||||
|
[EditorDisplay("View Flags"), EditorOrder(3270)]
|
||||||
|
public InputBinding Particles = new InputBinding(KeyboardKeys.None);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Interface
|
#region Interface
|
||||||
|
|||||||
@@ -85,10 +85,12 @@ namespace FlaxEditor.Options
|
|||||||
/// Never show the close button.
|
/// Never show the close button.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Never,
|
Never,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show the close button on tabs that are currently selected.
|
/// Show the close button on tabs that are currently selected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SelectedTab,
|
SelectedTab,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show the close button on all tabs that can be closed.
|
/// Show the close button on all tabs that can be closed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -179,6 +181,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>
|
||||||
@@ -268,7 +298,14 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Interface"), EditorOrder(322)]
|
[EditorDisplay("Interface"), EditorOrder(322)]
|
||||||
public bool ScrollToScriptOnAdd { get; set; } = true;
|
public bool ScrollToScriptOnAdd { get; set; } = true;
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_SDL
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
|
||||||
|
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
|
||||||
|
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
|
||||||
|
#elif PLATFORM_WINDOWS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
|
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -277,7 +314,7 @@ namespace FlaxEditor.Options
|
|||||||
public bool UseNativeWindowSystem { get; set; } = false;
|
public bool UseNativeWindowSystem { get; set; } = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_SDL || PLATFORM_WINDOWS
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
|
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -287,7 +324,7 @@ namespace FlaxEditor.Options
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating wether the minum tab width should be used. Editor restart required.
|
/// Gets or sets a value indicating whether the minimum tab width should be used. Editor restart required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
|
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
|
||||||
@@ -498,7 +535,7 @@ namespace FlaxEditor.Options
|
|||||||
public float ConnectionCurvature { get; set; } = 1.0f;
|
public float ConnectionCurvature { get; set; } = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value that indicates wether the context menu description panel is shown or not.
|
/// Gets or sets a value that indicates whether the context menu description panel is shown or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(true)]
|
[DefaultValue(true)]
|
||||||
[EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in visual scripting context menu.")]
|
[EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in visual scripting context menu.")]
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user