493 Commits

Author SHA1 Message Date
c1f6bcb83f some linux work from summer
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-10-12 18:06:23 +03:00
eca4f6d9bc Merge remote-tracking branch 'origin/1.11' into work
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-07-05 14:19:52 +03:00
802074fca3 Update package requirements for Wayland 2025-07-05 12:55:25 +03:00
0bb13e1d91 Add overloads for physics queries with user-provided buffers 2025-07-05 12:36:11 +03:00
db47531a6d Support marshalling Arrays as dynamic arrays in scripting API 2025-07-05 12:36:11 +03:00
Wojtek Figat
48c6339ebb Fix memory leak on material instances when updating layout of Text Render 2025-07-04 12:21:25 +02:00
Wojtek Figat
2dd34b288c Merge remote-tracking branch 'origin/master' into 1.11 2025-07-04 12:05:19 +02:00
Wojtek Figat
0bc595f16f Disable terarin normals smoothening 2025-07-04 12:04:36 +02:00
Wojtek Figat
7abed93972 Optimize terrain heightmap decoding to use shared code 2025-07-04 11:31:27 +02:00
51feaa0730 Release mouse relative mode when focus changes during mouse tracking
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-07-03 23:21:42 +03:00
8e69aa8bd6 Fix error while closing Editor
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-07-03 22:57:07 +03:00
90b2fded48 Merge remote-tracking branch 'origin/master' into sdl_platform
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
# Conflicts:
#	Source/Editor/Windows/SceneTreeWindow.cs
2025-07-03 22:05:29 +03:00
9125ffeb9e Update third-party label in About dialog 2025-07-03 22:02:37 +03:00
28980e5fbf Cleanup 2025-07-03 22:02:36 +03:00
aab0d772a4 Implement client-side window decorations for Editor windows 2025-07-03 22:02:36 +03:00
Wojtek Figat
4b10d7057a Fix crash when using material instance that has more parameters that base due to material error 2025-07-03 20:33:14 +02:00
Wojtek Figat
85aed8c4d7 Fix using material VS to PS node directly within material input 2025-07-03 20:32:41 +02:00
Wojtek Figat
da08be42b4 Fix deadlock in Debug builds on object dtor 2025-07-03 20:32:12 +02:00
Wojtek Figat
056fea9a8c Fix forward shading compilation when using fog inside unlit material 2025-07-03 14:48:38 +02:00
Wojtek Figat
bf345f13ce Fix reflection probes capture seams on cube face edges due to volumetric fog
#3252
2025-07-03 13:54:22 +02:00
Wojtek Figat
a138c6b062 Optimize environment probes filtering shader 2025-07-03 11:45:12 +02:00
Wojtek Figat
33e58c12cb Optimize ProbesRenderer to use time-slicing for cubemap faces rendering and filtering 2025-07-03 11:43:56 +02:00
Wojtek Figat
094a6562b8 Refactor ProbesRenderer 2025-07-03 10:18:51 +02:00
Wojtek Figat
7f783bb7da Fix crash when importing mesh with incorrect triangulation 2025-07-02 17:23:04 +02:00
Wojtek Figat
b08f218f30 Merge branch 'Zode-tageditor-quickexpand' 2025-07-01 16:47:07 +02:00
Wojtek Figat
c6640be04a Merge branch 'tageditor-quickexpand' of https://github.com/Zode/FlaxEngine into Zode-tageditor-quickexpand 2025-07-01 16:47:04 +02:00
Wojtek Figat
eff3c50d9c Merge branch 'xxSeys1-ContentSearchMouseOverFocusFix' 2025-07-01 16:34:42 +02:00
Wojtek Figat
3fa099ad06 Merge branch 'ContentSearchMouseOverFocusFix' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ContentSearchMouseOverFocusFix 2025-07-01 16:27:08 +02:00
Wojtek Figat
5e47a861f3 Merge branch 'xxSeys1-VisjectConnectionCmPolish' 2025-07-01 16:06:22 +02:00
Wojtek Figat
37b4b25ead Merge branch 'VisjectConnectionCmPolish' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-VisjectConnectionCmPolish 2025-07-01 16:06:13 +02:00
Wojtek Figat
edfd145226 Merge branch 'xxSeys1-FixCloseButtonAfterIBrokeIt' 2025-07-01 15:58:46 +02:00
Wojtek Figat
763ede4bd9 Merge branch 'FixCloseButtonAfterIBrokeIt' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-FixCloseButtonAfterIBrokeIt 2025-07-01 15:58:36 +02:00
Wojtek Figat
284da341e1 Merge branch 'xxSeys1-ItemsListExpandOnNavigate' 2025-07-01 15:56:53 +02:00
Wojtek Figat
53ed2431b5 Merge branch 'ItemsListExpandOnNavigate' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ItemsListExpandOnNavigate 2025-07-01 15:48:24 +02:00
Wojtek Figat
b4ab39b3bf Merge branch 'Tryibion-keep-scroll-scene-play' 2025-07-01 15:34:27 +02:00
Wojtek Figat
de61e3efb5 Merge branch 'keep-scroll-scene-play' of https://github.com/Tryibion/FlaxEngine into Tryibion-keep-scroll-scene-play 2025-07-01 15:34:07 +02:00
Wojtek Figat
29fb36fcd6 Merge branch 'Tryibion-fix-log-clear-play' 2025-07-01 10:52:39 +02:00
Wojtek Figat
78f0ff75f2 Move debug log clearing to handle pending entries too in publci api 2025-07-01 10:52:14 +02:00
Wojtek Figat
6efd456eaf Merge branch 'fix-log-clear-play' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-log-clear-play 2025-07-01 10:50:58 +02:00
Wojtek Figat
e0c96c0cde Merge branch 'Tryibion-fix-tooltip-scene' 2025-07-01 10:48:34 +02:00
Wojtek Figat
ada269568a Merge branch 'fix-tooltip-scene' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-tooltip-scene 2025-07-01 10:48:26 +02:00
Wojtek Figat
dd256ad518 Fix typo 2025-07-01 10:37:39 +02:00
Wojtek Figat
12c8bb4f31 Fix scene lightmaps removal clearing actors linkage to lightmaps 2025-07-01 08:27:29 +02:00
Wojtek Figat
4e4d380267 Fix fog to draw Fog Cutoff Distance via a plane, not sphere test
Add support for negative Fog Cutoff Distance on fog to draw it in front of the camera Far Plane, no matter the setup.
Fix hot-reloading Fog shader in Editor.
2025-06-29 20:02:54 +02:00
Wojtek Figat
448eb48c23 Fix fog to draw Fog Cutoff Distance via a plane, not sphere test
Add support for negative Fog Cutoff Distance on fog to draw it in front of the camera Far Plane, no matter the setup.
Fix hot-reloading Fog shader in Editor.
2025-06-29 20:02:24 +02:00
Wojtek Figat
78d519cb9a Fix ConcurrentSystemLocker to have exclusive lock as an option 2025-06-29 19:16:41 +02:00
Wojtek Figat
43d11264f8 Fix asset references to use separate lightweight locking instead of full asset mutex 2025-06-29 19:16:23 +02:00
Wojtek Figat
f126a83b79 Fix graphical issues when batching materials that use Forward Shading for instancing 2025-06-29 13:52:29 +02:00
Wojtek Figat
bdd7bae459 Add new Custom Lit shading model for custom lighting in materials (eg. Cel Shading) 2025-06-29 13:51:59 +02:00
Wojtek Figat
3dc7546dd4 Fix crash when constant buffer is unused by shader but still exists 2025-06-27 19:06:25 +02:00
Wojtek Figat
185151b025 Minor fixes 2025-06-27 18:52:25 +02:00
Wojtek Figat
8cdec15fa6 Fix GlobalSignDistanceFieldCustomBuffer to be thread-safe (scene rendering events are not guarded via mutex anymore) 2025-06-27 15:41:48 +02:00
Wojtek Figat
1b40775d62 Fix deadloop in HtmlParser when parsing text with incorrect tags 2025-06-27 11:56:09 +02:00
Wojtek Figat
45e82d21f4 Fix ConcurrentSystemLocker to guard for a single writer at once 2025-06-26 19:51:06 +02:00
Wojtek Figat
5c37584eca Minor adjustment for alignment of perf-critical variables in rendering 2025-06-26 19:50:42 +02:00
Wojtek Figat
674fda7375 Add resizing to Custom Code nodes in Materials 2025-06-26 19:50:04 +02:00
6296e1a9eb Fix linker errors 2025-06-26 15:32:38 +03:00
1586bb0702 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-26 15:31:59 +03:00
xxSeys1
bf10d0949e add a bit of spacing to the left edge of the popup to reduce colors bleeding into the background 2025-06-26 12:47:31 +02:00
Wojtek Figat
d1c43ec1fe Merge remote-tracking branch 'origin/master' into 1.11 2025-06-25 10:48:11 +02:00
edeaf6af09 Fix compilation without SDL 2025-06-24 22:57:49 +03:00
Wojtek Figat
dbd8297612 Add SortOrder to Environment Probe 2025-06-24 19:25:18 +02:00
Wojtek Figat
8d62a13cbc Add LayoutElementsContainer.Image with IBrush 2025-06-24 18:32:20 +02:00
951edd95db Cleanup 2025-06-24 16:47:45 +03:00
9951211596 Fix mono glib.h wrapper compilation error 2025-06-24 16:47:20 +03:00
6d337464f7 Support XDG Desktop Portal as color picker provider
Wayland and XWayland fallback implementation uses XDP in
order to query picked color from desktop.
2025-06-24 16:41:32 +03:00
Wojtek Figat
5a05038a9b Add new UIBrush that uses UIBrushAsset json resource with a brush data 2025-06-24 13:08:25 +02:00
xxSeys1
109d4423bb add accent color strip to search item icons 2025-06-23 20:14:18 +02:00
d0b552d74a Use logo as an icon in Linux windows 2025-06-23 18:58:02 +03:00
xxSeys1
6c1e380a3e fix search item hover auto focusing item
Change what happens when search items get focused to prevent focus being taken away from search box.
Also adds a highlight to mouse hovered search item.
2025-06-23 17:24:53 +02:00
83512822b1 Support clipboard actions in Content Browser and Scene tree on Wayland
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-06-23 17:50:02 +03:00
ccb78103ec Support clipboard actions in Content Browser and Scene tree on X11 2025-06-23 17:07:10 +03:00
6e79ffea34 Fix clipboard not working on X11 2025-06-23 17:07:10 +03:00
4f03d37a17 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-23 12:03:41 +03:00
Wojtek Figat
c57a1a7205 Fix particle emitters to wait for used textures to be loaded and streamed in for proper usage in a graph 2025-06-23 09:31:58 +02:00
Wojtek Figat
867ae2ceaa Add Texture Size node to particles 2025-06-23 09:31:15 +02:00
Wojtek Figat
ef5d45874a Fix compilation regression 2025-06-22 12:12:42 +02:00
Chandler Cox
169db79b2a Fix issue with tooltip not updating on scene reload. 2025-06-20 20:12:43 -05:00
Chandler Cox
9e4c1da032 Clear entries and pending entries before play for debug log. 2025-06-20 19:42:30 -05:00
Wojtek Figat
d7df403e5e Optimize ContainerControl.DisposeChildren 2025-06-20 09:05:41 +02:00
Wojtek Figat
d3a50cdacb Optimize Actor::DestroyChildren 2025-06-20 09:05:25 +02:00
Chandler Cox
3cb74d48ca Convert using event to using window method overrides. 2025-06-19 20:01:27 -05:00
Chandler Cox
8633ed2124 Merge branch 'master' into keep-scroll-scene-play 2025-06-19 19:58:04 -05:00
Wojtek Figat
2e10d776e9 Optimize updating actor rendering entry with better thread locking that support async writes on actor update 2025-06-19 14:04:06 +02:00
Wojtek Figat
4ac870f701 Optimize physics transformation updates propagation in async via Job System 2025-06-19 13:57:50 +02:00
Wojtek Figat
6144f6c74e Optimize physics simulation with higher limit of 8 threads 2025-06-19 09:50:07 +02:00
Wojtek Figat
edb6884942 Optimize PhysX work dispatcher to be shared by all scenes 2025-06-19 08:24:26 +02:00
Wojtek Figat
62e329ac6e Add more memory tags for Navigation 2025-06-18 23:00:43 +02:00
Wojtek Figat
68dce7e4dd Merge remote-tracking branch 'origin/master' into 1.11 2025-06-18 22:46:10 +02:00
Wojtek Figat
6479a3d3c6 Fix log spam in task when waiting for task to end 2025-06-18 22:41:42 +02:00
Wojtek Figat
e41c48f9e5 Optimize NavMesh builder when updating a large number of tiles 2025-06-18 22:41:26 +02:00
Wojtek Figat
9cfcbfa9d2 Fix memory leak on recast objects when building NavMesh tile 2025-06-17 23:28:15 +02:00
Wojtek Figat
bcd2b1f0f2 Fix Array::RemoveAt to move element and avoid data copies 2025-06-17 23:27:26 +02:00
6fb8419b3c Disable window flashing on Wayland to fix focus issues 2025-06-17 14:23:20 +03:00
a4272d6ca9 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-17 14:19:46 +03:00
Wojtek Figat
eb6010cba7 Fix BitArray again 2025-06-16 23:20:20 +02:00
Wojtek Figat
bd2add7edd Tweak memory command tip 2025-06-16 23:15:58 +02:00
Wojtek Figat
986693757c Merge remote-tracking branch 'origin/master' into 1.11 2025-06-16 22:46:17 +02:00
Wojtek Figat
5a23060e05 Add GPUTexture.UploadData for changing texture contents via TextureData container 2025-06-16 22:35:50 +02:00
Wojtek Figat
b92c18cf25 Fix missing/incorrect toolchain exception to log only once 2025-06-16 19:10:35 +02:00
Wojtek Figat
6a82eb114d Fix BitArray bit indexing 2025-06-16 19:05:44 +02:00
Wojtek Figat
97b37b3ce4 Add PRAGMA_DISABLE_OPTIMIZATION/PRAGMA_ENABLE_OPTIMIZATION 2025-06-16 18:00:26 +02:00
xxSeys1
bbe54969b0 fix close visject surface was_ flags to properly reset to false 2025-06-16 16:51:30 +02:00
4654117d5e Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-16 17:09:22 +03:00
xxSeys1
8164ce924f fix unfolding to actually work 2025-06-16 15:30:51 +02:00
Wojtek Figat
22911bbc45 Merge branch 'xxSeys1-VisjectCloseButtonFix' 2025-06-16 15:02:37 +02:00
Wojtek Figat
cae2720585 Merge branch 'VisjectCloseButtonFix' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-VisjectCloseButtonFix 2025-06-16 15:02:32 +02:00
Wojtek Figat
90b6293bc2 Add OnPlayEnding to editor modules and windows
#3514
2025-06-16 14:56:35 +02:00
xxSeys1
d110237423 fix GetVisibleItems() to only get visible items 2025-06-16 14:51:29 +02:00
Wojtek Figat
117f890612 Merge branch 'Zode-scenetree-scroll' 2025-06-16 14:50:14 +02:00
Wojtek Figat
a6a2fd2c66 Format code
#3526
2025-06-16 14:48:18 +02:00
Wojtek Figat
a05ca12770 Merge branch 'scenetree-scroll' of https://github.com/Zode/FlaxEngine into Zode-scenetree-scroll 2025-06-16 14:44:54 +02:00
Wojtek Figat
abe7785e94 Merge branch 'xxSeys1-PrefabEditorScrollToSelectionFix' 2025-06-16 14:43:40 +02:00
Wojtek Figat
2cedac8d96 Merge branch 'PrefabEditorScrollToSelectionFix' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-PrefabEditorScrollToSelectionFix 2025-06-16 14:43:34 +02:00
Wojtek Figat
ea854a0f7b Fix potential Grid shader accuracy issues
#3229
2025-06-16 14:41:43 +02:00
Wojtek Figat
d0817809ff Merge branch 'xxSeys1-ContentFinderImprovements' 2025-06-16 14:34:25 +02:00
Wojtek Figat
95f2216f97 Merge branch 'ContentFinderImprovements' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ContentFinderImprovements 2025-06-16 14:32:31 +02:00
Wojtek Figat
7e5edf1b33 Merge branch 'xxSeys1-ClearSearchOnAssetReferenceNavigate' 2025-06-16 14:30:58 +02:00
Wojtek Figat
c649a4f4b2 Merge branch 'ClearSearchOnAssetReferenceNavigate' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ClearSearchOnAssetReferenceNavigate 2025-06-16 14:30:53 +02:00
xxSeys1
cd7233d559 allow the user to unfold folded categories when scrolling with keyboard 2025-06-16 14:10:44 +02:00
6ff260d052 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-16 14:09:29 +03:00
88d2b72822 Update SDL to 3.3.x
Fixes popup focus issues on Linux
2025-06-16 14:09:04 +03:00
Wojtek Figat
3c74b315a8 Merge branch 'Zode-console-hotkey' 2025-06-15 23:47:29 +02:00
Wojtek Figat
f841575378 Merge branch 'console-hotkey' of https://github.com/Zode/FlaxEngine into Zode-console-hotkey 2025-06-15 23:25:09 +02:00
Wojtek Figat
d90377ed62 Merge branch 'Zode-import-export-warnings' 2025-06-15 23:23:22 +02:00
Wojtek Figat
c8d622bda9 Merge branch 'import-export-warnings' of https://github.com/Zode/FlaxEngine into Zode-import-export-warnings 2025-06-15 23:23:18 +02:00
Wojtek Figat
fbf2d8f567 Merge branch 'xxSeys1-ItemListImprovedKeyboardNav' 2025-06-15 23:06:26 +02:00
Wojtek Figat
42687a792c Merge branch 'ItemListImprovedKeyboardNav' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ItemListImprovedKeyboardNav 2025-06-15 22:59:20 +02:00
Wojtek Figat
5c43d35146 Merge branch 'Zode-node-alignment' 2025-06-15 22:32:29 +02:00
Wojtek Figat
c1e1dee975 Merge branch 'node-alignment' of https://github.com/Zode/FlaxEngine into Zode-node-alignment 2025-06-15 22:32:24 +02:00
Wojtek Figat
742d74a2d0 Merge branch 'xxSeys1-ModelSliders' 2025-06-15 21:43:04 +02:00
Wojtek Figat
614ffa70a0 Merge branch 'ModelSliders' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ModelSliders 2025-06-15 21:43:00 +02:00
Wojtek Figat
4b4331fd70 Merge branch 'Zode-visject-better-selection' 2025-06-15 21:28:42 +02:00
Wojtek Figat
e221f7204b Merge branch 'visject-better-selection' of https://github.com/Zode/FlaxEngine into Zode-visject-better-selection 2025-06-15 21:22:27 +02:00
Wojtek Figat
18fa8e1c47 Merge branch 'Zode-particles-sourcecode' 2025-06-15 20:48:22 +02:00
Wojtek Figat
2f02ec52ed Cleanup code
#3546
2025-06-15 20:48:19 +02:00
Wojtek Figat
9464f97e16 Merge branch 'particles-sourcecode' of https://github.com/Zode/FlaxEngine into Zode-particles-sourcecode 2025-06-15 20:45:18 +02:00
Wojtek Figat
54467a4a5e Merge branch 'Zode-layers-matrix-improvements' 2025-06-15 20:41:23 +02:00
Wojtek Figat
3a9e175043 Merge branch 'layers-matrix-improvements' of https://github.com/Zode/FlaxEngine into Zode-layers-matrix-improvements 2025-06-15 20:40:22 +02:00
Wojtek Figat
9dff048cb5 Merge branch 'Tryibion-main-menu-get-add' 2025-06-15 20:36:37 +02:00
Wojtek Figat
f376fd50a9 Merge branch 'main-menu-get-add' of https://github.com/Tryibion/FlaxEngine into Tryibion-main-menu-get-add 2025-06-15 20:36:32 +02:00
Wojtek Figat
e27cf04f91 Merge branch 'Zode-debug-quicktoggle' 2025-06-15 20:32:00 +02:00
Wojtek Figat
648504ceb1 Format code
#3544
2025-06-15 20:31:04 +02:00
xxSeys1
e2f741cab9 adjust model window and animated model slider speeds 2025-06-12 18:45:02 +02:00
Wojtek Figat
766091045b Improve version parsing to share code 2025-06-12 18:21:12 +02:00
xxSeys1
47e1547d29 improve behaviour of visject node cm menu 2025-06-12 18:12:06 +02:00
Wojtek Figat
e2d9452994 Add unified min Clang version 13 for Linux 2025-06-12 18:05:01 +02:00
Wojtek Figat
eadb4411ff Fix crash in GPU Memory profiler if resource went null 2025-06-12 17:35:02 +02:00
Wojtek Figat
bdc87c7bc6 Update min supported version of macOS to 13 and iOS to 15 2025-06-12 17:26:39 +02:00
Wojtek Figat
7606c9ac12 Update minimum CPU arch requirement on Windows to AVX2 with SSE4.2
94.48% support on PC according to Steam Hardware & Software Survey: May 2025 (https://store.steampowered.com/hwsurvey/)
2025-06-12 17:03:19 +02:00
Wojtek Figat
4240646ec7 Update minimum Windows version to 10 (to match .NET 8) 2025-06-12 08:31:32 +02:00
xxSeys1
214ec9f2b1 fix node delete button not checking if the user is performing certain actions on the surface before deleting node 2025-06-12 00:49:39 +02:00
Wojtek Figat
0fa53f860a Add UseLogInRelease to engine config to disable logging in Release builds 2025-06-11 23:35:03 +02:00
Zode
27ac755bbe Make particle emitter editor window source code button disable itself is no source code is available 2025-06-11 23:15:11 +03:00
Wojtek Figat
8ec138399a Add higher level streaming time budget in frame based on idle time 2025-06-11 18:40:35 +02:00
Wojtek Figat
5b6859a66f Add time slicing to Deserialization stage of async scenes loading to avoid hitching
#3261
2025-06-11 18:40:06 +02:00
Zode
bed1f6e9cc Make tag editor expand all if holding shift while clicking the ... button 2025-06-11 19:06:23 +03:00
Zode
00055ef663 Make tool strip buttons more responsive by also reaction to double left clicks 2025-06-11 17:47:27 +03:00
Zode
aa59a6faf7 Extract function to lessen repeat code for debug group buttons, add shift functionality to quick toggle others. 2025-06-11 17:46:37 +03:00
Wojtek Figat
e9835766bc Add red color to Tracy profiler zones that cause CPU waiting to improve profiling 2025-06-11 14:56:43 +02:00
Wojtek Figat
d6eb647d59 Optimize async scene loading to run in separate stages with time-slicing 2025-06-11 14:33:47 +02:00
Wojtek Figat
b50f3fcb64 Refactor level actions to support time budget and time slicing 2025-06-11 00:01:46 +02:00
Wojtek Figat
d6b4992991 Optimize actors registration in SceneRendering to track free items 2025-06-10 20:08:20 +02:00
Chandler Cox
fc561b5ec5 Merge pull request #2 from xxSeys1/noScrollOnScriptsReload
Dont scroll to node after scripts compilation
2025-06-10 10:03:06 -05:00
xxSeys1
dacc0068e0 dont scroll to node after scripts compilation 2025-06-10 16:49:30 +02:00
Zode
e7d2025010 Merge less flicker pr, and snatch the badge
Co-authored-by: Zode <jonzqzode@gmail.com>
Co-authored-by: Saas <kaktusreiniger@gmail.com>
2025-06-10 16:45:02 +03:00
xxSeys1
b418ab5275 reduce flickering in highlights and boxes 2025-06-10 14:58:31 +02:00
Zode
c1e782bb32 Add hotkey to quick focus debug console input 2025-06-09 23:34:02 +03:00
Wojtek Figat
cfd2f42b0c Optimize managed memory allocations in Editor profiler 2025-06-09 22:06:49 +02:00
Chandler Cox
e1a2a36978 Add GetOrAddButton utility for MainMenu. 2025-06-09 15:02:43 -05:00
xxSeys1
793bc33b2f fix right clicking on item reset search and scroll 2025-06-09 18:40:33 +02:00
xxSeys1
2109a2d261 update content finder popup to wrap on keyboard navigation
- Fixes auto scroll
- Make it wrap
- Add pressing backspace to focus search bar and select all text
2025-06-09 18:40:12 +02:00
Wojtek Figat
89c7f4b0a3 Fix ManagedDictionary cache to be cleared on hot-reload 2025-06-09 17:19:36 +02:00
Wojtek Figat
d7ff9fdade Optimize editor profiler native allocations when capturing data 2025-06-09 15:23:31 +02:00
Zode
9e50a39ebf Add define guards so that the messagebox only appears in editor builds 2025-06-09 16:19:39 +03:00
Zode
7fc564a0ac Pop error box on lightmap UV generation also 2025-06-09 15:07:52 +03:00
Zode
8dfb564fb3 Add messagebox to windows import too 2025-06-09 15:04:34 +03:00
Zode
f8daff273a Add import & export warning messageboxes. 2025-06-09 14:56:54 +03:00
xxSeys1
112e728465 fix scroll to node on selection in prefab editor 2025-06-09 13:56:41 +02:00
Wojtek Figat
057ec9d41e Anothher fix 2025-06-09 10:48:02 +02:00
Wojtek Figat
7fa4efcac5 Fix compilation in Release 2025-06-09 10:17:51 +02:00
Wojtek Figat
6547e7ee9c Fix compilation with Clang 2025-06-08 23:58:33 +02:00
Wojtek Figat
907c593671 Fix typos in doc comments 2025-06-08 19:47:09 +02:00
29868531ad SDL workaround for window size and position not updating
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-06-08 18:57:57 +03:00
95dfb6fdc6 Reduce minimum default window size for CommandLineBox popup 2025-06-08 18:57:12 +03:00
Zode
9c9d560ce5 Add hotkeys to visject formatting 2025-06-08 03:32:51 +03:00
Zode
f1945552ab Add horizontal and vertical distribution 2025-06-08 02:42:28 +03:00
Wojtek Figat
65ab42158d Update engine version 2025-06-08 00:58:39 +02:00
Wojtek Figat
99841e2e8d Fix crash when using invalid node index in skinned mesh 2025-06-08 00:58:31 +02:00
Wojtek Figat
73c30d3d89 Optimize asset references to support direct registration to reduce Delegate memory allocations and overhead 2025-06-08 00:58:15 +02:00
Zode
ecd5559aad Clean up a bit code after moving it around. 2025-06-08 00:41:02 +03:00
Zode
1fa83639c2 Fix update order inconsistencies between machines by exposing an action for when defered layout happens. 2025-06-08 00:38:59 +03:00
Zode
568719b615 Fix scroll issue caused by tree's defered layout update 2025-06-07 23:21:41 +03:00
Zode
74000fa766 Expand tree if necessary, so the selected node will be shown 2025-06-07 22:53:07 +03:00
Zode
1d63067614 Add ability to do additive and subtractive selections in visject surfaces using ctrl and shift during selection. 2025-06-07 21:04:59 +03:00
xxSeys1
85fd1389db clear content panel search when selecting asset picker asset 2025-06-07 18:17:40 +02:00
xxSeys1
cce042045e wrap scrolling items with arrow keys and simplify scrolling logic 2025-06-07 17:34:01 +02:00
Zode
53e3cee196 Scroll selected to view when emptying out search box 2025-06-07 17:15:54 +03:00
Zode
6ee3b23261 Add highlighting to layers matrix editor to improve UX 2025-06-07 16:57:28 +03:00
Zode
1a77ba4552 Add node alignment formatting options to visject 2025-06-07 13:15:39 +03:00
Wojtek Figat
bffb175a9b Code fixes 2025-06-07 01:25:22 +02:00
Wojtek Figat
125a973ff2 Rename Prefetch to MemoryPrefetch 2025-06-06 22:55:14 +02:00
Wojtek Figat
462f75abd0 Optimize memory allocation when reading animated model pose by cloth 2025-06-06 22:41:48 +02:00
Wojtek Figat
d95cd2f0be Optimize memory alloc on Animated Model init 2025-06-06 22:41:29 +02:00
Wojtek Figat
091f76bbf2 Add more improvements to usability of memory profiler 2025-06-06 22:40:43 +02:00
Wojtek Figat
e8b60060ab Fix memory profiler thread-local storage to avoid dynamic mem alloc due to recursive call 2025-06-06 14:52:27 +02:00
Wojtek Figat
cd637e8a7a Add more memory profiling coverage 2025-06-06 14:38:22 +02:00
Wojtek Figat
9d8e75caa3 Fix various code to improve quality 2025-06-06 11:19:32 +02:00
Wojtek Figat
eee4e55cf0 Fix debug shapes change 2025-06-05 22:26:45 +02:00
Wojtek Figat
0670c0bbd3 Fix compilation warnings 2025-06-05 18:32:36 +02:00
Wojtek Figat
f462a2187f Merge branch 'master' into 1.11 2025-06-05 18:03:17 +02:00
Wojtek Figat
c2cbaeed30 Add option to change Character Controller capsule origin to start at feet location 2025-06-05 17:48:07 +02:00
Wojtek Figat
e982a23ed3 Add CharacterController.Resize for quick crouching implementation for characters 2025-06-05 15:07:51 +02:00
Wojtek Figat
f6feae5cf2 Optimize collider cached scale 2025-06-05 15:06:03 +02:00
Wojtek Figat
ba75fd5882 Fix crash regression when textbox watermak is null 2025-06-05 12:47:45 +02:00
Wojtek Figat
1eaf40f2f7 Fix changing CharacterController center at runtime to maintain actor placement 2025-06-05 12:40:47 +02:00
Wojtek Figat
fe98a23cb4 Merge branch 'GoaLitiuM-update_tracy' 2025-06-05 00:01:04 +02:00
Wojtek Figat
77bf03128e Merge branch 'update_tracy' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-update_tracy 2025-06-04 23:53:32 +02:00
Wojtek Figat
8f49a492d8 Fix duplicating json assets to properly remap object IDs
#3441
2025-06-04 23:49:19 +02:00
8df3999f85 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-04 19:30:30 +03:00
Chandler Cox
dd4bb2f7f1 Dont scroll to node when play is starting or ending. 2025-06-04 11:16:01 -05:00
Wojtek Figat
496856d12e Add shader header proxy for easy .hlsl files creation within Editor 2025-06-04 00:12:43 +02:00
Wojtek Figat
e97d683545 Fix regression from #3389 2025-06-03 23:37:37 +02:00
Wojtek Figat
ae44d47043 Merge branch 'GoaLitiuM-float_equality' 2025-06-03 18:08:12 +02:00
Wojtek Figat
8b88def9d0 Revert some changes from #3389 that are not relevant for world units 2025-06-03 17:43:01 +02:00
Wojtek Figat
fa97229830 Merge branch 'float_equality' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-float_equality 2025-06-03 17:26:12 +02:00
Wojtek Figat
1946caac6e Fix compilation with Large Worlds 2025-06-03 17:26:04 +02:00
Wojtek Figat
6f5308126b Fix focus issue after closing context menu 2025-06-03 14:52:45 +02:00
Wojtek Figat
6a0c734cec Fix Visject surface select with Control to toggle selection of the node 2025-06-03 14:51:31 +02:00
Wojtek Figat
13b8863f0c Fix some material nodes height 2025-06-03 14:51:04 +02:00
Wojtek Figat
f2aaad0048 Add viewport icons scale relative to the distance and editor control over it
#2944 #2644
2025-06-03 14:50:47 +02:00
Wojtek Figat
55b441e9fa Fix transparency-related material options when using material with deferred shading 2025-06-03 12:55:54 +02:00
Wojtek Figat
6fece4ca38 Fix automatic collision importing from mode to remove unused material slots
#3475
2025-06-03 12:48:31 +02:00
Wojtek Figat
2fd9b4a62a Fix loading models with no meshes 2025-06-03 12:28:17 +02:00
Wojtek Figat
077f7a3cd1 Add PositionFormat and TexCoordFormat to model import option for mesh data encoding 2025-06-03 11:18:03 +02:00
Wojtek Figat
7da69f18d4 Add button to quickly jump into Localized String Table that contains it
#3301
2025-06-02 22:01:06 +02:00
6c63c2f650 Update tracy to 0.12.0 2025-06-02 20:00:06 +03:00
149b189629 Update SDL to 3.2.16 2025-06-02 19:23:34 +03:00
Wojtek Figat
fd8a8b5a4d Fix missing default value of localized string in editor 2025-06-02 18:02:34 +02:00
b1fd86e6b5 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-02 18:15:16 +03:00
5e8fdf879d Fix logging in gamepad related events 2025-06-02 18:15:10 +03:00
Wojtek Figat
fa89e710d8 Fix Terrain shader error when using Position Offset
#3479
2025-06-02 15:05:20 +02:00
Wojtek Figat
b51ba58063 Fix crash on invalid particle data to be a soft check instead 2025-06-02 14:56:51 +02:00
Wojtek Figat
057489e5b9 Fix Output Log scroll when using search
#3442 #3456
2025-06-02 14:42:18 +02:00
Wojtek Figat
5bae695ae9 Merge branch 'Tryibion-fix-unpause-no-game-win' 2025-06-02 14:05:23 +02:00
Wojtek Figat
5b3ed1fbc3 Merge branch 'fix-unpause-no-game-win' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-unpause-no-game-win 2025-06-02 14:05:19 +02:00
Wojtek Figat
f5092e5262 Merge branch 'Tryibion-skip-setting-prefab-root-name' 2025-06-02 14:03:50 +02:00
Wojtek Figat
3bd6160c3b Merge branch 'skip-setting-prefab-root-name' of https://github.com/Tryibion/FlaxEngine into Tryibion-skip-setting-prefab-root-name 2025-06-02 14:03:47 +02:00
Wojtek Figat
1d0a0a409d Fix panel scroll bars update to be performed once again if controls are gets changed during layout
#3470 #3486
2025-06-02 13:40:27 +02:00
Wojtek Figat
eb90ab84f2 Fix performing layout after changing selected tab
#3467 #3487
2025-06-02 13:17:51 +02:00
Wojtek Figat
6f37525674 Merge branch 'alsed-master' 2025-06-02 12:39:17 +02:00
Wojtek Figat
eeb8a7ea41 Merge branch 'master' of https://github.com/alsed/FlaxEngine into alsed-master 2025-06-02 12:39:13 +02:00
Wojtek Figat
df0b571c50 Merge branch 'xxSeys1-UnifyZoomBehavior' 2025-06-02 12:37:41 +02:00
Wojtek Figat
ec22427acd Merge branch 'UnifyZoomBehavior' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-UnifyZoomBehavior 2025-06-02 12:25:18 +02:00
Wojtek Figat
6c499e877f Fix prefab diff in Editor on mesh reference 2025-06-02 11:50:10 +02:00
Wojtek Figat
4d9407e4e9 Merge code on properties objects locking to use the same path for prefab and scene properties panels 2025-06-02 11:03:16 +02:00
Wojtek Figat
28c70f5078 Fix some editor UI
#3460 #3491
2025-06-02 11:00:33 +02:00
Wojtek Figat
14806a1ac7 Merge branch 'Tryibion-add-root-tree-line-option' 2025-06-02 10:19:35 +02:00
Wojtek Figat
1ebb3e67d6 Merge branch 'add-root-tree-line-option' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-root-tree-line-option 2025-06-02 10:17:34 +02:00
Wojtek Figat
991cdbb9a0 Merge branch 'Tryibion-fix-node-filter-prefab' 2025-06-02 10:16:28 +02:00
Wojtek Figat
278b177c46 Merge branch 'fix-node-filter-prefab' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-node-filter-prefab 2025-06-02 10:16:25 +02:00
Wojtek Figat
0630b6257a Merge branch 'Tryibion-better-prefab-dif-name' 2025-06-02 09:30:51 +02:00
Wojtek Figat
f86d9c47b7 Merge branch 'better-prefab-dif-name' of https://github.com/Tryibion/FlaxEngine into Tryibion-better-prefab-dif-name 2025-06-02 09:30:46 +02:00
Wojtek Figat
ae2088bb9d Fix Android NDK version parsing when using beta build
#3504
2025-06-02 00:06:13 +02:00
Wojtek Figat
9340c42f2b Merge branch 'xxSeys1-CrammedGradingFixed' 2025-06-01 23:54:40 +02:00
Wojtek Figat
8d7dfd5946 Merge branch 'CrammedGradingFixed' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-CrammedGradingFixed 2025-06-01 23:53:15 +02:00
Wojtek Figat
894cb273aa Merge branch 'xxSeys1-WindowShortcuts' 2025-06-01 23:32:43 +02:00
Wojtek Figat
2996e0c53c Merge branch 'WindowShortcuts' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-WindowShortcuts 2025-06-01 23:26:46 +02:00
Wojtek Figat
79ce82d8a0 Merge branch 'Weyzu-fix_dotnet_version_detection' 2025-06-01 22:43:56 +02:00
Wojtek Figat
3c8e59c114 Merge branch 'fix_dotnet_version_detection' of https://github.com/Weyzu/FlaxEngine into Weyzu-fix_dotnet_version_detection 2025-06-01 22:43:53 +02:00
Wojtek Figat
1493571810 Merge branch 'GoaLitiuM-fix_tree_performance' 2025-06-01 21:59:13 +02:00
Wojtek Figat
a613d89f47 Merge branch 'fix_tree_performance' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-fix_tree_performance 2025-06-01 21:55:58 +02:00
Wojtek Figat
5471c59d5f Merge branch 'xxSeys1-Atan2DefaultValueFix' 2025-06-01 21:39:16 +02:00
Wojtek Figat
ac42223f9e Merge branch 'Atan2DefaultValueFix' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-Atan2DefaultValueFix 2025-06-01 21:39:03 +02:00
Wojtek Figat
c21c9c13ad Merge branch 'xxSeys1-gravityTypoFix' 2025-06-01 21:23:42 +02:00
Wojtek Figat
8251509607 Merge branch 'gravityTypoFix' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-gravityTypoFix
# Conflicts:
#	Source/Engine/Physics/PhysicsSettings.h
2025-06-01 21:23:35 +02:00
xxSeys1
3083e3f611 fix wrong unit in physics settings 2025-06-01 16:04:30 +02:00
xxSeys1
66add1f3bd fix missing whitespaces 2025-06-01 16:01:55 +02:00
Wojtek Figat
b8a680df57 Merge branch 'xxSeys1-TerrainLayerWeightNodeWidth' 2025-06-01 15:55:10 +02:00
Wojtek Figat
e969b7fffb Merge branch 'TerrainLayerWeightNodeWidth' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-TerrainLayerWeightNodeWidth 2025-06-01 15:55:07 +02:00
Wojtek Figat
5d9657781a Merge branch 'Weyzu-fix_timeouts_in_task_wait' 2025-06-01 15:51:07 +02:00
Wojtek Figat
2cd03787cd Merge branch 'fix_timeouts_in_task_wait' of https://github.com/Weyzu/FlaxEngine into Weyzu-fix_timeouts_in_task_wait 2025-06-01 15:50:03 +02:00
Wojtek Figat
619c5ac3b0 Fix unit of gravity in doc comment
#3509
2025-06-01 15:45:27 +02:00
Wojtek Figat
89baa91552 Don't sue 2025-06-01 09:20:11 +02:00
Wojtek Figat
83b3b1af76 Fix terrain collision debug draw flickering when moving camera in Large Worlds
#3260
2025-06-01 09:19:49 +02:00
Wojtek Figat
19148f21ac Merge branch 'Tryibion-fix-anim-preview-bounds' 2025-05-31 23:59:22 +02:00
Wojtek Figat
2da8e392db Merge branch 'fix-anim-preview-bounds' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-anim-preview-bounds 2025-05-31 23:58:54 +02:00
Wojtek Figat
a812b8b108 Merge branch 'xxSeys1-ViewFlagAndDebugModeShortcuts' 2025-05-31 23:56:06 +02:00
Wojtek Figat
3dc96352e6 Merge branch 'ViewFlagAndDebugModeShortcuts' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ViewFlagAndDebugModeShortcuts 2025-05-31 23:51:10 +02:00
Wojtek Figat
c2b590d2cf Merge branch 'Tryibion-engine-play-mode' 2025-05-31 23:37:16 +02:00
Wojtek Figat
842d6969fe Merge branch 'engine-play-mode' of https://github.com/Tryibion/FlaxEngine into Tryibion-engine-play-mode 2025-05-31 23:37:11 +02:00
Wojtek Figat
0f3044ae72 Optimize debug drawing of terrain shape in Physics Colliders view mode
#3469
2025-05-31 23:27:51 +02:00
Wojtek Figat
11dec8e868 Fix incorrectly rendered transparency in Physics Colliders view mode
#3474
2025-05-30 15:51:35 +02:00
Wojtek Figat
d6b1f06721 Fix deprecated asset saving to skip temporary or virtual assets 2025-05-30 15:31:10 +02:00
Wojtek Figat
14fcc593c7 Fix various margins and spacings between UI elements in Editor to be consistent 2025-05-30 15:28:56 +02:00
Wojtek Figat
08ed5ae483 Add SCOPE_EXIT macro and use it in prefab tests to cleanup assets on test fail 2025-05-30 11:16:17 +02:00
Wojtek Figat
b065e6c989 Fix regression from 294dd3d363 2025-05-30 11:15:47 +02:00
Wojtek Figat
372a23cf3a Merge branch 'Tryibion-focus-actor-no-box' 2025-05-30 00:47:18 +02:00
Wojtek Figat
4721e8109f Merge branch 'focus-actor-no-box' of https://github.com/Tryibion/FlaxEngine into Tryibion-focus-actor-no-box 2025-05-30 00:47:05 +02:00
Wojtek Figat
b58aaccc53 Fix missing Physics Colliders view if Debug Draw is disabled
#3498
2025-05-30 00:46:09 +02:00
Wojtek Figat
294dd3d363 Fix json guid parsing to check for correct hex characters
#3476
2025-05-30 00:42:55 +02:00
Wojtek Figat
e00f552baf Fix missing xml comment 2025-05-30 00:39:20 +02:00
Wojtek Figat
8eff098850 Fix Linux build 2025-05-28 04:30:08 +02:00
Wojtek Figat
4fe9fdded6 Optimize redundant string allocation in managed binary module unload 2025-05-28 04:10:47 +02:00
Wojtek Figat
03d52d4eb9 Add support for building engine without logging 2025-05-28 04:05:12 +02:00
Wojtek Figat
ab61ed5a37 Add more memory profiling insights and groups 2025-05-28 04:03:44 +02:00
Wojtek Figat
72ee80242d Add integration with Tracy profiler to plot main memory categories 2025-05-26 05:37:53 +02:00
Wojtek Figat
9dc4dbc6d7 Add more memory profiler categories 2025-05-25 18:38:07 +02:00
Wojtek Figat
a74c5e7943 Another fix for iOS build 2025-05-25 18:01:30 +02:00
Wojtek Figat
8f9fa6995e Fix compilation issues 2025-05-25 17:40:00 +02:00
Wojtek Figat
98e59450f1 Add freeing managed assembly memory on reload/unload 2025-05-25 17:39:51 +02:00
Wojtek Figat
8c62f1120f Optimize dynamic memory allocations for managed runtime interop collections with a new Arena Allocation 2025-05-25 17:39:20 +02:00
Wojtek Figat
9aaba955d0 Fix profiler tables to use column headers aligned to center 2025-05-25 02:04:56 +02:00
Wojtek Figat
410ec0465c Optimize CSharp scripting runtime to use arena allocator per-assembly 2025-05-25 02:04:16 +02:00
Chandler Cox
ae9ded504d Add utility for if in play mode that returns true for shipped applications. 2025-05-23 23:21:45 -05:00
Wojtek Figat
f9cb4ddae2 Add new Arena Allocator for optimized dynamic memory allocations with a shared lifetime 2025-05-24 05:08:32 +02:00
Chandler Cox
9753e579c1 Check for Game window before usage to avoid errors in trying to unplay. 2025-05-23 18:16:48 -05:00
Chandler Cox
2e996c8e91 Remove redundant call to scene. Fixes error in prefab node filtering. 2025-05-23 17:11:45 -05:00
Chandler Cox
545a43de32 Add drawing root tree lines except for in scene and prefab tree. 2025-05-23 16:50:55 -05:00
Chandler Cox
e606c35093 Add node tree to show changes to whole prefab. 2025-05-23 16:23:22 -05:00
Chandler Cox
21ae2d5d40 Focus Actor position if no Actor bounding box. 2025-05-23 14:44:53 -05:00
Chandler Cox
4649298605 Dont allow setting prefab root name from scene instance. 2025-05-23 14:06:21 -05:00
Chandler Cox
ae9622d271 Re-add colors back in for nodes. 2025-05-23 13:29:05 -05:00
Chandler Cox
4366976015 Add better prefab diff viewing naming for actors 2025-05-23 13:27:01 -05:00
Chandler Cox
5b2a966ac6 Fix animation preview bounds scale. 2025-05-23 10:37:30 -05:00
Wojtek Figat
bb855e2663 Add suport for Tracy profiler on Mac 2025-05-22 05:34:36 +02:00
Wojtek Figat
d24f9d1e1e Add warning when using memory profiler without enabled on startup 2025-05-22 05:18:56 +02:00
Wojtek Figat
c1b1f4afc4 Add process memory stats for Apple platforms 2025-05-22 04:49:48 +02:00
Wojtek Figat
c639a3103c Add memory profiling events to the main areas of the engine 2025-05-22 04:47:01 +02:00
Wojtek Figat
32bc73610f Fix debug command type detection when it's used with argument 2025-05-22 04:45:12 +02:00
Wojtek Figat
66dcfafa2e Fix Vulkan descriptor sets pooling 2025-05-22 04:42:01 +02:00
Wojtek Figat
9215f2662f Add missing memory alloc profiling for virtual pages 2025-05-22 04:41:01 +02:00
Wojtek Figat
2dc404cbd3 Add new memory profiler 2025-05-22 04:40:32 +02:00
xxSeys1
59308df250 add shortcuts for viewflags and debug view modes 2025-05-18 16:28:16 +02:00
Wojtek Figat
9ba1c4c338 Fix typo in ec2957bf38 2025-05-16 20:24:01 +02:00
Wojtek Figat
ec2957bf38 Fix memory leak on sequential mesh buffers update
#3449
2025-05-16 20:23:16 +02:00
Wojtek Figat
8bb5655b2f Fix error when using invalid camera ray 2025-05-16 20:22:52 +02:00
xxSeys1
c24ecaaab1 fix crammed color grading editor value boxes 2025-05-15 19:27:48 +02:00
xxSeys1
483a33996f fix atan2 to use default box value 2025-05-15 11:43:38 +02:00
Wiktor Żurawik
6be8158209 Fix timeout calculation in Task::Wait 2025-05-13 23:10:57 +02:00
Wojtek Figat
8e7fcd3cad Merge branch 'xxSeys1-ItemsListNoSelectionAutoFirst' 2025-05-13 20:16:56 +02:00
Wojtek Figat
a792a8a533 Merge branch 'ItemsListNoSelectionAutoFirst' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ItemsListNoSelectionAutoFirst 2025-05-13 20:16:51 +02:00
Wojtek Figat
25d8c4645e Merge branch 'GoaLitiuM-fontlinecache_alloc' 2025-05-13 20:09:08 +02:00
Wojtek Figat
64c552d69d Merge branch 'fontlinecache_alloc' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-fontlinecache_alloc 2025-05-13 20:06:31 +02:00
Wojtek Figat
fafa400db0 Merge branch 'xxSeys1-documentationInReadme' 2025-05-13 19:59:21 +02:00
xxSeys1
0b20a5342e add info on docs source being available to readme 2025-05-13 16:00:16 +02:00
xxSeys1
fa4e56a32a unify zoom behavior when zooming in and out 2025-05-12 20:26:33 +02:00
xxSeys1
212bd7a011 adjust width of terrain related nodes and node elements 2025-05-12 20:11:08 +02:00
alsed
943864004f Update README.md
removed spirv-tools, since Flax build it during compilation.
2025-05-09 15:17:20 -04:00
Wiktor Żurawik
8ce4d94a96 Refactor .NET version detection error reporting 2025-05-09 17:04:41 +02:00
xxSeys1
6be193bfbf fix tooltip 2025-05-09 11:39:40 +02:00
Wojtek Figat
5d3947f117 Merge branch 'xxSeys1-improvedImportPath' 2025-05-08 14:38:25 +02:00
Wojtek Figat
c7bb7be20f Merge branch 'improvedImportPath' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-improvedImportPath 2025-05-08 14:38:20 +02:00
Wojtek Figat
f74b96bcb6 Merge branch 'xxSeys1-DisableCreateButton' 2025-05-08 14:32:54 +02:00
Wojtek Figat
cecfea1ecf Merge branch 'DisableCreateButton' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-DisableCreateButton 2025-05-08 14:32:48 +02:00
Wojtek Figat
09ce2b5a6d Merge branch 'xxSeys1-RigidbodyInfoGroup' 2025-05-08 14:29:12 +02:00
Wojtek Figat
2f9cdadb11 Merge branch 'RigidbodyInfoGroup' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-RigidbodyInfoGroup 2025-05-08 14:29:07 +02:00
Wojtek Figat
e218ce2d85 Merge branch 'Tryibion-fix-group-scene' 2025-05-08 14:28:13 +02:00
Wojtek Figat
5ec6993342 Merge branch 'fix-group-scene' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-group-scene 2025-05-08 14:28:01 +02:00
xxSeys1
87787cb5bf replace Todo doc comments 2025-05-05 15:15:32 +02:00
xxSeys1
5b618b4f31 add icons to more commonly used editor windows 2025-05-05 13:24:21 +02:00
xxSeys1
08a86066d0 add window shortcuts 2025-05-05 13:24:01 +02:00
xxSeys1
388eb654a5 update doc comment to reflect get only parameter 2025-05-05 09:58:36 +02:00
xxSeys1
d8059c3db3 disable create file dialog create button if asset can't be created 2025-05-04 20:08:12 +02:00
559d17e6c3 Reduce allocations in text rendering related functions 2025-05-04 15:05:46 +03:00
xxSeys1
dfe177447c add auto selecting first item in item list context menu if no selection 2025-05-03 22:11:38 +02:00
Chandler Cox
2a5aed6c15 Fix trying to add scene to actor group. 2025-05-02 21:58:02 -05:00
xxSeys1
f5ad8566eb make path creation method more generalized 2025-05-02 13:29:01 +02:00
7c5628d47e Fix crash caused by conflicting tracy DbgHelp lock helper names 2025-05-02 14:20:18 +03:00
9645008460 Update tracy to 0.11.1 2025-05-02 14:20:18 +03:00
12dbf09164 Fix tests 2025-05-02 14:19:55 +03:00
f09fd7ad34 Use exact value comparison in caching related functions
(cherry picked from commit 9d7c6b26422e127719836944d8d473910190e7d4)
2025-05-02 14:19:55 +03:00
8986290b12 Use exact component value equality checks in equality comparisons
(cherry picked from commit 2cddf3de97943844512b2d84aa6be122c6f0d409)
2025-05-02 14:19:54 +03:00
9a4d3a56a3 Fix slow Tree expansion/collapsion with large amount of tree nodes 2025-05-02 13:31:13 +03:00
xxSeys1
b0048d6540 add margin around info label 2025-05-01 22:32:28 +02:00
xxSeys1
b1b36ea1a3 move rigidbody info to dedicated info group in Properties Panel 2025-05-01 22:29:37 +02:00
xxSeys1
e568e6e17b improve import path ui 2025-05-01 19:15:43 +02:00
Wojtek Figat
af955ba418 Merge branch 'xxSeys1-prefabSearchOperatorTooltip' 2025-04-29 09:22:00 +02:00
Wojtek Figat
a56e2e7b1e Merge branch 'prefabSearchOperatorTooltip' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-prefabSearchOperatorTooltip 2025-04-29 09:21:55 +02:00
Wojtek Figat
a0cdb08893 Merge branch 'Zode-fix-profiler-memory' 2025-04-29 09:17:37 +02:00
Wojtek Figat
fbb829a915 Merge branch 'fix-profiler-memory' of https://github.com/Zode/FlaxEngine into Zode-fix-profiler-memory 2025-04-29 09:17:30 +02:00
Wojtek Figat
5790da6167 Merge branch 'Tryibion-fix-input-edit-ui' 2025-04-29 09:15:53 +02:00
Wojtek Figat
c6e4fbd966 Merge branch 'fix-input-edit-ui' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-input-edit-ui 2025-04-29 09:15:04 +02:00
Wojtek Figat
101ea44051 Merge branch 'Tryibion-fix-skel-mask-create' 2025-04-29 09:12:24 +02:00
Wojtek Figat
d6c6936f6d Merge branch 'fix-skel-mask-create' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-skel-mask-create 2025-04-29 09:12:19 +02:00
Wojtek Figat
4929e8172c Merge branch 'Tryibion-fix-scrollbar-drag' 2025-04-29 09:10:54 +02:00
Wojtek Figat
8c83156133 Merge branch 'fix-scrollbar-drag' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-scrollbar-drag 2025-04-29 09:09:42 +02:00
Wojtek Figat
d587921a83 Merge branch 'Tryibion-fix-add-blend-tooltip-spell' 2025-04-29 09:05:50 +02:00
Zode
6fe6ba20fb Fix profiler memory propagation 2025-04-26 21:40:12 +03:00
xxSeys1
2ea3cde203 add search operator tooltip to prefab editor search bar
somewhat of a follow up to #3300
2025-04-26 16:33:49 +02:00
Chandler Cox
059fe98c67 Fix scroll bars not updating when dragging. 2025-04-26 07:38:18 -05:00
Chandler Cox
1ab05b620a Another small grammer mistake. 2025-04-26 07:08:49 -05:00
Chandler Cox
4b387d040d Fix spelling on Additive Blend node tooltip. 2025-04-26 07:07:27 -05:00
Chandler Cox
9d527ab4a6 Remove editable from check for enabling inputs for game window GUI. 2025-04-25 20:36:53 -05:00
Chandler Cox
bbc221086a Fix GUI input when edit GUI option is false and game is being played. 2025-04-25 17:55:07 -05:00
Chandler Cox
e5b7e58a07 Fix newly created skeleton mask from being able to be opened. 2025-04-25 17:11:36 -05:00
alsed
cfef93134e Added Fedora instructions in Readme 2025-04-22 17:16:12 -04:00
84ada18299 Fix unlock mouse hotkey not unlocking CursorLockMode.Locked cursor 2025-04-21 23:13:23 +03:00
635fe8017e Fix EditorViewport buttons activating items on scene 2025-04-21 23:13:23 +03:00
834380ff05 Cleanup 2025-04-21 23:13:23 +03:00
dd65fc2289 Implement Wayland text clipboard data handling 2025-04-21 23:13:23 +03:00
86125bb625 Add support for VK_EXT_metal_surface extension 2025-04-21 23:13:23 +03:00
09a9d8b380 Update volk to 1.4.304 2025-04-21 23:13:23 +03:00
86b223ec93 Fix mouse relative mode activation triggering mouse move events on Mac 2025-04-21 23:13:23 +03:00
78f6080321 Initial support for building and running SDL platform on macOS 2025-04-21 23:13:23 +03:00
c7be6f6e0e Fix VC++ project file building on macOS Rider 2025-04-20 01:14:51 +03:00
c40c31fbb7 Reduce lock usage during window events 2025-04-19 21:14:13 +03:00
f5fbc1e32d Fix handling of WindowsManager locks 2025-04-19 21:14:13 +03:00
0a20378acd Handle Wayland dragging actions ending prematurely 2025-04-19 21:14:12 +03:00
d4e87877b6 Fix editor viewport activating while dragging a window 2025-04-19 21:14:12 +03:00
7eb7236b8a Fix occluded or hidden windows causing the engine to freeze on Wayland 2025-04-19 21:14:11 +03:00
dc0e4ffce2 Allow context menu to show when activating scene tree with right click 2025-04-19 21:14:11 +03:00
86fe93943d Fix crash when relative mode was left active on removed window 2025-04-19 21:14:10 +03:00
3258113ef8 Ensure mouse position is up-to-date during button down events 2025-04-19 21:14:10 +03:00
ebf3999cfe Fix rubber band selector activating outside of the viewport
This usually happens while trying to drag the window from window handle
2025-04-19 21:14:09 +03:00
a1ccbbb5b9 Use sensible window minimum size limits in editor windows 2025-04-19 21:14:09 +03:00
35072c40d8 Fix build on Linux 2025-04-19 21:14:08 +03:00
5c51021388 Fix merge 2025-04-19 21:14:08 +03:00
95fd527515 Apply drag and drop styling on refactored WindowDragHelper
Reapplies changes from commit 38b00f458c
2025-04-19 21:14:07 +03:00
113d851cea Fix cursor escaping constrained area when initially outside on Windows 2025-04-19 21:14:07 +03:00
72f0c460f9 Refix dragged maximized window generating wrong mouse position events 2025-04-19 21:14:06 +03:00
13ddd15b44 Focus viewports earlier to fix CursorLockMode not always activating 2025-04-19 21:14:06 +03:00
c9e24aaf5f Fix documentation generation 2025-04-19 21:14:05 +03:00
68c0ac0ffc Fix cursor locking bounds calculation 2025-04-19 21:14:05 +03:00
bebda275a9 Fix crash when Game viewport was hidden 2025-04-19 21:14:04 +03:00
287eaae850 Fix X11 external drag and drop not releasing consistently 2025-04-19 21:14:04 +03:00
7e59c3b9a7 Fix restoring locked cursor state when window gains focus again 2025-04-19 21:14:03 +03:00
38658a5b8c Fix CursorLockMode.Locked not working 2025-04-19 21:14:02 +03:00
88c75b8672 Fix dragged maximized window generating wrong mouse position events 2025-04-19 21:14:02 +03:00
17ab1e6830 Fix window handle clicking to not restore window from maximized state 2025-04-19 21:14:01 +03:00
1f45110e5f Fix rubber band selector activating when using Alt-key to orbit 2025-04-19 21:14:01 +03:00
5401166a07 Fix error when entering playmode while holding right mouse button 2025-04-19 21:14:00 +03:00
bfa8188782 Fix accepting drag and drop for files in Wayland 2025-04-19 21:14:00 +03:00
e777a71784 Fix error while dragging files around Content window 2025-04-19 21:13:59 +03:00
c13e91a0d0 Release rubber band selection when viewport starts controlling the view 2025-04-19 21:13:59 +03:00
aac5d57352 Update SDL to 3.2.10 2025-04-19 21:13:58 +03:00
ceca13c7b6 Avoid showing tooltips in inactive windows 2025-04-19 21:13:58 +03:00
2905470330 Update SDL3 to 3.2.4 2025-04-19 21:13:57 +03:00
2c17033822 Fix window dragging when not supported by Wayland compositor
(cherry picked from commit 3554747a67)
2025-04-19 21:13:57 +03:00
0a4cb9e9b1 Show current display server in Editor window tooltip
(cherry picked from commit 62968dd437)
2025-04-19 21:13:56 +03:00
096651f4c1 Properly mark floating windows with transparency support
(cherry picked from commit c660fac524)
2025-04-19 21:13:56 +03:00
275a08506b Enable transparency support in Vulkan swapchains
(cherry picked from commit 431a69e357)
2025-04-19 21:13:55 +03:00
4cd61cb381 Fix compilation for game builds
(cherry picked from commit f4fcc07288)
2025-04-19 21:13:54 +03:00
9ad1147581 Fix cloning SDL repository 2025-04-19 21:13:54 +03:00
35e09def1b Fix text input not working on X11 2025-04-19 21:13:53 +03:00
0469607a71 Fix button latching on Windows after drag and drop operation 2025-04-19 21:13:53 +03:00
d115d22ee6 Implement new window dragging system 2025-04-19 21:13:52 +03:00
8120ae621d Fix mouse resetting issues after ending relative mode 2025-04-19 21:13:52 +03:00
f873c2fa9f Fix frame stutter when window is focused 2025-04-19 21:13:51 +03:00
c3ffbe2f42 Fix error when docking to sides of tabbed panel 2025-04-19 21:13:51 +03:00
55a0a39881 Cleanup Linux SDL implementation 2025-04-19 21:13:50 +03:00
592215dd30 Support compiling third party library C files as C code 2025-04-19 21:13:50 +03:00
ef0c2a2785 Implement Wayland protocols module and file generation 2025-04-19 21:13:49 +03:00
37979e452a Fix mouse warping after ending relative mode 2025-04-19 21:13:49 +03:00
e9671bb727 Add git fetch method for dependencies 2025-04-19 21:13:48 +03:00
aa328bd591 Fix window ShowInTaskbar setting 2025-04-19 21:13:48 +03:00
188e4313f9 Fix various issues with child window positioning 2025-04-19 21:13:47 +03:00
df02c70e31 Add Window.IsAlwaysOnTop property 2025-04-19 21:13:47 +03:00
257f54b323 Use SDL locale 2025-04-19 21:13:46 +03:00
fb4b5b2575 Allow window with single tab to be dragged from tab area 2025-04-19 21:13:46 +03:00
4e1251276d Fix ValueBox mouse position resetting after releasing the button 2025-04-19 21:13:45 +03:00
a7b200dc57 Fix SDL build process on Linux 2025-04-19 21:13:44 +03:00
8cadbae80e Update SDL to 3.2.0 2025-04-19 21:13:44 +03:00
c3bae49aae Force cursor to center of Game Window when tab handle is clicked 2025-04-19 21:13:43 +03:00
Chandler Cox
6fa4fc6149 Fix rotation using SDL 2025-04-19 21:13:43 +03:00
f1ffe1acaa Fix Linux compilation without SDL 2025-04-19 21:13:42 +03:00
5c9ddf7f00 Fix compilation 2025-04-19 21:13:42 +03:00
431767a150 Update SDL3 2025-04-19 21:13:41 +03:00
8ba4e442a6 Fix compilation issues 2025-04-19 21:13:41 +03:00
2f8d19c267 Fix windows not being hidden initially 2025-04-19 21:13:40 +03:00
f2fd98f742 Fix parent window position handling with popup/tooltip windows 2025-04-19 21:13:40 +03:00
3ce35d6e81 Fix compilation errors in other platforms 2025-04-19 21:13:39 +03:00
796dbaa836 Fix CI for Linux 2025-04-19 21:13:39 +03:00
84b209ec7f Prevent building with SDL in unsupported platforms 2025-04-19 21:13:38 +03:00
fa976b34dc Fallback to X11 message box implementation when SDL fails 2025-04-19 21:13:38 +03:00
e7cda362b7 Fix popup and context menus not working on Wayland 2025-04-19 21:13:37 +03:00
a41a09c162 Hide warnings for unsupported SDL operations on Wayland 2025-04-19 21:13:37 +03:00
e82f84f0ab Log a warning for not implemented Wayland functionality 2025-04-19 21:13:36 +03:00
f1d387ceea Fix compilation in Linux 2025-04-19 21:13:36 +03:00
3893d4d1f8 Enable warning sound in question dialogs 2025-04-19 21:13:35 +03:00
cf7ac50faf Enable modern Windows dialog boxes 2025-04-19 21:13:35 +03:00
3f6bf15554 Implement relative mouse mode (raw input) for SDL platform 2025-04-19 21:13:34 +03:00
dac74829b4 Add flag for Window types 2025-04-19 21:13:34 +03:00
94d6f213a0 Enable native windowing system settings with SDL platform 2025-04-19 21:13:33 +03:00
8f2550ef61 Add command-line switches to force X11 and Wayland SDL drivers 2025-04-19 21:13:33 +03:00
b622a1cc5e Implement SDL platform, windowing and input handling 2025-04-19 21:13:32 +03:00
c83a3c32c7 Refactor application window class name 2025-04-19 21:13:32 +03:00
e7dcf7f7e7 Move Window related enums to separate header file 2025-04-19 21:13:31 +03:00
398785a2be Refactor Windows drag and drop implementation 2025-04-19 21:13:31 +03:00
05dba0f1f5 Refactor ScreenUtilities 2025-04-19 21:13:30 +03:00
39dbd32b2e Add more helper methods for managing Git repos 2025-04-19 21:13:30 +03:00
23a34a455a Fix centered window location on X11 2025-04-19 21:13:29 +03:00
4308328b48 Fix initial position of Tooltips 2025-04-19 21:13:29 +03:00
758 changed files with 112594 additions and 6888 deletions

View File

@@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@v3
- name: Install dependencies
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
uses: ./.github/actions/vulkan
- name: Setup .NET

View File

@@ -28,7 +28,7 @@ jobs:
git lfs pull
- name: Install dependencies
run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libwayland-dev
- name: Build
run: |
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=8

View File

@@ -28,6 +28,13 @@ TextureCube SkyLightTexture : register(t__SRV__);
Buffer<float4> ShadowsBuffer : register(t__SRV__);
Texture2D<float> ShadowMap : register(t__SRV__);
@4// Forward Shading: Utilities
// Public accessors for lighting data, use them as data binding might change but those methods will remain.
LightData GetDirectionalLight() { return DirectionalLight; }
LightData GetSkyLight() { return SkyLight; }
ProbeData GetEnvironmentProbe() { return EnvironmentProbe; }
ExponentialHeightFogData GetExponentialHeightFog() { return ExponentialHeightFog; }
uint GetLocalLightsCount() { return LocalLightsCount; }
LightData GetLocalLight(uint i) { return LocalLights[i]; }
@5// Forward Shading: Shaders
// Pixel Shader function for Forward Pass
@@ -76,9 +83,8 @@ void PS_Forward(
gBuffer.ShadingModel = MATERIAL_SHADING_MODEL;
// Calculate lighting from a single directional light
float4 shadowMask = 1.0f;
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
shadowMask = GetShadowMask(shadow);
float4 shadowMask = GetShadowMask(shadow);
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
// Calculate lighting from sky light
@@ -143,9 +149,9 @@ void PS_Forward(
#endif
#if USE_FOG
#if USE_FOG && MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT
// Calculate exponential height fog
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0);
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z);
// Apply fog to the output color
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE

View File

@@ -15,6 +15,7 @@
#include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.hlsl"
#include "./Flax/TerrainCommon.hlsl"
@7
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
@@ -334,7 +335,7 @@ VertexOutput VS(TerrainVertexInput input)
float lodValue = CurrentLOD;
float morphAlpha = lodCalculated - CurrentLOD;
// Sample heightmap
// Sample heightmap and splatmaps
float2 heightmapUVs = input.TexCoord * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
#if USE_SMOOTH_LOD_TRANSITION
float4 heightmapValueThisLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
@@ -342,7 +343,6 @@ VertexOutput VS(TerrainVertexInput input)
float2 heightmapUVsNextLOD = nextLODPos * HeightmapUVScaleBias.xy + HeightmapUVScaleBias.zw;
float4 heightmapValueNextLOD = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
float4 heightmapValue = lerp(heightmapValueThisLOD, heightmapValueNextLOD, morphAlpha);
bool isHole = max(heightmapValueThisLOD.b + heightmapValueThisLOD.a, heightmapValueNextLOD.b + heightmapValueNextLOD.a) >= 1.9f;
#if USE_TERRAIN_LAYERS
float4 splatmapValueThisLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
float4 splatmapValueNextLOD = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVsNextLOD, lodValue + 1);
@@ -355,7 +355,6 @@ VertexOutput VS(TerrainVertexInput input)
#endif
#else
float4 heightmapValue = Heightmap.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
bool isHole = (heightmapValue.b + heightmapValue.a) >= 1.9f;
#if USE_TERRAIN_LAYERS
float4 splatmap0Value = Splatmap0.SampleLevel(SamplerPointClamp, heightmapUVs, lodValue);
#if TERRAIN_LAYERS_DATA_SIZE > 1
@@ -363,12 +362,11 @@ VertexOutput VS(TerrainVertexInput input)
#endif
#endif
#endif
float height = (float)((int)(heightmapValue.x * 255.0) + ((int)(heightmapValue.y * 255) << 8)) / 65535.0;
float height = DecodeHeightmapHeight(heightmapValue);
// Extract normal and the holes mask
float2 normalTemp = float2(heightmapValue.b, heightmapValue.a) * 2.0f - 1.0f;
float3 normal = float3(normalTemp.x, sqrt(1.0 - saturate(dot(normalTemp, normalTemp))), normalTemp.y);
normal = normalize(normal);
bool isHole;
float3 normal = DecodeHeightmapNormal(heightmapValue, isHole);
output.Geometry.HolesMask = isHole ? 0 : 1;
if (isHole)
{
@@ -438,7 +436,6 @@ VertexOutput VS(TerrainVertexInput input)
// Apply world position offset per-vertex
#if USE_POSITION_OFFSET
output.Geometry.WorldPosition += material.PositionOffset;
output.Geometry.PrevWorldPosition += material.PositionOffset;
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
#endif

Binary file not shown.

BIN
Content/Shaders/Editor/Grid.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/Fog.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/ProbesFilter.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -2,9 +2,9 @@
"Name": "Flax",
"Version": {
"Major": 1,
"Minor": 10,
"Minor": 11,
"Revision": 0,
"Build": 6705
"Build": 6800
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
@@ -13,6 +13,7 @@
"Configuration": {
"UseCSharp": true,
"UseLargeWorlds": false,
"UseDotNet": true
"UseDotNet": true,
"UseSDL": true
}
}

View File

@@ -267,6 +267,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=comperand/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=coord/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cubemap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDGI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Deformer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=deformers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=defragmentation/@EntryIndexedValue">True</s:Boolean>

View File

@@ -14,4 +14,4 @@ bash ./Development/Scripts/Linux/CallBuildTool.sh --genproject "$@"
# Build bindings for all editor configurations
echo Building C# bindings...
# TODO: Detect the correct architecture here
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor
#Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor

View File

@@ -6,7 +6,7 @@
Flax Engine is a high quality modern 3D game engine written in C++ and C#.
From stunning graphics to powerful scripts, it's designed for fast workflow with many ready-to-use features waiting for you right now. To learn more see the website ([www.flaxengine.com](https://flaxengine.com)).
This repository contains full source code of the Flax Engine (excluding NDA-protected platforms support). Anyone is welcome to contribute or use the modified source in Flax-based games.
This repository contains full source code of the Flax Engine (excluding NDA-protected platforms support). Documentation source is also available in a separate repository. Anyone is welcome to contribute or use the modified source in Flax-based games.
# Development
@@ -46,21 +46,26 @@ Follow the instructions below to compile and run the engine from source.
* Install Visual Studio Code
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Ubuntu: `sudo apt install dotnet-sdk-8.0`
* Fedora: `sudo dnf install dotnet-sdk-8.0`
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
* Ubuntu: `sudo apt install vulkan-sdk`
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
* Install Git with LFS
* Ubuntu: `sudo apt-get install git git-lfs`
* Arch: `sudo pacman -S git git-lfs`
* `git-lfs install`
* Install the required packages:
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev zenity wayland-protocols libportal-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel zenity wayland-protocols-devel libportal`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib zenity wayland-protocols libportal`
* Install Clang compiler (version 6 or later):
* Ubuntu: `sudo apt-get install clang lldb lld`
* Fedora: `sudo dnf install clang llvm lldb lld`
* Arch: `sudo pacman -S clang lldb lld`
* Clone the repository (with LFS)
* git-lfs clone https://github.com/FlaxEngine/FlaxEngine.git
* Run `./GenerateProjectFiles.sh`
* Open workspace with Visual Code
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)

View File

@@ -174,7 +174,9 @@ void EditorAnalytics::StartSession()
// Bind events
GameCooker::OnEvent.Bind<RegisterGameCookingStart>();
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Bind<RegisterLightmapsBuildingStart>();
#if LOG_ENABLE
Log::Logger::OnError.Bind<RegisterError>();
#endif
}
void EditorAnalytics::EndSession()
@@ -187,7 +189,9 @@ void EditorAnalytics::EndSession()
// Unbind events
GameCooker::OnEvent.Unbind<RegisterGameCookingStart>();
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Unbind<RegisterLightmapsBuildingStart>();
#if LOG_ENABLE
Log::Logger::OnError.Unbind<RegisterError>();
#endif
// End session
{

View File

@@ -13,6 +13,11 @@ namespace FlaxEditor.Content.Create
/// <inheritdoc />
public string ResultUrl { get; }
/// <summary>
/// Gets a value indicating wether a file can be created based on the current settings.
/// </summary>
public abstract bool CanBeCreated { get; }
/// <summary>
/// Gets a value indicating whether this entry has settings to modify.
/// </summary>

View File

@@ -60,7 +60,8 @@ namespace FlaxEditor.Content.Create
Text = "Create",
AnchorPreset = AnchorPresets.BottomRight,
Offsets = new Margin(-ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
Parent = this
Parent = this,
Enabled = entry.CanBeCreated,
};
createButton.Clicked += OnSubmit;
var cancelButton = new Button
@@ -68,7 +69,7 @@ namespace FlaxEditor.Content.Create
Text = "Cancel",
AnchorPreset = AnchorPresets.BottomRight,
Offsets = new Margin(-ButtonsWidth - ButtonsMargin - ButtonsWidth - ButtonsMargin, ButtonsWidth, -ButtonsHeight - ButtonsMargin, ButtonsHeight),
Parent = this
Parent = this,
};
cancelButton.Clicked += OnCancel;
@@ -77,7 +78,7 @@ namespace FlaxEditor.Content.Create
{
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(2, 2, infoLabel.Bottom + 2, EditorHeight),
Parent = this
Parent = this,
};
// Settings editor
@@ -87,6 +88,7 @@ namespace FlaxEditor.Content.Create
_dialogSize = new Float2(TotalWidth, panel.Bottom);
_settingsEditor.Select(_entry.Settings);
_settingsEditor.Modified += () => createButton.Enabled = _entry.CanBeCreated;
}
/// <inheritdoc />

View File

@@ -12,6 +12,9 @@ namespace FlaxEditor.Content.Create
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class ParticleEmitterCreateEntry : CreateFileEntry
{
/// <inheritdoc/>
public override bool CanBeCreated => true;
/// <summary>
/// Types of the emitter templates that can be created.
/// </summary>

View File

@@ -14,6 +14,9 @@ namespace FlaxEditor.Content.Create
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class PrefabCreateEntry : CreateFileEntry
{
/// <inheritdoc />
public override bool CanBeCreated => _options.RootActorType != null;
/// <summary>
/// The create options.
/// </summary>
@@ -73,6 +76,9 @@ namespace FlaxEditor.Content.Create
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class WidgetCreateEntry : CreateFileEntry
{
/// <inheritdoc/>
public override bool CanBeCreated => _options.RootControlType != null;
/// <summary>
/// The create options.
/// </summary>

View File

@@ -17,6 +17,8 @@ namespace FlaxEditor.Content.Create
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
internal class SettingsCreateEntry : CreateFileEntry
{
public override bool CanBeCreated => _options.Type != null;
internal class Options
{
[Tooltip("The settings type.")]

View File

@@ -11,6 +11,9 @@ namespace FlaxEditor.Content.Create
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class VisualScriptCreateEntry : CreateFileEntry
{
/// <inheritdoc/>
public override bool CanBeCreated => _options.BaseClass != null;
/// <summary>
/// The create options.
/// </summary>

View File

@@ -145,7 +145,7 @@ namespace FlaxEditor.Content.GUI
set
{
value = Mathf.Clamp(value, 0.3f, 3.0f);
if (!Mathf.NearEqual(value, _viewScale))
if (value != _viewScale)
{
_viewScale = value;
ViewScaleChanged?.Invoke();

View File

@@ -282,7 +282,7 @@ namespace FlaxEditor.Content
if (data is DragDataFiles)
return DragDropEffect.Copy;
return _dragOverItems.Effect;
return _dragOverItems?.Effect ?? DragDropEffect.None;
}
/// <inheritdoc />

View File

@@ -20,7 +20,7 @@ namespace FlaxEditor.Content
}
/// <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 />
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;

View File

@@ -65,6 +65,9 @@ namespace FlaxEditor.Content
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class GenericJsonCreateEntry : CreateFileEntry
{
/// <inheritdoc/>
public override bool CanBeCreated => _options.Type != null;
/// <summary>
/// The create options.
/// </summary>

View File

@@ -10,11 +10,9 @@ using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
/// Base class for shader source files.
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
[ContentContextMenu("New/Shader Source")]
public class ShaderSourceProxy : ContentProxy
public abstract class ShaderBaseProxy : ContentProxy
{
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
@@ -29,6 +27,21 @@ namespace FlaxEditor.Content
return targetLocation.ShortName == "Source" && prevTargetLocation.ShortName == "Shaders";
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
Editor.Instance.CodeEditing.OpenFile(item.Path);
return null;
}
}
/// <summary>
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
[ContentContextMenu("New/Shader Source (.shader)")]
public class ShaderSourceProxy : ShaderBaseProxy
{
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
@@ -44,13 +57,6 @@ namespace FlaxEditor.Content
File.WriteAllText(outputPath, shaderTemplate, Encoding.UTF8);
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
Editor.Instance.CodeEditing.OpenFile(item.Path);
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x7542f5);
@@ -66,4 +72,33 @@ namespace FlaxEditor.Content
return item is ShaderSourceItem;
}
}
/// <summary>
/// Context proxy object for shader header files.
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
[ContentContextMenu("New/Shader Header (.hlsl)")]
public class ShaderHeaderProxy : ShaderBaseProxy
{
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
File.WriteAllText(outputPath, "\n", Encoding.UTF8);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x2545a5);
/// <inheritdoc />
public override string FileExtension => "hlsl";
/// <inheritdoc />
public override string Name => "Shader Header";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return false;
}
}
}

View File

@@ -30,6 +30,7 @@
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
#include "Engine/Content/JsonAsset.h"
#include "Engine/Content/AssetReference.h"
#include "Engine/Profiler/ProfilerMemory.h"
#if PLATFORM_TOOLS_WINDOWS
#include "Platform/Windows/WindowsPlatformTools.h"
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
@@ -380,6 +381,7 @@ bool GameCooker::IsCancelRequested()
PlatformTools* GameCooker::GetTools(BuildPlatform platform)
{
PROFILE_MEM(Editor);
PlatformTools* result = nullptr;
if (!Tools.TryGet(platform, result))
{
@@ -471,6 +473,7 @@ bool GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
LOG(Error, "Build platform {0} is not supported.", ::ToString(platform));
return true;
}
PROFILE_MEM(Editor);
// Setup
CancelFlag = 0;
@@ -624,6 +627,7 @@ void GameCookerImpl::ReportProgress(const String& info, float totalProgress)
void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
{
PROFILE_MEM(Editor);
if (Internal_OnCollectAssets == nullptr)
{
auto c = GameCooker::GetStaticClass();
@@ -651,6 +655,7 @@ void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
bool GameCookerImpl::Build()
{
PROFILE_MEM(Editor);
CookingData& data = *Data;
LOG(Info, "Starting Game Cooker...");
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
@@ -778,6 +783,8 @@ int32 GameCookerImpl::ThreadFunction()
bool GameCookerService::Init()
{
PROFILE_MEM(Editor);
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
GameCooker::OnCollectAssets.Bind(OnCollectAssets);
@@ -789,6 +796,7 @@ void GameCookerService::Update()
{
if (IsRunning)
{
PROFILE_MEM(Editor);
ScopeLock lock(ProgressLocker);
if (ProgressMsg.HasChars())

View File

@@ -186,7 +186,7 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
ADD_ENTRY("CFBundlePackageType", "APPL");
ADD_ENTRY("NSPrincipalClass", "NSApplication");
ADD_ENTRY("LSApplicationCategoryType", "public.app-category.games");
ADD_ENTRY("LSMinimumSystemVersion", "10.15");
ADD_ENTRY("LSMinimumSystemVersion", "13");
ADD_ENTRY("CFBundleIconFile", "icon.icns");
ADD_ENTRY_STR("CFBundleExecutable", executableName);
ADD_ENTRY_STR("CFBundleIdentifier", appIdentifier);

View File

@@ -36,6 +36,7 @@
#include "Engine/Engine/Base/GameBase.h"
#include "Engine/Engine/Globals.h"
#include "Engine/Tools/TextureTool/TextureTool.h"
#include "Engine/Threading/Threading.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Scripting/Enums.h"
#if PLATFORM_TOOLS_WINDOWS

View File

@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -52,6 +53,16 @@ namespace FlaxEditor.CustomEditors
/// </summary>
/// <param name="nodes">The nodes to select</param>
public void Select(List<SceneGraph.SceneGraphNode> nodes);
/// <summary>
/// Gets the current selection.
/// </summary>
public List<SceneGraphNode> Selection { get; }
/// <summary>
/// Indication of if the properties window is locked on specific objects.
/// </summary>
public bool LockSelection { get; set; }
}
/// <summary>
@@ -81,6 +92,8 @@ namespace FlaxEditor.CustomEditors
Offsets = Margin.Zero;
Pivot = Float2.Zero;
IsScrollable = true;
Spacing = Utilities.Constants.UIMargin;
Margin = new Margin(Utilities.Constants.UIMargin);
}
/// <inheritdoc />
@@ -95,7 +108,7 @@ namespace FlaxEditor.CustomEditors
{
FlaxEditor.Editor.LogWarning(ex);
// Refresh layout on errors to reduce lgo spam
// Refresh layout on errors to reduce log spam
_presenter.BuildLayout();
}

View File

@@ -6,6 +6,8 @@
#include "Engine/Core/Types/TimeSpan.h"
#include "Engine/Core/Types/Stopwatch.h"
#include "Engine/Core/Collections/Dictionary.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Engine/EngineService.h"
#include "Engine/Scripting/Scripting.h"
#include "Engine/Scripting/BinaryModule.h"
@@ -69,6 +71,7 @@ MTypeObject* CustomEditorsUtil::GetCustomEditor(MTypeObject* refType)
bool CustomEditorsUtilService::Init()
{
PROFILE_MEM(Editor);
TRACK_ASSEMBLY(((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly);
Scripting::BinaryModuleLoaded.Bind(&OnBinaryModuleLoaded);
@@ -77,6 +80,8 @@ bool CustomEditorsUtilService::Init()
void OnAssemblyLoaded(MAssembly* assembly)
{
PROFILE_CPU_NAMED("CustomEditors.OnAssemblyLoaded");
PROFILE_MEM(Editor);
Stopwatch stopwatch;
// Prepare FlaxEngine

View File

@@ -9,7 +9,6 @@ using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Modules;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
@@ -71,7 +70,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
var panel = layout.CustomContainer<UniformGridPanel>();
var panel = layout.UniformGrid();
panel.CustomControl.Height = 20.0f;
panel.CustomControl.SlotsVertically = 1;
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter || nestedPrefab)
@@ -133,35 +132,22 @@ namespace FlaxEditor.CustomEditors.Dedicated
var actor = (Actor)Values[0];
var scriptType = TypeUtils.GetType(actor.TypeName);
var item = scriptType.ContentItem;
if (Presenter.Owner is PropertiesWindow propertiesWindow)
if (Presenter.Owner != null)
{
var lockButton = cm.AddButton(propertiesWindow.LockObjects ? "Unlock" : "Lock");
var lockButton = cm.AddButton(Presenter.Owner.LockSelection ? "Unlock" : "Lock");
lockButton.ButtonClicked += button =>
{
propertiesWindow.LockObjects = !propertiesWindow.LockObjects;
var owner = Presenter?.Owner;
if (owner == null)
return;
owner.LockSelection = !owner.LockSelection;
// Reselect current selection
if (!propertiesWindow.LockObjects && Editor.Instance.SceneEditing.SelectionCount > 0)
if (!owner.LockSelection && owner.Selection.Count > 0)
{
var cachedSelection = Editor.Instance.SceneEditing.Selection.ToArray();
Editor.Instance.SceneEditing.Select(null);
Editor.Instance.SceneEditing.Select(cachedSelection);
}
};
}
else if (Presenter.Owner is PrefabWindow prefabWindow)
{
var lockButton = cm.AddButton(prefabWindow.LockSelectedObjects ? "Unlock" : "Lock");
lockButton.ButtonClicked += button =>
{
prefabWindow.LockSelectedObjects = !prefabWindow.LockSelectedObjects;
// Reselect current selection
if (!prefabWindow.LockSelectedObjects && prefabWindow.Selection.Count > 0)
{
var cachedSelection = prefabWindow.Selection.ToList();
prefabWindow.Select(null);
prefabWindow.Select(cachedSelection);
var cachedSelection = owner.Selection.ToList();
owner.Select(null);
owner.Select(cachedSelection);
}
};
}
@@ -258,6 +244,16 @@ namespace FlaxEditor.CustomEditors.Dedicated
else if (editor.Values[0] is SceneObject sceneObject)
{
node.TextColor = sceneObject.HasPrefabLink ? FlaxEngine.GUI.Style.Current.ProgressNormal : FlaxEngine.GUI.Style.Current.BackgroundSelected;
if (editor.Values.Info != ScriptMemberInfo.Null)
{
if (editor.Values.GetAttributes().FirstOrDefault(x => x is EditorDisplayAttribute) is EditorDisplayAttribute editorDisplayAttribute && !string.IsNullOrEmpty(editorDisplayAttribute.Name))
node.Text = $"{Utilities.Utils.GetPropertyNameUI(editorDisplayAttribute.Name)} ({Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name)})";
else
node.Text = Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name);
}
else if (sceneObject is Actor actor)
node.Text = $"{actor.Name} ({Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name)})";
else
node.Text = Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name);
}
// Array Item
@@ -268,6 +264,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Common type
else if (editor.Values.Info != ScriptMemberInfo.Null)
{
if (editor.Values.GetAttributes().FirstOrDefault(x => x is EditorDisplayAttribute) is EditorDisplayAttribute editorDisplayAttribute
&& !string.IsNullOrEmpty(editorDisplayAttribute.Name)
&& !editorDisplayAttribute.Name.Contains("_inline"))
node.Text = $"{Utilities.Utils.GetPropertyNameUI(editorDisplayAttribute.Name)} ({Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name)})";
else
node.Text = Utilities.Utils.GetPropertyNameUI(editor.Values.Info.Name);
}
// Custom type
@@ -316,7 +317,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var childEditor = editor.ChildrenEditors[i];
// Special case for root actor transformation (can be applied only in Prefab editor, not in Level)
if (isActorEditorInLevel && childEditor.Values.Info.Name is "LocalPosition" or "LocalOrientation" or "LocalScale")
if (isActorEditorInLevel && childEditor.Values.Info.Name is "LocalPosition" or "LocalOrientation" or "LocalScale" or "Name")
continue;
var child = ProcessDiff(childEditor, !isScriptEditorWithRefValue);
@@ -361,13 +362,39 @@ namespace FlaxEditor.CustomEditors.Dedicated
return result;
}
private TreeNode CreateDiffTree(Actor actor, CustomEditorPresenter presenter, LayoutElementsContainer layout)
{
var actorNode = Editor.Instance.Scene.GetActorNode(actor);
ValueContainer vc = new ValueContainer(ScriptMemberInfo.Null);
vc.SetType(new ScriptType(actorNode.EditableObject.GetType()));
vc.Add(actorNode.EditableObject);
var editor = CustomEditorsUtil.CreateEditor(vc, null, false);
editor.Initialize(presenter, layout, vc);
var node = ProcessDiff(editor, false);
layout.ClearLayout();
foreach (var child in actor.Children)
{
var childNode = CreateDiffTree(child, presenter, layout);
if (childNode == null)
continue;
if (node == null)
node = CreateDiffNode(editor);
node.AddChild(childNode);
}
return node;
}
private void ViewChanges(Control target, Float2 targetLocation)
{
// Build a tree out of modified properties
var rootNode = ProcessDiff(this, false);
var thisActor = (Actor)Values[0];
var rootActor = thisActor.IsPrefabRoot ? thisActor : thisActor.GetPrefabRoot();
var presenter = new CustomEditorPresenter(null);
var layout = new CustomElementsContainer<ContainerControl>();
var rootNode = CreateDiffTree(rootActor, presenter, layout);
// Skip if no changes detected
if (rootNode == null || rootNode.ChildrenCount == 0)
if (rootNode == null)
{
var cm1 = new ContextMenu();
cm1.AddButton("No changes detected");

View File

@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
_infoLabel = playbackGroup.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
var grid = playbackGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -59,7 +59,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var paintValue = new ReadOnlyValueContainer(new ScriptType(typeof(ClothPaintingGizmoMode)), _gizmoMode);
paintGroup.Object(paintValue);
{
var grid = paintGroup.CustomContainer<UniformGridPanel>();
var grid = paintGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -1,6 +1,5 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content.Settings;
using FlaxEngine;
@@ -16,6 +15,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
private int _layersCount;
private List<CheckBox> _checkBoxes;
private VerticalPanel _upperRightCell;
private VerticalPanel _bottomLeftCell;
private UniformGridPanel _grid;
private Border _horizontalHighlight;
private Border _verticalHighlight;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.InlineIntoParent;
@@ -37,12 +41,29 @@ namespace FlaxEditor.CustomEditors.Dedicated
Parent = panel,
};
var style = FlaxEngine.GUI.Style.Current;
_horizontalHighlight = new Border()
{
Parent = panel,
BorderColor = style.Foreground,
BorderWidth = 1.0f,
Visible = false,
};
_verticalHighlight = new Border()
{
Parent = panel,
BorderColor = style.Foreground,
BorderWidth = 1.0f,
Visible = false,
};
var upperLeftCell = new Label
{
Parent = gridPanel,
};
var upperRightCell = new VerticalPanel
_upperRightCell = new VerticalPanel
{
ClipChildren = false,
Pivot = new Float2(0.00001f, 0.0f),
@@ -54,7 +75,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
Parent = gridPanel,
};
var bottomLeftCell = new VerticalPanel
_bottomLeftCell = new VerticalPanel
{
Pivot = Float2.Zero,
Spacing = 0,
@@ -63,7 +84,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
Parent = gridPanel,
};
var grid = new UniformGridPanel(0)
_grid = new UniformGridPanel(0)
{
SlotsHorizontally = layersCount,
SlotsVertically = layersCount,
@@ -74,13 +95,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
int layerIndex = 0;
for (; layerIndex < layerNames.Length; layerIndex++)
{
upperRightCell.AddChild(new Label
_upperRightCell.AddChild(new Label
{
Height = labelsHeight,
Text = layerNames[layerNames.Length - layerIndex - 1],
HorizontalAlignment = TextAlignment.Near,
});
bottomLeftCell.AddChild(new Label
_bottomLeftCell.AddChild(new Label
{
Height = labelsHeight,
Text = layerNames[layerIndex],
@@ -90,13 +111,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
for (; layerIndex < layersCount; layerIndex++)
{
string name = "Layer " + layerIndex;
upperRightCell.AddChild(new Label
_upperRightCell.AddChild(new Label
{
Height = labelsHeight,
Text = name,
HorizontalAlignment = TextAlignment.Near,
});
bottomLeftCell.AddChild(new Label
_bottomLeftCell.AddChild(new Label
{
Height = labelsHeight,
Text = name,
@@ -118,7 +139,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var box = new CheckBox(0, 0, true)
{
Tag = new Float2(_layersCount - column - 1, row),
Parent = grid,
Parent = _grid,
Checked = GetBit(column, row),
};
box.StateChanged += OnCheckBoxChanged;
@@ -126,7 +147,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
for (; column < layersCount; column++)
{
grid.AddChild(new Label());
_grid.AddChild(new Label());
}
}
}
@@ -141,6 +162,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc />
public override void Refresh()
{
int selectedColumn = -1;
int selectedRow = -1;
var style = FlaxEngine.GUI.Style.Current;
bool mouseOverGrid = _grid.IsMouseOver;
// Only hide highlights if mouse is not over the grid to reduce flickering
if (!mouseOverGrid)
{
_horizontalHighlight.Visible = false;
_verticalHighlight.Visible = false;
}
// Sync check boxes
for (int i = 0; i < _checkBoxes.Count; i++)
{
@@ -148,6 +181,39 @@ namespace FlaxEditor.CustomEditors.Dedicated
int column = (int)((Float2)box.Tag).X;
int row = (int)((Float2)box.Tag).Y;
box.Checked = GetBit(column, row);
if (box.IsMouseOver)
{
selectedColumn = column;
selectedRow = row;
_horizontalHighlight.X = _grid.X - _bottomLeftCell.Width;
_horizontalHighlight.Y = _grid.Y + box.Y;
_horizontalHighlight.Width = _bottomLeftCell.Width + box.Width + box.X;
_horizontalHighlight.Height = box.Height;
_horizontalHighlight.Visible = true;
_verticalHighlight.X = _grid.X + box.X;
_verticalHighlight.Y = _grid.Y - _upperRightCell.Height;
_verticalHighlight.Width = box.Width;
_verticalHighlight.Height = _upperRightCell.Height + box.Height + box.Y;
_verticalHighlight.Visible = true;
}
}
for (int i = 0; i < _checkBoxes.Count; i++)
{
var box = _checkBoxes[i];
int column = (int)((Float2)box.Tag).X;
int row = (int)((Float2)box.Tag).Y;
if (!mouseOverGrid)
box.ImageColor = style.BorderSelected;
else if (selectedColumn > -1 && selectedRow > -1)
{
bool isRowOrColumn = column == selectedColumn || row == selectedRow;
box.ImageColor = style.BorderSelected * (isRowOrColumn ? 1.2f : 0.75f);
}
}
}

View File

@@ -92,12 +92,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Update add button
var update = group.Button("Update").Button;
group.Space(0);
update.TooltipText = "Refreshes the dashboard statistics";
update.Height = 16.0f;
update.Clicked += RebuildLayout;
// New locale add button
var addLocale = group.Button("Add Locale...").Button;
group.Space(0);
addLocale.TooltipText = "Shows a locale picker and creates new localization for it with not translated string tables";
addLocale.Height = 16.0f;
addLocale.ButtonClicked += delegate(Button button)
@@ -167,12 +169,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Export button
var exportLocalization = group.Button("Export...").Button;
group.Space(0);
exportLocalization.TooltipText = "Exports the localization strings into .pot file for translation";
exportLocalization.Height = 16.0f;
exportLocalization.Clicked += () => Export(tableEntries, allKeys);
// Find localized strings in code button
var findStringsCode = group.Button("Find localized strings in code").Button;
group.Space(0);
findStringsCode.TooltipText = "Searches for localized string usage in inside a project source files";
findStringsCode.Height = 16.0f;
findStringsCode.Clicked += delegate
@@ -186,12 +190,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
foreach (var file in files)
FindNewKeysCSharp(file, newKeys, allKeys);
// C++
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories);
// C/C++
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.c", SearchOption.AllDirectories)).ToArray();
filesCount += files.Length;
foreach (var file in files)
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;
foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys);

View File

@@ -54,7 +54,8 @@ public class ModelPrefabEditor : GenericEditor
}
// Creates the import path UI
Utilities.Utils.CreateImportPathUI(layout, modelPrefab.ImportPath, false);
var group = layout.Group("Import Path");
Utilities.Utils.CreateImportPathUI(group, modelPrefab.ImportPath);
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
_reimportButton = button.Button;

View File

@@ -92,7 +92,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
_infoLabel = playbackGroup.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
var grid = playbackGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -39,7 +39,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (ragdoll.Parent is AnimatedModel animatedModel && animatedModel.SkinnedModel)
{
// Builder
var grid = editorGroup.CustomContainer<UniformGridPanel>();
var grid = editorGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;
@@ -53,7 +53,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (Presenter.Owner != null)
{
// Selection
var grid = editorGroup.CustomContainer<UniformGridPanel>();
var grid = editorGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -1,6 +1,7 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using System.Reflection.Emit;
using FlaxEditor.CustomEditors.GUI;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -93,8 +94,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add info box
if (IsSingleObject && Values[0] is RigidBody && Editor.IsPlayMode)
{
_infoLabel = layout.Label(string.Empty).Label;
var group = layout.Group("Info");
_infoLabel = group.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
_infoLabel.Margin = new Margin(3);
}
}
}

View File

@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
_infoLabel = playbackGroup.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
var grid = playbackGroup.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -682,7 +682,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
private CustomElementsContainer<UniformGridPanel> UniformGridTwoByOne(LayoutElementsContainer cont)
{
var grid = cont.CustomContainer<UniformGridPanel>();
var grid = cont.UniformGrid();
grid.CustomControl.SlotsHorizontally = 2;
grid.CustomControl.SlotsVertically = 1;
grid.CustomControl.SlotPadding = Margin.Zero;

View File

@@ -43,11 +43,7 @@ namespace FlaxEditor.CustomEditors.Editors
base.Initialize(layout);
if (XElement.ValueBox.Parent is UniformGridPanel ug)
{
ug.Height += 2;
ug.SlotSpacing = new Float2(4);
ug.SlotPadding = new Margin(0, 0, 1, 1);
}
CheckLayout(ug);
// Override colors
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
@@ -75,11 +71,7 @@ namespace FlaxEditor.CustomEditors.Editors
base.Initialize(layout);
if (XElement.ValueBox.Parent is UniformGridPanel ug)
{
ug.Height += 2;
ug.SlotSpacing = new Float2(4);
ug.SlotPadding = new Margin(0, 0, 1, 1);
}
CheckLayout(ug);
// Override colors
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
@@ -138,11 +130,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
if (XElement.ValueBox.Parent is UniformGridPanel ug)
{
ug.Height += 2;
ug.SlotSpacing = new Float2(4);
ug.SlotPadding = new Margin(0, 0, 1, 1);
}
CheckLayout(ug);
// Override colors
var back = FlaxEngine.GUI.Style.Current.TextBoxBackground;
@@ -203,5 +191,13 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling";
}
}
private static void CheckLayout(UniformGridPanel ug)
{
// Enlarge to fix border visibility
ug.Height += 2;
ug.SlotSpacing += new Float2(2);
ug.SlotPadding += new Margin(0, 0, 1, 1);
}
}
}

View File

@@ -642,10 +642,10 @@ namespace FlaxEditor.CustomEditors.Editors
if (_canResize && !_readOnly)
{
var panel = dragArea.HorizontalPanel();
panel.Panel.Size = new Float2(0, 20);
panel.Panel.Margin = new Margin(2);
panel.Panel.Size = new Float2(0, 18);
panel.Panel.Margin = new Margin(0, 0, Utilities.Constants.UIMargin, 0);
var removeButton = panel.Button("-", "Remove last item");
var removeButton = panel.Button("-", "Remove the last item");
removeButton.Button.Size = new Float2(16, 16);
removeButton.Button.Enabled = size > _minCount;
removeButton.Button.AnchorPreset = AnchorPresets.TopRight;
@@ -656,7 +656,7 @@ namespace FlaxEditor.CustomEditors.Editors
Resize(Count - 1);
};
var addButton = panel.Button("+", "Add new item");
var addButton = panel.Button("+", "Add a new item");
addButton.Button.Size = new Float2(16, 16);
addButton.Button.Enabled = (!NotNullItems || size > 0) && size < _maxCount;
addButton.Button.AnchorPreset = AnchorPresets.TopRight;

View File

@@ -27,7 +27,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
float trackBallSize = 80.0f;
float trackBallSize = 100f;
float margin = 4.0f;
// Panel
@@ -50,7 +50,7 @@ namespace FlaxEditor.CustomEditors.Editors
// Scale editor
{
var grid = masterPanel.CustomContainer<UniformGridPanel>();
var grid = masterPanel.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.SlotPadding = new Margin(4, 2, 2, 2);
gridControl.ClipChildren = false;

View File

@@ -26,6 +26,7 @@ namespace FlaxEditor.CustomEditors.Editors
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
new OptionType("Video", typeof(VideoBrush)),
new OptionType("UI Brush", typeof(UIBrush)),
};
}
}

View File

@@ -21,6 +21,7 @@ namespace FlaxEditor.CustomEditors.Editors
public sealed class LocalizedStringEditor : GenericEditor
{
private TextBoxElement _idElement, _valueElement;
private Button _viewStringButton;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
@@ -70,6 +71,21 @@ namespace FlaxEditor.CustomEditors.Editors
};
addString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
addString.ButtonClicked += OnAddStringClicked;
var viewString = new Button
{
Visible = false,
Width = 16.0f,
BackgroundColor = Color.White,
BackgroundColorHighlighted = Color.Gray,
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Search12),
TooltipText = "Find localized text in Localized String Table asset for the current locale...",
Parent = valueElement.TextBox,
};
viewString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
viewString.LocalX -= 16.0f;
viewString.ButtonClicked += OnViewStringClicked;
_viewStringButton = viewString;
}
/// <inheritdoc />
@@ -80,6 +96,7 @@ namespace FlaxEditor.CustomEditors.Editors
if (_valueElement != null)
{
_valueElement.TextBox.WatermarkText = Localization.GetString(_idElement.Text);
_viewStringButton.Visible = !string.IsNullOrEmpty(_valueElement.TextBox.WatermarkText);
}
}
@@ -92,14 +109,21 @@ namespace FlaxEditor.CustomEditors.Editors
_valueElement = null;
}
private void OnSelectStringClicked(Button button)
private bool GetSettings(out LocalizationSettings settings)
{
var settings = GameSettings.Load<LocalizationSettings>();
settings = GameSettings.Load<LocalizationSettings>();
if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
{
MessageBox.Show("No valid localization settings setup.");
return;
return true;
}
return false;
}
private void OnSelectStringClicked(Button button)
{
if (GetSettings(out var settings))
return;
Profiler.BeginEvent("LocalizedStringEditor.OnSelectStringClicked");
var allKeys = new HashSet<string>();
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
@@ -136,6 +160,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
menu.Hide();
_idElement.TextBox.SetTextAsUser(after[0].Text);
_valueElement.TextBox.SetTextAsUser(string.Empty);
}
};
searchBox.TextChanged += delegate
@@ -158,12 +183,8 @@ namespace FlaxEditor.CustomEditors.Editors
private void OnAddStringClicked(Button button)
{
var settings = GameSettings.Load<LocalizationSettings>();
if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
{
MessageBox.Show("No valid localization settings setup.");
if (GetSettings(out var settings))
return;
}
Profiler.BeginEvent("LocalizedStringEditor.OnAddStringClicked");
var allKeys = new HashSet<string>();
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
@@ -231,5 +252,30 @@ namespace FlaxEditor.CustomEditors.Editors
_idElement.TextBox.SetTextAsUser(newKey);
Profiler.EndEvent();
}
private void OnViewStringClicked(Button button)
{
if (GetSettings(out var settings))
return;
var id = _idElement.TextBox.Text;
var value = _valueElement.TextBox.WatermarkText;
for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
{
var table = settings.LocalizedStringTables[i];
if (table && !table.WaitForLoaded())
{
var entries = table.Entries;
if (entries.TryGetValue(id, out var messages))
{
if (messages.Length != 0 && messages[0] == value)
{
Editor.Instance.ContentEditing.Open(table);
return;
}
}
}
}
MessageBox.Show("Unable to find localized string table.");
}
}
}

View File

@@ -46,7 +46,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;

View File

@@ -35,7 +35,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
_element = layout.TextBox(isMultiLine);
_defaultWatermarkColor = _element.TextBox.WatermarkTextColor;
_watermarkColor = _defaultWatermarkColor = _element.TextBox.WatermarkTextColor;
if (watermarkAttribute is WatermarkAttribute watermark)
{
_watermarkText = watermark.WatermarkText;

View File

@@ -604,6 +604,9 @@ namespace FlaxEditor.CustomEditors.Editors
root.SortChildrenRecursive();
root.Expand(true);
if (Input.GetKey(KeyboardKeys.Shift))
root.ExpandAll(true);
return menu;
}
}

View File

@@ -42,7 +42,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -131,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -220,7 +220,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;

View File

@@ -82,7 +82,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -469,7 +469,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -783,7 +783,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;

View File

@@ -52,7 +52,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -163,7 +163,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;
@@ -274,7 +274,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;

View File

@@ -39,7 +39,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var grid = layout.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = TextBox.DefaultHeight;

View File

@@ -22,7 +22,8 @@ namespace FlaxEditor.CustomEditors.Elements
ArrowImageClosed = new SpriteBrush(Style.Current.ArrowRight),
ArrowImageOpened = new SpriteBrush(Style.Current.ArrowDown),
EnableDropDownIcon = true,
ItemsMargin = new Margin(7, 7, 3, 3),
ItemsMargin = new Margin(Utilities.Constants.UIMargin),
ItemsSpacing = Utilities.Constants.UIMargin,
HeaderHeight = 18.0f,
EnableContainmentLines = true,
};

View File

@@ -20,13 +20,6 @@ namespace FlaxEditor.CustomEditors.GUI
/// </summary>
public const int SplitterSize = 2;
/// <summary>
/// The splitter margin (in pixels).
/// </summary>
public const int SplitterMargin = 4;
private const int SplitterSizeHalf = SplitterSize / 2;
private PropertiesListElement _element;
private float _splitterValue;
private Rectangle _splitterRect;
@@ -65,16 +58,18 @@ namespace FlaxEditor.CustomEditors.GUI
/// <param name="element">The element.</param>
public PropertiesList(PropertiesListElement element)
{
ClipChildren = false;
_element = element;
_splitterValue = 0.4f;
BottomMargin = TopMargin = RightMargin = SplitterMargin;
Margin = new Margin();
Spacing = Utilities.Constants.UIMargin;
UpdateSplitRect();
}
private void UpdateSplitRect()
{
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSizeHalf, 0.0f, Width), 0, SplitterSize, Height);
LeftMargin = _splitterValue * Width + SplitterMargin;
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSize * 0.5f, 0.0f, Width), 0, SplitterSize, Height);
LeftMargin = _splitterValue * Width + _spacing;
}
private void StartTracking()
@@ -222,23 +217,33 @@ namespace FlaxEditor.CustomEditors.GUI
/// <inheritdoc />
protected override void PerformLayoutAfterChildren()
{
// Sort controls from up to down into two columns: one for labels and one for the rest of the stuff
// Place non-label controls from top to down
float y = _margin.Top;
float w = Width - _margin.Width;
bool firstItem = true;
for (int i = 0; i < _children.Count; i++)
{
Control c = _children[i];
if (!(c is PropertyNameLabel))
{
var h = c.Height;
c.Bounds = new Rectangle(_margin.Left, y + _spacing, w, h);
var rect = new Rectangle(_margin.Left, y, w, c.Height);
if (c.Visible)
{
if (firstItem)
firstItem = false;
else
rect.Y += _spacing;
}
else if (!firstItem)
rect.Y += _spacing;
c.Bounds = rect;
if (c.Visible)
y = c.Bottom;
}
}
y += _margin.Bottom;
// Place labels accordingly to their respective controls placement
float namesWidth = _splitterValue * Width;
int count = _element.Labels.Count;
float[] yStarts = new float[count + 1];
@@ -271,7 +276,9 @@ namespace FlaxEditor.CustomEditors.GUI
{
var label = _element.Labels[i];
var rect = new Rectangle(0, yStarts[i] + 1, namesWidth, yStarts[i + 1] - yStarts[i] - 2);
var rect = new Rectangle(0, yStarts[i], namesWidth, yStarts[i + 1] - yStarts[i]);
if (i != count - 1)
rect.Height -= _spacing;
//label.Parent = this;
label.Bounds = rect;
}

View File

@@ -202,6 +202,17 @@ namespace FlaxEditor.CustomEditors
return element;
}
/// <summary>
/// Adds new uniform grid control.
/// </summary>
/// <returns>The created element.</returns>
public CustomElementsContainer<UniformGridPanel> UniformGrid()
{
var grid = CustomContainer<UniformGridPanel>();
grid.CustomControl.SlotSpacing = new Float2(Utilities.Constants.UIMargin);
return grid;
}
/// <summary>
/// Adds new custom element.
/// </summary>
@@ -276,10 +287,7 @@ namespace FlaxEditor.CustomEditors
/// <returns>The created element.</returns>
public ImageElement Image(SpriteHandle sprite)
{
var element = new ImageElement();
element.Image.Brush = new SpriteBrush(sprite);
OnAddElement(element);
return element;
return Image(new SpriteBrush(sprite));
}
/// <summary>
@@ -289,10 +297,7 @@ namespace FlaxEditor.CustomEditors
/// <returns>The created element.</returns>
public ImageElement Image(Texture texture)
{
var element = new ImageElement();
element.Image.Brush = new TextureBrush(texture);
OnAddElement(element);
return element;
return Image(new TextureBrush(texture));
}
/// <summary>
@@ -301,9 +306,19 @@ namespace FlaxEditor.CustomEditors
/// <param name="texture">The GPU texture.</param>
/// <returns>The created element.</returns>
public ImageElement Image(GPUTexture texture)
{
return Image(new GPUTextureBrush(texture));
}
/// <summary>
/// Adds brush image to the layout.
/// </summary>
/// <param name="brush">The brush.</param>
/// <returns>The created element.</returns>
public ImageElement Image(IBrush brush)
{
var element = new ImageElement();
element.Image.Brush = new GPUTextureBrush(texture);
element.Image.Brush = brush;
OnAddElement(element);
return element;
}

View File

@@ -20,6 +20,7 @@
#include "Engine/Engine/Engine.h"
#include "Engine/ShadowsOfMordor/Builder.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "FlaxEngine.Gen.h"
#if PLATFORM_LINUX
#include "Engine/Tools/TextureTool/TextureTool.h"
@@ -47,6 +48,7 @@ void Editor::CloseSplashScreen()
bool Editor::CheckProjectUpgrade()
{
PROFILE_MEM(Editor);
const auto versionFilePath = Globals::ProjectCacheFolder / TEXT("version");
// Load version cache file
@@ -366,6 +368,8 @@ bool Editor::BackupProject()
int32 Editor::LoadProduct()
{
PROFILE_MEM(Editor);
// Flax Editor product
Globals::ProductName = TEXT("Flax Editor");
Globals::CompanyName = TEXT("Flax");
@@ -626,6 +630,7 @@ int32 Editor::LoadProduct()
Window* Editor::CreateMainWindow()
{
PROFILE_MEM(Editor);
Window* window = Managed->GetMainWindow();
#if PLATFORM_LINUX
@@ -662,6 +667,7 @@ bool Editor::Init()
return true;
}
PROFILE_CPU();
PROFILE_MEM(Editor);
// If during last lightmaps baking engine crashed we could try to restore the progress
ShadowsOfMordor::Builder::Instance()->CheckIfRestoreState();
@@ -693,11 +699,13 @@ bool Editor::Init()
void Editor::BeforeRun()
{
PROFILE_MEM(Editor);
Managed->BeforeRun();
}
void Editor::BeforeExit()
{
PROFILE_MEM(Editor);
CloseSplashScreen();
Managed->Exit();
@@ -708,6 +716,8 @@ void Editor::BeforeExit()
void EditorImpl::OnUpdate()
{
PROFILE_MEM(Editor);
// Update c# editor
Editor::Managed->Update();

View File

@@ -670,6 +670,8 @@ namespace FlaxEditor
{
FlaxEngine.Networking.NetworkManager.Stop(); // Shutdown any multiplayer from playmode
PlayModeEnding?.Invoke();
for (int i = 0; i < _modules.Count; i++)
_modules[i].OnPlayEnding();
}
internal void OnPlayEnd()
@@ -1031,6 +1033,8 @@ namespace FlaxEditor
{
Internal_GetEditorBoxWithChildren(FlaxEngine.Object.GetUnmanagedPtr(actor), out var box);
BoundingSphere.FromBox(ref box, out sphere);
if (sphere == BoundingSphere.Empty)
sphere = new BoundingSphere(actor.Position, sphere.Radius);
sphere.Radius = Math.Max(sphere.Radius, 15.0f);
}
else

View File

@@ -299,6 +299,7 @@ namespace FlaxEditor.GUI
{
// Select asset
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
}
}
else if (Button1Rect.Contains(location))
@@ -312,6 +313,7 @@ namespace FlaxEditor.GUI
{
// Select asset
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
}
else if (Button3Rect.Contains(location))
{

View File

@@ -51,7 +51,7 @@ namespace FlaxEditor.GUI
/// <summary>
/// The column title horizontal text alignment
/// </summary>
public TextAlignment TitleAlignment = TextAlignment.Near;
public TextAlignment TitleAlignment = TextAlignment.Center;
/// <summary>
/// The column title margin.

View File

@@ -1,7 +1,10 @@
#if PLATFORM_WINDOWS
#if PLATFORM_WINDOWS || PLATFORM_SDL
#define USE_IS_FOREGROUND
#else
#endif
#if PLATFORM_SDL
#define USE_SDL_WORKAROUNDS
#endif
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
@@ -121,7 +124,7 @@ namespace FlaxEditor.GUI.ContextMenu
}
/// <summary>
/// Shows the empty menu popup o na screen.
/// Shows the empty menu popup on a screen.
/// </summary>
/// <param name="control">The target control.</param>
/// <param name="area">The target control area to cover.</param>
@@ -256,7 +259,9 @@ namespace FlaxEditor.GUI.ContextMenu
desc.AllowMaximize = false;
desc.AllowDragAndDrop = false;
desc.IsTopmost = true;
desc.IsRegularWindow = false;
desc.Type = WindowType.Popup;
desc.Parent = parentWin.Window;
desc.Title = "ContextMenu";
desc.HasSizingFrame = false;
OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc);
@@ -266,6 +271,12 @@ namespace FlaxEditor.GUI.ContextMenu
_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
_parentCM = parent as ContextMenuBase;
Parent = _window.GUI;
@@ -285,6 +296,17 @@ namespace FlaxEditor.GUI.ContextMenu
}
}
private static void ForceDefocus(ContainerControl c)
{
foreach (var cc in c.Children)
{
if (cc.ContainsFocus)
cc.Defocus();
if (cc is ContainerControl ccc)
ForceDefocus(ccc);
}
}
/// <summary>
/// Hide popup menu and all child menus.
/// </summary>
@@ -299,6 +321,9 @@ namespace FlaxEditor.GUI.ContextMenu
// Close child
HideChild();
// Force defocus
ForceDefocus(this);
// Unlink from window
Parent = null;
@@ -426,6 +451,17 @@ namespace FlaxEditor.GUI.ContextMenu
}
}
#if USE_SDL_WORKAROUNDS
private void OnWindowGotFocus()
{
}
private void OnWindowMouseDown(ref Float2 mousePosition, MouseButton button, ref bool handled)
{
// The user clicked outside the popup window
Hide();
}
#else
private void OnWindowGotFocus()
{
var child = _childCM;
@@ -439,6 +475,7 @@ namespace FlaxEditor.GUI.ContextMenu
});
}
}
#endif
private void OnWindowLostFocus()
{
@@ -537,7 +574,12 @@ namespace FlaxEditor.GUI.ContextMenu
// Let root context menu to check if none of the popup windows
if (_parentCM == null && UseVisibilityControl && !IsForeground)
{
#if USE_SDL_WORKAROUNDS
if (!IsMouseOver)
Hide();
#else
Hide();
#endif
}
}
#endif

View File

@@ -326,8 +326,11 @@ namespace FlaxEditor.GUI.Dialogs
// Update eye dropper tool
if (_activeEyedropper)
{
// Try reading the color under the cursor in realtime if supported by the platform
Float2 mousePosition = Platform.MousePosition;
SelectedColor = ScreenUtilities.GetColorAt(mousePosition);
Color color = ScreenUtilities.GetColorAt(mousePosition);
if (color != Color.Transparent)
SelectedColor = color;
}
}

View File

@@ -1,545 +0,0 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI.Docking
{
/// <summary>
/// Helper class used to handle docking windows dragging and docking.
/// </summary>
public class DockHintWindow
{
private FloatWindowDockPanel _toMove;
private Float2 _dragOffset;
private Float2 _defaultWindowSize;
private Rectangle _rectDock;
private Rectangle _rectWindow;
private Float2 _mouse;
private DockState _toSet;
private DockPanel _toDock;
private bool _lateDragOffsetUpdate;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
private DockHintWindow(FloatWindowDockPanel toMove)
{
_toMove = toMove;
_toSet = DockState.Float;
var window = toMove.Window.Window;
// Remove focus from drag target
_toMove.Focus();
_toMove.Defocus();
// Focus window
window.Focus();
// Check if window is maximized and restore window.
if (window.IsMaximized)
{
// Restore window and set position to mouse.
var mousePos = window.MousePosition;
var previousSize = window.Size;
window.Restore();
window.Position = Platform.MousePosition - mousePos * window.Size / previousSize;
}
// Calculate dragging offset and move window to the destination position
var mouseScreenPosition = Platform.MousePosition;
// If the _toMove window was not focused when initializing this window, the result vector only contains zeros
// and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler.
if (mouseScreenPosition != Float2.Zero)
CalculateDragOffset(mouseScreenPosition);
else
_lateDragOffsetUpdate = true;
// Get initial size
_defaultWindowSize = window.Size;
// Init proxy window
Proxy.Init(ref _defaultWindowSize);
// Bind events
Proxy.Window.MouseUp += OnMouseUp;
Proxy.Window.MouseMove += OnMouseMove;
Proxy.Window.LostFocus += OnLostFocus;
// Start tracking mouse
Proxy.Window.StartTrackingMouse(false);
// Update window GUI
Proxy.Window.GUI.PerformLayout();
// Update rectangles
UpdateRects();
// Hide base window
window.Hide();
// Enable hit window presentation
Proxy.Window.RenderingEnabled = true;
Proxy.Window.Show();
Proxy.Window.Focus();
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
public void Dispose()
{
// End tracking mouse
Proxy.Window.EndTrackingMouse();
// Disable rendering
Proxy.Window.RenderingEnabled = false;
// Unbind events
Proxy.Window.MouseUp -= OnMouseUp;
Proxy.Window.MouseMove -= OnMouseMove;
Proxy.Window.LostFocus -= OnLostFocus;
// Hide the proxy
Proxy.Hide();
if (_toMove == null)
return;
// Check if window won't be docked
if (_toSet == DockState.Float)
{
var window = _toMove.Window?.Window;
if (window == null)
return;
var mouse = Platform.MousePosition;
// Move base window
window.Position = mouse - _dragOffset;
// Show base window
window.Show();
}
else
{
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
// Check if window has only single tab
if (hasNoChildPanels && _toMove.TabsCount == 1)
{
// Dock window
_toMove.GetTab(0).Show(_toSet, _toDock);
}
// Check if dock as tab and has no child panels
else if (hasNoChildPanels && _toSet == DockState.DockFill)
{
// Dock all tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
}
}
else
{
var selectedTab = _toMove.SelectedTab;
// Dock the first tab into the target location
var firstTab = _toMove.GetTab(0);
firstTab.Show(_toSet, _toDock);
// Dock rest of the tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
}
// Keep selected tab being selected
selectedTab?.SelectTab();
}
// Focus target window
_toDock.Root.Focus();
}
_toMove = null;
}
/// <summary>
/// Creates the new dragging hit window.
/// </summary>
/// <param name="toMove">Floating dock panel to move.</param>
/// <returns>The dock hint window object.</returns>
public static DockHintWindow Create(FloatWindowDockPanel toMove)
{
if (toMove == null)
throw new ArgumentNullException();
return new DockHintWindow(toMove);
}
/// <summary>
/// Creates the new dragging hit window.
/// </summary>
/// <param name="toMove">Dock window to move.</param>
/// <returns>The dock hint window object.</returns>
public static DockHintWindow Create(DockWindow toMove)
{
if (toMove == null)
throw new ArgumentNullException();
// Show floating
toMove.ShowFloating();
// Move window to the mouse position (with some offset for caption bar)
var window = (WindowRootControl)toMove.Root;
var mouse = Platform.MousePosition;
window.Window.Position = mouse - new Float2(8, 8);
// Get floating panel
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
return new DockHintWindow(floatingPanelToMove);
}
/// <summary>
/// Calculates window rectangle in the dock window.
/// </summary>
/// <param name="state">Window dock state.</param>
/// <param name="rect">Dock panel rectangle.</param>
/// <returns>Calculated window rectangle.</returns>
public static Rectangle CalculateDockRect(DockState state, ref Rectangle rect)
{
Rectangle result = rect;
switch (state)
{
case DockState.DockFill:
result.Location.Y += DockPanel.DefaultHeaderHeight;
result.Size.Y -= DockPanel.DefaultHeaderHeight;
break;
case DockState.DockTop:
result.Size.Y *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockLeft:
result.Size.X *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockBottom:
result.Location.Y += result.Size.Y * (1 - DockPanel.DefaultSplitterValue);
result.Size.Y *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockRight:
result.Location.X += result.Size.X * (1 - DockPanel.DefaultSplitterValue);
result.Size.X *= DockPanel.DefaultSplitterValue;
break;
}
return result;
}
private void CalculateDragOffset(Float2 mouseScreenPosition)
{
var baseWinPos = _toMove.Window.Window.Position;
_dragOffset = mouseScreenPosition - baseWinPos;
}
private void UpdateRects()
{
// Cache mouse position
_mouse = Platform.MousePosition;
// Check intersection with any dock panel
var uiMouse = _mouse;
_toDock = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
// Check dock state to use
bool showProxyHints = _toDock != null;
bool showBorderHints = showProxyHints;
bool showCenterHint = showProxyHints;
if (showProxyHints)
{
// If moved window has not only tabs but also child panels disable docking as tab
if (_toMove.ChildPanelsCount > 0)
showCenterHint = false;
// Disable docking windows with one or more dock panels inside
if (_toMove.ChildPanelsCount > 0)
showBorderHints = false;
// Get dock area
_rectDock = _toDock.DockAreaBounds;
// Cache dock rectangles
var size = _rectDock.Size;
var offset = _rectDock.Location;
var borderMargin = 4.0f;
var hintWindowsSize = Proxy.HintWindowsSize * Platform.DpiScale;
var hintWindowsSize2 = hintWindowsSize * 0.5f;
var centerX = size.X * 0.5f;
var centerY = size.Y * 0.5f;
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
// Hit test
DockState toSet = DockState.Float;
if (showBorderHints)
{
if (_rUpper.Contains(_mouse))
toSet = DockState.DockTop;
else if (_rBottom.Contains(_mouse))
toSet = DockState.DockBottom;
else if (_rLeft.Contains(_mouse))
toSet = DockState.DockLeft;
else if (_rRight.Contains(_mouse))
toSet = DockState.DockRight;
}
if (showCenterHint && _rCenter.Contains(_mouse))
toSet = DockState.DockFill;
_toSet = toSet;
// Show proxy hint windows
Proxy.Down.Position = _rBottom.Location;
Proxy.Left.Position = _rLeft.Location;
Proxy.Right.Position = _rRight.Location;
Proxy.Up.Position = _rUpper.Location;
Proxy.Center.Position = _rCenter.Location;
}
else
{
_toSet = DockState.Float;
}
// Update proxy hint windows visibility
Proxy.Down.IsVisible = showProxyHints & showBorderHints;
Proxy.Left.IsVisible = showProxyHints & showBorderHints;
Proxy.Right.IsVisible = showProxyHints & showBorderHints;
Proxy.Up.IsVisible = showProxyHints & showBorderHints;
Proxy.Center.IsVisible = showProxyHints & showCenterHint;
// Calculate proxy/dock/window rectangles
if (_toDock == null)
{
// Floating window over nothing
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
}
else
{
if (_toSet == DockState.Float)
{
// Floating window over dock panel
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
}
else
{
// Use only part of the dock panel to show hint
_rectWindow = CalculateDockRect(_toSet, ref _rectDock);
}
}
// Update proxy window
Proxy.Window.ClientBounds = _rectWindow;
}
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
{
if (button == MouseButton.Left)
{
Dispose();
}
}
private void OnMouseMove(ref Float2 mousePos)
{
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
if (_lateDragOffsetUpdate)
{
// Calculate dragging offset and move window to the destination position
CalculateDragOffset(mousePos);
// Reset state
_lateDragOffsetUpdate = false;
}
UpdateRects();
}
private void OnLostFocus()
{
Dispose();
}
/// <summary>
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
/// </summary>
public static class Proxy
{
/// <summary>
/// The drag proxy window.
/// </summary>
public static Window Window;
/// <summary>
/// The left hint proxy window.
/// </summary>
public static Window Left;
/// <summary>
/// The right hint proxy window.
/// </summary>
public static Window Right;
/// <summary>
/// The up hint proxy window.
/// </summary>
public static Window Up;
/// <summary>
/// The down hint proxy window.
/// </summary>
public static Window Down;
/// <summary>
/// The center hint proxy window.
/// </summary>
public static Window Center;
/// <summary>
/// The hint windows size.
/// </summary>
public const float HintWindowsSize = 32.0f;
/// <summary>
/// Initializes the hit proxy windows. Those windows are used to indicate drag target areas (left, right, top, bottom, etc.).
/// </summary>
public static void InitHitProxy()
{
CreateProxy(ref Left, "DockHint.Left");
CreateProxy(ref Right, "DockHint.Right");
CreateProxy(ref Up, "DockHint.Up");
CreateProxy(ref Down, "DockHint.Down");
CreateProxy(ref Center, "DockHint.Center");
}
/// <summary>
/// Initializes the hint window.
/// </summary>
/// <param name="initSize">Initial size of the proxy window.</param>
public static void Init(ref Float2 initSize)
{
if (Window == null)
{
var settings = CreateWindowSettings.Default;
settings.Title = "DockHint.Window";
settings.Size = initSize;
settings.AllowInput = true;
settings.AllowMaximize = false;
settings.AllowMinimize = false;
settings.HasBorder = false;
settings.HasSizingFrame = false;
settings.IsRegularWindow = false;
settings.SupportsTransparency = true;
settings.ShowInTaskbar = false;
settings.ShowAfterFirstPaint = false;
settings.IsTopmost = true;
Window = Platform.CreateWindow(ref settings);
Window.Opacity = 0.6f;
Window.GUI.BackgroundColor = Style.Current.Selection;
Window.GUI.AddChild<DragVisuals>();
}
else
{
// Resize proxy
Window.ClientSize = initSize;
}
InitHitProxy();
}
private sealed class DragVisuals : Control
{
public DragVisuals()
{
AnchorPreset = AnchorPresets.StretchAll;
Offsets = Margin.Zero;
}
public override void Draw()
{
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
}
}
private static void CreateProxy(ref Window win, string name)
{
if (win != null)
return;
var settings = CreateWindowSettings.Default;
settings.Title = name;
settings.Size = new Float2(HintWindowsSize * Platform.DpiScale);
settings.AllowInput = false;
settings.AllowMaximize = false;
settings.AllowMinimize = false;
settings.HasBorder = false;
settings.HasSizingFrame = false;
settings.IsRegularWindow = false;
settings.SupportsTransparency = true;
settings.ShowInTaskbar = false;
settings.ActivateWhenFirstShown = false;
settings.IsTopmost = true;
settings.ShowAfterFirstPaint = false;
win = Platform.CreateWindow(ref settings);
win.Opacity = 0.6f;
win.GUI.BackgroundColor = Style.Current.Selection;
win.GUI.AddChild<DragVisuals>();
}
/// <summary>
/// Hides proxy windows.
/// </summary>
public static void Hide()
{
HideProxy(ref Window);
HideProxy(ref Left);
HideProxy(ref Right);
HideProxy(ref Up);
HideProxy(ref Down);
HideProxy(ref Center);
}
private static void HideProxy(ref Window win)
{
if (win)
{
win.Hide();
}
}
/// <summary>
/// Releases proxy data and windows.
/// </summary>
public static void Dispose()
{
DisposeProxy(ref Window);
DisposeProxy(ref Left);
DisposeProxy(ref Right);
DisposeProxy(ref Up);
DisposeProxy(ref Down);
DisposeProxy(ref Center);
}
private static void DisposeProxy(ref Window win)
{
if (win)
{
win.Close(ClosingReason.User);
win = null;
}
}
}
}
}

View File

@@ -50,6 +50,11 @@ namespace FlaxEditor.GUI.Docking
/// </summary>
public Float2 MousePosition = Float2.Minimum;
/// <summary>
/// The mouse position.
/// </summary>
public Float2 MouseStartPosition = Float2.Minimum;
/// <summary>
/// The start drag asynchronous window.
/// </summary>
@@ -165,7 +170,7 @@ namespace FlaxEditor.GUI.Docking
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
{
// Create docking hint window but in an async manner
DockHintWindow.Create(_panel as FloatWindowDockPanel);
WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
}
else
{
@@ -176,7 +181,7 @@ namespace FlaxEditor.GUI.Docking
_panel.SelectTab(index - 1);
// Create docking hint window
DockHintWindow.Create(win);
WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
}
}
}
@@ -355,6 +360,7 @@ namespace FlaxEditor.GUI.Docking
if (IsSingleFloatingWindow)
return base.OnMouseDown(location, button);
MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross);
MouseStartPosition = location;
// Check buttons
if (button == MouseButton.Left)
@@ -441,6 +447,20 @@ namespace FlaxEditor.GUI.Docking
StartDrag(MouseDownWindow);
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
else if (MouseDownWindow != null && _panel.TabsCount > 1)
{

View File

@@ -182,6 +182,25 @@ namespace FlaxEditor.GUI.Docking
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
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();
@@ -199,6 +218,8 @@ namespace FlaxEditor.GUI.Docking
windowGUI.UnlockChildrenRecursive();
windowGUI.PerformLayout();
if (showWindow)
{
// Show
window.Show();
window.BringToFront();
@@ -208,6 +229,7 @@ namespace FlaxEditor.GUI.Docking
// Perform layout again
windowGUI.PerformLayout();
}
}
/// <summary>
/// Shows the window.

View File

@@ -11,6 +11,42 @@ namespace FlaxEditor.GUI.Docking
/// <seealso cref="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 WindowRootControl _window;
@@ -40,6 +76,26 @@ namespace FlaxEditor.GUI.Docking
Parent = window;
_window.Window.Closing += OnClosing;
_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>
@@ -52,7 +108,7 @@ namespace FlaxEditor.GUI.Docking
return;
// Create docking hint window
DockHintWindow.Create(this);
WindowDragHelper.StartDragging(this);
}
/// <summary>
@@ -71,23 +127,29 @@ namespace FlaxEditor.GUI.Docking
settings.Title = title;
settings.Size = size;
settings.Position = location;
settings.MinimumSize = new Float2(1);
settings.MinimumSize = new Float2(200, 150);
settings.MaximumSize = Float2.Zero; // Unlimited size
settings.Fullscreen = false;
settings.HasBorder = true;
settings.SupportsTransparency = false;
settings.SupportsTransparency = true;
settings.ActivateWhenFirstShown = true;
settings.AllowInput = true;
settings.AllowMinimize = true;
settings.AllowMaximize = true;
settings.AllowDragAndDrop = true;
settings.IsTopmost = false;
settings.IsRegularWindow = true;
settings.Type = WindowType.Regular;
settings.HasSizingFrame = true;
settings.ShowAfterFirstPaint = false;
settings.ShowInTaskbar = true;
settings.StartPosition = startPosition;
if (Utilities.Utils.UseCustomWindowDecorations())
{
settings.HasBorder = false;
//settings.HasSizingFrame = false;
}
// Create window
return Platform.CreateWindow(ref settings);
}

View File

@@ -81,7 +81,6 @@ namespace FlaxEditor.GUI.Docking
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
{
// Check all floating windows
// TODO: gather windows order and take it into account when performing test
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
@@ -94,9 +93,44 @@ namespace FlaxEditor.GUI.Docking
}
// Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
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)
{
// Add to the windows list

View File

@@ -0,0 +1,458 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI.Docking
{
/// <summary>
/// Helper class used to handle docking windows dragging and docking.
/// </summary>
public class WindowDragHelper
{
private FloatWindowDockPanel _toMove;
private Float2 _dragOffset;
private Rectangle _rectDock;
private Float2 _mouse;
private DockState _toSet;
private DockPanel _toDock;
private Window _dragSourceWindow;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
private Control _dockHintDown, _dockHintUp, _dockHintLeft, _dockHintRight, _dockHintCenter;
/// <summary>
/// The hint control size.
/// </summary>
public const float HintControlSize = 32.0f;
/// <summary>
/// The opacity of the dragged window when hint controls are shown.
/// </summary>
public const float DragWindowOpacity = 0.4f;
/// <summary>
/// Returns true if any windows are being dragged.
/// </summary>
public static bool IsDragActive { get; private set; }
private WindowDragHelper(FloatWindowDockPanel toMove, Window dragSourceWindow)
{
IsDragActive = true;
_toMove = toMove;
_toSet = DockState.Float;
var window = toMove.Window.Window;
// Bind events
FlaxEngine.Scripting.Update += OnUpdate;
window.MouseUp += OnMouseUp;
// Update rectangles
UpdateRects(Platform.MousePosition);
// Ensure the dragged window stays on top of every other window
window.IsAlwaysOnTop = true;
_dragSourceWindow = dragSourceWindow;
if (_dragSourceWindow != null) // Detaching a tab from existing window
{
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
_dragSourceWindow.MouseUp += OnMouseUp; // The mouse up event is sent to the source window on Windows
// TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
window.DoDragDrop(window.Title, _dragOffset, dragSourceWindowWayland);
}
else
{
_dragOffset = window.MousePosition;
window.DoDragDrop(window.Title, _dragOffset, window);
}
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
public void Dispose()
{
IsDragActive = false;
var window = _toMove?.Window?.Window;
// Unbind events
FlaxEngine.Scripting.Update -= OnUpdate;
if (window != null)
window.MouseUp -= OnMouseUp;
if (_dragSourceWindow != null)
_dragSourceWindow.MouseUp -= OnMouseUp;
RemoveDockHints();
if (_toMove == null)
return;
if (window != null)
{
window.Opacity = 1.0f;
window.IsAlwaysOnTop = false;
window.BringToFront();
}
// Check if window won't be docked
if (_toSet == DockState.Float)
{
if (window == null)
return;
// Show base window
window.Show();
}
else
{
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
// Check if window has only single tab
if (hasNoChildPanels && _toMove.TabsCount == 1)
{
// Dock window
_toMove.GetTab(0).Show(_toSet, _toDock);
}
// Check if dock as tab and has no child panels
else if (hasNoChildPanels && _toSet == DockState.DockFill)
{
// Dock all tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
}
}
else
{
var selectedTab = _toMove.SelectedTab;
// Dock the first tab into the target location
if (_toMove.TabsCount > 0)
{
var firstTab = _toMove.GetTab(0);
firstTab.Show(_toSet, _toDock);
// Dock rest of the tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
}
}
// Keep selected tab being selected
selectedTab?.SelectTab();
}
// Focus target window
_toDock.Root.Focus();
}
_toMove = null;
}
/// <summary>
/// Start dragging a floating dock panel.
/// </summary>
/// <param name="toMove">Floating dock panel to move.</param>
/// <returns>The window drag helper object.</returns>
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove)
{
if (toMove == null)
throw new ArgumentNullException();
return new WindowDragHelper(toMove, null);
}
/// <summary>
/// Start dragging a docked panel into a floating window.
/// </summary>
/// <param name="toMove">Dock window to move.</param>
/// <param name="dragSourceWindow">The window where dragging started from.</param>
/// <returns>The window drag helper object.</returns>
public static WindowDragHelper StartDragging(DockWindow toMove, Window dragSourceWindow)
{
if (toMove == null)
throw new ArgumentNullException();
// Create floating window
toMove.CreateFloating();
// Get floating panel
var window = (WindowRootControl)toMove.Root;
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
return new WindowDragHelper(floatingPanelToMove, dragSourceWindow);
}
private sealed class DragVisuals : Control
{
public DragVisuals()
{
AnchorPreset = AnchorPresets.StretchAll;
Offsets = Margin.Zero;
}
public override void Draw()
{
base.Draw();
Render2D.DrawRectangle(new Rectangle(Float2.Zero, Size), Style.Current.SelectionBorder);
}
}
private void AddDockHints()
{
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp += OnMouseUp;
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
Control AddHintControl(Float2 pivot)
{
DragVisuals hintControl = _toDock.AddChild<DragVisuals>();
hintControl.Size = new Float2(HintControlSize);
hintControl.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
hintControl.Pivot = pivot;
hintControl.PivotRelative = true;
return hintControl;
}
}
private void RemoveDockHints()
{
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
_dockHintRight?.Parent.RemoveChild(_dockHintRight);
_dockHintCenter?.Parent.RemoveChild(_dockHintCenter);
_dockHintDown = _dockHintUp = _dockHintLeft = _dockHintRight = _dockHintCenter = null;
}
private void UpdateRects(Float2 mousePos)
{
// Cache mouse position
_mouse = mousePos;
// Check intersection with any dock panel
DockPanel dockPanel = null;
if (_toMove.MasterPanel.HitTest(ref _mouse, _toMove, out var hitResults))
{
dockPanel = hitResults[0];
// Prefer panel which currently has focus
foreach (var hit in hitResults)
{
if (hit.RootWindow.Window.IsFocused)
{
dockPanel = hit;
break;
}
}
// Prefer panel in the same window we hit earlier
if (dockPanel?.RootWindow != _toDock?.RootWindow)
{
foreach (var hit in hitResults)
{
if (hit.RootWindow == _toDock?.RootWindow)
{
dockPanel = _toDock;
break;
}
}
}
}
if (dockPanel != _toDock)
{
RemoveDockHints();
_toDock = dockPanel;
AddDockHints();
// Make sure the all the dock hint areas are not under other windows
_toDock?.RootWindow.Window.BringToFront();
//_toDock?.RootWindow.Window.Focus();
// Make the dragged window transparent when dock hints are visible
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
}
// Check dock state to use
bool showProxyHints = _toDock != null;
bool showBorderHints = showProxyHints;
bool showCenterHint = showProxyHints;
Control hoveredHintControl = null;
Float2 hoveredSizeOverride = Float2.Zero;
if (showProxyHints)
{
// If moved window has not only tabs but also child panels disable docking as tab
if (_toMove.ChildPanelsCount > 0)
showCenterHint = false;
// Disable docking windows with one or more dock panels inside
if (_toMove.ChildPanelsCount > 0)
showBorderHints = false;
// Get dock area
_rectDock = _toDock.DockAreaBounds;
// Cache dock rectangles
var size = _rectDock.Size / Platform.DpiScale;
var offset = _toDock.PointFromScreen(_rectDock.Location);
var borderMargin = 4.0f;
var hintWindowsSize = HintControlSize;
var hintWindowsSize2 = hintWindowsSize * 0.5f;
var hintPreviewSize = new Float2(Math.Max(HintControlSize * 2, size.X * 0.5f), Math.Max(HintControlSize * 2, size.Y * 0.5f));
var centerX = size.X * 0.5f;
var centerY = size.Y * 0.5f;
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
// Hit test, and calculate the approximation for filled area when hovered over the hint
DockState toSet = DockState.Float;
if (showBorderHints)
{
if (_rUpper.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockTop;
hoveredHintControl = _dockHintUp;
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
}
else if (_rBottom.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockBottom;
hoveredHintControl = _dockHintDown;
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
}
else if (_rLeft.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockLeft;
hoveredHintControl = _dockHintLeft;
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
}
else if (_rRight.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockRight;
hoveredHintControl = _dockHintRight;
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
}
}
if (showCenterHint && _rCenter.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockFill;
hoveredHintControl = _dockHintCenter;
hoveredSizeOverride = new Float2(size.X, size.Y);
}
_toSet = toSet;
}
else
{
_toSet = DockState.Float;
}
// Update sizes and opacity of hint controls
if (_toDock != null)
{
if (hoveredHintControl != _dockHintDown)
{
_dockHintDown.Size = new Float2(HintControlSize);
_dockHintDown.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintLeft)
{
_dockHintLeft.Size = new Float2(HintControlSize);
_dockHintLeft.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintRight)
{
_dockHintRight.Size = new Float2(HintControlSize);
_dockHintRight.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintUp)
{
_dockHintUp.Size = new Float2(HintControlSize);
_dockHintUp.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintCenter)
{
_dockHintCenter.Size = new Float2(HintControlSize);
_dockHintCenter.BackgroundColor = Style.Current.Selection.AlphaMultiplied(0.6f);
}
if (_toSet != DockState.Float)
{
if (hoveredHintControl != null)
{
hoveredHintControl.BackgroundColor = Style.Current.Selection.AlphaMultiplied(1.0f);
hoveredHintControl.Size = hoveredSizeOverride;
}
}
}
// Update hint controls visibility and location
if (showProxyHints)
{
if (hoveredHintControl != _dockHintDown)
_dockHintDown.Location = _rBottom.Location;
if (hoveredHintControl != _dockHintLeft)
_dockHintLeft.Location = _rLeft.Location;
if (hoveredHintControl != _dockHintRight)
_dockHintRight.Location = _rRight.Location;
if (hoveredHintControl != _dockHintUp)
_dockHintUp.Location = _rUpper.Location;
if (hoveredHintControl != _dockHintCenter)
_dockHintCenter.Location = _rCenter.Location;
_dockHintDown.Visible = showProxyHints & showBorderHints;
_dockHintLeft.Visible = showProxyHints & showBorderHints;
_dockHintRight.Visible = showProxyHints & showBorderHints;
_dockHintUp.Visible = showProxyHints & showBorderHints;
_dockHintCenter.Visible = showProxyHints & showCenterHint;
}
}
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
{
if (button == MouseButton.Left)
Dispose();
}
private void OnUpdate()
{
var mousePos = Platform.MousePosition;
if (_mouse != mousePos)
OnMouseMove(mousePos);
}
private void OnMouseMove(Float2 mousePos)
{
if (_dragSourceWindow != null)
_toMove.Window.Window.Position = mousePos - _dragOffset;
UpdateRects(mousePos);
}
}
}

View File

@@ -41,7 +41,7 @@ namespace FlaxEditor.GUI.Input
get => _min;
set
{
if (!Mathd.NearEqual(_min, value))
if (_min != value)
{
if (value > _max)
throw new ArgumentException();
@@ -58,7 +58,7 @@ namespace FlaxEditor.GUI.Input
get => _max;
set
{
if (!Mathd.NearEqual(_max, value))
if (_max != value)
{
if (value < _min)
throw new ArgumentException();

View File

@@ -38,7 +38,7 @@ namespace FlaxEditor.GUI.Input
get => _min;
set
{
if (!Mathf.NearEqual(_min, value))
if (_min != value)
{
if (value > _max)
throw new ArgumentException();
@@ -54,7 +54,7 @@ namespace FlaxEditor.GUI.Input
get => _max;
set
{
if (!Mathf.NearEqual(_max, value))
if (_max != value)
{
if (value < _min)
throw new ArgumentException();

View File

@@ -54,7 +54,7 @@ namespace FlaxEditor.GUI.Input
set
{
value = Mathf.Clamp(value, Minimum, Maximum);
if (!Mathf.NearEqual(value, _value))
if (value != _value)
{
_value = value;
@@ -311,7 +311,7 @@ namespace FlaxEditor.GUI.Input
get => _min;
set
{
if (!Mathf.NearEqual(_min, value))
if (_min != value)
{
if (value > _max)
throw new ArgumentException();
@@ -330,7 +330,7 @@ namespace FlaxEditor.GUI.Input
get => _max;
set
{
if (!Mathf.NearEqual(_max, value))
if (_max != value)
{
if (value < _min)
throw new ArgumentException();

View File

@@ -266,6 +266,7 @@ namespace FlaxEditor.GUI.Input
return base.OnMouseDown(location, button);
}
#if !PLATFORM_SDL
/// <inheritdoc />
public override void OnMouseMove(Float2 location)
{
@@ -292,13 +293,45 @@ namespace FlaxEditor.GUI.Input
base.OnMouseMove(location);
}
#else
/// <inheritdoc />
public override void OnMouseMoveRelative(Float2 mouseMotion)
{
var location = Root.TrackingMouseOffset;
if (_isSliding)
{
// Update sliding
ApplySliding(Root.TrackingMouseOffset.X * _slideSpeed);
return;
}
// Update cursor type so user knows they can slide value
if (CanUseSliding && SlideRect.Contains(location) && !_isSliding)
{
Cursor = CursorType.SizeWE;
_cursorChanged = true;
}
else if (_cursorChanged && !_isSliding)
{
Cursor = CursorType.Default;
_cursorChanged = false;
}
base.OnMouseMoveRelative(mouseMotion);
}
#endif
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (button == MouseButton.Left && _isSliding)
{
#if !PLATFORM_SDL
// End sliding and return mouse to original location
RootWindow.MousePosition = _mouseClickedPosition;
#endif
EndSliding();
return true;
}

View File

@@ -227,9 +227,8 @@ namespace FlaxEditor.GUI
{
int order = -1 * SortScore.CompareTo(otherItem.SortScore);
if (order == 0)
{
order = string.Compare(Name, otherItem.Name, StringComparison.Ordinal);
}
return order;
}
return base.Compare(other);
@@ -509,7 +508,7 @@ namespace FlaxEditor.GUI
OnSearchFilterChanged();
}
private List<Item> GetVisibleItems()
private List<Item> GetVisibleItems(bool ignoreFoldedCategories)
{
var result = new List<Item>();
var items = ItemsPanel.Children;
@@ -523,7 +522,7 @@ namespace FlaxEditor.GUI
for (int i = 0; i < _categoryPanels.Count; i++)
{
var category = _categoryPanels[i];
if (!category.Visible)
if (!category.Visible || (ignoreFoldedCategories && category is DropPanel panel && panel.IsClosed))
continue;
for (int j = 0; j < category.Children.Count; j++)
{
@@ -535,6 +534,12 @@ namespace FlaxEditor.GUI
return result;
}
private void ExpandToItem(Item item)
{
if (item.Parent is DropPanel dropPanel)
dropPanel.Open(false);
}
/// <inheritdoc />
protected override void OnShow()
{
@@ -563,8 +568,17 @@ namespace FlaxEditor.GUI
case KeyboardKeys.Escape:
Hide();
return true;
case KeyboardKeys.ArrowDown:
case KeyboardKeys.Backspace:
// Allow the user to quickly focus the searchbar
if (_searchBox != null && !_searchBox.IsFocused)
{
_searchBox.Focus();
_searchBox.SelectAll();
return true;
}
break;
case KeyboardKeys.ArrowDown:
case KeyboardKeys.ArrowUp:
if (RootWindow.FocusedControl == null)
{
// Focus search box if nothing is focused
@@ -572,45 +586,44 @@ namespace FlaxEditor.GUI
return true;
}
// Focus the first visible item or then next one
var items = GetVisibleItems();
// Get the next item
bool controlDown = Root.GetKey(KeyboardKeys.Control);
var items = GetVisibleItems(!controlDown);
var focusedIndex = items.IndexOf(focusedItem);
if (focusedIndex == -1)
focusedIndex = -1;
if (focusedIndex + 1 < items.Count)
{
var item = items[focusedIndex + 1];
item.Focus();
_scrollPanel.ScrollViewTo(item);
// If the user hasn't selected anything yet and is holding control, focus first folded item
if (focusedIndex == -1 && controlDown)
focusedIndex = GetVisibleItems(true).Count - 1;
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, items.Count - 1);
var nextItem = items[nextIndex];
// Focus the next item
nextItem.Focus();
// Allow the user to expand groups while scrolling
if (controlDown)
ExpandToItem(nextItem);
_scrollPanel.ScrollViewTo(nextItem);
return true;
}
break;
}
case KeyboardKeys.ArrowUp:
if (focusedItem != null)
{
// Focus the previous visible item or the search box
var items = GetVisibleItems();
var focusedIndex = items.IndexOf(focusedItem);
if (focusedIndex == 0)
{
_searchBox?.Focus();
}
else if (focusedIndex > 0)
{
var item = items[focusedIndex - 1];
item.Focus();
_scrollPanel.ScrollViewTo(item);
return true;
}
}
break;
case KeyboardKeys.Return:
if (focusedItem != null)
{
OnClickItem(focusedItem);
return true;
}
else
{
// Select first item if no item is focused (most likely to be the best result), saves the user from pressing arrow down first
var visibleItems = GetVisibleItems(true);
if (visibleItems.Count > 0)
{
OnClickItem(visibleItems[0]);
return true;
}
}
break;
}

View File

@@ -12,16 +12,6 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.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;
/// <summary>
@@ -60,200 +50,12 @@ namespace FlaxEditor.GUI
/// <summary>
/// Initializes a new instance of the <see cref="MainMenu"/> class.
/// </summary>
/// <param name="mainWindow">The main window.</param>
public MainMenu(RootControl mainWindow)
public MainMenu()
: base(0, 0, 0, 20)
{
AutoFocus = false;
AnchorPreset = AnchorPresets.HorizontalStretchTop;
#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>
@@ -266,6 +68,19 @@ namespace FlaxEditor.GUI
return AddChild(new MainMenuButton(text));
}
/// <summary>
/// Gets or adds a button.
/// </summary>
/// <param name="text">The button text</param>
/// <returns>The existing or created button control.</returns>
public MainMenuButton GetOrAddButton(string text)
{
MainMenuButton result = GetButton(text);
if (result == null)
result = AddButton(text);
return result;
}
/// <summary>
/// Gets the button.
/// </summary>
@@ -285,26 +100,6 @@ namespace FlaxEditor.GUI
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 />
public override bool OnKeyDown(KeyboardKeys key)
{
@@ -320,16 +115,8 @@ namespace FlaxEditor.GUI
protected override void PerformLayoutAfterChildren()
{
float x = 0;
#if PLATFORM_WINDOWS
if (_useCustomWindowSystem)
{
// Icon
_icon.X = x;
_icon.Size = new Float2(Height);
x += _icon.Width;
}
#endif
WindowDecorations decorations = Parent.GetChild<WindowDecorations>();
x += decorations?.Icon?.Width ?? 0;
// Arrange controls
MainMenuButton rightMostButton = null;
@@ -349,36 +136,20 @@ namespace FlaxEditor.GUI
}
}
#if PLATFORM_WINDOWS
if (_useCustomWindowSystem)
{
// Buttons
_closeButton.Height = Height;
_closeButton.X = Width - _closeButton.Width;
_maximizeButton.Height = Height;
_maximizeButton.X = _closeButton.X - _maximizeButton.Width;
_minimizeButton.Height = Height;
_minimizeButton.X = _maximizeButton.X - _minimizeButton.Width;
// Title
_title.Bounds = new Rectangle(x + 2, 0, _minimizeButton.Left - x - 4, Height);
//_title.Text = _title.Width < 300.0f ? Editor.Instance.ProjectInfo.Name : _window.Title;
}
#endif
// Fill the right side if title and buttons are not present
if (decorations?.Title == null)
Width = Parent.Width;
else
Width = x;
}
#if PLATFORM_WINDOWS
/// <inheritdoc />
public override void OnDestroy()
{
base.OnDestroy();
if (_window != null)
{
_window.Closed -= OnWindowClosed;
OnWindowClosed();
if (_selected != null)
Selected = null;
}
}
#endif
}
}

View File

@@ -42,14 +42,12 @@ namespace FlaxEditor.GUI
Text = text;
var style = Style.Current;
#if PLATFORM_WINDOWS
if (Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
if (!Utilities.Utils.UseCustomWindowDecorations())
{
BackgroundColorMouseOver = style.BackgroundHighlighted;
BackgroundColorMouseOverOpened = style.Background;
}
else
#endif
{
BackgroundColorMouseOver = BackgroundColorMouseOverOpened = style.LightBackground * 1.3f;
}

View File

@@ -47,6 +47,7 @@ namespace FlaxEditor.GUI.Tabs
if (EnabledInHierarchy && Tab.Enabled)
{
Tabs.SelectedTab = Tab;
Tab.PerformLayout(true);
Tabs.Focus();
}
return true;

View File

@@ -122,6 +122,14 @@ namespace FlaxEditor.GUI
return this;
}
private void OnClicked()
{
if (AutoCheck)
Checked = !Checked;
Clicked?.Invoke();
(Parent as ToolStrip)?.OnButtonClicked(this);
}
/// <inheritdoc />
public override void Draw()
{
@@ -196,11 +204,7 @@ namespace FlaxEditor.GUI
if (button == MouseButton.Left && _primaryMouseDown)
{
_primaryMouseDown = false;
if (AutoCheck)
Checked = !Checked;
Clicked?.Invoke();
(Parent as ToolStrip)?.OnButtonClicked(this);
OnClicked();
return true;
}
if (button == MouseButton.Right && _secondaryMouseDown)
@@ -215,6 +219,18 @@ namespace FlaxEditor.GUI
return base.OnMouseUp(location, button);
}
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (button == MouseButton.Left)
{
OnClicked();
return true;
}
return false;
}
/// <inheritdoc />
public override void OnMouseLeave()
{

View File

@@ -40,6 +40,7 @@ namespace FlaxEditor.GUI.Tree
private readonly bool _supportMultiSelect;
private Margin _margin;
private bool _autoSize = true;
private bool _deferLayoutUpdate = false;
/// <summary>
/// The TreeNode that is being dragged over. This could have a value when not dragging.
@@ -67,6 +68,16 @@ namespace FlaxEditor.GUI.Tree
/// </summary>
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
/// <summary>
/// Allow nodes to Draw the root tree line.
/// </summary>
public bool DrawRootTreeLine = true;
/// <summary>
/// Occurs when the deferred layout operation was performed.
/// </summary>
public event Action AfterDeferredLayout;
/// <summary>
/// Gets or sets the margin for the child tree nodes.
/// </summary>
@@ -353,9 +364,26 @@ namespace FlaxEditor.GUI.Tree
BulkSelectUpdateExpanded(false);
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
if (_isLayoutLocked && !force)
return;
// In case the tree was fully expanded or collapsed along its children, avoid calculating the layout multiple times for each child
_deferLayoutUpdate = true;
}
/// <inheritdoc />
public override void Update(float deltaTime)
{
if (_deferLayoutUpdate)
{
base.PerformLayout();
AfterDeferredLayout?.Invoke();
_deferLayoutUpdate = false;
}
var node = SelectedNode;
// Check if has focus and if any node is focused and it isn't a root

View File

@@ -760,20 +760,21 @@ namespace FlaxEditor.GUI.Tree
// Show tree guidelines
if (Editor.Instance.Options.Options.Interface.ShowTreeLines)
{
TreeNode parentNode = Parent as TreeNode;
ContainerControl parent = Parent;
TreeNode parentNode = parent as TreeNode;
bool thisNodeIsLast = false;
while (parentNode != null && parentNode != ParentTree.Children[0])
while (parentNode != null && (parentNode != tree.Children[0] || tree.DrawRootTreeLine))
{
float bottomOffset = 0;
float topOffset = 0;
if (Parent == parentNode && this == Parent.Children[0])
if (parent == parentNode && this == parent.Children[0])
topOffset = 2;
if (thisNodeIsLast && parentNode.Children.Count == 1)
bottomOffset = topOffset != 0 ? 4 : 2;
if (Parent == parentNode && this == Parent.Children[Parent.Children.Count - 1] && !_opened)
if (parent == parentNode && this == parent.Children[^1] && !_opened)
{
thisNodeIsLast = true;
bottomOffset = topOffset != 0 ? 4 : 2;
@@ -784,6 +785,8 @@ namespace FlaxEditor.GUI.Tree
if (_iconCollaped.IsValid)
leftOffset += 18;
var lineRect1 = new Rectangle(parentNode.TextRect.Left - leftOffset, parentNode.HeaderRect.Top + topOffset, 1, parentNode.HeaderRect.Height - bottomOffset);
if (HasAnyVisibleChild && CustomArrowRect.HasValue && CustomArrowRect.Value.Intersects(lineRect1))
lineRect1 = Rectangle.Empty; // Skip drawing line if it's overlapping the arrow rectangle
Render2D.FillRectangle(lineRect1, isSelected ? style.ForegroundGrey : style.LightBackground);
parentNode = parentNode.Parent as TreeNode;
}

View File

@@ -0,0 +1,342 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI;
/// <summary>
/// Represents the title bar of the window with buttons.
/// </summary>
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
public class WindowDecorations : ContainerControl
{
private Image _icon;
private Label _title;
private Button _closeButton;
private Button _minimizeButton;
private Button _maximizeButton;
private LocalizedString _charChromeRestore, _charChromeMaximize;
private Window _window;
/// <summary>
/// The title label in the title bar.
/// </summary>
public Label Title => _title;
/// <summary>
/// The icon used in the title bar.
/// </summary>
public Image Icon => _icon;
/// <summary>
/// The tooltip shown when hovering over the icon.
/// </summary>
public string IconTooltipText
{
get => _icon?.TooltipText ?? null;
set
{
if (_icon != null)
_icon.TooltipText = value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="WindowDecorations"/> class.
/// </summary>
/// <param name="window">The window.</param>
/// <param name="iconOnly">When set, omit drawing title and buttons.</param>
public WindowDecorations(RootControl window, bool iconOnly = false)
: base(0, 0, 0, 20)
{
_window = window.RootWindow.Window;
AutoFocus = false;
AnchorPreset = AnchorPresets.HorizontalStretchTop;
BackgroundColor = Color.Transparent;
var windowIcon = FlaxEngine.Content.LoadAsyncInternal<Texture>(EditorAssets.WindowIcon);
_icon = new Image
{
Margin = new Margin(4, 4, 4, 4),
Brush = new TextureBrush(windowIcon),
Color = Style.Current.Foreground,
BackgroundColor = Style.Current.LightBackground,
KeepAspectRatio = false,
Parent = this,
};
if (!iconOnly)
{
_icon.Margin = new Margin(6, 6, 6, 6);
Height = 28;
_window.HitTest += OnHitTest;
_window.Closed += OnWindowClosed;
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.WindowIconsFont);
Font iconFont = windowIconsFont?.CreateFont(9);
_title = new Label(0, 0, Width, Height)
{
Text = _window.Title,
HorizontalAlignment = TextAlignment.Center,
VerticalAlignment = TextAlignment.Center,
ClipText = true,
TextColor = Style.Current.ForegroundGrey,
TextColorHighlighted = Style.Current.ForegroundGrey,
BackgroundColor = Style.Current.LightBackground,
Parent = this,
};
_closeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Style.Current.LightBackground,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Color.Red,
BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
Parent = this,
};
_closeButton.Clicked += () => _window.Close(ClosingReason.User);
_minimizeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Style.Current.LightBackground,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
Parent = this,
};
_minimizeButton.Clicked += () => _window.Minimize();
_maximizeButton = new Button
{
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Style.Current.LightBackground,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
Parent = this,
};
_maximizeButton.Clicked += () =>
{
if (_window.IsMaximized)
_window.Restore();
else
_window.Maximize();
};
_charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
_charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
}
}
/// <inheritdoc />
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (_maximizeButton != null)
{
var maximizeText = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
if (_maximizeButton.Text != maximizeText)
_maximizeButton.Text = maximizeText;
}
}
private void OnWindowClosed()
{
if (_window != null)
{
_window.HitTest -= OnHitTest;
_window = null;
}
}
/// <summary>
/// Perform hit test on the window.
/// </summary>
/// <param name="mouse">The mouse position</param>
/// <returns>The hit code for given position.</returns>
protected virtual WindowHitCodes OnHitTest(ref Float2 mouse)
{
if (_window.IsMinimized)
return WindowHitCodes.NoWhere;
var dpiScale = _window.DpiScale;
var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
if (!_window.IsMaximized)
{
var winSize = _window.Size;
// Distance from which the mouse is considered to be on the border/corner
float distance = 5.0f * dpiScale;
if (pos.Y > winSize.Y - distance && pos.X < distance)
return WindowHitCodes.BottomLeft;
if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
return WindowHitCodes.BottomRight;
if (pos.Y < distance && pos.X < distance)
return WindowHitCodes.TopLeft;
if (pos.Y < distance && pos.X > winSize.X - distance)
return WindowHitCodes.TopRight;
if (pos.X > winSize.X - distance)
return WindowHitCodes.Right;
if (pos.X < distance)
return WindowHitCodes.Left;
if (pos.Y < distance)
return WindowHitCodes.Top;
if (pos.Y > winSize.Y - distance)
return WindowHitCodes.Bottom;
}
var controlUnderMouse = GetChildAt(pos, control => control != _title);
if (_title.Bounds.Contains(pos) && controlUnderMouse == null)
return WindowHitCodes.Caption;
return WindowHitCodes.Client;
}
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
// These may not work with main window due to SDL not passing mouse events
// when interacting with hit tests on caption area...
if (Title.Bounds.Contains(location) && button == MouseButton.Left)
{
if (_window.IsMaximized)
_window.Restore();
else
_window.Maximize();
return true;
}
else if (Icon.Bounds.Contains(location) && button == MouseButton.Left)
{
_window.Close(ClosingReason.User);
return true;
}
return base.OnMouseDoubleClick(location, button);
}
/// <inheritdoc />
protected override void PerformLayoutAfterChildren()
{
// Calculate extents for title bounds area excluding the icon and main menu area
float x = 0;
// Icon
if (_icon != null)
{
_icon.X = x;
_icon.Size = new Float2(Height);
x += _icon.Width;
}
// Main menu if present
if (Parent.GetChild<MainMenu>() is MainMenu mainMenu)
{
for (int i = 0; i < mainMenu.Children.Count; i++)
{
var c = mainMenu.Children[i];
if (c is MainMenuButton b && c.Visible)
{
b.Bounds = new Rectangle(x, 0, b.Width, Height);
x += b.Width;
}
}
}
// Buttons
float rightMostButtonX = Width;
if (_closeButton != null)
{
_closeButton.Height = Height;
_closeButton.X = rightMostButtonX - _closeButton.Width;
rightMostButtonX = _closeButton.X;
}
if (_maximizeButton != null)
{
_maximizeButton.Height = Height;
_maximizeButton.X = rightMostButtonX - _maximizeButton.Width;
rightMostButtonX = _maximizeButton.X;
}
if (_minimizeButton != null)
{
_minimizeButton.Height = Height;
_minimizeButton.X = rightMostButtonX - _minimizeButton.Width;
rightMostButtonX = _minimizeButton.X;
}
// Title
if (_title != null)
{
_title.Text = _window.Title;
_title.Bounds = new Rectangle(x, 0, rightMostButtonX - x, Height);
}
}
/// <inheritdoc />
public override void Draw()
{
base.Draw();
DrawBorders();
}
/// <summary>
/// Draw borders around the window.
/// </summary>
public virtual void DrawBorders()
{
var win = RootWindow.Window;
if (win.IsMaximized)
return;
if (Editor.Instance.UI.StatusBar == null)
return;
const float thickness = 1.0f;
Color color = Editor.Instance.UI.StatusBar.StatusColor;
Rectangle rect = new Rectangle(thickness * 0.5f, thickness * 0.5f, Parent.Width - thickness, Parent.Height - thickness);
Render2D.DrawRectangle(rect, color);
}
/// <inheritdoc />
public override void OnDestroy()
{
base.OnDestroy();
if (_window != null)
{
_window.Closed -= OnWindowClosed;
OnWindowClosed();
}
}
}

View File

@@ -402,10 +402,11 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa
break;
}
}
WindowsManager::WindowsLocker.Unlock();
for (const auto& e : inputEvents)
{
auto window = e.Target ? e.Target : defaultWindow;
if (!window)
if (!window || window->IsClosed())
continue;
switch (e.Type)
{
@@ -435,12 +436,14 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa
case InputDevice::EventType::MouseMove:
window->OnMouseMove(window->ScreenToClient(e.MouseData.Position));
break;
case InputDevice::EventType::MouseMoveRelative:
window->OnMouseMoveRelative(e.MouseMovementData.PositionRelative);
break;
case InputDevice::EventType::MouseLeave:
window->OnMouseLeave();
break;
}
}
WindowsManager::WindowsLocker.Unlock();
}
WindowsManager::WindowsLocker.Lock();
Array<Window*, InlinedAllocation<32>> windows;

View File

@@ -13,6 +13,7 @@
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
#include "Engine/Content/Assets/VisualScript.h"
#include "Engine/Content/Content.h"
#include "Engine/Level/Actor.h"
#include "Engine/CSG/CSGBuilder.h"
#include "Engine/Engine/CommandLine.h"
#include "Engine/Renderer/ProbesRenderer.h"
@@ -74,7 +75,7 @@ void OnLightmapsBuildFinished(bool failed)
OnLightmapsBake(ShadowsOfMordor::BuildProgressStep::GenerateLightmapCharts, 0, 0, false);
}
void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
void OnBakeEvent(bool started, Actor* e)
{
if (Internal_EnvProbeBake == nullptr)
{
@@ -82,7 +83,7 @@ void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
ASSERT(Internal_EnvProbeBake);
}
MObject* probeObj = e.Actor ? e.Actor->GetManagedInstance() : nullptr;
MObject* probeObj = e ? e->GetManagedInstance() : nullptr;
MainThreadManagedInvokeAction::ParamsBuilder params;
params.AddParam(started);
@@ -90,12 +91,12 @@ void OnBakeEvent(bool started, const ProbesRenderer::Entry& e)
MainThreadManagedInvokeAction::Invoke(Internal_EnvProbeBake, params);
}
void OnRegisterBake(const ProbesRenderer::Entry& e)
void OnRegisterBake(Actor* e)
{
OnBakeEvent(true, e);
}
void OnFinishBake(const ProbesRenderer::Entry& e)
void OnFinishBake(Actor* e)
{
OnBakeEvent(false, e);
}
@@ -156,7 +157,9 @@ ManagedEditor::ManagedEditor()
lightmapsBuilder->OnBuildProgress.Bind<OnLightmapsBuildProgress>();
lightmapsBuilder->OnBuildFinished.Bind<OnLightmapsBuildFinished>();
CSG::Builder::OnBrushModified.Bind<OnBrushModified>();
#if LOG_ENABLE
Log::Logger::OnMessage.Bind<OnLogMessage>();
#endif
VisualScripting::DebugFlow.Bind<OnVisualScriptingDebugFlow>();
}
@@ -172,7 +175,9 @@ ManagedEditor::~ManagedEditor()
lightmapsBuilder->OnBuildProgress.Unbind<OnLightmapsBuildProgress>();
lightmapsBuilder->OnBuildFinished.Unbind<OnLightmapsBuildFinished>();
CSG::Builder::OnBrushModified.Unbind<OnBrushModified>();
#if LOG_ENABLE
Log::Logger::OnMessage.Unbind<OnLogMessage>();
#endif
VisualScripting::DebugFlow.Unbind<OnVisualScriptingDebugFlow>();
}

View File

@@ -1013,7 +1013,7 @@ namespace FlaxEditor.Modules
ContentItem item;
if (path.EndsWith(".cs"))
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);
else if (path.EndsWith(".shader") || path.EndsWith(".hlsl"))
item = new ShaderSourceItem(path);
@@ -1135,6 +1135,7 @@ namespace FlaxEditor.Modules
Proxy.Add(new FontProxy());
Proxy.Add(new ShaderProxy());
Proxy.Add(new ShaderSourceProxy());
Proxy.Add(new ShaderHeaderProxy());
Proxy.Add(new ParticleEmitterProxy());
Proxy.Add(new ParticleEmitterFunctionProxy());
Proxy.Add(new ParticleSystemProxy());

View File

@@ -222,7 +222,7 @@ namespace FlaxEditor.Modules
outputExtension = extension;
// 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
Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path));

View File

@@ -76,6 +76,13 @@ namespace FlaxEditor.Modules
{
}
/// <summary>
/// Called when Editor will leave the play mode.
/// </summary>
public virtual void OnPlayEnding()
{
}
/// <summary>
/// Called when Editor leaves the play mode.
/// </summary>

View File

@@ -255,12 +255,17 @@ namespace FlaxEditor.Modules
// When applying changes to prefab from actor in level ignore it's root transformation (see ActorEditor.ProcessDiff)
var originalTransform = instance.LocalTransform;
var originalName = instance.Name;
if (instance.IsPrefabRoot && instance.HasScene)
{
instance.LocalTransform = prefab.GetDefaultInstance().Transform;
instance.Name = prefab.GetDefaultInstance().Name;
}
// Call backend
var failed = PrefabManager.Internal_ApplyAll(FlaxEngine.Object.GetUnmanagedPtr(instance));
instance.LocalTransform = originalTransform;
instance.Name = originalName;
if (failed)
throw new Exception("Failed to apply the prefab. See log to learn more.");

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.SceneGraph;
using FlaxEditor.SceneGraph.Actors;
using FlaxEngine;
namespace FlaxEditor.Modules
@@ -561,7 +562,8 @@ namespace FlaxEditor.Modules
public void CreateParentForSelectedActors()
{
List<SceneGraphNode> selection = Editor.SceneEditing.Selection;
var actors = selection.Where(x => x is ActorNode).Select(x => ((ActorNode)x).Actor);
// Get Actors but skip scene node
var actors = selection.Where(x => x is ActorNode and not SceneNode).Select(x => ((ActorNode)x).Actor);
var actorsCount = actors.Count();
if (actorsCount == 0)
return;
@@ -709,7 +711,11 @@ namespace FlaxEditor.Modules
private void OnActorChildNodesDispose(ActorNode node)
{
if (Selection.Count == 0)
return;
// TODO: cache if selection contains any actor child node and skip this loop if no need to iterate
// TODO: or build a hash set with selected nodes for quick O(1) checks (cached until selection changes)
// Deselect child nodes
for (int i = 0; i < node.ChildNodes.Count; i++)

View File

@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FlaxEditor.SceneGraph;
using FlaxEditor.SceneGraph.Actors;
using FlaxEngine;
@@ -658,6 +659,48 @@ namespace FlaxEditor.Modules
//node?.TreeNode.OnActiveChanged();
}
private void OnActorDestroyChildren(Actor actor)
{
// Instead of doing OnActorParentChanged for every child lets remove all of them at once from that actor
ActorNode node = GetActorNode(actor);
if (node != null)
{
if (Editor.SceneEditing.HasSthSelected)
{
// Clear selection if one of the removed actors is selected
var selection = new HashSet<Actor>();
foreach (var e in Editor.SceneEditing.Selection)
{
if (e is ActorNode q && q.Actor)
selection.Add(q.Actor);
}
var count = actor.ChildrenCount;
for (int i = 0; i < count; i++)
{
var child = actor.GetChild(i);
if (selection.Contains(child))
{
Editor.SceneEditing.Deselect();
break;
}
}
}
// Remove all child nodes (upfront remove all nodes to run faster)
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i] is ActorNode child)
child.parentNode = null;
}
node.TreeNode.DisposeChildren();
for (int i = 0; i < node.ChildNodes.Count; i++)
{
node.ChildNodes[i].Dispose();
}
node.ChildNodes.Clear();
}
}
/// <summary>
/// Gets the actor node.
/// </summary>
@@ -709,6 +752,7 @@ namespace FlaxEditor.Modules
Level.ActorOrderInParentChanged += OnActorOrderInParentChanged;
Level.ActorNameChanged += OnActorNameChanged;
Level.ActorActiveChanged += OnActorActiveChanged;
Level.ActorDestroyChildren += OnActorDestroyChildren;
}
/// <inheritdoc />
@@ -726,6 +770,7 @@ namespace FlaxEditor.Modules
Level.ActorOrderInParentChanged -= OnActorOrderInParentChanged;
Level.ActorNameChanged -= OnActorNameChanged;
Level.ActorActiveChanged -= OnActorActiveChanged;
Level.ActorDestroyChildren -= OnActorDestroyChildren;
// Cleanup graph
Root.Dispose();

View File

@@ -267,7 +267,7 @@ namespace FlaxEditor.Modules
}
/// <inheritdoc />
public override void OnPlayBegin()
public override void OnPlayBeginning()
{
Editor.Windows.FlashMainWindow();
@@ -306,7 +306,8 @@ namespace FlaxEditor.Modules
public override void OnPlayEnd()
{
var gameWin = Editor.Windows.GameWin;
if (gameWin != null)
{
switch (gameWin.FocusOnPlayOption)
{
case Options.InterfaceOptions.PlayModeFocus.None: break;
@@ -320,6 +321,7 @@ namespace FlaxEditor.Modules
}
break;
}
}
Editor.UI.UncheckPauseButton();

View File

@@ -16,7 +16,6 @@ using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
using FlaxEditor.Content.Settings;
using FlaxEditor.Options;
@@ -29,6 +28,40 @@ namespace FlaxEditor.Modules
/// <seealso cref="FlaxEditor.Modules.EditorModule" />
public sealed class UIModule : EditorModule
{
private class MainWindowDecorations : WindowDecorations
{
public MainWindowDecorations(RootControl window, bool iconOnly)
: base(window, iconOnly)
{
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
// Fallback to the edit window for shortcuts
var editor = Editor.Instance;
return editor.Windows.EditWin.InputActions.Process(editor, this, key);
}
/// <inheritdoc />
public override void DrawBorders()
{
// Draw main window borders if using a custom style
var win = RootWindow.Window;
if (win.IsMaximized)
return;
var color = Editor.Instance.UI.StatusBar.StatusColor;
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
}
}
private Label _progressLabel;
private ProgressBar _progressBar;
private Button _outputLogButton;
@@ -97,6 +130,11 @@ namespace FlaxEditor.Modules
/// </summary>
public MainMenu MainMenu;
/// <summary>
/// The window decorations (title bar with buttons)
/// </summary>
public WindowDecorations WindowDecorations;
/// <summary>
/// The tool strip control.
/// </summary>
@@ -377,19 +415,11 @@ namespace FlaxEditor.Modules
InitToolstrip(mainWindow);
InitStatusBar(mainWindow);
InitDockPanel(mainWindow);
InitWindowDecorations(mainWindow);
Editor.Options.OptionsChanged += OnOptionsChanged;
// Add dummy control for drawing the main window borders if using a custom style
#if PLATFORM_WINDOWS
if (!Editor.Options.Options.Interface.UseNativeWindowSystem)
#endif
{
mainWindow.AddChild(new CustomWindowBorderControl
{
Size = Float2.Zero,
});
}
mainWindow.PerformLayout(true);
}
/// <inheritdoc />
@@ -410,23 +440,6 @@ namespace FlaxEditor.Modules
}
}
private class CustomWindowBorderControl : Control
{
/// <inheritdoc />
public override void Draw()
{
var win = RootWindow.Window;
if (win.IsMaximized)
return;
var color = Editor.Instance.UI.StatusBar.StatusColor;
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
}
}
/// <inheritdoc />
public override void OnEndInit()
{
@@ -458,13 +471,6 @@ namespace FlaxEditor.Modules
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)
{
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);
@@ -518,10 +524,12 @@ namespace FlaxEditor.Modules
private void InitMainMenu(RootControl mainWindow)
{
MainMenu = new MainMenu(mainWindow)
MainMenu = new MainMenu()
{
Parent = mainWindow
};
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
MainMenu.Height = 28;
var inputOptions = Editor.Options.Options.Input;
@@ -628,19 +636,19 @@ namespace FlaxEditor.Modules
MenuWindow = MainMenu.AddButton("Window");
cm = MenuWindow.ContextMenu;
cm.VisibleChanged += OnMenuWindowVisibleChanged;
cm.AddButton("Content", Editor.Windows.ContentWin.FocusOrShow);
cm.AddButton("Scene", Editor.Windows.SceneWin.FocusOrShow);
cm.AddButton("Toolbox", Editor.Windows.ToolboxWin.FocusOrShow);
cm.AddButton("Properties", Editor.Windows.PropertiesWin.FocusOrShow);
cm.AddButton("Game", Editor.Windows.GameWin.FocusOrShow);
cm.AddButton("Editor", Editor.Windows.EditWin.FocusOrShow);
cm.AddButton("Debug Log", Editor.Windows.DebugLogWin.FocusOrShow);
cm.AddButton("Output Log", Editor.Windows.OutputLogWin.FocusOrShow);
cm.AddButton("Graphics Quality", Editor.Windows.GraphicsQualityWin.FocusOrShow);
cm.AddButton("Game Cooker", Editor.Windows.GameCookerWin.FocusOrShow);
cm.AddButton("Content", inputOptions.ContentWindow,Editor.Windows.ContentWin.FocusOrShow);
cm.AddButton("Scene", inputOptions.SceneWindow, Editor.Windows.SceneWin.FocusOrShow);
cm.AddButton("Toolbox", inputOptions.ToolboxWindow, Editor.Windows.ToolboxWin.FocusOrShow);
cm.AddButton("Properties", inputOptions.PropertiesWindow, Editor.Windows.PropertiesWin.FocusOrShow);
cm.AddButton("Game", inputOptions.GameWindow, Editor.Windows.GameWin.FocusOrShow);
cm.AddButton("Editor", inputOptions.EditorWindow, Editor.Windows.EditWin.FocusOrShow);
cm.AddButton("Debug Log", inputOptions.DebugLogWindow, Editor.Windows.DebugLogWin.FocusOrShow);
cm.AddButton("Output Log", inputOptions.OutputLogWindow, Editor.Windows.OutputLogWin.FocusOrShow);
cm.AddButton("Graphics Quality", inputOptions.GraphicsQualityWindow, Editor.Windows.GraphicsQualityWin.FocusOrShow);
cm.AddButton("Game Cooker", inputOptions.GameCookerWindow, Editor.Windows.GameCookerWin.FocusOrShow);
cm.AddButton("Profiler", inputOptions.ProfilerWindow, Editor.Windows.ProfilerWin.FocusOrShow);
cm.AddButton("Content Search", Editor.ContentFinding.ShowSearch);
cm.AddButton("Visual Script Debugger", Editor.Windows.VisualScriptDebuggerWin.FocusOrShow);
cm.AddButton("Content Search", inputOptions.ContentSearchWindow, Editor.ContentFinding.ShowSearch);
cm.AddButton("Visual Script Debugger", inputOptions.VisualScriptDebuggerWindow, Editor.Windows.VisualScriptDebuggerWin.FocusOrShow);
cm.AddSeparator();
cm.AddButton("Save window layout", Editor.Windows.SaveLayout);
_menuWindowApplyWindowLayout = cm.AddChildMenu("Window layouts");
@@ -661,6 +669,20 @@ namespace FlaxEditor.Modules
cm.AddButton("Information about Flax", () => new AboutDialog().Show());
}
private void InitWindowDecorations(RootControl mainWindow)
{
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
var driver = Platform.DisplayServer;
if (!string.IsNullOrEmpty(driver))
driver = $" ({driver})";
WindowDecorations = new MainWindowDecorations(mainWindow, !Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
{
Parent = mainWindow,
IconTooltipText = $"{mainWindow.RootWindow.Title}\nVersion {Globals.EngineVersion}\nConfiguration {configuration}\nGraphics {GPUDevice.Instance.RendererType}{driver}",
};
}
private void OnOptionsChanged(EditorOptions options)
{
var inputOptions = options.Input;
@@ -1070,6 +1092,7 @@ namespace FlaxEditor.Modules
{
// Clear UI references (GUI cannot be used after window closing)
MainMenu = null;
WindowDecorations = null;
ToolStrip = null;
MasterPanel = null;
StatusBar = null;

View File

@@ -10,7 +10,6 @@ using System.Text;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.GUI.Dialogs;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEditor.Windows.Profiler;
@@ -758,17 +757,19 @@ namespace FlaxEditor.Modules
var settings = CreateWindowSettings.Default;
settings.Title = "Flax Editor";
settings.Size = Platform.DesktopSize * 0.75f;
settings.MinimumSize = new Float2(200, 150);
settings.StartPosition = WindowStartPosition.CenterScreen;
settings.ShowAfterFirstPaint = true;
#if PLATFORM_WINDOWS
if (!Editor.Instance.Options.Options.Interface.UseNativeWindowSystem)
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
{
settings.HasBorder = false;
#if PLATFORM_WINDOWS && !PLATFORM_SDL
// Skip OS sizing frame and implement it using LeftButtonHit
settings.HasSizingFrame = false;
#endif
}
#elif PLATFORM_LINUX
#if PLATFORM_LINUX && !PLATFORM_SDL
settings.HasBorder = false;
#endif
MainWindow = Platform.CreateWindow(ref settings);
@@ -1223,6 +1224,13 @@ namespace FlaxEditor.Modules
Windows[i].OnPlayBegin();
}
/// <inheritdoc />
public override void OnPlayEnding()
{
for (int i = 0; i < Windows.Count; i++)
Windows[i].OnPlayEnding();
}
/// <inheritdoc />
public override void OnPlayEnd()
{

View File

@@ -33,6 +33,25 @@ namespace FlaxEditor.Options
OpenPrefab,
}
/// <summary>
/// Shortcut availability in play mode.
/// </summary>
public enum PlayModeShortcutAvailability
{
/// <summary>
/// None of the window shortcuts will be available in play mode.
/// </summary>
None,
/// <summary>
/// Only the profiler window shortcut will be available in play mode.
/// </summary>
ProfilerOnly,
/// <summary>
/// All window shortcuts will be available in play mode.
/// </summary>
All,
}
/// <summary>
/// Input editor options data container.
/// </summary>
@@ -40,6 +59,16 @@ namespace FlaxEditor.Options
[HideInEditor]
public sealed class InputOptions
{
/// <summary>
/// Gets a value based on the current settings that indicates wether window shortcuts will be avaliable during play mode.
/// </summary>
public static bool WindowShortcutsAvaliable => !Editor.IsPlayMode || Editor.Instance.Options.Options.Input.PlayModeWindowShortcutAvaliability == PlayModeShortcutAvailability.All;
/// <summary>
/// Gets a value based on the current settings that indicates wether the profiler window shortcut will be avaliable during play mode.
/// </summary>
public static bool ProfilerShortcutAvaliable => WindowShortcutsAvaliable || Editor.Instance.Options.Options.Input.PlayModeWindowShortcutAvaliability == PlayModeShortcutAvailability.ProfilerOnly;
#region Common
[DefaultValue(typeof(InputBinding), "Ctrl+S")]
@@ -110,6 +139,10 @@ namespace FlaxEditor.Options
[EditorDisplay("Common"), EditorOrder(240)]
public InputBinding ToggleFullscreen = new InputBinding(KeyboardKeys.F11);
[DefaultValue(typeof(InputBinding), "Ctrl+BackQuote")]
[EditorDisplay("Common"), EditorOrder(250)]
public InputBinding FocusConsoleCommand = new InputBinding(KeyboardKeys.BackQuote, KeyboardKeys.Control);
#endregion
#region File
@@ -230,9 +263,9 @@ namespace FlaxEditor.Options
#region Profiler
[DefaultValue(typeof(InputBinding), "None")]
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha7")]
[EditorDisplay("Profiler", "Open Profiler Window"), EditorOrder(630)]
public InputBinding ProfilerWindow = new InputBinding(KeyboardKeys.None);
public InputBinding ProfilerWindow = new InputBinding(KeyboardKeys.Alpha7, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Profiler", "Start/Stop Profiler"), EditorOrder(631)]
@@ -356,24 +389,307 @@ namespace FlaxEditor.Options
#endregion
#region Debug Views
[DefaultValue(typeof(InputBinding), "Alt+Alpha4")]
[EditorDisplay("Debug Views"), EditorOrder(2000)]
public InputBinding Default = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+Alpha3")]
[EditorDisplay("Debug Views"), EditorOrder(2010)]
public InputBinding Unlit = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2020)]
public InputBinding NoPostFX = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Alt+Alpha2")]
[EditorDisplay("Debug Views"), EditorOrder(2030)]
public InputBinding Wireframe = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+Alpha5")]
[EditorDisplay("Debug Views"), EditorOrder(2040)]
public InputBinding LightBuffer = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2050)]
public InputBinding ReflectionsBuffer = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2060)]
public InputBinding DepthBuffer = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2070)]
public InputBinding MotionVectors = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2080)]
public InputBinding LightmapUVDensity = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2090)]
public InputBinding VertexColors = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Alt+Alpha1")]
[EditorDisplay("Debug Views"), EditorOrder(2100)]
public InputBinding PhysicsColliders = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2110)]
public InputBinding LODPreview = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2120)]
public InputBinding MaterialComplexity = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2130)]
public InputBinding QuadOverdraw = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2140)]
public InputBinding GloablSDF = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2150)]
public InputBinding GlobalSurfaceAtlas = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Debug Views"), EditorOrder(2160)]
public InputBinding GlobalIllumination = new InputBinding(KeyboardKeys.None);
#endregion
#region View Flags
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3000)]
public InputBinding AntiAliasing = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3010)]
public InputBinding Shadows = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha7")]
[EditorDisplay("View Flags"), EditorOrder(3020)]
public InputBinding EditorSprites = new InputBinding(KeyboardKeys.Alpha7, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3030)]
public InputBinding Reflections = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3040)]
public InputBinding ScreenSpaceReflections = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3050)]
public InputBinding AmbientOcclusion = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha6")]
[EditorDisplay("View Flags", "Global Illumination"), EditorOrder(3060)]
public InputBinding GlobalIlluminationViewFlag = new InputBinding(KeyboardKeys.Alpha6, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3070)]
public InputBinding DirectionalLights = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3080)]
public InputBinding PointLights = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3090)]
public InputBinding SpotLights = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3100)]
public InputBinding SkyLights = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3110)]
public InputBinding Sky = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3120)]
public InputBinding Fog = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3130)]
public InputBinding SpecularLight = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3140)]
public InputBinding Decals = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha3")]
[EditorDisplay("View Flags"), EditorOrder(3150)]
public InputBinding CustomPostProcess = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3160)]
public InputBinding Bloom = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3170)]
public InputBinding ToneMapping = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha2")]
[EditorDisplay("View Flags"), EditorOrder(3180)]
public InputBinding EyeAdaptation = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3190)]
public InputBinding CameraArtifacts = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3200)]
public InputBinding LensFlares = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3210)]
public InputBinding DepthOfField = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3220)]
public InputBinding MotionBlur = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("View Flags"), EditorOrder(3230)]
public InputBinding ContactShadows = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha1")]
[EditorDisplay("View Flags"), EditorOrder(3240)]
public InputBinding PhysicsDebug = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha5")]
[EditorDisplay("View Flags"), EditorOrder(3250)]
public InputBinding LightsDebug = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Alpha4")]
[EditorDisplay("View Flags"), EditorOrder(3260)]
public InputBinding DebugDraw = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control, KeyboardKeys.Shift);
#endregion
#region Interface
[DefaultValue(typeof(InputBinding), "Ctrl+W")]
[EditorDisplay("Interface"), EditorOrder(2000)]
[EditorDisplay("Interface"), EditorOrder(3500)]
public InputBinding CloseTab = new InputBinding(KeyboardKeys.W, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "Ctrl+Tab")]
[EditorDisplay("Interface"), EditorOrder(2010)]
[EditorDisplay("Interface"), EditorOrder(3510)]
public InputBinding NextTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "Shift+Ctrl+Tab")]
[EditorDisplay("Interface"), EditorOrder(2020)]
[EditorDisplay("Interface"), EditorOrder(3520)]
public InputBinding PreviousTab = new InputBinding(KeyboardKeys.Tab, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(SceneNodeDoubleClick.Expand)]
[EditorDisplay("Interface"), EditorOrder(2030)]
[EditorDisplay("Interface"), EditorOrder(3530)]
public SceneNodeDoubleClick DoubleClickSceneNode = SceneNodeDoubleClick.Expand;
#endregion
#region Windows
/// <summary>
/// Gets or sets a value indicating what window shortcuts will be available during play mode.
/// </summary>
[DefaultValue(PlayModeShortcutAvailability.ProfilerOnly)]
[EditorDisplay("Windows", "Avaliability in Play Mode"), EditorOrder(3000)]
public PlayModeShortcutAvailability PlayModeWindowShortcutAvaliability { get; set; } = PlayModeShortcutAvailability.ProfilerOnly;
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha5")]
[EditorDisplay("Windows"), EditorOrder(3010)]
public InputBinding ContentWindow = new InputBinding(KeyboardKeys.Alpha5, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha4")]
[EditorDisplay("Windows"), EditorOrder(3020)]
public InputBinding SceneWindow = new InputBinding(KeyboardKeys.Alpha4, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(3030)]
public InputBinding ToolboxWindow = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha3")]
[EditorDisplay("Windows"), EditorOrder(3040)]
public InputBinding PropertiesWindow = new InputBinding(KeyboardKeys.Alpha3, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha2")]
[EditorDisplay("Windows"), EditorOrder(3050)]
public InputBinding GameWindow = new InputBinding(KeyboardKeys.Alpha2, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha1")]
[EditorDisplay("Windows"), EditorOrder(3060)]
public InputBinding EditorWindow = new InputBinding(KeyboardKeys.Alpha1, KeyboardKeys.Control);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(3070)]
public InputBinding DebugLogWindow = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(3080)]
public InputBinding OutputLogWindow = new InputBinding(KeyboardKeys.C, KeyboardKeys.Control, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(3090)]
public InputBinding GraphicsQualityWindow = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(4000)]
public InputBinding GameCookerWindow = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(4010)]
public InputBinding ContentSearchWindow = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Windows"), EditorOrder(4020)]
public InputBinding VisualScriptDebuggerWindow = new InputBinding(KeyboardKeys.None);
#endregion
#region Node editors
[DefaultValue(typeof(InputBinding), "Shift+W")]
[EditorDisplay("Node editors"), EditorOrder(4500)]
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+A")]
[EditorDisplay("Node editors"), EditorOrder(4510)]
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+S")]
[EditorDisplay("Node editors"), EditorOrder(4520)]
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+D")]
[EditorDisplay("Node editors"), EditorOrder(4530)]
public InputBinding NodesAlignRight = new InputBinding(KeyboardKeys.D, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Alt+Shift+W")]
[EditorDisplay("Node editors"), EditorOrder(4540)]
public InputBinding NodesAlignMiddle = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+Shift+S")]
[EditorDisplay("Node editors"), EditorOrder(4550)]
public InputBinding NodesAlignCenter = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Q")]
[EditorDisplay("Node editors"), EditorOrder(4560)]
public InputBinding NodesAutoFormat = new InputBinding(KeyboardKeys.Q);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Node editors"), EditorOrder(4570)]
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Node editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
#endregion
}
}

View File

@@ -160,6 +160,34 @@ namespace FlaxEditor.Options
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>
/// 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>
@@ -167,14 +195,12 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(10), Tooltip("Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.")]
public float InterfaceScale { get; set; } = 1.0f;
#if PLATFORM_WINDOWS
/// <summary>
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar. Editor restart required.")]
public bool UseNativeWindowSystem { get; set; } = false;
#endif
[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;
/// <summary>
/// Gets or sets a value indicating whether show selected camera preview in the editor window.

View File

@@ -6,6 +6,7 @@
#include "Engine/Core/Log.h"
#include "Engine/Engine/Globals.h"
#include "Engine/Core/Math/Quaternion.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Serialization/JsonWriters.h"
#include "Engine/Serialization/JsonTools.h"
#include <ThirdParty/pugixml/pugixml.hpp>
@@ -327,6 +328,7 @@ ProjectInfo* ProjectInfo::Load(const String& path)
}
// Load
PROFILE_MEM(Editor);
auto project = New<ProjectInfo>();
if (project->LoadProject(path))
{

View File

@@ -35,7 +35,8 @@ namespace FlaxEditor.SceneGraph
return false;
}
BoundingSphere sphere = new BoundingSphere(Transform.Translation, 7.0f);
var center = _actor.Transform.Translation;
ViewportIconsRenderer.GetBounds(ref center, ref ray.Ray.Position, out var sphere);
return CollisionsHelper.RayIntersectsSphere(ref ray.Ray, ref sphere, out distance);
}
}

View File

@@ -76,9 +76,13 @@ namespace FlaxEditor.SceneGraph.Actors
// Skip removing this terrain file sif it's still referenced
var sceneReferences = Editor.GetAssetReferences(e.SceneId);
if (sceneReferences != null && sceneReferences.Contains(e.TerrainId))
{
Debug.Log($"Skip removing files used by terrain {e.TerrainId} on scene {e.SceneId} as it's still in use");
continue;
}
// Delete files
Debug.Log($"Removing files used by removed terrain {e.TerrainId} on scene {e.SceneId}");
foreach (var file in e.Files)
{
if (file != null && File.Exists(file))

View File

@@ -28,7 +28,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
_infoLabel = playbackGroup.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
var grid = layout.UniformGrid();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;

View File

@@ -320,7 +320,7 @@ namespace FlaxEditor.SceneGraph.GUI
if (noFilter && actor != null)
{
// Pick the correct id when inside a prefab window.
var id = actor.HasPrefabLink && actor.Scene.Scene == null ? actor.PrefabObjectID : actor.ID;
var id = actor.HasPrefabLink && actor.Scene == null ? actor.PrefabObjectID : actor.ID;
isExpanded = Editor.Instance.ProjectCache.IsExpandedActor(ref id);
}

View File

@@ -27,7 +27,7 @@ namespace FlaxEditor.SceneGraph
/// <summary>
/// The parent node.
/// </summary>
protected SceneGraphNode parentNode;
internal SceneGraphNode parentNode;
/// <summary>
/// Gets the children list.

View File

@@ -13,6 +13,7 @@
#include "Engine/Engine/EngineService.h"
#include "Engine/Platform/Thread.h"
#include "Engine/Threading/IRunnable.h"
#include "Engine/Profiler/ProfilerMemory.h"
void OnAsyncBegin(Thread* thread);
void OnAsyncEnd();
@@ -232,6 +233,8 @@ void OnAsyncEnd()
bool CodeEditingManagerService::Init()
{
PROFILE_MEM(Editor);
// Try get editors
#if USE_VISUAL_STUDIO_DTE
VisualStudioEditor::FindEditors(&CodeEditors);

View File

@@ -23,6 +23,7 @@
#include "Engine/Scripting/Scripting.h"
#include "Engine/Scripting/Script.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Level/Level.h"
#include "FlaxEngine.Gen.h"
@@ -77,7 +78,7 @@ namespace ScriptsBuilderImpl
void onScriptsReloadEnd();
void onScriptsLoaded();
void GetClassName(const StringAnsi& fullname, StringAnsi& className);
void GetClassName(const StringAnsiView fullname, StringAnsi& className);
void onCodeEditorAsyncOpenBegin()
{
@@ -120,9 +121,13 @@ void ScriptsBuilderImpl::sourceDirEvent(const String& path, FileSystemAction act
// Discard non-source files or generated files
if ((!path.EndsWith(TEXT(".cs")) &&
!path.EndsWith(TEXT(".cpp")) &&
!path.EndsWith(TEXT(".c")) &&
!path.EndsWith(TEXT(".hpp")) &&
!path.EndsWith(TEXT(".h"))) ||
path.EndsWith(TEXT(".Gen.cs")))
{
return;
}
ScopeLock scopeLock(_locker);
_lastSourceCodeEdited = DateTime::Now();
@@ -272,7 +277,7 @@ bool ScriptsBuilder::GenerateProject(const StringView& customArgs)
return RunBuildTool(args);
}
void ScriptsBuilderImpl::GetClassName(const StringAnsi& fullname, StringAnsi& className)
void ScriptsBuilderImpl::GetClassName(const StringAnsiView fullname, StringAnsi& className)
{
const auto lastDotIndex = fullname.FindLast('.');
if (lastDotIndex != -1)
@@ -413,6 +418,7 @@ void ScriptsBuilder::GetBinariesConfiguration(const Char*& target, const Char*&
bool ScriptsBuilderImpl::compileGameScriptsAsyncInner()
{
PROFILE_MEM(Editor);
LOG(Info, "Starting scripts compilation...");
CallEvent(EventType::CompileStarted);
@@ -519,6 +525,8 @@ void ScriptsBuilderImpl::onEditorAssemblyUnloading(MAssembly* assembly)
bool ScriptsBuilderImpl::compileGameScriptsAsync()
{
PROFILE_MEM(Editor);
// Start
{
ScopeLock scopeLock(_locker);
@@ -562,6 +570,7 @@ bool ScriptsBuilderService::Init()
// Check flag
if (_isInited)
return false;
PROFILE_MEM(Editor);
_isInited = true;
// Link for Editor assembly unload event to clear cached Internal_OnCompilationEnd to prevent errors
@@ -659,6 +668,9 @@ bool ScriptsBuilderService::Init()
void ScriptsBuilderService::Update()
{
PROFILE_CPU();
PROFILE_MEM(Editor);
// Send compilation events
{
ScopeLock scopeLock(_compileEventsLocker);

Some files were not shown because too many files have changed in this diff Show More