313 Commits

Author SHA1 Message Date
c6bc90a82a _lagdriver fixes
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-09-12 13:52:55 +03:00
43b576d961 Add support for Visual Studio 2026 and v145 MSVC toolset
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-09-10 20:05:28 +03:00
1d8f221f1b Merge remote-tracking branch 'origin/1.11' into sdl_platform_1.11
# Conflicts:
#	Source/Engine/Platform/Windows/WindowsPlatform.cpp
#	Source/Tools/Flax.Build/Build/ProjectTarget.cs
#	Source/Tools/Flax.Build/Configuration.cs
2025-09-07 19:31:16 +03:00
d70a003617 Improve tab-less dock window behavior in other platforms
Add checks for #3215 to hide the tab bar only if it doesn't prevent
window dragging in Wayland sessions with native decorations.
2025-09-07 19:27:24 +03:00
b443b74d18 Merge branch 'master' into sdl_platform
# Conflicts:
#	Source/Editor/GUI/Docking/DockHintWindow.cs
#	Source/Editor/Options/InterfaceOptions.cs
2025-09-07 19:02:09 +03:00
Wojtek Figat
42b542d190 Improve recent changes to memory barriers on Vulkan 2025-09-07 00:17:11 +02:00
Wojtek Figat
576b0710e0 Fix GPU particles issues with missing sorting keys data when shader is not yet loaded 2025-09-06 23:37:24 +02:00
Wojtek Figat
44e70692a2 Fix render memory alignment issues to prevent crashes on Android 2025-09-06 23:36:54 +02:00
Wojtek Figat
857b0c5ac3 Fix various graphics issues detected by Vulkan Validation Layers on Android 2025-09-06 23:32:54 +02:00
Wojtek Figat
1f6d837117 Fix regression from 6d05bf16b1 2025-09-05 08:51:43 +02:00
Wojtek Figat
67220d3f80 Add support for large 16kb page sizes on Android 2025-09-04 22:28:53 +02:00
Wojtek Figat
c5d06b2c8b Fix crash regression from #3588 when editing active particle emitters 2025-09-04 22:05:31 +02:00
Wojtek Figat
3b19e1b40c Fix collision data memory preview text 2025-09-04 21:47:51 +02:00
Wojtek Figat
831fb0f442 Optimize textures/buffers uploading on Vulkan with page allocator 2025-09-04 21:38:07 +02:00
Wojtek Figat
cd22cd059d Various small fixes and improvements 2025-09-04 15:56:33 +02:00
Wojtek Figat
3e363c8275 Remove ConcurrentSystemLocker and use ReadWriteLock instead of better threading synchronization 2025-09-04 14:48:52 +02:00
Wojtek Figat
c44d939c08 Add ReadWriteLock to platform api 2025-09-04 14:46:56 +02:00
Wojtek Figat
c0c9df49dc Optimize DDGI probes update to overlap both irradiance and distance data at once 2025-09-03 23:21:45 +02:00
Wojtek Figat
80de56f469 Optimize Global SDF dispatches with UAV write overlaps
2-3x faster rasterization
2025-09-03 23:12:55 +02:00
Wojtek Figat
f1ecbf828e Fix debug check on Vulkan backbuffer texture usage 2025-09-03 22:11:48 +02:00
Wojtek Figat
f1c4fd464a Optimize GPU textures and buffers uploads with a batched memory barrier 2025-09-03 22:11:26 +02:00
Wojtek Figat
212b0de29b Add RenderListAlloc to simplify rendering memory allocations 2025-09-03 13:00:28 +02:00
Wojtek Figat
5a2555f845 Improve cdb09847ec and 499ef51875 to swap key bits during sorting
#2271
2025-09-02 22:30:50 +02:00
Wojtek Figat
c57e128ff1 Merge remote-tracking branch 'origin/master' into 1.11
# Conflicts:
#	Source/Engine/Level/Scene/SceneRendering.cpp
#	Source/Engine/Physics/Colliders/Collider.cpp
#	Source/Engine/Physics/Colliders/Collider.h
2025-09-02 22:23:45 +02:00
Wojtek Figat
eff5f84185 Improve shadow maps sharing in nested scene rendering 2025-09-02 22:14:07 +02:00
Wojtek Figat
ad1163bccc Fix HashSet::Add returning incorrect value 2025-09-02 21:41:54 +02:00
Wojtek Figat
1042ad4e7d Fix object ids remapping inside nested prefabs
#3255
2025-09-02 21:41:36 +02:00
Wojtek Figat
8fdda1a71a Fix scene object reference serialization in C++ to use correct serializer
#3255
2025-08-30 23:52:54 +02:00
Wojtek Figat
3f7fe635d8 Fix 5222f1d35c for inactive preprocessor conditional block 2025-08-29 23:04:46 +02:00
Wojtek Figat
fcebc57ed0 Merge branch 'xxSeys1-addSphere' 2025-08-29 22:32:21 +02:00
Wojtek Figat
c40e447bb7 Merge branch 'addSphere' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-addSphere 2025-08-29 22:31:00 +02:00
Wojtek Figat
e6f94bb154 Merge branch 'fibref-textrender-scaling-fix' 2025-08-29 22:27:41 +02:00
Wojtek Figat
adbc546978 Merge branch 'textrender-scaling-fix' of https://github.com/fibref/FlaxEngine into fibref-textrender-scaling-fix 2025-08-29 22:26:32 +02:00
Wojtek Figat
2d171967e9 Merge branch 'Tryibion-collection-duplicate' 2025-08-29 22:24:58 +02:00
Wojtek Figat
33a0e6ac7d Merge branch 'collection-duplicate' of https://github.com/Tryibion/FlaxEngine into Tryibion-collection-duplicate 2025-08-29 22:24:09 +02:00
Wojtek Figat
848cc38bf1 Fix reverting prefab object reference in nested prefabs
#3255
2025-08-29 22:04:03 +02:00
Wojtek Figat
91cd1e8065 Fix regression from ef7c7f2d30 to ignore unmodified scripts in diff 2025-08-29 21:49:14 +02:00
Wojtek Figat
9fafb47abb Fix debug drawing wheeled vehicle in prefab viewport
#3591
2025-08-29 21:03:44 +02:00
Wojtek Figat
5222f1d35c Add support for parsing inheritance with preprocessor blocks inside it 2025-08-29 21:03:04 +02:00
Wojtek Figat
785649f9d5 Merge branch 'Tryibion-show-prefab-add-delete' 2025-08-28 23:48:33 +02:00
Wojtek Figat
d47ac95681 Modernize the code to use unified scene access #3513 2025-08-28 23:48:25 +02:00
Wojtek Figat
703e0cb7ca Merge branch 'show-prefab-add-delete' of https://github.com/Tryibion/FlaxEngine into Tryibion-show-prefab-add-delete 2025-08-28 22:56:22 +02:00
Wojtek Figat
ef7c7f2d30 Fix script fields prefab diff showing and reverting with undo
#3594
2025-08-28 22:52:46 +02:00
Wojtek Figat
f3d375e356 Fix prefab root name and transform being changed when applying local changes of sub-object
#3235
2025-08-28 22:26:50 +02:00
frank
a3073321cf fix scaling for TextRender 2025-08-28 17:24:06 +08:00
Chandler Cox
824b49dd88 Better duplication of collection. 2025-08-26 20:25:02 -05:00
Wojtek Figat
d0e7bff03a Merge branch 'Tryibion-add-collision-v&t' 2025-08-26 18:05:46 +02:00
Wojtek Figat
d314d5b324 Format memory usage to human-readable format
#3495
2025-08-26 18:05:42 +02:00
Wojtek Figat
a027ed3b63 Merge branch 'add-collision-v&t' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-collision-v&t 2025-08-26 17:57:01 +02:00
Wojtek Figat
bcedb05a2c Fix regression from 6a8553a277 on local lights 2025-08-26 17:55:32 +02:00
Wojtek Figat
b36be95947 Fix Editor undo on collection properties that return different object on get
#3256
2025-08-26 14:59:10 +02:00
Wojtek Figat
826009c1b4 Merge remote-tracking branch 'origin/master' into 1.11
# Conflicts:
#	Content/Editor/DebugMaterials/DDGIDebugProbes.flax
#	Source/Engine/Scripting/Scripting.cpp
2025-08-25 23:48:08 +02:00
Wojtek Figat
4ca399af71 Add model import options auto-restore from model prefab 2025-08-25 23:15:37 +02:00
Wojtek Figat
c1f022520d Update ReSharper settings 2025-08-25 22:15:44 +02:00
Wojtek Figat
2efd20f223 Merge branch 'xxSeys1-ToolboxSearchFilterAndControls' 2025-08-25 22:15:08 +02:00
Wojtek Figat
00dd432fbc Simplify code #3360 2025-08-25 22:15:00 +02:00
Wojtek Figat
f707508d70 Merge branch 'ToolboxSearchFilterAndControls' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-ToolboxSearchFilterAndControls 2025-08-25 14:49:00 +02:00
Wojtek Figat
b965ca6c8c Fix Content Window navigation bar to expand toolstrip for proper scroll bar display
#3326
2025-08-25 14:38:55 +02:00
Wojtek Figat
26f4bcbc25 Fix UI Control Reference picker to support base/inherited types 2025-08-25 10:09:25 +02:00
Wojtek Figat
6fea9eefaa Merge branch 'xxSeys1-BrokenLink' 2025-08-24 21:11:39 +02:00
Wojtek Figat
47caa6af28 Add BrokenLink32/BrokenLink64 icons
#3218
2025-08-24 21:11:32 +02:00
Wojtek Figat
9aedb37ac2 Merge branch 'BrokenLink' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-BrokenLink 2025-08-24 21:10:26 +02:00
Wojtek Figat
e4bc2c69c7 Merge branch 'Zode-customeditorwindow-expose-constructor' 2025-08-24 14:00:20 +02:00
Wojtek Figat
6db9265112 Merge branch 'customeditorwindow-expose-constructor' of https://github.com/Zode/FlaxEngine into Zode-customeditorwindow-expose-constructor 2025-08-24 14:00:13 +02:00
Wojtek Figat
21a84c5b84 Merge branch 'xxSeys1-AutoSizePropertiesSplitter' 2025-08-24 13:59:20 +02:00
Wojtek Figat
633b5857c9 Merge branch 'AutoSizePropertiesSplitter' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-AutoSizePropertiesSplitter 2025-08-24 13:59:16 +02:00
Wojtek Figat
9f9dac1543 Merge branch 'Tryibion-layer-methods' 2025-08-24 13:46:56 +02:00
Wojtek Figat
df6f8fd8ae Codestyle adjustments #3343 2025-08-24 13:46:53 +02:00
Wojtek Figat
4bd8ce37ac Merge branch 'layer-methods' of https://github.com/Tryibion/FlaxEngine into Tryibion-layer-methods 2025-08-24 13:43:35 +02:00
Wojtek Figat
40e204839f Merge branch 'Tryibion-splash-image' 2025-08-24 13:37:55 +02:00
Wojtek Figat
d6c75b3f86 Simplify code in #3119 2025-08-24 13:37:48 +02:00
Wojtek Figat
687c283533 Merge branch 'splash-image' of https://github.com/Tryibion/FlaxEngine into Tryibion-splash-image 2025-08-24 13:24:35 +02:00
Wojtek Figat
70ee8501a5 Merge branch 'xxSeys1-TabHeight' 2025-08-24 13:21:15 +02:00
Wojtek Figat
2c34bd2308 Merge branch 'TabHeight' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-TabHeight 2025-08-24 13:21:12 +02:00
fc341a86e7 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-08-24 09:44:28 +03:00
Wojtek Figat
5023e3277b Merge branch 'Swiggies-animated-model-additions' 2025-08-22 23:04:00 +02:00
Wojtek Figat
9003d855b3 Merge branch 'animated-model-additions' of https://github.com/Swiggies/FlaxEngine into Swiggies-animated-model-additions 2025-08-22 23:03:54 +02:00
Wojtek Figat
75906719d4 Merge branch 'xxSeys1-SimplifyListCtrlScrolling' 2025-08-22 22:34:09 +02:00
Wojtek Figat
9a59925a36 Merge branch 'SimplifyListCtrlScrolling' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-SimplifyListCtrlScrolling 2025-08-22 22:34:05 +02:00
Wojtek Figat
d5ca80c2c1 Merge branch 'Tryibion-fix-particle-effect-params-overide-update' 2025-08-22 22:31:12 +02:00
Wojtek Figat
cb07ee77aa Change #3588 to be editor-only 2025-08-22 22:31:08 +02:00
Wojtek Figat
680783f2b0 Merge branch 'fix-particle-effect-params-overide-update' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-particle-effect-params-overide-update 2025-08-22 22:29:59 +02:00
Zode
4a28b4bd6c Expose hideOnClose and scrollBars in constructor for CustomEditorWindows. 2025-08-22 01:26:34 +03:00
Wojtek Figat
4bf36f3467 Merge branch 'Tryibion-shift-select-nodes' 2025-08-19 23:00:43 +02:00
Wojtek Figat
2c1713d300 Fix rare issues with shift tree selection 2025-08-19 23:00:29 +02:00
Wojtek Figat
8136691914 Merge branch 'shift-select-nodes' of https://github.com/Tryibion/FlaxEngine into Tryibion-shift-select-nodes
# Conflicts:
#	Source/Editor/GUI/Tree/Tree.cs
2025-08-19 18:45:33 +02:00
Wojtek Figat
da23e287c0 Merge branch 'Tryibion-cookandrun-buildconfig' 2025-08-19 18:22:49 +02:00
Wojtek Figat
e0825d870d Merge branch 'cookandrun-buildconfig' of https://github.com/Tryibion/FlaxEngine into Tryibion-cookandrun-buildconfig 2025-08-19 18:22:44 +02:00
Wojtek Figat
86dbe6b93d Merge branch 'Tryibion-add-gamewin-audio-events' 2025-08-19 18:21:42 +02:00
Wojtek Figat
e71b74c625 Merge branch 'add-gamewin-audio-events' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-gamewin-audio-events 2025-08-19 18:21:32 +02:00
Wojtek Figat
45f6ef29e9 Merge branch 'xxSeys1-MoreSearchableCM' 2025-08-19 18:20:04 +02:00
Wojtek Figat
0fabca19cd Merge branch 'MoreSearchableCM' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-MoreSearchableCM 2025-08-19 18:20:01 +02:00
Wojtek Figat
0bc242c738 Merge branch 'MrCapy0-Color-Gradient-Node' 2025-08-19 13:22:34 +02:00
Wojtek Figat
8c548ceff2 Merge branch 'Color-Gradient-Node' of https://github.com/MrCapy0/FlaxEngine into MrCapy0-Color-Gradient-Node 2025-08-19 13:21:32 +02:00
Wojtek Figat
46fda05000 Merge branch 'xxSeys1-VjStraightenConnections' 2025-08-19 13:20:44 +02:00
Wojtek Figat
1fee95be1c Merge branch 'VjStraightenConnections' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-VjStraightenConnections 2025-08-19 13:20:41 +02:00
Wojtek Figat
8c66ae99a3 Merge branch 'Tryibion-initial-nuget' 2025-08-19 13:18:54 +02:00
Wojtek Figat
1cf98e2188 Merge branch 'initial-nuget' of https://github.com/Tryibion/FlaxEngine into Tryibion-initial-nuget 2025-08-19 13:18:51 +02:00
Wojtek Figat
6a8553a277 Fix incorrect Lambert Diffuse shadowing to use just N dot L for accurate lighting
#3615 #3616
2025-08-18 11:03:50 +02:00
Chandler Cox
a02b7d4a1a Add events for when audio settings are changed for the game window. 2025-08-17 11:58:42 -05:00
Wojtek Figat
606dfa4e2e Merge branch 'Tryibion-add-ctor-matbrush-inst' 2025-08-15 14:41:08 +02:00
Wojtek Figat
b6f853a01c Merge branch 'add-ctor-matbrush-inst' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-ctor-matbrush-inst 2025-08-15 14:41:05 +02:00
Wojtek Figat
fc2112ec93 Fix SSAO artifacts with "flat normals" look
#3617
2025-08-15 14:34:02 +02:00
Wojtek Figat
6ccfbfeff1 Fix saving skinned models with blend shapes
#3612
2025-08-15 14:20:16 +02:00
Wojtek Figat
f21accd466 Fix crash when memory stream reading fails and perform soft error handling
#3612
2025-08-15 14:19:59 +02:00
Chandler Cox
38b4ace1a8 Use material base as ctor parameter. 2025-08-15 07:01:48 -05:00
Wojtek Figat
774b6bd72c Update engine materials 2025-08-15 13:09:05 +02:00
Wojtek Figat
9c4606fefc Merge branch 'GoaLitiuM-linux_hotreload_cleanup_fix' 2025-08-14 22:47:05 +02:00
Wojtek Figat
0e50e47cce Merge branch 'linux_hotreload_cleanup_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-linux_hotreload_cleanup_fix 2025-08-14 22:46:45 +02:00
Wojtek Figat
285fa870d0 Merge branch 'Tryibion-fix-anim-event-backwards' 2025-08-14 22:41:24 +02:00
Wojtek Figat
69ed0bf56f Merge branch 'fix-anim-event-backwards' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-anim-event-backwards 2025-08-14 22:41:20 +02:00
Wojtek Figat
237b9bccd5 Merge branch 'xxSeys1-PauseOnErrorInfo' 2025-08-14 22:23:39 +02:00
Wojtek Figat
f5fd7319e1 Merge branch 'PauseOnErrorInfo' of https://github.com/xxSeys1/FlaxEngine into xxSeys1-PauseOnErrorInfo
# Conflicts:
#	Source/Editor/Windows/DebugLogWindow.cs
2025-08-14 22:23:32 +02:00
Wojtek Figat
e04c0c4ace Merge branch 'Tryibion-fix-not-finised-tag-richtextbox' 2025-08-14 22:21:31 +02:00
Wojtek Figat
f6d0b073da Merge branch 'fix-not-finised-tag-richtextbox' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-not-finised-tag-richtextbox 2025-08-14 22:21:27 +02:00
Wojtek Figat
68a7cf4f18 Merge branch 'Tryibion-make-empty-stringview-const' 2025-08-14 22:15:58 +02:00
Wojtek Figat
a91360529f Merge branch 'make-empty-stringview-const' of https://github.com/Tryibion/FlaxEngine into Tryibion-make-empty-stringview-const 2025-08-14 22:15:53 +02:00
Wojtek Figat
bf9ca14deb Fix sampling textures in decals to use custom mip-level
#3599
2025-08-14 22:14:03 +02:00
Wojtek Figat
cb92a2b8cb Optimize decals rendering with depth test
#3599
2025-08-14 13:04:57 +02:00
Wojtek Figat
8a73d79936 Update engine materials 2025-08-14 12:24:12 +02:00
Wojtek Figat
2f7d7a0f2a Allow pasting State nodes in Anim Graph
#3596
2025-08-14 12:24:02 +02:00
Wojtek Figat
d43c0c593f Merge branch 'Tryibion-add-scaled-time-node' 2025-08-14 11:54:34 +02:00
Wojtek Figat
1087bd2445 Fix #3342 to properly place new param in Constant Buffer
#3299
2025-08-14 11:53:25 +02:00
Wojtek Figat
5e19a9729b Merge branch 'add-scaled-time-node' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-scaled-time-node 2025-08-14 11:37:09 +02:00
Wojtek Figat
69e12d77be Add preventing autosave when using editor context menus
#3220
2025-08-13 23:25:57 +02:00
Wojtek Figat
cdb09847ec Fix draw calls batching to ignore distance in opaque passes for better draw calls instancing
#2271
2025-08-13 21:30:18 +02:00
Saas
169d3e964d Switch from Debug.Write to Editor.Log 2025-08-13 13:29:13 +02:00
Chandler Cox
cf503cf921 Add material instance ctor for MaterialBrush 2025-08-12 21:03:35 -05:00
Wojtek Figat
6fd4ef735e Add InvokeOnUpdate to C++ scripting api 2025-08-12 23:35:12 +02:00
Wojtek Figat
303087c4c4 Fix regression in renaming textbox placement of newly added actor to prefab 2025-08-12 23:18:18 +02:00
68da28ffe8 Update SDL to 3.2.20 2025-08-12 15:39:19 +03:00
Wojtek Figat
427e76e76e Update volk to version 1.4.304 2025-08-12 15:24:48 +03:00
b183b5bcfc Merge remote-tracking branch 'origin/master' into sdl_platform 2025-08-12 15:22:34 +03:00
Wojtek Figat
278dead0bd Add PLATFORM_CONSOLE define and fix desktop to be as Windows/UWP, not Win32 2025-08-12 12:34:32 +02:00
Wojtek Figat
cdff7708fb Add automatic periodic Vulkan Pipeline State Cache serialization 2025-08-12 10:25:02 +02:00
Wojtek Figat
b4d501cd6a Add OcclusionQueryPools to Vulkan and move code to cpp file 2025-08-12 10:21:51 +02:00
Wojtek Figat
9cf9fae453 Add Vulkan device cache customization per-platform and reuse code 2025-08-12 00:09:54 +02:00
Wojtek Figat
7fcf6f9c97 Add various improvements 2025-08-11 23:47:48 +02:00
Wojtek Figat
1bedfd3adf Disable auto-GC every 60 ticks in game 2025-08-11 19:00:38 +02:00
Wojtek Figat
80d19a002f Optimize Audio streaming to reduce lock contention 2025-08-11 18:42:55 +02:00
Wojtek Figat
99707b6586 Add various profiler events for more insights 2025-08-11 18:15:47 +02:00
Wojtek Figat
9f14bb7279 Optimize GPU particles simulation by scheduling larger sims first to overlap more work 2025-08-11 13:24:11 +02:00
Wojtek Figat
a18314c669 Add various minor improvements 2025-08-11 13:23:46 +02:00
Wojtek Figat
c946fa239e Fix gpu particles crash from 0ea555b041 on first draw 2025-08-10 22:54:37 +02:00
Wojtek Figat
d109e5ca9f Add AGS lib to D3D11 for efficient UAV writes overlaps on AMD GPUs 2025-08-10 17:16:36 +02:00
Wojtek Figat
bc0e1f81e7 Add AGS third party module
AGS 6.3
2025-08-10 17:16:09 +02:00
Wojtek Figat
c1c806490f Add nvapi lib to D3D11 for efficient UAV writes overlaps on NVIDIA GPUs 2025-08-10 16:05:18 +02:00
Wojtek Figat
4fd6343fb9 Fix missing memory barrier on particle indirect args building to ensure buffer copies are done afetr whole buffer update ends 2025-08-10 16:04:24 +02:00
Wojtek Figat
a2e9d8d77b Add nvapi third party module
R580-Developer SDK
2025-08-10 16:02:34 +02:00
Wojtek Figat
ff3d785483 Optimize GPU particles simulation, sorting and drawing with better resource transition barriers 2025-08-09 23:59:52 +02:00
Wojtek Figat
82231981dc Add debug tool detection for Nsight Graphics 2025-08-09 23:58:47 +02:00
Wojtek Figat
1915e1e7f4 Optimize compute shader pipeline binding on D3D12 and Vulkan when unchanged 2025-08-09 23:58:15 +02:00
Wojtek Figat
b5a431d2f5 Add explicit GPU resource transitions, memory and compute barriers 2025-08-09 23:57:43 +02:00
Wojtek Figat
3907bc4957 Optimize sorted particle indices format to 16-bit for small emitters 2025-08-08 18:46:10 +02:00
Wojtek Figat
854f3acd4c Optimize GPU particles Bitonic sort to use separate buffers for indices and keys to avoid additional buffer copy 2025-08-08 18:24:44 +02:00
Wojtek Figat
519a9c0a14 Add direct dispatch for Bitonic Sort when using small input buffer 2025-08-08 17:03:39 +02:00
Wojtek Figat
0ea555b041 Optimize GPU Particles simulation to perform memory buffer copies/updates before dispatch 2025-08-08 16:25:09 +02:00
Wojtek Figat
90d1e63b58 Add minor optimizations to particles drawing 2025-08-08 13:11:05 +02:00
Wojtek Figat
0369d9b2cb Optimize CSSetShader on D3D11 when remains unchanged 2025-08-08 11:03:03 +02:00
Wojtek Figat
9fabc1028a Optimize GPU particles indirect args building with a single batched upload of default data 2025-08-07 23:51:02 +02:00
Wojtek Figat
2a9260ddd5 Optimize emitters to cull shadow passes sorting and drawing 2025-08-07 23:49:21 +02:00
Wojtek Figat
3d84380175 Optimize particles sorting by splitting key generation and sorting to reduce CS switches 2025-08-07 19:09:58 +02:00
Wojtek Figat
545df6ce35 Add profiler event to GPU particles indirect args setup 2025-08-07 18:57:39 +02:00
Wojtek Figat
d4355e31d8 Optimize GPU particles drawing with batched indirect args setup before sorting 2025-08-07 18:41:58 +02:00
Wojtek Figat
3ffb067e55 Optimize Particles drawing to use a whole RenderContextBatch 2025-08-07 09:27:28 +02:00
Wojtek Figat
959371a995 Fix particles regression on DirectX 2025-08-06 23:39:46 +02:00
Wojtek Figat
cf9c203855 Various optimizations 2025-08-06 18:48:18 +02:00
Wojtek Figat
a5838f739d Optimize GPU particles indirect args building code 2025-08-05 23:01:07 +02:00
Wojtek Figat
b1710c4d01 Add async particles drawing (GPU emitters are sync) 2025-08-05 22:53:09 +02:00
Wojtek Figat
baf0cfce8e Add support for using custom memory allocator in lambda bind to Function 2025-08-05 22:13:21 +02:00
Wojtek Figat
a1a6d4738f Fix async draw wait labels type 2025-08-05 12:28:29 +02:00
Wojtek Figat
761ea094d6 Optimize render module indices data 4 times 2025-08-05 11:50:26 +02:00
Wojtek Figat
8e043e533e Optimize SpriteRenderer to lazy-init 2025-08-05 11:02:03 +02:00
Wojtek Figat
1a88fefd76 Optimize CPU particles drawing to support async 2025-08-05 09:03:47 +02:00
Wojtek Figat
abe496fe12 Fix crash on particles sorting memory access 2025-08-04 10:31:52 +02:00
Wojtek Figat
c9e0637b0f Fix crash when unloading texture with leftover streaming task that was idle 2025-08-02 22:03:19 +02:00
Wojtek Figat
db660721ce Fix debug command length bug 2025-08-02 22:01:25 +02:00
Wojtek Figat
2730d63257 More build fixes 2025-08-02 21:50:09 +02:00
Wojtek Figat
31764d6d4e Fix crash on memory access in Vulkan descriptor set data 2025-08-02 17:56:26 +02:00
Wojtek Figat
34ba45cd5a Add Stack to Sanitizers options 2025-08-02 17:36:48 +02:00
Wojtek Figat
5de5d8f683 Add more events for GPU profiling 2025-08-02 17:12:53 +02:00
Wojtek Figat
744c94b3cc Compilation errors fixing 2025-08-02 17:05:13 +02:00
Wojtek Figat
b26d6ea108 Fix various issues 2025-08-02 08:31:24 +02:00
Wojtek Figat
5c5341e346 Optimize Color Grading LUT to be cached if unchanged from the previous frame 2025-08-01 23:16:57 +02:00
Wojtek Figat
0f81c64964 Refactor Color Grading LUT rendering to have config for 2D/3D mode 2025-07-31 20:05:08 +02:00
Wojtek Figat
7603109dce Add StringUtils::Copy for char to Char 2025-07-31 20:04:03 +02:00
Wojtek Figat
01617ae684 Optimize Debug Commands name building and support nested classes with name hierarchy 2025-07-31 20:03:26 +02:00
Wojtek Figat
4aa2676084 Fix MClass::GetNamespace typo that returned name instead 2025-07-31 20:02:42 +02:00
Wojtek Figat
a8b9211c32 Fix output log console to resize width to contain whole item text 2025-07-31 17:34:22 +02:00
Wojtek Figat
9c5060584d Fix output log console to remove executed command from history no matter the placement 2025-07-31 17:32:41 +02:00
Wojtek Figat
846a0b5685 Fix PSO init to release old data on recreation 2025-07-31 15:08:38 +02:00
Wojtek Figat
08154d8fe5 Fix support for nesting classes inside other scripting classes 2025-07-31 15:07:57 +02:00
Wojtek Figat
a53a438c3c Fix to use static VkInstance 2025-07-31 12:10:42 +02:00
Wojtek Figat
bb8f569c41 Fix Motion Vectors rendering skipping when not needed by SSR 2025-07-30 23:46:42 +02:00
Wojtek Figat
6307ad7979 Fix shadow bias artifacts on Low shadows quality 2025-07-30 23:46:17 +02:00
Wojtek Figat
b6229350a3 Fix crash on invalid GPUBuffer vertex layout in empty buffer 2025-07-30 23:45:53 +02:00
Wojtek Figat
5dc4ebade1 Fix Vulkan perf tracing with Tracy on Switch 2025-07-30 23:25:27 +02:00
Wojtek Figat
3cd5890db1 Update volk to version 1.4.304 2025-07-30 19:11:15 +02:00
Wojtek Figat
522d8d89e6 Fix Global SDF to properly lock static chunks access 2025-07-30 19:09:21 +02:00
Wojtek Figat
492a5f979d Fix yield on Android 2025-07-30 19:08:58 +02:00
Wojtek Figat
5e4d564338 Add **GPU profiling support to Tracy integration** 2025-07-30 19:08:45 +02:00
Wojtek Figat
8fcbef863e Add GPUResourceMapMode.NoWait flag to control buffer data reading
c68b75a298
2025-07-30 08:42:26 +02:00
Wojtek Figat
c68b75a298 Fix GPUBufferDX11::Map to wait on data to avoid missing data when reading staging buffers 2025-07-29 21:43:09 +02:00
Wojtek Figat
8f63a99a2c Fix game splash screen to wait fr texture to be streamed in, not just allocated 2025-07-29 21:42:37 +02:00
Wojtek Figat
6d05bf16b1 Optimize Asset::GetPath in cooked build 2025-07-29 21:41:59 +02:00
Wojtek Figat
b8218e9ab4 Fix shader asset path in debug name in cooked build 2025-07-29 17:34:42 +02:00
Wojtek Figat
99323c1d2f Add customizable per-platform affinity for content and pool threads 2025-07-29 10:41:41 +02:00
Wojtek Figat
17c0892ff1 Add debug name for PSO catching on D3D12/Vulkan during profiling incl. Development builds 2025-07-28 23:08:26 +02:00
Wojtek Figat
ad6764e6d7 Fix Asset.WaitForLoaded to yield or sleep thread for proper multithreading on some platforms 2025-07-28 18:35:37 +02:00
Wojtek Figat
0bfd38e065 Fix compilation on platforms without cloth sim 2025-07-28 18:34:29 +02:00
Wojtek Figat
a00ffe6ec3 Add Platform::Yield 2025-07-28 18:33:05 +02:00
Wojtek Figat
a7ffd9e57f Add more profiler events 2025-07-28 15:15:09 +02:00
Wojtek Figat
354eaac56c Add optional testing utility for malloc/free operations 2025-07-27 23:20:06 +02:00
Wojtek Figat
8c51ea511a Fix incorrect documentation comments on HashSet/Dictionary item removal 2025-07-27 11:07:58 +02:00
Wojtek Figat
2af266727f Add utility names to gamepad buttons doc and add usefull profiler event for mono 2025-07-26 00:12:10 +02:00
Wojtek Figat
f37b75df7b Add support for using shadow maps from linked scene rendering (eg. for 1p weapons) 2025-07-25 19:59:58 +02:00
Wojtek Figat
6132e45e25 Fix shadow lights checking loop if shadows are disabled 2025-07-25 16:00:44 +02:00
Chandler Cox
753035c452 Fix issue with infinite loop if \ is used instead of / for tag closing. 2025-07-24 18:04:39 -05:00
Wojtek Figat
acc1777638 Add shared utility for command line arguments merging 2025-07-24 12:38:52 +02:00
Wojtek Figat
69585618ed Optimize scripting objects spawning on AOT platforms 2025-07-24 12:27:28 +02:00
Wojtek Figat
af0ea65d78 Add option to disable pipeline cache on specific Vulkan platforms 2025-07-24 12:20:09 +02:00
Wojtek Figat
751d179cdb Fix missing brace 2025-07-24 11:34:48 +02:00
Chandler Cox
2dc44ac1a6 Fix infinite loop on rich text box tag parsing with incomplete end of tag. 2025-07-23 19:52:42 -05:00
Wojtek Figat
2550b9f88e Fix missing TypeConverter support in AOT build 2025-07-23 22:15:38 +02:00
Wojtek Figat
c3cf8fba98 Optimize managed code 2025-07-23 18:17:10 +02:00
Wojtek Figat
6f172f8f2c Fix crash when prefab root object failed to deserialize 2025-07-23 18:16:32 +02:00
Wojtek Figat
735d611de1 Fix AOT libs rebuild when corlib was modified to avoid version mismatch 2025-07-23 18:15:52 +02:00
Chandler Cox
d6a33d5a1c Add const to String::Empty 2025-07-23 10:23:30 -05:00
Chandler Cox
6cbd40e6d8 Make StringView::Empty const to fix issues with user accidentally changing the value. 2025-07-22 22:01:55 -05:00
Wojtek Figat
8ac2385447 Update dependencies for Switch 2025-07-22 22:58:57 +02:00
Chandler Cox
b8e00f2ed1 Change checking max to use ceiltoint 2025-07-19 21:30:49 -05:00
Chandler Cox
b6e18ccae5 Fix edge case for anim event on min or max frame when looping. Fix anim event playback when is running negative. 2025-07-19 21:05:57 -05:00
Chandler Cox
1fb6586dff Add collection item duplication. 2025-07-19 16:09:33 -05:00
Chandler Cox
e6265105b5 Move to interface options. 2025-07-19 15:39:11 -05:00
Wojtek Figat
892e2e0d1e Fix fullscreen borderless window on macOS 2025-07-19 16:46:10 +02:00
Wojtek Figat
90551b32bc Add version to game settings 2025-07-19 16:40:34 +02:00
Wojtek Figat
cd08eeaf95 Fix running cooked game o macOS 2025-07-19 16:08:27 +02:00
Olly Rybak
f8dadac453 Fixed up some names and added docs 2025-07-19 22:37:35 +10:00
Wojtek Figat
f87e2c2229 Merge branch '1.11' of https://gitlab.flaxengine.com/flax/flaxengine into 1.11 2025-07-19 11:14:58 +02:00
Wojtek Figat
18035a8604 Fix incorrect image buffer usage in Render Output Control 2025-07-19 11:14:54 +02:00
Chandler Cox
fc46219a82 Add support for multi-select disable. 2025-07-17 23:09:36 -05:00
Chandler Cox
2546e19d65 Add shift selection for tree nodes 2025-07-17 23:07:06 -05:00
Wojtek Figat
6763436eff Add logging missing instance layer on Vulkan 2025-07-15 20:10:01 +02:00
Wojtek Figat
2754d61c05 Fix building Tracy for Switch 2025-07-15 19:31:07 +02:00
Wojtek Figat
7fd278a689 Fix .NET version to use selection for consoles with fixed setup 2025-07-15 13:34:43 +02:00
Wojtek Figat
2d2c5411cd Add variable DDGI probe size in debug view based on cascade 2025-07-15 12:49:05 +02:00
Wojtek Figat
3e0c085bf3 Add error log when adding/removign actors during rendering or when ConcurrentSystemLocker deadlocks 2025-07-15 12:34:40 +02:00
Wojtek Figat
c882b547c8 Fix game UI focus loss when hiding focused control to maintain gamepad navigation in Editor 2025-07-15 12:34:02 +02:00
Wojtek Figat
9646dd3fc2 Fix AutoFocus on ContainerControl to be false by default 2025-07-15 12:33:33 +02:00
Wojtek Figat
c0cce748cc Optimize Array::RemoveAtKeepOrder 2025-07-15 00:12:31 +02:00
Wojtek Figat
ab8612a914 Add profiler events to editor gizmo 2025-07-14 22:24:27 +02:00
Wojtek Figat
20f1e67700 Optimize Spline debug rendering far from camera 2025-07-14 21:09:28 +02:00
Wojtek Figat
eda7f7e90f Merge remote-tracking branch 'origin/master' into 1.11 2025-07-14 20:26:56 +02:00
Wojtek Figat
a22b33d3bb Fix missing sphere bounds update for splines 2025-07-14 20:26:41 +02:00
Wojtek Figat
8ed2d6da56 Optimize Debug Draw performance of splines to use frustum culling 2025-07-14 20:26:24 +02:00
Wojtek Figat
bb37f980ed Fix regression in debug draw from 4af26a5516 2025-07-14 20:25:49 +02:00
Wojtek Figat
349547f66c Merge remote-tracking branch 'origin/master' into 1.11
# Conflicts:
#	Source/Engine/Particles/Particles.cpp
2025-07-14 18:35:53 +02:00
Wojtek Figat
a1e4ed05c4 Don't force load asset on asset clone if it's unused 2025-07-14 18:14:09 +02:00
Wojtek Figat
10e9aee8ce Add particle data layout debugger tab 2025-07-14 10:28:43 +02:00
Wojtek Figat
4af26a5516 SImplify editor code for actors debug shapes drawing 2025-07-11 23:00:53 +02:00
Wojtek Figat
3e82e550f3 Add option for debug shapes drawing for particle emitters
#3267
2025-07-11 23:00:41 +02:00
Saas
33b540ed9e fix naming and treat unfolded category items as normal items 2025-07-10 20:07:52 +02:00
Saas
50871d8885 simplify and fix edge case in item list scrolling while holding control 2025-07-09 18:41:41 +02:00
Wojtek Figat
c27a9808c4 Fix unwanted code 2025-07-09 10:02:20 +02:00
Wojtek Figat
bdaf31b54f Optimize Arena Allocator to store page metadata within itself to save on allocs 2025-07-09 00:22:35 +02:00
Wojtek Figat
3abbf08f1f Optimize foliage rendering with concurrent arena allocator 2025-07-08 22:18:00 +02:00
Wojtek Figat
a8eb4fc140 Add allocator tag support for Dictionary and HashSet 2025-07-07 23:22:32 +02:00
xxSeys1
83374164db haha I did not copy paste that comment 2025-07-06 21:31:26 +02:00
xxSeys1
c5bfc6bc3d add option to add sphere in add colliders menu 2025-07-06 21:28:01 +02:00
Chandler Cox
d698bf96cc Apply particle effect parameter overrides when emitter is changed and when activated in the tree. 2025-07-05 19:36:45 -05:00
Chandler Cox
b3f88e156c Small change to out variable that is not used anymore. 2025-07-05 18:11:26 -05:00
Chandler Cox
7418d60f24 Add editor option for build configuration when using cook and run. 2025-07-05 18:09:30 -05:00
MrCapy0
3981d5090c change color gradiant node 8 to 11 stops 2025-07-05 10:27:45 -04:00
a93a940630 Fix hot-reload files not getting cleaned up during startup
Implements minimal required filter support for `FileSystem::DirectoryGetFiles`
in order to support removing hot-reload files on Linux/Apple systems.
2025-07-03 19:41:43 +03:00
3e353db1fa Refactor UnixFileSystem 2025-07-03 19:41:43 +03:00
xxSeys1
75647d149a make visual script editor method override cm searchable 2025-06-28 19:40:03 +02:00
xxSeys1
d7ab497b0e fix adding empty multi action to undo stack 2025-06-28 16:22:29 +02:00
xxSeys1
683a48a6e3 add default shortcuts to distribute node options 2025-06-28 16:02:44 +02:00
xxSeys1
a41fc51f92 add visject node formatting option to straighten node connections
Also fixes a bunch of missing trailing "." in doc comments and changes "Node editors" category in the input options to "Node Editors" to match the case of all other categories.
2025-06-28 15:53:32 +02:00
Chandler Cox
c8622d1801 Change method name from add to restore. 2025-06-20 15:26:58 -05:00
Chandler Cox
fdd22c3380 Remove extra code. 2025-06-19 22:09:33 -05:00
Chandler Cox
53761df85e Add utility methods for redundant code. 2025-06-19 22:07:28 -05:00
Chandler Cox
ecaae2b458 Add downloading nuget package if needed. 2025-06-19 21:34:55 -05:00
Chandler Cox
28eaac37dc Initial work on nuget packages. 2025-06-11 18:17:19 -05:00
Chandler Cox
6b78b498f7 Use direct count from internal call. 2025-06-04 10:17:41 -05:00
Chandler Cox
71991ff8c7 Show added and removed actors in prefab diff view. 2025-06-03 15:25:45 -05:00
Chandler Cox
954cf3eb5b Add option to show verticies and triangles of collision model in a collider data window. 2025-05-23 17:57:14 -05:00
Olly Rybak
245d7de818 Fixed renamed parameters 2025-05-14 19:45:29 +10:00
Olly
49e0cc937e Added SetNodeTransformation with ModelBoneNode
To get and set a series of bones based on their ID

(cherry picked from commit e0a113483e910660e45c53e059502733ce1d6ad6)
2025-05-14 19:29:39 +10:00
xxSeys1
1704cfba4d do not clear user search on script reload 2025-04-25 18:32:05 +02:00
xxSeys1
4e44831bbe fix searchbox width 2025-04-11 19:07:39 +02:00
xxSeys1
0c1e0e48d4 always sort the search results alphabetically 2025-04-10 22:12:47 +02:00
xxSeys1
6884df02fd remove trailing . on message 2025-04-10 21:34:00 +02:00
xxSeys1
63655d18c5 add a info message on Debug Log pause on warning 2025-04-10 21:31:12 +02:00
xxSeys1
4170699348 add hint if there are no search results 2025-04-10 09:25:52 +02:00
xxSeys1
d58a9beb3d why was this not in the last commit? 2025-04-09 23:45:43 +02:00
xxSeys1
5049f3b2d8 add hint if no filters are active 2025-04-09 23:45:00 +02:00
xxSeys1
6e44eebb9e another fix 2025-04-09 17:01:17 +02:00
xxSeys1
aecbab5613 more fixes 2025-04-09 14:30:08 +02:00
xxSeys1
6bf90f29c5 fixes 2025-04-09 14:29:19 +02:00
xxSeys1
19edce1770 add controls and filter to actor toolbox search 2025-04-09 10:43:52 +02:00
Chandler Cox
e17b96b2d6 Add additional methods for layers. 2025-04-07 11:14:33 -05:00
Chandler Cox
9b6feb9367 Add Scaled Time to Material Time node. 2025-04-07 10:02:20 -05:00
xxSeys1
391c67b1a9 add visibility options for the tab close button 2025-03-23 14:09:59 +01:00
xxSeys1
975cc79085 code style fixes 2025-03-16 22:18:21 +01:00
xxSeys1
468babae87 auto resize PropertiesList splitter bar based on longest text 2025-03-16 20:32:20 +01:00
xxSeys1
516d4263c9 add broken link icon 2025-02-11 23:56:28 +01:00
xxSeys1
ba35123420 add minimum tab width 2025-02-11 18:15:46 +01:00
xxSeys1
409703d675 add editor option for tab height 2025-02-11 16:39:33 +01:00
xxSeys1
570c3f7462 add option for single tab tab header bar visibility 2025-02-11 16:39:15 +01:00
Chandler Cox
42d02a9e63 Add small fade to bottom bar. 2025-02-08 18:49:04 -06:00
Chandler Cox
819c93f6fb Increase margins. 2024-12-24 14:26:59 -06:00
Chandler Cox
0c645cbc78 Allow user to add splash image to splash screen. 2024-12-24 12:12:59 -06:00
499 changed files with 52643 additions and 6138 deletions

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

View File

@@ -13,7 +13,7 @@
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x4 InvWorld;
float4x4 SVPositionToWorld;
float4x4 SvPositionToWorld;
@1META_CB_END
// Use depth buffer for per-pixel decal layering
@@ -27,12 +27,63 @@ struct MaterialInput
float3 WorldPosition;
float TwoSidedSign;
float2 TexCoord;
float4 TexCoord_DDX_DDY;
float3x3 TBN;
float4 SvPosition;
float3 PreSkinnedPosition;
float3 PreSkinnedNormal;
};
// Calculates decal texcoords for a given pixel position (sampels depth buffer and projects value to decal space).
float2 SvPositionToDecalUV(float4 svPosition)
{
float2 screenUV = svPosition.xy * ScreenSize.zw;
svPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = mul(float4(svPosition.xyz, 1), SvPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
return positionOS.xz + 0.5f;
}
// Manually compute ddx/ddy for decal texture cooordinates to avoid the 2x2 pixels artifacts on the edges of geometry under decal
// [Reference: https://www.humus.name/index.php?page=3D&ID=84]
float4 CalculateTextureDerivatives(float4 svPosition, float2 texCoord)
{
float4 svDiffX = float4(1, 0, 0, 0);
float2 uvDiffX0 = texCoord - SvPositionToDecalUV(svPosition - svDiffX);
float2 uvDiffX1 = SvPositionToDecalUV(svPosition + svDiffX) - texCoord;
float2 dx = dot(uvDiffX0, uvDiffX0) < dot(uvDiffX1, uvDiffX1) ? uvDiffX0 : uvDiffX1;
float4 svDiffY = float4(0, 1, 0, 0);
float2 uvDiffY0 = texCoord - SvPositionToDecalUV(svPosition - svDiffY);
float2 uvDiffY1 = SvPositionToDecalUV(svPosition + svDiffY) - texCoord;
float2 dy = dot(uvDiffY0, uvDiffY0) < dot(uvDiffY1, uvDiffY1) ? uvDiffY0 : uvDiffY1;
return float4(dx, dy);
}
// Computes the mipmap level for a specific texture dimensions to be sampled at decal texture cooordinates.
// [Reference: https://hugi.scene.org/online/coding/hugi%2014%20-%20comipmap.htm]
float CalculateTextureMipmap(MaterialInput input, float2 textureSize)
{
float2 dx = input.TexCoord_DDX_DDY.xy * textureSize;
float2 dy = input.TexCoord_DDX_DDY.zw * textureSize;
float d = max(dot(dx, dx), dot(dy, dy));
return (0.5 * 0.5) * log2(d); // Hardcoded half-mip rate reduction to avoid artifacts when decal is moved over dither texture
}
float CalculateTextureMipmap(MaterialInput input, Texture2D t)
{
float2 textureSize;
t.GetDimensions(textureSize.x, textureSize.y);
return CalculateTextureMipmap(input, textureSize);
}
float CalculateTextureMipmap(MaterialInput input, TextureCube t)
{
float2 textureSize;
t.GetDimensions(textureSize.x, textureSize.y);
return CalculateTextureMipmap(input, textureSize);
}
// Transforms a vector from tangent space to world space
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
{
@@ -116,7 +167,6 @@ Material GetMaterialPS(MaterialInput input)
}
// Input macro specified by the material: DECAL_BLEND_MODE
#define DECAL_BLEND_MODE_TRANSLUCENT 0
#define DECAL_BLEND_MODE_STAIN 1
#define DECAL_BLEND_MODE_NORMAL 2
@@ -153,7 +203,7 @@ void PS_Decal(
float2 screenUV = SvPosition.xy * ScreenSize.zw;
SvPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = mul(float4(SvPosition.xyz, 1), SVPositionToWorld);
float4 positionHS = mul(float4(SvPosition.xyz, 1), SvPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
@@ -166,8 +216,9 @@ void PS_Decal(
materialInput.TexCoord = decalUVs;
materialInput.TwoSidedSign = 1;
materialInput.SvPosition = SvPosition;
// Build tangent to world transformation matrix
materialInput.TexCoord_DDX_DDY = CalculateTextureDerivatives(materialInput.SvPosition, materialInput.TexCoord);
// Calculate tangent-space
float3 ddxWp = ddx(positionWS);
float3 ddyWp = ddy(positionWS);
materialInput.TBN[0] = normalize(ddyWp);

View File

@@ -20,6 +20,8 @@ float TimeParam;
float4 ViewInfo;
float4 ScreenSize;
float4 ViewSize;
float3 ViewPadding0;
float UnscaledTimeParam;
@1META_CB_END
// Shader resources

View File

@@ -19,6 +19,8 @@ float4 ViewInfo;
float4 ScreenSize;
float4 TemporalAAJitter;
float4x4 InverseViewProjectionMatrix;
float3 ViewPadding0;
float UnscaledTimeParam;
@1META_CB_END
// Shader resources

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultRadialMenu.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@@ -73,6 +73,24 @@
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=TYPEDEF/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=CCD/@EntryIndexedValue">CCD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=GPU/@EntryIndexedValue">GPU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=175CE9C669E52F4D92FD2C07848740BD/@EntryIndexedValue">&lt;NamingElement Priority="11" Title="Class and struct public fields"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="PUBLIC"&gt;&lt;type Name="class field" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=32EB6D69783B3E4481A733193E338089/@EntryIndexedValue">&lt;NamingElement Priority="9" Title="Class and struct methods"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="member function" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=3C4E0D59F298854F9608A9B454E8FF5E/@EntryIndexedValue">&lt;NamingElement Priority="17" Title="Typedefs"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="type alias" /&gt;&lt;type Name="typedef" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=499C9026DADA2B448BCD0B2C54746A59/@EntryIndexedValue">&lt;NamingElement Priority="14" Title="Other constants"&gt;&lt;Descriptor Static="True" Constexpr="Indeterminate" Const="True" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="class field" /&gt;&lt;type Name="local variable" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=50D2535711CE1A43A3B06EF841C36CFD/@EntryIndexedValue">&lt;NamingElement Priority="13" Title="Enum members"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="scoped enumerator" /&gt;&lt;type Name="unscoped enumerator" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=6AD3BADA1260CC4D840AB26323C51827/@EntryIndexedValue">&lt;NamingElement Priority="15" Title="Global constants"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="True" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=904CDCA174AACE4AA52660A247CDF9A0/@EntryIndexedValue">&lt;NamingElement Priority="7" Title="Global variables"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=95BCDE767C97B64DB3DAE800DBBBC758/@EntryIndexedValue">&lt;NamingElement Priority="5" Title="Parameters"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="function parameter" /&gt;&lt;type Name="lambda parameter" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=C03AE454FC2CBA43819AC75E4D6C9C8C/@EntryIndexedValue">&lt;NamingElement Priority="1" Title="Classes and structs"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="__interface" /&gt;&lt;type Name="class" /&gt;&lt;type Name="struct" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=D49E31C610641E4CAD0407DB79ACC851/@EntryIndexedValue">&lt;NamingElement Priority="8" Title="Global functions"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global function" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=D73FBB3529BC5449B6C85BB37B26A8D4/@EntryIndexedValue">&lt;NamingElement Priority="16" Title="Namespaces"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="namespace" /&gt;&lt;type Name="namespace alias" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DA41807CE47AEB4CBE1724C44D0B786E/@EntryIndexedValue">&lt;NamingElement Priority="6" Title="Local variables"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="local variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DDF30C9A1DA74B4DBBC56D25FDF886AA/@EntryIndexedValue">&lt;NamingElement Priority="10" Title="Class and struct fields"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="class field" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=EF70A6BF54ACE446971DDB32344C25A3/@EntryIndexedValue">&lt;NamingElement Priority="12" Title="Union members"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="union member" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=F37818C54C323A4A80B1A478629985AE/@EntryIndexedValue">&lt;NamingElement Priority="2" Title="Enums"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="enum" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
@@ -213,6 +231,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=YZ/@EntryIndexedValue">YZ</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PublicFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/Environment/Hierarchy/PsiConfigurationSettingsKey/CustomLocation/@EntryValue">C:\Users\Wojtek\AppData\Local\JetBrains\Transient\ReSharperPlatformVs15\v08_f9eacea9\SolutionCaches</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ENaming_002ECppNamingOptionsMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002EFunctionReturnStyleSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002ENamespaceIndentationSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@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

@@ -57,9 +57,9 @@ Follow the instructions below to compile and run the engine from source.
* 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 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`
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
* Install Clang compiler (version 6 or later):
* Ubuntu: `sudo apt-get install clang lldb lld`
* Fedora: `sudo dnf install clang llvm lldb lld`

View File

@@ -20,13 +20,6 @@ class PlatformTools;
#define GAME_BUILD_DOTNET_RUNTIME_MAX_VER 9
#endif
#if OFFICIAL_BUILD
// Use the fixed .NET SDK version in packaged builds for compatibility (FlaxGame is precompiled with it)
#define GAME_BUILD_DOTNET_VER TEXT("-dotnet=" MACRO_TO_STR(GAME_BUILD_DOTNET_RUNTIME_MIN_VER))
#else
#define GAME_BUILD_DOTNET_VER TEXT("")
#endif
/// <summary>
/// Game building options. Used as flags.
/// </summary>
@@ -374,6 +367,8 @@ public:
/// </summary>
void GetBuildPlatformName(const Char*& platform, const Char*& architecture) const;
String GetDotnetCommandArg() const;
public:
/// <summary>

View File

@@ -312,6 +312,14 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
}
}
String CookingData::GetDotnetCommandArg() const
{
int32 version = Tools->GetDotnetVersion();
if (version == 0)
return String::Empty;
return String::Format(TEXT("-dotnet={}"), version);
}
void CookingData::StepProgress(const String& info, const float stepProgress) const
{
const float singleStepProgress = 1.0f / (StepsCount + 1);
@@ -675,8 +683,7 @@ bool GameCookerImpl::Build()
MCore::Thread::Attach();
// Build Started
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
// Build start
{
CallEvent(GameCooker::EventType::BuildStarted);
data.Tools->OnBuildStarted(data);
@@ -749,8 +756,8 @@ bool GameCookerImpl::Build()
}
IsRunning = false;
CancelFlag = 0;
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
{
// Build end
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildEnded(data, failed);
data.Tools->OnBuildEnded(data, failed);

View File

@@ -195,4 +195,9 @@ bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* pla
return false;
}
int32 GDKPlatformTools::GetDotnetVersion() const
{
return GAME_BUILD_DOTNET_RUNTIME_MIN_VER;
}
#endif

View File

@@ -26,6 +26,7 @@ public:
public:
// [PlatformTools]
int32 GetDotnetVersion() const override;
DotNetAOTModes UseAOT() const override;
bool OnDeployBinaries(CookingData& data) override;
};

View File

@@ -231,6 +231,8 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
LOG(Info, "Building app package...");
{
const String dmgPath = data.OriginalOutputPath / appName + TEXT(".dmg");
if (FileSystem::FileExists(dmgPath))
FileSystem::DeleteFile(dmgPath);
CreateProcessSettings procSettings;
procSettings.HiddenWindow = true;
procSettings.WorkingDirectory = data.OriginalOutputPath;

View File

@@ -528,6 +528,9 @@ bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
void WindowsPlatformTools::OnBuildStarted(CookingData& data)
{
if (EnumHasAllFlags(data.Options, BuildOptions::NoCook))
return;
// Remove old executable
Array<String> files;
FileSystem::DirectoryGetFiles(files, data.NativeCodeOutputPath, TEXT("*.exe"), DirectorySearchOption::TopDirectoryOnly);

View File

@@ -70,6 +70,20 @@ public:
/// </summary>
virtual ArchitectureType GetArchitecture() const = 0;
/// <summary>
/// Gets the .Net version to use for the cooked game.
/// </summary>
virtual int32 GetDotnetVersion() const
{
#if OFFICIAL_BUILD
// Use the fixed .NET SDK version in packaged builds for compatibility (FlaxGame is precompiled with it)
return GAME_BUILD_DOTNET_RUNTIME_MIN_VER;
#else
// Use the highest version found on a system (Flax.Build will decide)
return 0;
#endif
}
/// <summary>
/// Gets the value indicating whenever platform requires AOT (needs C# assemblies to be precompiled).
/// </summary>

View File

@@ -189,7 +189,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("CompileLog.txt");
auto args = String::Format(
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3} -aotMode={5} {6}"),
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()), GAME_BUILD_DOTNET_VER);
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()), data.GetDotnetCommandArg());
#if PLATFORM_WINDOWS
if (data.Platform == BuildPlatform::LinuxX64)
#elif PLATFORM_LINUX

View File

@@ -88,7 +88,7 @@ bool DeployDataStep::Perform(CookingData& data)
{
// Ask Flax.Build to provide .NET SDK location for the current platform
String sdks;
bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), GAME_BUILD_DOTNET_VER), data.CacheDirectory);
bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), data.GetDotnetCommandArg()), data.CacheDirectory);
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
int32 idx = sdks.Find(TEXT("DotNetSdk, "), StringSearchCase::CaseSensitive);
if (idx != -1)
@@ -200,7 +200,7 @@ bool DeployDataStep::Perform(CookingData& data)
String sdks;
const Char *platformName, *archName;
data.GetBuildPlatformName(platformName, archName);
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={} {}"), platformName, archName, GAME_BUILD_DOTNET_VER);
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={} {}"), platformName, archName, data.GetDotnetCommandArg());
bool failed = ScriptsBuilder::RunBuildTool(args, data.CacheDirectory);
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
Array<String> parts;
@@ -244,10 +244,13 @@ bool DeployDataStep::Perform(CookingData& data)
}
if (version.IsEmpty())
{
int32 minVer = GAME_BUILD_DOTNET_RUNTIME_MIN_VER, maxVer = GAME_BUILD_DOTNET_RUNTIME_MAX_VER;
if (srcDotnetFromEngine)
{
// Detect version from runtime files inside Engine Platform folder
for (int32 i = GAME_BUILD_DOTNET_RUNTIME_MAX_VER; i >= GAME_BUILD_DOTNET_RUNTIME_MIN_VER; i--)
if (data.Tools->GetDotnetVersion() != 0)
minVer = maxVer = data.Tools->GetDotnetVersion();
for (int32 i = maxVer; i >= minVer; i--)
{
// Check runtime files inside Engine Platform folder
String testPath1 = srcDotnet / String::Format(TEXT("lib/net{}.0"), i);
@@ -262,7 +265,7 @@ bool DeployDataStep::Perform(CookingData& data)
}
if (version.IsEmpty())
{
data.Error(String::Format(TEXT("Failed to find supported .NET {} version for the current host platform."), GAME_BUILD_DOTNET_RUNTIME_MIN_VER));
data.Error(String::Format(TEXT("Failed to find supported .NET {} version (min {}) for the current host platform."), maxVer, minVer));
return true;
}
}
@@ -364,7 +367,7 @@ bool DeployDataStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("StripDotnetLibs.txt");
String args = String::Format(
TEXT("-log -logfile=\"{}\" -runDotNetClassLibStripping -mutex -binaries=\"{}\" {}"),
logFile, data.DataOutputPath, GAME_BUILD_DOTNET_VER);
logFile, data.DataOutputPath, data.GetDotnetCommandArg());
for (const String& define : data.CustomDefines)
{
args += TEXT(" -D");

View File

@@ -12,7 +12,7 @@
void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
{
const DotNetAOTModes aotMode = data.Tools->UseAOT();
if (aotMode == DotNetAOTModes::None)
if (aotMode == DotNetAOTModes::None || EnumHasAllFlags(data.Options, BuildOptions::NoCook))
return;
const auto& buildSettings = *BuildSettings::Get();
@@ -69,7 +69,7 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("AOTLog.txt");
String args = String::Format(
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\" {}"),
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath, GAME_BUILD_DOTNET_VER);
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath, data.GetDotnetCommandArg());
if (!buildSettings.SkipUnusedDotnetLibsPackaging)
args += TEXT(" -skipUnusedDotnetLibs=false"); // Run AOT on whole class library (not just used libs)
for (const String& define : data.CustomDefines)

View File

@@ -18,8 +18,8 @@ namespace FlaxEditor
private readonly CustomEditorPresenter _presenter;
private CustomEditorWindow _customEditor;
public Win(CustomEditorWindow customEditor)
: base(Editor.Instance, false, ScrollBars.Vertical)
public Win(CustomEditorWindow customEditor, bool hideOnClose, ScrollBars scrollBars)
: base(Editor.Instance, hideOnClose, scrollBars)
{
Title = customEditor.GetType().Name;
_customEditor = customEditor;
@@ -64,9 +64,9 @@ namespace FlaxEditor
/// <summary>
/// Initializes a new instance of the <see cref="CustomEditorWindow"/> class.
/// </summary>
protected CustomEditorWindow()
protected CustomEditorWindow(bool hideOnClose = false, ScrollBars scrollBars = ScrollBars.Vertical)
{
_win = new Win(this);
_win = new Win(this, hideOnClose, scrollBars);
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}

View File

@@ -749,6 +749,15 @@ namespace FlaxEditor.CustomEditors
}
}
private Actor FindActor(CustomEditor editor)
{
if (editor.Values[0] is Actor actor)
return actor;
if (editor.ParentEditor != null)
return FindActor(editor.ParentEditor);
return null;
}
private Actor FindPrefabRoot(CustomEditor editor)
{
if (editor.Values[0] is Actor actor)
@@ -767,32 +776,35 @@ namespace FlaxEditor.CustomEditors
return FindPrefabRoot(actor.Parent);
}
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId)
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId, Actor endPoint)
{
var visited = new HashSet<Actor>();
return FindObjectWithPrefabObjectId(actor, ref prefabObjectId, endPoint, visited);
}
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId, Actor endPoint, HashSet<Actor> visited)
{
if (visited.Contains(actor) || actor is Scene || actor == endPoint)
return null;
if (actor.PrefabObjectID == prefabObjectId)
return actor;
for (int i = 0; i < actor.ScriptsCount; i++)
{
if (actor.GetScript(i).PrefabObjectID == prefabObjectId)
{
var a = actor.GetScript(i);
if (a != null)
return a;
}
var script = actor.GetScript(i);
if (script != null && script.PrefabObjectID == prefabObjectId)
return script;
}
for (int i = 0; i < actor.ChildrenCount; i++)
{
if (actor.GetChild(i).PrefabObjectID == prefabObjectId)
{
var a = actor.GetChild(i);
if (a != null)
return a;
}
var child = actor.GetChild(i);
if (child != null && child.PrefabObjectID == prefabObjectId)
return child;
}
return null;
// Go up in the hierarchy
return FindObjectWithPrefabObjectId(actor.Parent, ref prefabObjectId, endPoint, visited);
}
/// <summary>
@@ -826,7 +838,7 @@ namespace FlaxEditor.CustomEditors
}
var prefabObjectId = referenceSceneObject.PrefabObjectID;
var prefabInstanceRef = FindObjectWithPrefabObjectId(prefabInstanceRoot, ref prefabObjectId);
var prefabInstanceRef = FindObjectWithPrefabObjectId(FindActor(this), ref prefabObjectId, prefabInstanceRoot);
if (prefabInstanceRef == null)
{
Editor.LogWarning("Missing prefab instance reference in the prefab instance. Cannot revert to it.");

View File

@@ -63,6 +63,11 @@ namespace FlaxEditor.CustomEditors
/// Indication of if the properties window is locked on specific objects.
/// </summary>
public bool LockSelection { get; set; }
/// <summary>
/// Gets the scene editing context.
/// </summary>
public ISceneEditingContext SceneContext { get; }
}
/// <summary>

View File

@@ -1,8 +1,5 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.CustomEditors.Elements;
@@ -10,12 +7,14 @@ using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using FlaxEngine.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FlaxEditor.CustomEditors.Dedicated
{
@@ -240,6 +239,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
node.TextColor = Color.OrangeRed;
node.Text = Utilities.Utils.GetPropertyNameUI(removed.PrefabObject.GetType().Name);
}
// Removed Actor
else if (editor is RemovedActorDummy removedActor)
{
node.TextColor = Color.OrangeRed;
node.Text = $"{removedActor.PrefabObject.Name} ({Utilities.Utils.GetPropertyNameUI(removedActor.PrefabObject.GetType().Name)})";
}
// Actor or Script
else if (editor.Values[0] is SceneObject sceneObject)
{
@@ -295,16 +300,40 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Not used
}
}
private class RemovedActorDummy : CustomEditor
{
/// <summary>
/// The removed prefab object (from the prefab default instance).
/// </summary>
public Actor PrefabObject;
/// <summary>
/// The prefab instance's parent.
/// </summary>
public Actor ParentActor;
/// <summary>
/// The order of the removed actor in the parent.
/// </summary>
public int OrderInParent;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
// Not used
}
}
private TreeNode ProcessDiff(CustomEditor editor, bool skipIfNotModified = true)
{
// Special case for new Script added to actor
if (editor.Values[0] is Script script && !script.HasPrefabLink)
// Special case for new Script or child actor added to actor
if ((editor.Values[0] is Script script && !script.HasPrefabLink) || (editor.Values[0] is Actor a && !a.HasPrefabLink))
return CreateDiffNode(editor);
// Skip if no change detected
var isRefEdited = editor.Values.IsReferenceValueModified;
if (!isRefEdited && skipIfNotModified)
if (!isRefEdited && skipIfNotModified && editor is not ScriptsEditor)
return null;
TreeNode result = null;
@@ -359,6 +388,44 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
}
// Compare child actors for removed actors.
if (editor is ActorEditor && editor.Values.HasReferenceValue && editor.Values.ReferenceValue is Actor prefabObjectActor)
{
var thisActor = editor.Values[0] as Actor;
for (int i = 0; i < prefabObjectActor.ChildrenCount; i++)
{
var prefabActorChild = prefabObjectActor.Children[i];
if (thisActor == null)
continue;
bool isRemoved = true;
for (int j = 0; j < thisActor.ChildrenCount; j++)
{
var actorChild = thisActor.Children[j];
if (actorChild.PrefabObjectID == prefabActorChild.PrefabObjectID)
{
isRemoved = false;
break;
}
}
if (isRemoved)
{
var dummy = new RemovedActorDummy
{
PrefabObject = prefabActorChild,
ParentActor = thisActor,
OrderInParent = prefabActorChild.OrderInParent,
};
var child = CreateDiffNode(dummy);
if (result == null)
result = CreateDiffNode(editor);
result.AddChild(child);
}
}
}
if (editor is ScriptsEditor && result != null && result.ChildrenCount == 0)
return null;
return result;
}
@@ -438,6 +505,15 @@ namespace FlaxEditor.CustomEditors.Dedicated
Presenter.BuildLayoutOnUpdate();
}
private static void GetAllPrefabObjects(List<object> objects, Actor actor)
{
objects.Add(actor);
objects.AddRange(actor.Scripts);
var children = actor.Children;
foreach (var child in children)
GetAllPrefabObjects(objects, child);
}
private void OnDiffRevert(CustomEditor editor)
{
// Special case for removed Script from actor
@@ -459,6 +535,22 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
// Special case for reverting removed Actors
if (editor is RemovedActorDummy removedActor)
{
Editor.Log("Reverting removed actor changes to prefab (adding it)");
var parentActor = removedActor.ParentActor;
var restored = parentActor.AddChild(removedActor.PrefabObject.GetType());
var prefabId = parentActor.PrefabID;
var prefabObjectId = removedActor.PrefabObject.PrefabObjectID;
string data = JsonSerializer.Serialize(removedActor.PrefabObject);
JsonSerializer.Deserialize(restored, data);
Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent);
Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId);
return;
}
// Special case for new Script added to actor
if (editor.Values[0] is Script script && !script.HasPrefabLink)
{
@@ -470,8 +562,37 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
// Special case for new Actor added to actor
if (editor.Values[0] is Actor a && !a.HasPrefabLink)
{
Editor.Log("Reverting added actor changes to prefab (removing it)");
editor.RevertToReferenceValue();
// TODO: Keep previous selection.
var context = Presenter.Owner.SceneContext;
context.Select(SceneGraph.SceneGraphFactory.FindNode(a.ID));
context.DeleteSelection();
return;
}
if (Presenter.Undo != null && Presenter.Undo.Enabled)
{
var thisActor = (Actor)Values[0];
var rootActor = thisActor.IsPrefabRoot ? thisActor : thisActor.GetPrefabRoot();
var prefabObjects = new List<object>();
GetAllPrefabObjects(prefabObjects, rootActor);
using (new UndoMultiBlock(Presenter.Undo, prefabObjects, "Revert to Prefab"))
{
editor.RevertToReferenceValue();
editor.RefreshInternal();
}
}
else
{
editor.RevertToReferenceValue();
editor.RefreshInternal();
}
}
}
}

View File

@@ -106,7 +106,6 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton = new Button
{
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Link32),
Parent = LinkedLabel,
Width = 18,
Height = 18,
@@ -189,6 +188,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.SetColors(backgroundColor);
_linkButton.BorderColor = _linkButton.BorderColorSelected = _linkButton.BorderColorHighlighted = Color.Transparent;
_linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling";
_linkButton.BackgroundBrush = new SpriteBrush(LinkValues ? Editor.Instance.Icons.Link32 : Editor.Instance.Icons.BrokenLink32);
}
}

View File

@@ -70,7 +70,9 @@ namespace FlaxEditor.CustomEditors.Editors
menu.ItemsContainer.RemoveChildren();
menu.AddButton("Copy", linkedEditor.Copy);
var b = menu.AddButton("Paste", linkedEditor.Paste);
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
b = menu.AddButton("Paste", linkedEditor.Paste);
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
menu.AddSeparator();
@@ -404,8 +406,10 @@ namespace FlaxEditor.CustomEditors.Editors
var menu = new ContextMenu();
menu.AddButton("Copy", linkedEditor.Copy);
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
var paste = menu.AddButton("Paste", linkedEditor.Paste);
paste.Enabled = linkedEditor.CanPaste;
paste.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
if (_canReorder)
{
@@ -741,6 +745,34 @@ namespace FlaxEditor.CustomEditors.Editors
cloned[srcIndex] = tmp;
SetValue(cloned);
}
/// <summary>
/// Duplicates the list item.
/// </summary>
/// <param name="index">The index to duplicate.</param>
public void Duplicate(int index)
{
if (IsSetBlocked)
return;
var count = Count;
var newValues = Allocate(count + 1);
var oldValues = (IList)Values[0];
for (int i = 0; i <= index; i++)
{
newValues[i] = oldValues[i];
}
newValues[index + 1] = Utilities.Utils.CloneValue(oldValues[index]);
for (int i = index + 1; i < count; i++)
{
newValues[i + 1] = oldValues[i];
}
SetValue(newValues);
}
/// <summary>
/// Shifts the specified item at the given index and moves it through the list to the other item. It supports undo.

View File

@@ -22,7 +22,7 @@ internal class UIControlRefPickerControl : FlaxObjectRefPickerControl
/// <inheritdoc />
protected override bool IsValid(Object obj)
{
return obj == null || (obj is UIControl control && control.Control.GetType() == ControlType);
return obj == null || (obj is UIControl control && ControlType.IsAssignableFrom(control.Control.GetType()));
}
}

View File

@@ -14,6 +14,9 @@ namespace FlaxEditor.CustomEditors.GUI
public class PropertiesList : PanelWithMargins
{
// TODO: sync splitter for whole presenter
private const float SplitterPadding = 15;
private const float EditorsMinWidthRatio = 0.4f;
/// <summary>
/// The splitter size (in pixels).
@@ -25,6 +28,7 @@ namespace FlaxEditor.CustomEditors.GUI
private Rectangle _splitterRect;
private bool _splitterClicked, _mouseOverSplitter;
private bool _cursorChanged;
private bool _hasCustomSplitterValue;
/// <summary>
/// Gets or sets the splitter value (always in range [0; 1]).
@@ -66,6 +70,26 @@ namespace FlaxEditor.CustomEditors.GUI
UpdateSplitRect();
}
private void AutoSizeSplitter()
{
if (_hasCustomSplitterValue || !Editor.Instance.Options.Options.Interface.AutoSizePropertiesPanelSplitter)
return;
Font font = Style.Current.FontMedium;
float largestWidth = 0f;
for (int i = 0; i < _element.Labels.Count; i++)
{
Label currentLabel = _element.Labels[i];
Float2 dimensions = font.MeasureText(currentLabel.Text);
float width = dimensions.X + currentLabel.Margin.Left + SplitterPadding;
largestWidth = Mathf.Max(largestWidth, width);
}
SplitterValue = Mathf.Clamp(largestWidth / Width, 0, 1 - EditorsMinWidthRatio);
}
private void UpdateSplitRect()
{
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSize * 0.5f, 0.0f, Width), 0, SplitterSize, Height);
@@ -122,6 +146,7 @@ namespace FlaxEditor.CustomEditors.GUI
SplitterValue = location.X / Width;
Cursor = CursorType.SizeWE;
_cursorChanged = true;
_hasCustomSplitterValue = true;
}
else if (_mouseOverSplitter)
{
@@ -195,6 +220,7 @@ namespace FlaxEditor.CustomEditors.GUI
// Refresh
UpdateSplitRect();
PerformLayout(true);
AutoSizeSplitter();
}
/// <inheritdoc />

View File

@@ -528,7 +528,11 @@ namespace FlaxEditor
var timeSinceLastSave = Time.UnscaledGameTime - _lastAutoSaveTimer;
var timeToNextSave = options.AutoSaveFrequency * 60.0f - timeSinceLastSave;
if (timeToNextSave <= 0.0f || _autoSaveNow)
if (timeToNextSave <= 0.0f && GetWindows().Any(x => x.GUI.Children.Any(c => c is GUI.ContextMenu.ContextMenuBase)))
{
// Skip aut-save if any context menu is opened to wait for user to end interaction
}
else if (timeToNextSave <= 0.0f || _autoSaveNow)
{
Log("Auto save");
_lastAutoSaveTimer = Time.UnscaledGameTime;

View File

@@ -39,6 +39,7 @@ namespace FlaxEditor
public SpriteHandle Globe32;
public SpriteHandle CamSpeed32;
public SpriteHandle Link32;
public SpriteHandle BrokenLink32;
public SpriteHandle Add32;
public SpriteHandle Left32;
public SpriteHandle Right32;
@@ -94,6 +95,7 @@ namespace FlaxEditor
public SpriteHandle Search64;
public SpriteHandle Bone64;
public SpriteHandle Link64;
public SpriteHandle BrokenLink64;
public SpriteHandle Build64;
public SpriteHandle Add64;
public SpriteHandle ShipIt64;

View File

@@ -117,9 +117,10 @@ namespace FlaxEditor.GUI.ContextMenu
public ContextMenuBase()
: base(0, 0, 120, 32)
{
_direction = ContextMenuDirection.RightDown;
Visible = false;
AutoFocus = true;
_direction = ContextMenuDirection.RightDown;
_isSubMenu = true;
}

View File

@@ -76,6 +76,8 @@ namespace FlaxEditor.GUI.Dialogs
public ColorSelector(float wheelSize)
: base(0, 0, wheelSize, wheelSize)
{
AutoFocus = true;
_colorWheelSprite = Editor.Instance.Icons.ColorWheel128;
_wheelRect = new Rectangle(0, 0, wheelSize, wheelSize);
}

View File

@@ -1,6 +1,7 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -13,12 +14,12 @@ namespace FlaxEditor.GUI.Docking
public class DockPanelProxy : ContainerControl
{
private DockPanel _panel;
private InterfaceOptions.TabCloseButtonVisibility closeButtonVisibility;
private double _dragEnterTime = -1;
#if PLATFORM_WINDOWS
private const bool HideTabForSingleTab = true;
#else
private const bool HideTabForSingleTab = false;
#endif
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
private readonly bool _hideTabForSingleTab = Utilities.Utils.HideSingleTabWindowTabBars();
/// <summary>
/// The is mouse down flag (left button).
@@ -60,8 +61,8 @@ namespace FlaxEditor.GUI.Docking
/// </summary>
public DockWindow StartDragAsyncWindow;
private Rectangle HeaderRectangle => new Rectangle(0, 0, Width, DockPanel.DefaultHeaderHeight);
private bool IsSingleFloatingWindow => HideTabForSingleTab && _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
private Rectangle HeaderRectangle => new Rectangle(0, 0, Width, _tabHeight);
private bool IsSingleFloatingWindow => _hideTabForSingleTab && _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
/// <summary>
/// Initializes a new instance of the <see cref="DockPanelProxy"/> class.
@@ -70,11 +71,17 @@ namespace FlaxEditor.GUI.Docking
internal DockPanelProxy(DockPanel panel)
: base(0, 0, 64, 64)
{
AutoFocus = false;
_panel = panel;
AnchorPreset = AnchorPresets.StretchAll;
Offsets = Margin.Zero;
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
OnEditorOptionsChanged(Editor.Instance.Options.Options);
}
private void OnEditorOptionsChanged(EditorOptions options)
{
closeButtonVisibility = options.Interface.ShowTabCloseButton;
}
private DockWindow GetTabAtPos(Float2 position, out bool closeButton)
@@ -85,11 +92,11 @@ namespace FlaxEditor.GUI.Docking
var tabsCount = _panel.TabsCount;
if (tabsCount == 1)
{
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
if (HeaderRectangle.Contains(position))
{
closeButton = crossRect.Contains(position);
result = _panel.GetTab(0);
closeButton = crossRect.Contains(position) && IsCloseButtonVisible(result, closeButtonVisibility);
}
}
else
@@ -98,15 +105,17 @@ namespace FlaxEditor.GUI.Docking
for (int i = 0; i < tabsCount; i++)
{
var tab = _panel.GetTab(i);
var titleSize = tab.TitleSize;
var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
var tabRect = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
float width = CalculateTabWidth(tab, closeButtonVisibility);
if (_useMinimumTabWidth && width < _minimumTabWidth)
width = _minimumTabWidth;
var tabRect = new Rectangle(x, 0, width, HeaderRectangle.Height);
var isMouseOver = tabRect.Contains(position);
if (isMouseOver)
{
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
closeButton = crossRect.Contains(position);
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
closeButton = crossRect.Contains(position) && IsCloseButtonVisible(tab, closeButtonVisibility);
result = tab;
break;
}
@@ -117,6 +126,24 @@ namespace FlaxEditor.GUI.Docking
return result;
}
private bool IsCloseButtonVisible(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode)
{
return visibilityMode != InterfaceOptions.TabCloseButtonVisibility.Never &&
(visibilityMode == InterfaceOptions.TabCloseButtonVisibility.Always ||
(visibilityMode == InterfaceOptions.TabCloseButtonVisibility.SelectedTab && _panel.SelectedTab == win));
}
private float CalculateTabWidth(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode)
{
var iconWidth = win.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
var width = win.TitleSize.X + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
if (IsCloseButtonVisible(win, visibilityMode))
width += 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultButtonsSize;
return width;
}
private void GetTabRect(DockWindow win, out Rectangle bounds)
{
FlaxEngine.Assertions.Assert.IsTrue(_panel.ContainsTab(win));
@@ -134,10 +161,10 @@ namespace FlaxEditor.GUI.Docking
{
var tab = _panel.GetTab(i);
var titleSize = tab.TitleSize;
float width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin;
float width = CalculateTabWidth(tab, closeButtonVisibility);
if (tab == win)
{
bounds = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
bounds = new Rectangle(x, 0, width, HeaderRectangle.Height);
return;
}
x += width;
@@ -217,7 +244,7 @@ namespace FlaxEditor.GUI.Docking
{
Render2D.DrawSprite(
tab.Icon,
new Rectangle(DockPanel.DefaultLeftTextMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
new Rectangle(DockPanel.DefaultLeftTextMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
style.Foreground);
}
@@ -226,17 +253,20 @@ namespace FlaxEditor.GUI.Docking
Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, DockPanel.DefaultHeaderHeight),
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, HeaderRectangle.Height),
style.Foreground,
TextAlignment.Near,
TextAlignment.Center);
// Draw cross
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
if (IsCloseButtonVisible(tab, closeButtonVisibility))
{
// Draw cross
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
}
}
else
{
@@ -250,10 +280,14 @@ namespace FlaxEditor.GUI.Docking
// Cache data
var tab = _panel.GetTab(i);
var tabColor = Color.Black;
var titleSize = tab.TitleSize;
var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
var tabRect = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
float width = CalculateTabWidth(tab, closeButtonVisibility);
if (_useMinimumTabWidth && width < _minimumTabWidth)
width = _minimumTabWidth;
var tabRect = new Rectangle(x, 0, width, headerRect.Height);
var isMouseOver = tabRect.Contains(MousePosition);
var isSelected = _panel.SelectedTab == tab;
@@ -280,7 +314,7 @@ namespace FlaxEditor.GUI.Docking
{
Render2D.DrawSprite(
tab.Icon,
new Rectangle(x + DockPanel.DefaultLeftTextMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
new Rectangle(x + DockPanel.DefaultLeftTextMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
style.Foreground);
}
@@ -289,27 +323,27 @@ namespace FlaxEditor.GUI.Docking
Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, DockPanel.DefaultHeaderHeight),
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, HeaderRectangle.Height),
style.Foreground,
TextAlignment.Near,
TextAlignment.Center);
// Draw cross
if (isSelected || isMouseOver)
if (IsCloseButtonVisible(tab, closeButtonVisibility))
{
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, tabColor * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
}
// Move
// Set the start position for the next tab
x += width;
}
// Draw selected tab strip
Render2D.FillRectangle(new Rectangle(0, DockPanel.DefaultHeaderHeight - 2, Width, 2), containsFocus ? style.BackgroundSelected : style.BackgroundNormal);
Render2D.FillRectangle(new Rectangle(0, HeaderRectangle.Height - 2, Width, 2), containsFocus ? style.BackgroundSelected : style.BackgroundNormal);
}
}
@@ -542,7 +576,7 @@ namespace FlaxEditor.GUI.Docking
if (IsSingleFloatingWindow)
rect = new Rectangle(0, 0, Width, Height);
else
rect = new Rectangle(0, DockPanel.DefaultHeaderHeight, Width, Height - DockPanel.DefaultHeaderHeight);
rect = new Rectangle(0, HeaderRectangle.Height, Width, Height - HeaderRectangle.Height);
}
private DragDropEffect TrySelectTabUnderLocation(ref Float2 location)

View File

@@ -368,6 +368,8 @@ namespace FlaxEditor.GUI.Input
public SliderControl(float value, float x = 0, float y = 0, float width = 120, float min = float.MinValue, float max = float.MaxValue)
: base(x, y, width, TextBox.DefaultHeight)
{
AutoFocus = true;
_min = min;
_max = max;
_value = Mathf.Clamp(value, min, max);

View File

@@ -514,20 +514,15 @@ namespace FlaxEditor.GUI
var items = ItemsPanel.Children;
for (int i = 0; i < items.Count; i++)
{
if (items[i] is Item item && item.Visible)
var currentItem = items[i];
if (currentItem is Item item && item.Visible)
result.Add(item);
}
if (_categoryPanels != null)
{
for (int i = 0; i < _categoryPanels.Count; i++)
else if (currentItem is DropPanel category && (!ignoreFoldedCategories || !category.IsClosed) && currentItem.Visible)
{
var category = _categoryPanels[i];
if (!category.Visible || (ignoreFoldedCategories && category is DropPanel panel && panel.IsClosed))
continue;
for (int j = 0; j < category.Children.Count; j++)
{
if (category.Children[j] is Item item2 && item2.Visible)
result.Add(item2);
if (category.Children[j] is Item categoryItem && categoryItem.Visible)
result.Add(categoryItem);
}
}
}
@@ -591,10 +586,6 @@ namespace FlaxEditor.GUI
var items = GetVisibleItems(!controlDown);
var focusedIndex = items.IndexOf(focusedItem);
// 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];

View File

@@ -11,6 +11,9 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.Panel" />
public class NavigationBar : Panel
{
private float _toolstripHeight = 0;
private Margin _toolstripMargin;
/// <summary>
/// The default buttons margin.
/// </summary>
@@ -50,9 +53,42 @@ namespace FlaxEditor.GUI
{
if (toolstrip == null)
return;
if (_toolstripHeight <= 0.0f)
{
// Cache initial toolstrip state
_toolstripHeight = toolstrip.Height;
_toolstripMargin = toolstrip.ItemsMargin;
}
// Control toolstrip bottom margin to prevent navigation bar scroll going over the buttons
var toolstripLocked = toolstrip.IsLayoutLocked;
toolstrip.IsLayoutLocked = true;
var toolstripHeight = _toolstripHeight;
var toolstripMargin = _toolstripMargin;
if (HScrollBar.Visible)
{
float scrollMargin = 8;
toolstripHeight += scrollMargin;
toolstripMargin.Bottom += scrollMargin;
}
toolstrip.Height = toolstripHeight;
toolstrip.IsLayoutLocked = toolstripLocked;
toolstrip.ItemsMargin = toolstripMargin;
var lastToolstripButton = toolstrip.LastButton;
var parentSize = Parent.Size;
Bounds = new Rectangle(lastToolstripButton.Right + 8.0f, 0, parentSize.X - X - 8.0f, toolstrip.Height);
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
base.PerformLayout(force);
// Stretch excluding toolstrip margin to fill the space
if (Parent is ToolStrip toolStrip)
Height = toolStrip.Height;
}
}
}

View File

@@ -130,6 +130,10 @@ namespace FlaxEditor.GUI
/// <returns>Created popup.</returns>
public static RenamePopup Show(Control control, Rectangle area, string value, bool isMultiline)
{
// hardcoded flushing layout for tree controls
if (control is Tree.TreeNode treeNode && treeNode.ParentTree != null)
treeNode.ParentTree.FlushPendingPerformLayout();
// Calculate the control size in the window space to handle scaled controls
var upperLeft = control.PointToWindow(area.UpperLeft);
var bottomRight = control.PointToWindow(area.BottomRight);

View File

@@ -13,15 +13,7 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
public class ToolStrip : ContainerControl
{
/// <summary>
/// The default margin vertically.
/// </summary>
public const int DefaultMarginV = 1;
/// <summary>
/// The default margin horizontally.
/// </summary>
public const int DefaultMarginH = 2;
private Margin _itemsMargin;
/// <summary>
/// Event fired when button gets clicked with the primary mouse button.
@@ -66,10 +58,26 @@ namespace FlaxEditor.GUI
}
}
/// <summary>
/// Gets or sets the space around items.
/// </summary>
public Margin ItemsMargin
{
get => _itemsMargin;
set
{
if (_itemsMargin != value)
{
_itemsMargin = value;
PerformLayout();
}
}
}
/// <summary>
/// Gets the height for the items.
/// </summary>
public float ItemsHeight => Height - 2 * DefaultMarginV;
public float ItemsHeight => Height - _itemsMargin.Height;
/// <summary>
/// Initializes a new instance of the <see cref="ToolStrip"/> class.
@@ -82,6 +90,7 @@ namespace FlaxEditor.GUI
AnchorPreset = AnchorPresets.HorizontalStretchTop;
BackgroundColor = Style.Current.LightBackground;
Offsets = new Margin(0, 0, y, height * Editor.Instance.Options.Options.Interface.IconsScale);
_itemsMargin = new Margin(2, 2, 1, 1);
}
/// <summary>
@@ -161,7 +170,7 @@ namespace FlaxEditor.GUI
protected override void PerformLayoutBeforeChildren()
{
// Arrange controls
float x = DefaultMarginH;
float x = _itemsMargin.Left;
float h = ItemsHeight;
for (int i = 0; i < _children.Count; i++)
{
@@ -169,8 +178,8 @@ namespace FlaxEditor.GUI
if (c.Visible)
{
var w = c.Width;
c.Bounds = new Rectangle(x, DefaultMarginV, w, h);
x += w + DefaultMarginH;
c.Bounds = new Rectangle(x, _itemsMargin.Top, w, h);
x += w + _itemsMargin.Width;
}
}
}

View File

@@ -41,6 +41,7 @@ namespace FlaxEditor.GUI.Tree
private Margin _margin;
private bool _autoSize = true;
private bool _deferLayoutUpdate = false;
private TreeNode _lastSelectedNode;
/// <summary>
/// The TreeNode that is being dragged over. This could have a value when not dragging.
@@ -67,7 +68,7 @@ namespace FlaxEditor.GUI.Tree
/// Gets the first selected node or null.
/// </summary>
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
/// <summary>
/// Allow nodes to Draw the root tree line.
/// </summary>
@@ -364,6 +365,19 @@ namespace FlaxEditor.GUI.Tree
BulkSelectUpdateExpanded(false);
}
/// <summary>
/// Flushes any pending layout perming action that has been delayed until next update to optimize performance of the complex tree hierarchy.
/// </summary>
public void FlushPendingPerformLayout()
{
if (_deferLayoutUpdate)
{
base.PerformLayout();
AfterDeferredLayout?.Invoke();
_deferLayoutUpdate = false;
}
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
@@ -378,25 +392,31 @@ namespace FlaxEditor.GUI.Tree
public override void Update(float deltaTime)
{
if (_deferLayoutUpdate)
{
base.PerformLayout();
AfterDeferredLayout?.Invoke();
_deferLayoutUpdate = false;
}
FlushPendingPerformLayout();
var window = Root;
bool shiftDown = window.GetKey(KeyboardKeys.Shift);
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
var node = SelectedNode;
// Use last selection for last selected node if sift is down
if (Selection.Count < 2)
_lastSelectedNode = null;
else if (shiftDown)
_lastSelectedNode ??= Selection[^1];
// Skip root to prevent blocking input
if (_lastSelectedNode != null && _lastSelectedNode.IsRoot)
_lastSelectedNode = null;
var node = _lastSelectedNode ?? SelectedNode;
// Check if has focus and if any node is focused and it isn't a root
if (ContainsFocus && node != null && node.AutoFocus)
{
var window = Root;
if (window.GetKeyDown(KeyboardKeys.ArrowUp) || window.GetKeyDown(KeyboardKeys.ArrowDown))
_keyUpdateTime = KeyUpdateTimeout;
if (_keyUpdateTime >= KeyUpdateTimeout && window is WindowRootControl windowRoot && windowRoot.Window.IsFocused)
{
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
// Check if arrow flags are different
if (keyDownArrow != keyUpArrow)
{
@@ -406,24 +426,38 @@ namespace FlaxEditor.GUI.Tree
Assert.AreNotEqual(-1, myIndex);
// Up
TreeNode toSelect = null;
List<TreeNode> toSelect = new List<TreeNode>();
if (shiftDown && _supportMultiSelect)
{
toSelect.AddRange(Selection);
}
if (keyUpArrow)
{
if (myIndex == 0)
{
// Select parent
toSelect = parentNode;
if (toSelect.Contains(parentNode))
toSelect.Remove(node);
else if (parentNode != null)
toSelect.Add(parentNode);
_lastSelectedNode = parentNode;
}
else
{
// Select previous parent child
toSelect = nodeParent.GetChild(myIndex - 1) as TreeNode;
var select = nodeParent.GetChild(myIndex - 1) as TreeNode;
// Select last child if is valid and expanded and has any children
if (toSelect != null && toSelect.IsExpanded && toSelect.HasAnyVisibleChild)
if (select != null && select.IsExpanded && select.HasAnyVisibleChild)
{
toSelect = toSelect.GetChild(toSelect.ChildrenCount - 1) as TreeNode;
select = select.GetChild(select.ChildrenCount - 1) as TreeNode;
}
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
}
// Down
@@ -432,32 +466,48 @@ namespace FlaxEditor.GUI.Tree
if (node.IsExpanded && node.HasAnyVisibleChild)
{
// Select the first child
toSelect = node.GetChild(0) as TreeNode;
var select = node.GetChild(0) as TreeNode;
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
else if (myIndex == nodeParent.ChildrenCount - 1)
{
// Select next node after parent
while (parentNode != null && toSelect == null)
TreeNode select = null;
while (parentNode != null && select == null)
{
int parentIndex = parentNode.IndexInParent;
if (parentIndex != -1 && parentIndex < parentNode.Parent.ChildrenCount - 1)
{
toSelect = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode;
select = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode;
}
parentNode = parentNode.Parent as TreeNode;
}
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
else
{
// Select next parent child
toSelect = nodeParent.GetChild(myIndex + 1) as TreeNode;
var select = nodeParent.GetChild(myIndex + 1) as TreeNode;
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
}
if (toSelect != null && toSelect.AutoFocus)
if (toSelect.Count > 0)
{
// Select
Select(toSelect);
toSelect.Focus();
_lastSelectedNode?.Focus();
}
// Reset time

View File

@@ -319,6 +319,8 @@ namespace FlaxEditor.GUI.Tree
public TreeNode(bool canChangeOrder, SpriteHandle iconCollapsed, SpriteHandle iconOpened)
: base(0, 0, 64, 16)
{
AutoFocus = true;
_canChangeOrder = canChangeOrder;
_animationProgress = 1.0f;
_cachedHeight = _headerHeight;

View File

@@ -155,6 +155,7 @@ namespace FlaxEditor.Gizmo
// Ensure player is not moving objects
if (ActiveAxis != Axis.None)
return;
Profiler.BeginEvent("Pick");
// Get mouse ray and try to hit any object
var ray = Owner.MouseRay;
@@ -243,6 +244,8 @@ namespace FlaxEditor.Gizmo
{
sceneEditing.Deselect();
}
Profiler.EndEvent();
}
/// <inheritdoc />

View File

@@ -11,6 +11,7 @@
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MException.h"
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Content/Assets/VisualScript.h"
#include "Engine/Content/Content.h"
#include "Engine/Level/Actor.h"
@@ -627,6 +628,14 @@ void ManagedEditor::WipeOutLeftoverSceneObjects()
ObjectsRemovalService::Flush();
}
Array<Window*> ManagedEditor::GetWindows()
{
WindowsManager::WindowsLocker.Lock();
auto result = WindowsManager::Windows;
WindowsManager::WindowsLocker.Unlock();
return result;
}
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
{
ASSERT(!HasManagedInstance());

View File

@@ -259,6 +259,7 @@ public:
API_FUNCTION(Internal) static Array<VisualScriptLocal> GetVisualScriptLocals();
API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local);
API_FUNCTION(Internal) static void WipeOutLeftoverSceneObjects();
API_FUNCTION(Internal) static Array<Window*> GetWindows();
private:
void OnEditorAssemblyLoaded(MAssembly* assembly);

View File

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

View File

@@ -569,6 +569,10 @@ namespace FlaxEditor.Modules
return;
}
// Skip if already added
if (SceneGraphFactory.Nodes.ContainsKey(actor.ID))
return;
var node = SceneGraphFactory.BuildActorNode(actor);
if (node != null)
{

View File

@@ -54,6 +54,9 @@ namespace FlaxEditor.Modules.SourceCodeEditing
case CodeEditorTypes.VS2022:
Name = "Visual Studio 2022";
break;
case CodeEditorTypes.VS2026:
Name = "Visual Studio 2026";
break;
case CodeEditorTypes.VSCode:
Name = "Visual Studio Code";
break;
@@ -110,6 +113,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
case CodeEditorTypes.VS2017:
case CodeEditorTypes.VS2019:
case CodeEditorTypes.VS2022:
case CodeEditorTypes.VS2026:
// TODO: finish dynamic files adding to the project
//Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync();
break;

View File

@@ -652,43 +652,47 @@ namespace FlaxEditor.Options
#endregion
#region Node editors
#region Node Editors
[DefaultValue(typeof(InputBinding), "Shift+W")]
[EditorDisplay("Node editors"), EditorOrder(4500)]
[EditorDisplay("Node Editors"), EditorOrder(4500)]
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+A")]
[EditorDisplay("Node editors"), EditorOrder(4510)]
[EditorDisplay("Node Editors"), EditorOrder(4510)]
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+S")]
[EditorDisplay("Node editors"), EditorOrder(4520)]
[EditorDisplay("Node Editors"), EditorOrder(4520)]
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+D")]
[EditorDisplay("Node editors"), EditorOrder(4530)]
[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)]
[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)]
[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)]
[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), "Shift+Q")]
[EditorDisplay("Node Editors"), EditorOrder(4560)]
public InputBinding NodesStraightenConnections = new InputBinding(KeyboardKeys.Q, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Node editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Alt+W")]
[EditorDisplay("Node Editors"), EditorOrder(4570)]
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.W, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+A")]
[EditorDisplay("Node Editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.A, KeyboardKeys.Alt);
#endregion
}

View File

@@ -76,6 +76,25 @@ namespace FlaxEditor.Options
DockBottom = DockState.DockBottom
}
/// <summary>
/// Options for the visibility status of the tab close button.
/// </summary>
public enum TabCloseButtonVisibility
{
/// <summary>
/// Never show the close button.
/// </summary>
Never,
/// <summary>
/// Show the close button on tabs that are currently selected.
/// </summary>
SelectedTab,
/// <summary>
/// Show the close button on all tabs that can be closed.
/// </summary>
Always
}
/// <summary>
/// Options for the action taken by the play button.
/// </summary>
@@ -194,13 +213,6 @@ namespace FlaxEditor.Options
[DefaultValue(1.0f), Limit(0.1f, 10.0f)]
[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;
/// <summary>
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
/// <summary>
/// Gets or sets a value indicating whether show selected camera preview in the editor window.
@@ -209,20 +221,6 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(80), Tooltip("Determines whether show selected camera preview in the edit window.")]
public bool ShowSelectedCameraPreview { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Interface", "Center Mouse On Game Window Focus"), EditorOrder(100), Tooltip("Determines whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.")]
public bool CenterMouseOnGameWinFocus { get; set; } = false;
/// <summary>
/// Gets or sets the method window opening.
/// </summary>
[DefaultValue(DockStateProxy.Float)]
[EditorDisplay("Interface", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")]
public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float;
/// <summary>
/// Gets or sets the editor icons scale. Editor restart required.
/// </summary>
@@ -258,6 +256,13 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(310)]
public bool SeparateValueAndUnit { get; set; }
/// <summary>
/// Gets or sets the option to auto size the Properties panel splitter based on the longest property name. Editor restart recommended.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Interface"), EditorOrder(311)]
public bool AutoSizePropertiesPanelSplitter { get; set; }
/// <summary>
/// Gets or sets tree line visibility.
/// </summary>
@@ -291,6 +296,73 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(322)]
public bool ScrollToScriptOnAdd { get; set; } = true;
#if PLATFORM_SDL
/// <summary>
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
#elif PLATFORM_WINDOWS
/// <summary>
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows"), EditorOrder(70), Tooltip("Determines whether use native window title bar. Editor restart required.")]
public bool UseNativeWindowSystem { get; set; } = false;
#endif
#if PLATFORM_SDL || PLATFORM_WINDOWS
/// <summary>
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Tabs & Windows", "Hide Single-Tab Window Tab Bars"), EditorOrder(71)]
public bool HideSingleTabWindowTabBars { get; set; } = true;
#endif
/// <summary>
/// Gets or sets a value indicating wether the minum tab width should be used. Editor restart required.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
public bool UseMinimumTabWidth { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating the minimum tab width. If a tab is smaller than this width, its width will be set to this. Editor restart required.
/// </summary>
[DefaultValue(80.0f), Limit(50.0f, 150.0f)]
[EditorDisplay("Tabs & Windows"), EditorOrder(99), VisibleIf(nameof(UseMinimumTabWidth))]
public float MinimumTabWidth { get; set; } = 80.0f;
/// <summary>
/// Gets or sets a value indicating the height of window tabs. Editor restart required.
/// </summary>
[DefaultValue(20.0f), Limit(15.0f, 40.0f)]
[EditorDisplay("Tabs & Windows"), EditorOrder(100)]
public float TabHeight { get; set; } = 20.0f;
/// <summary>
/// Gets or sets a value indicating whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows", "Center Mouse On Game Window Focus"), EditorOrder(101), Tooltip("Determines whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.")]
public bool CenterMouseOnGameWinFocus { get; set; } = false;
/// <summary>
/// Gets or sets the method window opening.
/// </summary>
[DefaultValue(DockStateProxy.Float)]
[EditorDisplay("Tabs & Windows", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")]
public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float;
/// <summary>
/// Gets or sets a value indicating when the tab close button should be visible.
/// </summary>
[DefaultValue(TabCloseButtonVisibility.SelectedTab)]
[EditorDisplay("Tabs & Windows"), EditorOrder(151)]
public TabCloseButtonVisibility ShowTabCloseButton { get; set; } = TabCloseButtonVisibility.SelectedTab;
/// <summary>
/// Gets or sets the timestamps prefix mode for output log messages.
/// </summary>
@@ -446,6 +518,12 @@ namespace FlaxEditor.Options
[DefaultValue(1), Range(1, 4)]
[EditorDisplay("Cook & Run"), EditorOrder(600)]
public int NumberOfGameClientsToLaunch = 1;
/// <summary>
/// Gets or sets the build configuration to use when using Cook and Run option in the editor.
/// </summary>
[EditorDisplay("Cook & Run"), EditorOrder(601), ExpandGroups, Tooltip("The build configuration to use when using Cook and Run option in the editor.")]
public BuildConfiguration CookAndRunBuildConfiguration { get; set; } = BuildConfiguration.Development;
/// <summary>
/// Gets or sets the curvature of the line connecting to connected visject nodes.

View File

@@ -141,6 +141,8 @@ namespace FlaxEditor.SceneGraph.Actors
b.TooltipText = "Add a box collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Sphere", () => OnAddCollider(window, CreateSphere));
b.TooltipText = "Add a sphere collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Capsule", () => OnAddCollider(window, CreateCapsule));
b.TooltipText = "Add a capsule collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Convex", () => OnAddCollider(window, CreateConvex));
b.TooltipText = "Generate and add a convex collider for every selected model.";
b = menu.ContextMenu.AddButton("Triangle Mesh", () => OnAddCollider(window, CreateTriangle));
@@ -267,6 +269,20 @@ namespace FlaxEditor.SceneGraph.Actors
spawner(collider);
}
private void CreateCapsule(StaticModel actor, Spawner spawner, bool singleNode)
{
var collider = new CapsuleCollider
{
Transform = actor.Transform,
Position = actor.Box.Center,
// Size the capsule to best fit the actor
Radius = (float)actor.Sphere.Radius / Mathf.Max((float)actor.Scale.MaxValue, 0.0001f) * 0.707f,
Height = 100f,
};
spawner(collider);
}
private void CreateConvex(StaticModel actor, Spawner spawner, bool singleNode)
{
CreateMeshCollider(actor, spawner, singleNode, CollisionDataType.ConvexMesh);

View File

@@ -1,8 +1,9 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEditor.Viewport;
using FlaxEngine;
using System.Collections.Generic;
namespace FlaxEditor
{
@@ -39,9 +40,23 @@ namespace FlaxEditor
/// </summary>
void RenameSelection();
/// <summary>
/// Deletes selected objects.
/// </summary>
void DeleteSelection();
/// <summary>
/// Focuses selected objects.
/// </summary>
void FocusSelection();
/// <summary>
/// Spawns the specified actor to the game (with undo).
/// </summary>
/// <param name="actor">The actor.</param>
/// <param name="parent">The parent actor. Set null as default.</param>
/// <param name="orderInParent">The order under the parent to put the spawned actor.</param>
/// <param name="autoSelect">True if automatically select the spawned actor, otherwise false.</param>
void Spawn(Actor actor, Actor parent = null, int orderInParent = -1, bool autoSelect = true);
}
}

View File

@@ -97,13 +97,16 @@ namespace FlaxEditor.SceneGraph
/// <returns>Hit object or null if there is no intersection at all.</returns>
public SceneGraphNode RayCast(ref Ray ray, ref Ray view, out Real distance, RayCastData.FlagTypes flags = RayCastData.FlagTypes.None)
{
Profiler.BeginEvent("RayCastScene");
var data = new RayCastData
{
Ray = ray,
View = view,
Flags = flags
};
return RayCast(ref data, out distance, out _);
var result = RayCast(ref data, out distance, out _);
Profiler.EndEvent();
return result;
}
/// <summary>
@@ -117,13 +120,16 @@ namespace FlaxEditor.SceneGraph
/// <returns>Hit object or null if there is no intersection at all.</returns>
public SceneGraphNode RayCast(ref Ray ray, ref Ray view, out Real distance, out Vector3 normal, RayCastData.FlagTypes flags = RayCastData.FlagTypes.None)
{
Profiler.BeginEvent("RayCastScene");
var data = new RayCastData
{
Ray = ray,
View = view,
Flags = flags
};
return RayCast(ref data, out distance, out normal);
var result = RayCast(ref data, out distance, out normal);
Profiler.EndEvent();
return result;
}
internal static Quaternion RaycastNormalRotation(ref Vector3 normal)
@@ -175,7 +181,7 @@ namespace FlaxEditor.SceneGraph
public List<SceneGraphNode> Selection => SceneContext.Selection;
/// <summary>
/// Gets the list of selected scene graph nodes in the editor context.
/// Gets the scene editing context.
/// </summary>
public abstract ISceneEditingContext SceneContext { get; }
}

View File

@@ -62,6 +62,11 @@ API_ENUM(Namespace="FlaxEditor", Attributes="HideInEditor") enum class CodeEdito
/// </summary>
VS2022,
/// <summary>
/// Visual Studio 2026
/// </summary>
VS2026,
/// <summary>
/// Visual Studio Code
/// </summary>

View File

@@ -43,6 +43,9 @@ VisualStudioEditor::VisualStudioEditor(VisualStudioVersion version, const String
case VisualStudioVersion::VS2022:
_type = CodeEditorTypes::VS2022;
break;
case VisualStudioVersion::VS2026:
_type = CodeEditorTypes::VS2026;
break;
default: CRASH;
break;
}
@@ -70,6 +73,9 @@ void VisualStudioEditor::FindEditors(Array<CodeEditor*>* output)
VisualStudioVersion version;
switch (info.VersionMajor)
{
case 18:
version = VisualStudioVersion::VS2026;
break;
case 17:
version = VisualStudioVersion::VS2022;
break;

View File

@@ -10,7 +10,7 @@
/// <summary>
/// Microsoft Visual Studio version types
/// </summary>
DECLARE_ENUM_8(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022);
DECLARE_ENUM_9(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022, VS2026);
/// <summary>
/// Implementation of code editor utility that is using Microsoft Visual Studio.

View File

@@ -233,6 +233,8 @@ namespace FlaxEditor.Surface.Archetypes
public BlendPointsEditor(Animation.MultiBlend node, bool is2D, float x, float y, float width, float height)
: base(x, y, width, height)
{
AutoFocus = true;
_node = node;
_is2D = is2D;
}

View File

@@ -810,7 +810,7 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new StateMachineState(id, context, arch, groupArch),
Title = "State",
Description = "The animation states machine state node",
Flags = NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI | NodeFlags.NoSpawnViaPaste,
Flags = NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
Size = new Float2(100, 0),
DefaultValues = new object[]
{

View File

@@ -199,7 +199,7 @@ namespace FlaxEditor.Surface.Archetypes
private Label _labelValue;
private FloatValueBox _timeValue;
private ColorValueBox _colorValue;
private const int MaxStops = 8;
private const int MaxStops = 12;
/// <inheritdoc />
public ColorGradientNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
@@ -1386,10 +1386,11 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Time",
Description = "Game time constant",
Flags = NodeFlags.MaterialGraph,
Size = new Float2(110, 20),
Size = new Float2(110, 40),
Elements = new[]
{
NodeElementArchetype.Factory.Output(0, "", typeof(float), 0),
NodeElementArchetype.Factory.Output(0, "Time", typeof(float), 0),
NodeElementArchetype.Factory.Output(1, "Unscaled Time", typeof(float), 1),
}
},
new NodeArchetype
@@ -1506,7 +1507,11 @@ namespace FlaxEditor.Surface.Archetypes
0.95f,
Color.White,
// Empty stops 2-7
// Empty stops 2-11
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,

View File

@@ -64,6 +64,7 @@ namespace FlaxEditor.Surface.Elements
{
ParentNode = parentNode;
Archetype = archetype;
AutoFocus = true;
var back = Style.Current.TextBoxBackground;
var grayOutFactor = 0.6f;

View File

@@ -5,39 +5,39 @@ using FlaxEngine;
namespace FlaxEditor.Surface
{
/// <summary>
/// Node Alignment type
/// Node Alignment type.
/// </summary>
[HideInEditor]
public enum NodeAlignmentType
{
/// <summary>
/// Align nodes vertically to top, matching top-most node
/// Align nodes vertically to top, matching top-most node.
/// </summary>
Top,
/// <summary>
/// Align nodes vertically to middle, using average of all nodes
/// Align nodes vertically to middle, using average of all nodes.
/// </summary>
Middle,
/// <summary>
/// Align nodes vertically to bottom, matching bottom-most node
/// Align nodes vertically to bottom, matching bottom-most node.
/// </summary>
Bottom,
/// <summary>
/// Align nodes horizontally to left, matching left-most node
/// Align nodes horizontally to left, matching left-most node.
/// </summary>
Left,
/// <summary>
/// Align nodes horizontally to center, using average of all nodes
/// Align nodes horizontally to center, using average of all nodes.
/// </summary>
Center,
/// <summary>
/// Align nodes horizontally to right, matching right-most node
/// Align nodes horizontally to right, matching right-most node.
/// </summary>
Right,
}
}
}

View File

@@ -59,6 +59,7 @@ namespace FlaxEditor.Surface
protected SurfaceControl(VisjectSurfaceContext context, float width, float height)
: base(0, 0, width, height)
{
AutoFocus = true;
ClipChildren = false;
Surface = context.Surface;

View File

@@ -28,7 +28,7 @@ namespace FlaxEditor.Surface
/// </summary>
/// <param name="scriptType">The input type to process.</param>
/// <param name="cache">Node groups cache that can be used for reusing groups for different nodes.</param>
/// <param name="version">The cache version number. Can be used to reject any cached data after <see cref="NodesCache"/> rebuilt.</param>
/// <param name="version">The cache version number. Can be used to reject any cached data after.<see cref="NodesCache"/> rebuilt.</param>
public delegate void IterateType(ScriptType scriptType, Dictionary<KeyValuePair<string, ushort>, GroupArchetype> cache, int version);
internal static readonly List<NodesCache> Caches = new List<NodesCache>(8);
@@ -412,6 +412,7 @@ namespace FlaxEditor.Surface
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection;
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Auto format", Editor.Instance.Options.Options.Input.NodesAutoFormat, () => { FormatGraph(SelectedNodes); });
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Straighten connections", Editor.Instance.Options.Options.Input.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); });
_cmFormatNodesMenu.ContextMenu.AddSeparator();
_cmAlignNodesTopButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align top", Editor.Instance.Options.Options.Input.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); });

View File

@@ -1,9 +1,9 @@
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
using FlaxEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEngine;
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
namespace FlaxEditor.Surface
{
@@ -14,26 +14,26 @@ namespace FlaxEditor.Surface
private class NodeFormattingData
{
/// <summary>
/// Starting from 0 at the main nodes
/// Starting from 0 at the main nodes.
/// </summary>
public int Layer;
/// <summary>
/// Position in the layer
/// Position in the layer.
/// </summary>
public int Offset;
/// <summary>
/// How far the subtree needs to be moved additionally
/// How far the subtree needs to be moved additionally.
/// </summary>
public int SubtreeOffset;
}
/// <summary>
/// Formats a graph where the nodes can be disjointed.
/// Uses the Sugiyama method
/// Uses the Sugiyama method.
/// </summary>
/// <param name="nodes">List of nodes</param>
/// <param name="nodes">List of nodes.</param>
public void FormatGraph(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
@@ -78,9 +78,9 @@ namespace FlaxEditor.Surface
}
/// <summary>
/// Formats a graph where all nodes are connected
/// Formats a graph where all nodes are connected.
/// </summary>
/// <param name="nodes">List of connected nodes</param>
/// <param name="nodes">List of connected nodes.</param>
protected void FormatConnectedGraph(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
@@ -160,11 +160,71 @@ namespace FlaxEditor.Surface
}
/// <summary>
/// Assigns a layer to every node
/// Straightens every connection between nodes in <paramref name="nodes"/>.
/// </summary>
/// <param name="nodeData">The exta node data</param>
/// <param name="endNodes">The end nodes</param>
/// <returns>The number of the maximum layer</returns>
/// <param name="nodes">List of nodes.</param>
public void StraightenGraphConnections(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
return;
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
// Only process nodes that have any connection
List<SurfaceNode> connectedNodes = nodes.Where(n => n.GetBoxes().Any(b => b.HasAnyConnection)).ToList();
if (connectedNodes.Count == 0)
return;
for (int i = 0; i < connectedNodes.Count - 1; i++)
{
SurfaceNode nodeA = connectedNodes[i];
List<Box> connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.IsOutput && b.HasAnyConnection).ToList();
for (int j = 0; j < connectedOutputBoxes.Count; j++)
{
Box boxA = connectedOutputBoxes[j];
for (int b = 0; b < boxA.Connections.Count; b++)
{
Box boxB = boxA.Connections[b];
// Ensure the other node is selected
if (!connectedNodes.Contains(boxB.ParentNode))
continue;
// Node with no outgoing connections reached. Advance to next node in list
if (boxA == null || boxB == null)
continue;
SurfaceNode nodeB = boxB.ParentNode;
// Calculate the Y offset needed for nodeB to align boxB's Y to boxA's Y
float boxASurfaceY = boxA.PointToParent(this, Float2.Zero).Y;
float boxBSurfaceY = boxB.PointToParent(this, Float2.Zero).Y;
float deltaY = (boxASurfaceY - boxBSurfaceY) / ViewScale;
Float2 delta = new Float2(0f, deltaY);
nodeB.Location += delta;
if (Undo != null)
undoActions.Add(new MoveNodesAction(Context, new[] { nodeB.ID }, delta));
}
}
}
if (undoActions.Count > 0)
Undo?.AddAction(new MultiUndoAction(undoActions, "Straightned "));
MarkAsEdited(false);
}
/// <summary>
/// Assigns a layer to every node.
/// </summary>
/// <param name="nodeData">The exta node data.</param>
/// <param name="endNodes">The end nodes.</param>
/// <returns>The number of the maximum layer.</returns>
private int SetLayers(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes)
{
// Longest path layering
@@ -201,12 +261,12 @@ namespace FlaxEditor.Surface
/// <summary>
/// Sets the node offsets
/// Sets the node offsets.
/// </summary>
/// <param name="nodeData">The exta node data</param>
/// <param name="endNodes">The end nodes</param>
/// <param name="maxLayer">The number of the maximum layer</param>
/// <returns>The number of the maximum offset</returns>
/// <param name="nodeData">The exta node data.</param>
/// <param name="endNodes">The end nodes.</param>
/// <param name="maxLayer">The number of the maximum layer.</param>
/// <returns>The number of the maximum offset.</returns>
private int SetOffsets(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes, int maxLayer)
{
int maxOffset = 0;
@@ -287,10 +347,10 @@ namespace FlaxEditor.Surface
/// Align given nodes on a graph using the given alignment type.
/// Ignores any potential overlap.
/// </summary>
/// <param name="nodes">List of nodes</param>
/// <param name="alignmentType">Alignemnt type</param>
/// <param name="nodes">List of nodes.</param>
/// <param name="alignmentType">Alignemnt type.</param>
public void AlignNodes(List<SurfaceNode> nodes, NodeAlignmentType alignmentType)
{
{
if(nodes.Count <= 1)
return;
@@ -328,8 +388,8 @@ namespace FlaxEditor.Surface
/// <summary>
/// Distribute the given nodes as equally as possible inside the bounding box, if no fit can be done it will use a default pad of 10 pixels between nodes.
/// </summary>
/// <param name="nodes">List of nodes</param>
/// <param name="vertically">If false will be done horizontally, if true will be done vertically</param>
/// <param name="nodes">List of nodes.</param>
/// <param name="vertically">If false will be done horizontally, if true will be done vertically.</param>
public void DistributeNodes(List<SurfaceNode> nodes, bool vertically)
{
if(nodes.Count <= 1)

View File

@@ -120,6 +120,8 @@ namespace FlaxEditor.Surface
private void UpdateSelectionRectangle()
{
if (Root == null)
return;
var p1 = _rootControl.PointFromParent(ref _leftMouseDownPos);
var p2 = _rootControl.PointFromParent(ref _mousePos);
var selectionRect = Rectangle.FromPoints(p1, p2);

View File

@@ -416,6 +416,7 @@ namespace FlaxEditor.Surface
new InputActionsContainer.Binding(options => options.Cut, Cut),
new InputActionsContainer.Binding(options => options.Duplicate, Duplicate),
new InputActionsContainer.Binding(options => options.NodesAutoFormat, () => { FormatGraph(SelectedNodes); }),
new InputActionsContainer.Binding(options => options.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); }),
new InputActionsContainer.Binding(options => options.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); }),
new InputActionsContainer.Binding(options => options.NodesAlignMiddle, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Middle); }),
new InputActionsContainer.Binding(options => options.NodesAlignBottom, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Bottom); }),
@@ -542,11 +543,12 @@ namespace FlaxEditor.Surface
nodes.Add(context);
context = context.Parent;
}
float margin = 1;
float x = NavigationBar.DefaultButtonsMargin;
float h = toolStrip.ItemsHeight - 2 * ToolStrip.DefaultMarginV;
float h = toolStrip.ItemsHeight - 2 * margin;
for (int i = nodes.Count - 1; i >= 0; i--)
{
var button = new VisjectContextNavigationButton(this, nodes[i].Context, x, ToolStrip.DefaultMarginV, h);
var button = new VisjectContextNavigationButton(this, nodes[i].Context, x, margin, h);
button.PerformLayout();
x += button.Width + NavigationBar.DefaultButtonsMargin;
navigationBar.AddChild(button);

View File

@@ -61,6 +61,7 @@ namespace FlaxEditor.Utilities
/// <param name="value">The value.</param>
public void SetMemberValue(object instance, object value)
{
var originalInstance = instance;
var finalMember = MemberPath.GetLastMember(ref instance);
var type = finalMember.Type;
@@ -92,6 +93,12 @@ namespace FlaxEditor.Utilities
}
finalMember.SetValue(instance, value);
if (instance != originalInstance && finalMember.Index != null)
{
// Set collection back to the parent object (in case of properties that always return a new object like 'Spline.SplineKeyframes')
finalMember.Member.SetValue(originalInstance, instance);
}
}
/// <inheritdoc />

View File

@@ -1571,5 +1571,19 @@ namespace FlaxEditor.Utilities
_ => throw new ArgumentOutOfRangeException()
};
}
internal static bool HideSingleTabWindowTabBars()
{
#if PLATFORM_SDL
// We should not hide the tab bars if tab handle is the only way to dock the window
bool clientSideDecorations = UseCustomWindowDecorations(false);
bool draggableDecorations = clientSideDecorations || Platform.SupportsNativeDecorationDragging;
return draggableDecorations && Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
#elif PLATFORM_WINDOWS
return Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
#else
return false;
#endif
}
}
}

View File

@@ -340,6 +340,13 @@ namespace FlaxEditor.Viewport
{
_debugDrawData.Clear();
if (task is SceneRenderTask sceneRenderTask)
{
// Sync debug view to avoid lag on culling/LODing
var view = sceneRenderTask.View;
DebugDraw.SetView(ref view);
}
// Collect selected objects debug shapes and visuals
var selectedParents = TransformGizmo.SelectedParents;
if (selectedParents.Count > 0)
@@ -374,14 +381,7 @@ namespace FlaxEditor.Viewport
// Draw selected objects debug shapes and visuals
if (DrawDebugDraw && (renderContext.View.Flags & ViewFlags.DebugDraw) == ViewFlags.DebugDraw)
{
unsafe
{
fixed (IntPtr* actors = _debugDrawData.ActorsPtrs)
{
DebugDraw.DrawActors(new IntPtr(actors), _debugDrawData.ActorsCount, true);
}
}
_debugDrawData.DrawActors(true);
DebugDraw.Draw(ref renderContext, target.View(), targetDepth.View(), true);
}
}

View File

@@ -243,7 +243,12 @@ namespace FlaxEditor.Viewport
_tempDebugDrawContext = DebugDraw.AllocateContext();
DebugDraw.SetContext(_tempDebugDrawContext);
DebugDraw.UpdateContext(_tempDebugDrawContext, 1.0f);
if (task is SceneRenderTask sceneRenderTask)
{
// Sync debug view to avoid lag on culling/LODing
var view = sceneRenderTask.View;
DebugDraw.SetView(ref view);
}
for (int i = 0; i < selectedParents.Count; i++)
{
if (selectedParents[i].IsActiveInHierarchy)
@@ -643,14 +648,7 @@ namespace FlaxEditor.Viewport
if (selectedParents[i].IsActiveInHierarchy)
selectedParents[i].OnDebugDraw(_debugDrawData);
}
unsafe
{
fixed (IntPtr* actors = _debugDrawData.ActorsPtrs)
{
DebugDraw.DrawActors(new IntPtr(actors), _debugDrawData.ActorsCount, false);
}
}
_debugDrawData.DrawActors();
// Debug draw all actors in prefab and collect actors
var view = Task.View;
@@ -670,10 +668,7 @@ namespace FlaxEditor.Viewport
if ((view.Flags & ViewFlags.PhysicsDebug) != 0 || view.Mode == ViewMode.PhysicsColliders)
{
foreach (var actor in _debugDrawActors)
{
if (actor is Collider c && c.IsActiveInHierarchy)
DebugDraw.DrawColliderDebugPhysics(c, renderContext.View);
}
DebugDraw.DrawDebugPhysics(actor, renderContext.View);
}
// Draw lights debug

View File

@@ -264,6 +264,7 @@ namespace FlaxEditor.Viewport.Previews
{
DebugDraw.SetContext(_debugDrawContext);
DebugDraw.UpdateContext(_debugDrawContext, 1.0f / Mathf.Max(Engine.FramesPerSecond, 1));
DebugDraw.SetView(ref renderContext.View);
CustomDebugDraw?.Invoke(context, ref renderContext);
OnDebugDraw(context, ref renderContext);
DebugDraw.Draw(ref renderContext, target.View(), targetDepth.View(), true);

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