186 Commits

Author SHA1 Message Date
3008d8037d _unbox
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-12-21 20:17:24 +02:00
0973363c64 wip 2 no leaks 2025-12-21 17:45:46 +02:00
5d45b9ea1c Fix managed boolean array conversion to native array 2025-12-20 01:51:37 +02:00
c40f7c12f2 Fix incorrect class namespace in bindings class name lookups 2025-12-19 23:57:31 +02:00
1b2d6372b2 Fix warnings 2025-12-19 13:16:35 +02:00
0782ea889c Fix command-line parsing for SDL CreateProcess arguments 2025-12-19 13:16:35 +02:00
ef89501111 Add function for parsing command-line arguments into argument list 2025-12-19 13:16:35 +02:00
608353b996 _managed handle pool start 2025-12-19 13:14:11 +02:00
221325ef09 _freemanaged dllexport used 2025-12-19 13:14:10 +02:00
8f57c91a9e _track disabled 2025-12-19 13:14:10 +02:00
968de34cae _wip 2025-12-19 13:14:10 +02:00
6586a98f8d Ensure managed converter functions are exported with optimizations 2025-12-19 13:14:10 +02:00
b3510b0e44 Add USED attribute for forcing compiler to emit the symbol 2025-12-19 13:14:10 +02:00
d5a92c1942 Fix missing exports for managed converter structures 2025-12-19 13:14:10 +02:00
417f82826f Expose RenderContext to scripting API 2025-12-19 13:14:10 +02:00
63bed0986a Fix clang bindings code generation for non-const ref parameters 2025-12-19 13:14:10 +02:00
c40eefc79d Fix compilation errors with /permissive- standard conformance mode 2025-12-19 13:14:10 +02:00
d68631dd20 Fix Editor project file generation to use custom code editor arguments 2025-12-19 13:14:10 +02:00
e77b772010 Get code editor name through CodeEditingManager 2025-12-19 13:14:10 +02:00
e41e956386 Fix default code editor not using Visual Studio as fallback editor 2025-12-19 13:14:10 +02:00
33e47c646b Fix invalid code editor when selected editor is not detected 2025-12-19 13:14:10 +02:00
b30ce6b84f Support Visual Studio 2026 as a generator for CMake dependencies 2025-12-19 01:31:42 +02:00
02f67b25f3 Verify the last project path before using it 2025-12-19 01:31:42 +02:00
469a422681 Add -lastproject editor command-line option to open the last project 2025-12-19 01:31:41 +02:00
42fa0ffdd1 Use last opened project as initial directory in project file dialog 2025-12-19 01:31:41 +02:00
f97ee72f1c Fix SpecialFolder::AppData on Apple systems 2025-12-19 01:31:41 +02:00
89c93dd4f7 Use XDG user directories on Linux special paths 2025-12-19 01:31:40 +02:00
60cd8f702e Fix Flax C#-project launchSettings.json to launch without project 2025-12-19 01:31:40 +02:00
f376ec5c8a Launch editor when debugging C++ projects in Rider Linux/macOS 2025-12-19 01:31:40 +02:00
82bb297119 Use standard output for logging by default 2025-12-16 21:16:05 +02:00
ed994cb560 Run editor with selected project configuration in launchSettings.json 2025-12-16 21:16:05 +02:00
8efe2134f0 Fix duplicate properties for default configuration in C# projects 2025-12-16 21:16:05 +02:00
8efc4715c6 Improve Linux .NET runtime identifier detection
Use the runtime identifier detected during runtime instead of
calling the dotnet tool in order to query it.
2025-12-16 00:15:40 +02:00
48c60144ae Set C# language version to 14 with .NET 10 2025-12-16 00:15:40 +02:00
249cde467e Improve installed .NET runtime version detection 2025-12-16 00:15:40 +02:00
e2eadc87b6 Fix Editor state after loading a scene without compiled game modules 2025-12-16 00:15:40 +02:00
bc4b94d2bc Use in over ref modifier in Math functions input parameters 2025-12-16 00:15:30 +02:00
ecf074801f Fix ref usage warnings with in-parameters 2025-12-16 00:15:30 +02:00
74bac97f44 Deprecate UseFastPDBLinking
This is no longer supported in VS2026
2025-12-16 00:15:30 +02:00
d7eebb699c Pass const ref parameters as in parameters in C# bindings
_amend in parameters
2025-12-16 00:15:29 +02:00
dde07bac8d Fix mixed newline characters in generated bindings 2025-12-16 00:14:16 +02:00
5c8e593d89 Show properties without getter in generic editor 2025-12-16 00:14:16 +02:00
46fd5a5855 Ensure Flax.Build tasks and utilities output error messages as errors 2025-12-16 00:11:06 +02:00
74c1e200ce Implement Platform::CreateProcess with SDL backend
Supports handling process standard output and standard error
streams separately in realtime.
2025-12-16 00:10:01 +02:00
31945a53a2 Update SDL to 3.3.4 2025-12-15 19:32:47 +02:00
3e91ba3fb2 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-12-15 19:03:05 +02:00
092beb6ae9 Fix compilation error 2025-11-28 11:59:56 +02:00
eb69186271 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-11-28 11:58:44 +02:00
0ac3ab2329 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-11-19 18:30:08 +02:00
466f9a4797 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-11-11 21:40:06 +02:00
c61ecc0545 Merge branch 'master' into sdl_platform 2025-10-30 22:42:29 +02:00
22ba7f2ee5 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-10-24 18:31:50 +03:00
f52f3920cb Update SDL to 3.2.24 2025-10-18 02:19:56 +03:00
f99a244b8e Merge remote-tracking branch 'origin/master' into sdl_platform
# Conflicts:
#	Source/Editor/Windows/GameWindow.cs
2025-10-18 02:19:30 +03:00
668a4dbb4d Merge remote-tracking branch 'origin/master' into sdl_platform 2025-10-14 01:09:26 +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
fc341a86e7 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-08-24 09:44:28 +03: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
51feaa0730 Release mouse relative mode when focus changes during mouse tracking
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-07-03 23:21:42 +03:00
8e69aa8bd6 Fix error while closing Editor
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-07-03 22:57:07 +03:00
90b2fded48 Merge remote-tracking branch 'origin/master' into sdl_platform
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
# Conflicts:
#	Source/Editor/Windows/SceneTreeWindow.cs
2025-07-03 22:05:29 +03:00
9125ffeb9e Update third-party label in About dialog 2025-07-03 22:02:37 +03:00
28980e5fbf Cleanup 2025-07-03 22:02:36 +03:00
aab0d772a4 Implement client-side window decorations for Editor windows 2025-07-03 22:02:36 +03:00
6296e1a9eb Fix linker errors 2025-06-26 15:32:38 +03:00
1586bb0702 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-26 15:31:59 +03:00
edeaf6af09 Fix compilation without SDL 2025-06-24 22:57:49 +03:00
951edd95db Cleanup 2025-06-24 16:47:45 +03:00
9951211596 Fix mono glib.h wrapper compilation error 2025-06-24 16:47:20 +03:00
6d337464f7 Support XDG Desktop Portal as color picker provider
Wayland and XWayland fallback implementation uses XDP in
order to query picked color from desktop.
2025-06-24 16:41:32 +03:00
d0b552d74a Use logo as an icon in Linux windows 2025-06-23 18:58:02 +03:00
83512822b1 Support clipboard actions in Content Browser and Scene tree on Wayland
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-06-23 17:50:02 +03:00
ccb78103ec Support clipboard actions in Content Browser and Scene tree on X11 2025-06-23 17:07:10 +03:00
6e79ffea34 Fix clipboard not working on X11 2025-06-23 17:07:10 +03:00
4f03d37a17 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-23 12:03:41 +03:00
6fb8419b3c Disable window flashing on Wayland to fix focus issues 2025-06-17 14:23:20 +03:00
a4272d6ca9 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-17 14:19:46 +03:00
4654117d5e Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-16 17:09:22 +03:00
6ff260d052 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-16 14:09:29 +03:00
88d2b72822 Update SDL to 3.3.x
Fixes popup focus issues on Linux
2025-06-16 14:09:04 +03:00
29868531ad SDL workaround for window size and position not updating
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2025-06-08 18:57:57 +03:00
95dfb6fdc6 Reduce minimum default window size for CommandLineBox popup 2025-06-08 18:57:12 +03:00
8df3999f85 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-04 19:30:30 +03:00
149b189629 Update SDL to 3.2.16 2025-06-02 19:23:34 +03:00
b1fd86e6b5 Merge remote-tracking branch 'origin/master' into sdl_platform 2025-06-02 18:15:16 +03:00
5e8fdf879d Fix logging in gamepad related events 2025-06-02 18:15:10 +03:00
84ada18299 Fix unlock mouse hotkey not unlocking CursorLockMode.Locked cursor 2025-04-21 23:13:23 +03:00
635fe8017e Fix EditorViewport buttons activating items on scene 2025-04-21 23:13:23 +03:00
834380ff05 Cleanup 2025-04-21 23:13:23 +03:00
dd65fc2289 Implement Wayland text clipboard data handling 2025-04-21 23:13:23 +03:00
86125bb625 Add support for VK_EXT_metal_surface extension 2025-04-21 23:13:23 +03:00
09a9d8b380 Update volk to 1.4.304 2025-04-21 23:13:23 +03:00
86b223ec93 Fix mouse relative mode activation triggering mouse move events on Mac 2025-04-21 23:13:23 +03:00
78f6080321 Initial support for building and running SDL platform on macOS 2025-04-21 23:13:23 +03:00
c7be6f6e0e Fix VC++ project file building on macOS Rider 2025-04-20 01:14:51 +03:00
c40c31fbb7 Reduce lock usage during window events 2025-04-19 21:14:13 +03:00
f5fbc1e32d Fix handling of WindowsManager locks 2025-04-19 21:14:13 +03:00
0a20378acd Handle Wayland dragging actions ending prematurely 2025-04-19 21:14:12 +03:00
d4e87877b6 Fix editor viewport activating while dragging a window 2025-04-19 21:14:12 +03:00
7eb7236b8a Fix occluded or hidden windows causing the engine to freeze on Wayland 2025-04-19 21:14:11 +03:00
dc0e4ffce2 Allow context menu to show when activating scene tree with right click 2025-04-19 21:14:11 +03:00
86fe93943d Fix crash when relative mode was left active on removed window 2025-04-19 21:14:10 +03:00
3258113ef8 Ensure mouse position is up-to-date during button down events 2025-04-19 21:14:10 +03:00
ebf3999cfe Fix rubber band selector activating outside of the viewport
This usually happens while trying to drag the window from window handle
2025-04-19 21:14:09 +03:00
a1ccbbb5b9 Use sensible window minimum size limits in editor windows 2025-04-19 21:14:09 +03:00
35072c40d8 Fix build on Linux 2025-04-19 21:14:08 +03:00
5c51021388 Fix merge 2025-04-19 21:14:08 +03:00
95fd527515 Apply drag and drop styling on refactored WindowDragHelper
Reapplies changes from commit 38b00f458c
2025-04-19 21:14:07 +03:00
113d851cea Fix cursor escaping constrained area when initially outside on Windows 2025-04-19 21:14:07 +03:00
72f0c460f9 Refix dragged maximized window generating wrong mouse position events 2025-04-19 21:14:06 +03:00
13ddd15b44 Focus viewports earlier to fix CursorLockMode not always activating 2025-04-19 21:14:06 +03:00
c9e24aaf5f Fix documentation generation 2025-04-19 21:14:05 +03:00
68c0ac0ffc Fix cursor locking bounds calculation 2025-04-19 21:14:05 +03:00
bebda275a9 Fix crash when Game viewport was hidden 2025-04-19 21:14:04 +03:00
287eaae850 Fix X11 external drag and drop not releasing consistently 2025-04-19 21:14:04 +03:00
7e59c3b9a7 Fix restoring locked cursor state when window gains focus again 2025-04-19 21:14:03 +03:00
38658a5b8c Fix CursorLockMode.Locked not working 2025-04-19 21:14:02 +03:00
88c75b8672 Fix dragged maximized window generating wrong mouse position events 2025-04-19 21:14:02 +03:00
17ab1e6830 Fix window handle clicking to not restore window from maximized state 2025-04-19 21:14:01 +03:00
1f45110e5f Fix rubber band selector activating when using Alt-key to orbit 2025-04-19 21:14:01 +03:00
5401166a07 Fix error when entering playmode while holding right mouse button 2025-04-19 21:14:00 +03:00
bfa8188782 Fix accepting drag and drop for files in Wayland 2025-04-19 21:14:00 +03:00
e777a71784 Fix error while dragging files around Content window 2025-04-19 21:13:59 +03:00
c13e91a0d0 Release rubber band selection when viewport starts controlling the view 2025-04-19 21:13:59 +03:00
aac5d57352 Update SDL to 3.2.10 2025-04-19 21:13:58 +03:00
ceca13c7b6 Avoid showing tooltips in inactive windows 2025-04-19 21:13:58 +03:00
2905470330 Update SDL3 to 3.2.4 2025-04-19 21:13:57 +03:00
2c17033822 Fix window dragging when not supported by Wayland compositor
(cherry picked from commit 3554747a67)
2025-04-19 21:13:57 +03:00
0a4cb9e9b1 Show current display server in Editor window tooltip
(cherry picked from commit 62968dd437)
2025-04-19 21:13:56 +03:00
096651f4c1 Properly mark floating windows with transparency support
(cherry picked from commit c660fac524)
2025-04-19 21:13:56 +03:00
275a08506b Enable transparency support in Vulkan swapchains
(cherry picked from commit 431a69e357)
2025-04-19 21:13:55 +03:00
4cd61cb381 Fix compilation for game builds
(cherry picked from commit f4fcc07288)
2025-04-19 21:13:54 +03:00
9ad1147581 Fix cloning SDL repository 2025-04-19 21:13:54 +03:00
35e09def1b Fix text input not working on X11 2025-04-19 21:13:53 +03:00
0469607a71 Fix button latching on Windows after drag and drop operation 2025-04-19 21:13:53 +03:00
d115d22ee6 Implement new window dragging system 2025-04-19 21:13:52 +03:00
8120ae621d Fix mouse resetting issues after ending relative mode 2025-04-19 21:13:52 +03:00
f873c2fa9f Fix frame stutter when window is focused 2025-04-19 21:13:51 +03:00
c3ffbe2f42 Fix error when docking to sides of tabbed panel 2025-04-19 21:13:51 +03:00
55a0a39881 Cleanup Linux SDL implementation 2025-04-19 21:13:50 +03:00
592215dd30 Support compiling third party library C files as C code 2025-04-19 21:13:50 +03:00
ef0c2a2785 Implement Wayland protocols module and file generation 2025-04-19 21:13:49 +03:00
37979e452a Fix mouse warping after ending relative mode 2025-04-19 21:13:49 +03:00
e9671bb727 Add git fetch method for dependencies 2025-04-19 21:13:48 +03:00
aa328bd591 Fix window ShowInTaskbar setting 2025-04-19 21:13:48 +03:00
188e4313f9 Fix various issues with child window positioning 2025-04-19 21:13:47 +03:00
df02c70e31 Add Window.IsAlwaysOnTop property 2025-04-19 21:13:47 +03:00
257f54b323 Use SDL locale 2025-04-19 21:13:46 +03:00
fb4b5b2575 Allow window with single tab to be dragged from tab area 2025-04-19 21:13:46 +03:00
4e1251276d Fix ValueBox mouse position resetting after releasing the button 2025-04-19 21:13:45 +03:00
a7b200dc57 Fix SDL build process on Linux 2025-04-19 21:13:44 +03:00
8cadbae80e Update SDL to 3.2.0 2025-04-19 21:13:44 +03:00
c3bae49aae Force cursor to center of Game Window when tab handle is clicked 2025-04-19 21:13:43 +03:00
Chandler Cox
6fa4fc6149 Fix rotation using SDL 2025-04-19 21:13:43 +03:00
f1ffe1acaa Fix Linux compilation without SDL 2025-04-19 21:13:42 +03:00
5c9ddf7f00 Fix compilation 2025-04-19 21:13:42 +03:00
431767a150 Update SDL3 2025-04-19 21:13:41 +03:00
8ba4e442a6 Fix compilation issues 2025-04-19 21:13:41 +03:00
2f8d19c267 Fix windows not being hidden initially 2025-04-19 21:13:40 +03:00
f2fd98f742 Fix parent window position handling with popup/tooltip windows 2025-04-19 21:13:40 +03:00
3ce35d6e81 Fix compilation errors in other platforms 2025-04-19 21:13:39 +03:00
796dbaa836 Fix CI for Linux 2025-04-19 21:13:39 +03:00
84b209ec7f Prevent building with SDL in unsupported platforms 2025-04-19 21:13:38 +03:00
fa976b34dc Fallback to X11 message box implementation when SDL fails 2025-04-19 21:13:38 +03:00
e7cda362b7 Fix popup and context menus not working on Wayland 2025-04-19 21:13:37 +03:00
a41a09c162 Hide warnings for unsupported SDL operations on Wayland 2025-04-19 21:13:37 +03:00
e82f84f0ab Log a warning for not implemented Wayland functionality 2025-04-19 21:13:36 +03:00
f1d387ceea Fix compilation in Linux 2025-04-19 21:13:36 +03:00
3893d4d1f8 Enable warning sound in question dialogs 2025-04-19 21:13:35 +03:00
cf7ac50faf Enable modern Windows dialog boxes 2025-04-19 21:13:35 +03:00
3f6bf15554 Implement relative mouse mode (raw input) for SDL platform 2025-04-19 21:13:34 +03:00
dac74829b4 Add flag for Window types 2025-04-19 21:13:34 +03:00
94d6f213a0 Enable native windowing system settings with SDL platform 2025-04-19 21:13:33 +03:00
8f2550ef61 Add command-line switches to force X11 and Wayland SDL drivers 2025-04-19 21:13:33 +03:00
b622a1cc5e Implement SDL platform, windowing and input handling 2025-04-19 21:13:32 +03:00
c83a3c32c7 Refactor application window class name 2025-04-19 21:13:32 +03:00
e7dcf7f7e7 Move Window related enums to separate header file 2025-04-19 21:13:31 +03:00
398785a2be Refactor Windows drag and drop implementation 2025-04-19 21:13:31 +03:00
05dba0f1f5 Refactor ScreenUtilities 2025-04-19 21:13:30 +03:00
39dbd32b2e Add more helper methods for managing Git repos 2025-04-19 21:13:30 +03:00
23a34a455a Fix centered window location on X11 2025-04-19 21:13:29 +03:00
4308328b48 Fix initial position of Tooltips 2025-04-19 21:13:29 +03:00
504 changed files with 102529 additions and 4654 deletions

View File

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

View File

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

View File

@@ -13,6 +13,7 @@
"Configuration": { "Configuration": {
"UseCSharp": true, "UseCSharp": true,
"UseLargeWorlds": false, "UseLargeWorlds": false,
"UseDotNet": true "UseDotNet": true,
"UseSDL": true
} }
} }

View File

@@ -15,7 +15,7 @@ if errorlevel 1 goto BuildToolFailed
:: Build bindings for all editor configurations :: Build bindings for all editor configurations
echo Building C# bindings... echo Building C# bindings...
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor,FlaxGame
popd popd
echo Done! echo Done!

View File

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

View File

@@ -749,7 +749,7 @@ namespace FlaxEditor.Content
} }
// Draw short name // Draw short name
Render2D.PushClip(ref textRect); Render2D.PushClip(textRect);
var scale = 0.95f * view.ViewScale; var scale = 0.95f * view.ViewScale;
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale); Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale);
Render2D.PopClip(); Render2D.PopClip();

View File

@@ -20,7 +20,7 @@ namespace FlaxEditor.Content
} }
/// <inheritdoc /> /// <inheritdoc />
public override string TypeDescription => Path.EndsWith(".h") ? "C++ Header File" : "C++ Source Code"; public override string TypeDescription => Path.EndsWith(".h") || Path.EndsWith(".hpp") ? "C++ Header File" : "C++ Source Code";
/// <inheritdoc /> /// <inheritdoc />
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128; public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;

View File

@@ -263,7 +263,7 @@ namespace FlaxEditor.Content.Thumbnails
// Create render task but disabled for now // Create render task but disabled for now
_output = GPUDevice.Instance.CreateTexture("ThumbnailsOutput"); _output = GPUDevice.Instance.CreateTexture("ThumbnailsOutput");
var desc = GPUTextureDescription.New2D(PreviewsCache.AssetIconSize, PreviewsCache.AssetIconSize, PreviewsCache.AssetIconsAtlasFormat); var desc = GPUTextureDescription.New2D(PreviewsCache.AssetIconSize, PreviewsCache.AssetIconSize, PreviewsCache.AssetIconsAtlasFormat);
_output.Init(ref desc); _output.Init(desc);
_task = Object.New<RenderTask>(); _task = Object.New<RenderTask>();
_task.Order = 50; // Render this task later _task.Order = 50; // Render this task later
_task.Enabled = false; _task.Enabled = false;

View File

@@ -60,14 +60,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (prefab && !prefab.WaitForLoaded()) if (prefab && !prefab.WaitForLoaded())
{ {
var prefabObjectId = actor.PrefabObjectID; var prefabObjectId = actor.PrefabObjectID;
var prefabInstance = prefab.GetDefaultInstance(ref prefabObjectId); var prefabInstance = prefab.GetDefaultInstance(prefabObjectId);
if (prefabInstance != null) if (prefabInstance != null)
{ {
// Use default prefab instance as a reference for the editor // Use default prefab instance as a reference for the editor
Values.SetReferenceValue(prefabInstance); Values.SetReferenceValue(prefabInstance);
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs) // Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
prefab.GetNestedObject(ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId); prefab.GetNestedObject(prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId); var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
var panel = layout.UniformGrid(); var panel = layout.UniformGrid();
panel.CustomControl.Height = 20.0f; panel.CustomControl.Height = 20.0f;
@@ -207,7 +207,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{ {
var actor = (Actor)Values[0]; var actor = (Actor)Values[0];
var prefabObjectId = actor.PrefabObjectID; var prefabObjectId = actor.PrefabObjectID;
var prefabInstance = prefab.GetDefaultInstance(ref prefabObjectId); var prefabInstance = prefab.GetDefaultInstance(prefabObjectId);
if (prefabInstance != null) if (prefabInstance != null)
{ {
Values.SetReferenceValue(prefabInstance); Values.SetReferenceValue(prefabInstance);
@@ -525,7 +525,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var restored = actor.AddScript(removed.PrefabObject.GetType()); var restored = actor.AddScript(removed.PrefabObject.GetType());
var prefabId = actor.PrefabID; var prefabId = actor.PrefabID;
var prefabObjectId = restored.PrefabObjectID; var prefabObjectId = restored.PrefabObjectID;
Script.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId); Script.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), prefabId, prefabObjectId);
string data = JsonSerializer.Serialize(removed.PrefabObject); string data = JsonSerializer.Serialize(removed.PrefabObject);
JsonSerializer.Deserialize(restored, data); JsonSerializer.Deserialize(restored, data);
@@ -547,7 +547,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
string data = JsonSerializer.Serialize(removedActor.PrefabObject); string data = JsonSerializer.Serialize(removedActor.PrefabObject);
JsonSerializer.Deserialize(restored, data); JsonSerializer.Deserialize(restored, data);
Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent); Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent);
Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId); Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), prefabId, prefabObjectId);
return; return;
} }

View File

@@ -190,12 +190,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
foreach (var file in files) foreach (var file in files)
FindNewKeysCSharp(file, newKeys, allKeys); FindNewKeysCSharp(file, newKeys, allKeys);
// C++ // C/C++
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories); files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.c", SearchOption.AllDirectories)).ToArray();
filesCount += files.Length; filesCount += files.Length;
foreach (var file in files) foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys); FindNewKeysCpp(file, newKeys, allKeys);
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories); files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray();;
filesCount += files.Length; filesCount += files.Length;
foreach (var file in files) foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys); FindNewKeysCpp(file, newKeys, allKeys);

View File

@@ -164,11 +164,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14); var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14);
// Deselect // Deselect
if (isSelected && button1Rect.Contains(ref location)) if (isSelected && button1Rect.Contains(location))
Value = new ModelInstanceActor.MeshReference { Actor = null, LODIndex = -1, MeshIndex = -1 }; Value = new ModelInstanceActor.MeshReference { Actor = null, LODIndex = -1, MeshIndex = -1 };
// Picker dropdown menu // Picker dropdown menu
if ((isSelected ? button2Rect : button1Rect).Contains(ref location)) if ((isSelected ? button2Rect : button1Rect).Contains(location))
ShowDropDownMenu(); ShowDropDownMenu();
return base.OnMouseUp(location, button); return base.OnMouseUp(location, button);

View File

@@ -40,7 +40,7 @@ public class ModelPrefabEditor : GenericEditor
if (prefab) if (prefab)
{ {
var prefabObjectId = modelPrefab.PrefabObjectID; var prefabObjectId = modelPrefab.PrefabObjectID;
var prefabObject = prefab.GetDefaultInstance(ref prefabObjectId); var prefabObject = prefab.GetDefaultInstance(prefabObjectId);
if (prefabObject.PrefabID == _prefabId) if (prefabObject.PrefabID == _prefabId)
break; break;
_prefabId = prefabObject.PrefabID; _prefabId = prefabObject.PrefabID;

View File

@@ -192,7 +192,7 @@ namespace FlaxEditor.CustomEditors.Editors
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (DropdownRect.Contains(ref location)) if (DropdownRect.Contains(location))
{ {
Focus(); Focus();
ShowPicker(); ShowPicker();
@@ -206,7 +206,7 @@ namespace FlaxEditor.CustomEditors.Editors
{ {
base.OnMouseMove(location); base.OnMouseMove(location);
if (DropdownRect.Contains(ref location)) if (DropdownRect.Contains(location))
Cursor = CursorType.Default; Cursor = CursorType.Default;
else else
Cursor = CursorType.IBeam; Cursor = CursorType.IBeam;

View File

@@ -155,7 +155,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && _arrangeButtonRect.Contains(ref location)) if (button == MouseButton.Left && _arrangeButtonRect.Contains(location))
{ {
_arrangeButtonInUse = true; _arrangeButtonInUse = true;
Focus(); Focus();
@@ -371,7 +371,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && _arrangeButtonRect.Contains(ref location)) if (button == MouseButton.Left && _arrangeButtonRect.Contains(location))
{ {
_arrangeButtonInUse = true; _arrangeButtonInUse = true;
Focus(); Focus();

View File

@@ -321,11 +321,11 @@ namespace FlaxEditor.CustomEditors.Editors
var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14); var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14);
// Deselect // Deselect
if (_value != null && button1Rect.Contains(ref location)) if (_value != null && button1Rect.Contains(location))
Value = null; Value = null;
// Picker dropdown menu // Picker dropdown menu
if (_supportsPickDropDown && (isSelected ? button2Rect : button1Rect).Contains(ref location)) if (_supportsPickDropDown && (isSelected ? button2Rect : button1Rect).Contains(location))
{ {
ShowDropDownMenu(); ShowDropDownMenu();
return true; return true;

View File

@@ -247,7 +247,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <returns>The items.</returns> /// <returns>The items.</returns>
protected virtual List<ItemInfo> GetItemsForType(ScriptType type) protected virtual List<ItemInfo> GetItemsForType(ScriptType type)
{ {
return GetItemsForType(type, type.IsClass, true); return GetItemsForType(type, type.IsClass, true, true);
} }
/// <summary> /// <summary>
@@ -273,10 +273,14 @@ namespace FlaxEditor.CustomEditors.Editors
var attributes = p.GetAttributes(true); var attributes = p.GetAttributes(true);
var showInEditor = attributes.Any(x => x is ShowInEditorAttribute); var showInEditor = attributes.Any(x => x is ShowInEditorAttribute);
// Skip properties without getter or setter // Skip properties without getter
if (!p.HasGet || (!p.HasSet && !showInEditor && !usePropertiesWithoutSetter)) if (!p.HasGet || (!p.HasSet && !showInEditor && !usePropertiesWithoutSetter))
continue; continue;
// Skip getter-only properties declared in built-in types
if (!p.HasSet && usePropertiesWithoutSetter && p.Type.DeclaringType.Assembly == typeof(Editor).Assembly)
continue;
// Skip hidden fields, handle special attributes // Skip hidden fields, handle special attributes
if ((!p.IsPublic && !showInEditor) || attributes.Any(x => x is HideInEditorAttribute)) if ((!p.IsPublic && !showInEditor) || attributes.Any(x => x is HideInEditorAttribute))
continue; continue;

View File

@@ -219,11 +219,11 @@ namespace FlaxEditor.CustomEditors.Editors
var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14); var button2Rect = new Rectangle(button1Rect.Right + 2, 1, 14, 14);
// Deselect // Deselect
if (_value && button1Rect.Contains(ref location) && _type == ScriptType.Null) if (_value && button1Rect.Contains(location) && _type == ScriptType.Null)
Value = ScriptType.Null; Value = ScriptType.Null;
// Picker dropdown menu // Picker dropdown menu
if ((isSelected && _type == ScriptType.Null ? button2Rect : button1Rect).Contains(ref location)) if ((isSelected && _type == ScriptType.Null ? button2Rect : button1Rect).Contains(location))
ShowDropDownMenu(); ShowDropDownMenu();
return base.OnMouseUp(location, button); return base.OnMouseUp(location, button);

View File

@@ -526,6 +526,23 @@ int32 Editor::LoadProduct()
return 12; return 12;
} }
// Get the last opened project path
String localCachePath;
FileSystem::GetSpecialFolderPath(SpecialFolder::AppData, localCachePath);
String editorConfigPath = localCachePath / TEXT("Flax");
String lastProjectSettingPath = editorConfigPath / TEXT("LastProject.txt");
if (!FileSystem::DirectoryExists(editorConfigPath))
FileSystem::CreateDirectory(editorConfigPath);
String lastProjectPath;
if (FileSystem::FileExists(lastProjectSettingPath))
File::ReadAllText(lastProjectSettingPath, lastProjectPath);
if (!FileSystem::DirectoryExists(lastProjectPath))
lastProjectPath = String::Empty;
// Try to open the last project when requested
if (projectPath.IsEmpty() && CommandLine::Options.LastProject.IsTrue() && !lastProjectPath.IsEmpty())
projectPath = lastProjectPath;
// Missing project case // Missing project case
if (projectPath.IsEmpty()) if (projectPath.IsEmpty())
{ {
@@ -541,7 +558,7 @@ int32 Editor::LoadProduct()
Array<String> files; Array<String> files;
if (FileSystem::ShowOpenFileDialog( if (FileSystem::ShowOpenFileDialog(
nullptr, nullptr,
StringView::Empty, lastProjectPath,
TEXT("Project files (*.flaxproj)\0*.flaxproj\0All files (*.*)\0*.*\0"), TEXT("Project files (*.flaxproj)\0*.flaxproj\0All files (*.*)\0*.*\0"),
false, false,
TEXT("Select project to open in Editor"), TEXT("Select project to open in Editor"),
@@ -625,6 +642,10 @@ int32 Editor::LoadProduct()
} }
} }
// Update the last opened project path
if (lastProjectPath.Compare(Project->ProjectFolderPath) != 0)
File::WriteAllText(lastProjectSettingPath, Project->ProjectFolderPath, Encoding::UTF8);
return 0; return 0;
} }

View File

@@ -1056,7 +1056,7 @@ namespace FlaxEditor
if (actor) if (actor)
{ {
Internal_GetEditorBoxWithChildren(FlaxEngine.Object.GetUnmanagedPtr(actor), out var box); Internal_GetEditorBoxWithChildren(FlaxEngine.Object.GetUnmanagedPtr(actor), out var box);
BoundingSphere.FromBox(ref box, out sphere); BoundingSphere.FromBox(box, out sphere);
if (sphere == BoundingSphere.Empty) if (sphere == BoundingSphere.Empty)
sphere = new BoundingSphere(actor.Position, sphere.Radius); sphere = new BoundingSphere(actor.Position, sphere.Radius);
sphere.Radius = Math.Max(sphere.Radius, 15.0f); sphere.Radius = Math.Max(sphere.Radius, 15.0f);

View File

@@ -96,7 +96,7 @@ namespace FlaxEditor.GUI
private void DoDrag() private void DoDrag()
{ {
// Do the drag drop operation if has selected element // Do the drag drop operation if has selected element
if (new Rectangle(Float2.Zero, Size).Contains(ref _mouseDownPos)) if (new Rectangle(Float2.Zero, Size).Contains(_mouseDownPos))
{ {
if (Validator.SelectedAsset != null) if (Validator.SelectedAsset != null)
DoDragDrop(DragAssets.GetDragData(Validator.SelectedAsset)); DoDragDrop(DragAssets.GetDragData(Validator.SelectedAsset));

View File

@@ -1,7 +1,10 @@
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS || PLATFORM_SDL
#define USE_IS_FOREGROUND #define USE_IS_FOREGROUND
#else #else
#endif #endif
#if PLATFORM_SDL
#define USE_SDL_WORKAROUNDS
#endif
// Copyright (c) Wojciech Figat. All rights reserved. // Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic; using System.Collections.Generic;
@@ -122,7 +125,7 @@ namespace FlaxEditor.GUI.ContextMenu
} }
/// <summary> /// <summary>
/// Shows the empty menu popup o na screen. /// Shows the empty menu popup on a screen.
/// </summary> /// </summary>
/// <param name="control">The target control.</param> /// <param name="control">The target control.</param>
/// <param name="area">The target control area to cover.</param> /// <param name="area">The target control area to cover.</param>
@@ -257,7 +260,9 @@ namespace FlaxEditor.GUI.ContextMenu
desc.AllowMaximize = false; desc.AllowMaximize = false;
desc.AllowDragAndDrop = false; desc.AllowDragAndDrop = false;
desc.IsTopmost = true; desc.IsTopmost = true;
desc.IsRegularWindow = false; desc.Type = WindowType.Popup;
desc.Parent = parentWin.Window;
desc.Title = "ContextMenu";
desc.HasSizingFrame = false; desc.HasSizingFrame = false;
OnWindowCreating(ref desc); OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc); _window = Platform.CreateWindow(ref desc);
@@ -266,6 +271,12 @@ namespace FlaxEditor.GUI.ContextMenu
_window.GotFocus += OnWindowGotFocus; _window.GotFocus += OnWindowGotFocus;
_window.LostFocus += OnWindowLostFocus; _window.LostFocus += OnWindowLostFocus;
} }
#if USE_IS_FOREGROUND && USE_SDL_WORKAROUNDS
// The focus between popup and parent windows doesn't change, force hide the popup when clicked on parent
parentWin.Window.MouseDown += OnWindowMouseDown;
_window.Closed += () => parentWin.Window.MouseDown -= OnWindowMouseDown;
#endif
// Attach to the window // Attach to the window
_parentCM = parent as ContextMenuBase; _parentCM = parent as ContextMenuBase;
@@ -441,6 +452,17 @@ namespace FlaxEditor.GUI.ContextMenu
} }
} }
#if USE_SDL_WORKAROUNDS
private void OnWindowGotFocus()
{
}
private void OnWindowMouseDown(ref Float2 mousePosition, MouseButton button, ref bool handled)
{
// The user clicked outside the popup window
Hide();
}
#else
private void OnWindowGotFocus() private void OnWindowGotFocus()
{ {
var child = _childCM; var child = _childCM;
@@ -454,6 +476,7 @@ namespace FlaxEditor.GUI.ContextMenu
}); });
} }
} }
#endif
private void OnWindowLostFocus() private void OnWindowLostFocus()
{ {
@@ -552,7 +575,12 @@ namespace FlaxEditor.GUI.ContextMenu
// Let root context menu to check if none of the popup windows // Let root context menu to check if none of the popup windows
if (_parentCM == null && UseVisibilityControl && !IsForeground) if (_parentCM == null && UseVisibilityControl && !IsForeground)
{ {
#if USE_SDL_WORKAROUNDS
if (!IsMouseOver)
Hide();
#else
Hide(); Hide();
#endif
} }
} }
#endif #endif

View File

@@ -62,7 +62,7 @@ namespace FlaxEditor.GUI
for (int i = 0; i < children.Count; i++) for (int i = 0; i < children.Count; i++)
{ {
if (children[i] is KeyframePoint p) if (children[i] is KeyframePoint p)
p.IsSelected = p.Bounds.Intersects(ref selectionRect); p.IsSelected = p.Bounds.Intersects(selectionRect);
} }
_editor.UpdateTangents(); _editor.UpdateTangents();
} }
@@ -85,7 +85,7 @@ namespace FlaxEditor.GUI
internal void OnMove(Float2 location) internal void OnMove(Float2 location)
{ {
// Skip updating keyframes until move actual starts to be meaningful // Skip updating keyframes until move actual starts to be meaningful
if (Float2.Distance(ref _movingSelectionStartPosLock, ref location) < 1.5f) if (Float2.Distance(_movingSelectionStartPosLock, location) < 1.5f)
return; return;
_movingSelectionStartPosLock = Float2.Minimum; _movingSelectionStartPosLock = Float2.Minimum;

View File

@@ -689,8 +689,8 @@ namespace FlaxEditor.GUI
if (selectedOnly && !point.IsSelected) if (selectedOnly && !point.IsSelected)
continue; continue;
var pos = point.Point; var pos = point.Point;
Float2.Min(ref posMin, ref pos, out posMin); Float2.Min(posMin, pos, out posMin);
Float2.Max(ref posMax, ref pos, out posMax); Float2.Max(posMax, pos, out posMax);
} }
// Apply margin around the area // Apply margin around the area
@@ -703,16 +703,16 @@ namespace FlaxEditor.GUI
PointFromKeyframesToContents(ref posMin, ref viewRect); PointFromKeyframesToContents(ref posMin, ref viewRect);
PointFromKeyframesToContents(ref posMax, ref viewRect); PointFromKeyframesToContents(ref posMax, ref viewRect);
var tmp = posMin; var tmp = posMin;
Float2.Min(ref posMin, ref posMax, out posMin); Float2.Min(posMin, posMax, out posMin);
Float2.Max(ref posMax, ref tmp, out posMax); Float2.Max(posMax, tmp, out posMax);
var contentsSize = posMax - posMin; var contentsSize = posMax - posMin;
// Convert from Contents to Main Panel // Convert from Contents to Main Panel
posMin = _contents.PointToParent(posMin); posMin = _contents.PointToParent(posMin);
posMax = _contents.PointToParent(posMax); posMax = _contents.PointToParent(posMax);
tmp = posMin; tmp = posMin;
Float2.Min(ref posMin, ref posMax, out posMin); Float2.Min(posMin, posMax, out posMin);
Float2.Max(ref posMax, ref tmp, out posMax); Float2.Max(posMax, tmp, out posMax);
// Update zoom (leave unchanged when focusing a single point) // Update zoom (leave unchanged when focusing a single point)
var zoomMask = EnableZoom; var zoomMask = EnableZoom;
@@ -941,7 +941,7 @@ namespace FlaxEditor.GUI
{ {
SetupGrid(out var min, out var max, out var pixelRange); SetupGrid(out var min, out var max, out var pixelRange);
Render2D.PushClip(ref viewRect); Render2D.PushClip(viewRect);
if ((ShowAxes & UseMode.Vertical) == UseMode.Vertical) if ((ShowAxes & UseMode.Vertical) == UseMode.Vertical)
DrawAxis(Float2.UnitX, viewRect, min.X, max.X, pixelRange.X); DrawAxis(Float2.UnitX, viewRect, min.X, max.X, pixelRange.X);
@@ -954,7 +954,7 @@ namespace FlaxEditor.GUI
// Draw curve // Draw curve
if (!_showCollapsed) if (!_showCollapsed)
{ {
Render2D.PushClip(ref rect); Render2D.PushClip(rect);
DrawCurve(ref viewRect); DrawCurve(ref viewRect);
Render2D.PopClip(); Render2D.PopClip();
} }

View File

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

View File

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

View File

@@ -19,11 +19,7 @@ namespace FlaxEditor.GUI.Docking
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight; private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth; private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth; private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
#if PLATFORM_WINDOWS private readonly bool _hideTabForSingleTab = Utilities.Utils.HideSingleTabWindowTabBars();
private readonly bool _hideTabForSingleTab = Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
#else
private readonly bool _hideTabForSingleTab = false;
#endif
/// <summary> /// <summary>
/// The is mouse down flag (left button). /// The is mouse down flag (left button).
@@ -54,6 +50,11 @@ namespace FlaxEditor.GUI.Docking
/// The mouse position. /// The mouse position.
/// </summary> /// </summary>
public Float2 MousePosition = Float2.Minimum; public Float2 MousePosition = Float2.Minimum;
/// <summary>
/// The mouse position.
/// </summary>
public Float2 MouseStartPosition = Float2.Minimum;
/// <summary> /// <summary>
/// The start drag asynchronous window. /// The start drag asynchronous window.
@@ -196,7 +197,7 @@ namespace FlaxEditor.GUI.Docking
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating) if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
{ {
// Create docking hint window but in an async manner // Create docking hint window but in an async manner
DockHintWindow.Create(_panel as FloatWindowDockPanel); WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
} }
else else
{ {
@@ -207,7 +208,7 @@ namespace FlaxEditor.GUI.Docking
_panel.SelectTab(index - 1); _panel.SelectTab(index - 1);
// Create docking hint window // Create docking hint window
DockHintWindow.Create(win); WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
} }
} }
} }
@@ -393,6 +394,7 @@ namespace FlaxEditor.GUI.Docking
if (IsSingleFloatingWindow) if (IsSingleFloatingWindow)
return base.OnMouseDown(location, button); return base.OnMouseDown(location, button);
MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross); MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross);
MouseStartPosition = location;
// Check buttons // Check buttons
if (button == MouseButton.Left) if (button == MouseButton.Left)
@@ -479,6 +481,20 @@ namespace FlaxEditor.GUI.Docking
StartDrag(MouseDownWindow); StartDrag(MouseDownWindow);
MouseDownWindow = null; MouseDownWindow = null;
} }
// Check if single tab is tried to be moved
else if (MouseDownWindow != null && _panel.TabsCount <= 1)
{
if ((MousePosition - MouseStartPosition).Length > 3)
{
// Clear flag
IsMouseLeftButtonDown = false;
// Check tab under the mouse
if (!IsMouseDownOverCross && MouseDownWindow != null)
StartDrag(MouseDownWindow);
MouseDownWindow = null;
}
}
// Check if has more than one tab to change order // Check if has more than one tab to change order
else if (MouseDownWindow != null && _panel.TabsCount > 1) else if (MouseDownWindow != null && _panel.TabsCount > 1)
{ {

View File

@@ -182,6 +182,25 @@ namespace FlaxEditor.GUI.Docking
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param> /// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param> /// <param name="position">Window location.</param>
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent) public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
{
CreateFloating(location, size, position, true);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
public void CreateFloating()
{
CreateFloating(Float2.Zero, Float2.Zero);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
/// <param name="location">Window location.</param>
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
/// <param name="showWindow">Window visibility.</param>
public void CreateFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent, bool showWindow = false)
{ {
Undock(); Undock();
@@ -199,14 +218,17 @@ namespace FlaxEditor.GUI.Docking
windowGUI.UnlockChildrenRecursive(); windowGUI.UnlockChildrenRecursive();
windowGUI.PerformLayout(); windowGUI.PerformLayout();
// Show if (showWindow)
window.Show(); {
window.BringToFront(); // Show
window.Focus(); window.Show();
OnShow(); window.BringToFront();
window.Focus();
OnShow();
// Perform layout again // Perform layout again
windowGUI.PerformLayout(); windowGUI.PerformLayout();
}
} }
/// <summary> /// <summary>

View File

@@ -11,6 +11,42 @@ namespace FlaxEditor.GUI.Docking
/// <seealso cref="DockPanel" /> /// <seealso cref="DockPanel" />
public class FloatWindowDockPanel : DockPanel public class FloatWindowDockPanel : DockPanel
{ {
private class FloatWindowDecorations : WindowDecorations
{
private FloatWindowDockPanel _panel;
public FloatWindowDecorations(FloatWindowDockPanel panel)
: base(panel.RootWindow)
{
_panel = panel;
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (Title.Bounds.Contains(location) && button == MouseButton.Left)
{
_panel.BeginDrag();
return true;
}
return base.OnMouseDown(location, button);
}
#if !PLATFORM_WINDOWS
/// <inheritdoc />
protected override WindowHitCodes OnHitTest(ref Float2 mouse)
{
var hit = base.OnHitTest(ref mouse);
if (hit == WindowHitCodes.Caption)
{
// Override the system behaviour when interacting with the caption area
hit = WindowHitCodes.Client;
}
return hit;
}
#endif
}
private MasterDockPanel _masterPanel; private MasterDockPanel _masterPanel;
private WindowRootControl _window; private WindowRootControl _window;
@@ -40,6 +76,26 @@ namespace FlaxEditor.GUI.Docking
Parent = window; Parent = window;
_window.Window.Closing += OnClosing; _window.Window.Closing += OnClosing;
_window.Window.LeftButtonHit += OnLeftButtonHit; _window.Window.LeftButtonHit += OnLeftButtonHit;
if (Utilities.Utils.UseCustomWindowDecorations())
{
var decorations = Parent.AddChild(new FloatWindowDecorations(this));
decorations.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false);
}
}
/// <inheritdoc />
protected override void PerformLayoutBeforeChildren()
{
base.PerformLayoutBeforeChildren();
var decorations = Parent.GetChild<FloatWindowDecorations>();
if (decorations != null)
{
// Apply offset for the title bar
foreach (var child in Children)
child.Bounds = child.Bounds with { Y = decorations.Height, Height = Parent.Height - decorations.Height };
}
} }
/// <summary> /// <summary>
@@ -52,7 +108,7 @@ namespace FlaxEditor.GUI.Docking
return; return;
// Create docking hint window // Create docking hint window
DockHintWindow.Create(this); WindowDragHelper.StartDragging(this);
} }
/// <summary> /// <summary>
@@ -71,22 +127,28 @@ namespace FlaxEditor.GUI.Docking
settings.Title = title; settings.Title = title;
settings.Size = size; settings.Size = size;
settings.Position = location; settings.Position = location;
settings.MinimumSize = new Float2(1); settings.MinimumSize = new Float2(200, 150);
settings.MaximumSize = Float2.Zero; // Unlimited size settings.MaximumSize = Float2.Zero; // Unlimited size
settings.Fullscreen = false; settings.Fullscreen = false;
settings.HasBorder = true; settings.HasBorder = true;
settings.SupportsTransparency = false; settings.SupportsTransparency = true;
settings.ActivateWhenFirstShown = true; settings.ActivateWhenFirstShown = true;
settings.AllowInput = true; settings.AllowInput = true;
settings.AllowMinimize = true; settings.AllowMinimize = true;
settings.AllowMaximize = true; settings.AllowMaximize = true;
settings.AllowDragAndDrop = true; settings.AllowDragAndDrop = true;
settings.IsTopmost = false; settings.IsTopmost = false;
settings.IsRegularWindow = true; settings.Type = WindowType.Regular;
settings.HasSizingFrame = true; settings.HasSizingFrame = true;
settings.ShowAfterFirstPaint = false; settings.ShowAfterFirstPaint = false;
settings.ShowInTaskbar = true; settings.ShowInTaskbar = true;
settings.StartPosition = startPosition; settings.StartPosition = startPosition;
if (Utilities.Utils.UseCustomWindowDecorations())
{
settings.HasBorder = false;
//settings.HasSizingFrame = false;
}
// Create window // Create window
return Platform.CreateWindow(ref settings); return Platform.CreateWindow(ref settings);

View File

@@ -81,7 +81,6 @@ namespace FlaxEditor.GUI.Docking
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded) public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
{ {
// Check all floating windows // Check all floating windows
// TODO: gather windows order and take it into account when performing test
for (int i = 0; i < FloatingPanels.Count; i++) for (int i = 0; i < FloatingPanels.Count; i++)
{ {
var win = FloatingPanels[i]; var win = FloatingPanels[i];
@@ -94,9 +93,44 @@ namespace FlaxEditor.GUI.Docking
} }
// Base // Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
return base.HitTest(ref position); return base.HitTest(ref position);
} }
/// <summary>
/// Performs hit test over dock panel.
/// </summary>
/// <param name="position">Window space position to test.</param>
/// <param name="excluded">Floating window to omit during searching (and all docked to that one).</param>
/// <param name="hitResults">Results of the hit test</param>
/// <returns>True if any dock panels were hit, otherwise false.</returns>
public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
{
// Check all floating windows
List<DockPanel> results = new(FloatingPanels.Count);
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
var result = win.HitTest(ref position);
if (result != null)
results.Add(result);
}
}
// Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
var baseResult = base.HitTest(ref position);
if (baseResult != null)
results.Add(baseResult);
hitResults = results.ToArray();
return hitResults.Length > 0;
}
internal void LinkWindow(DockWindow window) internal void LinkWindow(DockWindow window)
{ {
// Add to the windows list // Add to the windows list

View File

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

View File

@@ -180,7 +180,7 @@ namespace FlaxEditor.GUI.Input
Focus(); Focus();
float mousePosition = location.X; float mousePosition = location.X;
if (_thumbRect.Contains(ref location)) if (_thumbRect.Contains(location))
{ {
// Start sliding // Start sliding
_isSliding = true; _isSliding = true;

View File

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

View File

@@ -12,16 +12,6 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.ContainerControl" /> /// <seealso cref="FlaxEngine.GUI.ContainerControl" />
public sealed class MainMenu : ContainerControl public sealed class MainMenu : ContainerControl
{ {
#if PLATFORM_WINDOWS
private bool _useCustomWindowSystem;
private Image _icon;
private Label _title;
private Button _closeButton;
private Button _minimizeButton;
private Button _maximizeButton;
private LocalizedString _charChromeRestore, _charChromeMaximize;
private Window _window;
#endif
private MainMenuButton _selected; private MainMenuButton _selected;
/// <summary> /// <summary>
@@ -60,200 +50,12 @@ namespace FlaxEditor.GUI
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MainMenu"/> class. /// Initializes a new instance of the <see cref="MainMenu"/> class.
/// </summary> /// </summary>
/// <param name="mainWindow">The main window.</param> public MainMenu()
public MainMenu(RootControl mainWindow)
: base(0, 0, 0, 20) : base(0, 0, 0, 20)
{ {
AutoFocus = false; AutoFocus = false;
AnchorPreset = AnchorPresets.HorizontalStretchTop; AnchorPreset = AnchorPresets.HorizontalStretchTop;
BackgroundColor = Style.Current.LightBackground;
#if PLATFORM_WINDOWS
_useCustomWindowSystem = !Editor.Instance.Options.Options.Interface.UseNativeWindowSystem;
if (_useCustomWindowSystem)
{
BackgroundColor = Style.Current.LightBackground;
Height = 28;
var windowIcon = FlaxEngine.Content.LoadAsyncInternal<Texture>(EditorAssets.WindowIcon);
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.WindowIconsFont);
Font iconFont = windowIconsFont?.CreateFont(9);
_window = mainWindow.RootWindow.Window;
_window.HitTest += OnHitTest;
_window.Closed += OnWindowClosed;
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
_icon = new Image
{
Margin = new Margin(6, 6, 6, 6),
Brush = new TextureBrush(windowIcon),
Color = Style.Current.Foreground,
KeepAspectRatio = false,
TooltipText = string.Format("{0}\nVersion {1}\nConfiguration {3}\nGraphics {2}", _window.Title, Globals.EngineVersion, GPUDevice.Instance.RendererType, configuration),
Parent = this,
};
_title = new Label(0, 0, Width, Height)
{
Text = _window.Title,
HorizontalAlignment = TextAlignment.Center,
VerticalAlignment = TextAlignment.Center,
ClipText = true,
TextColor = Style.Current.ForegroundGrey,
TextColorHighlighted = Style.Current.ForegroundGrey,
Parent = this,
};
_closeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Color.Red,
BackgroundColorSelected = Color.Red.RGBMultiplied(1.3f),
Parent = this,
};
_closeButton.Clicked += () => _window.Close(ClosingReason.User);
_minimizeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
Parent = this,
};
_minimizeButton.Clicked += () => _window.Minimize();
_maximizeButton = new Button
{
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
BorderColorSelected = Color.Transparent,
TextColor = Style.Current.Foreground,
Width = 46,
BackgroundColorHighlighted = Style.Current.LightBackground.RGBMultiplied(1.3f),
Parent = this,
};
_maximizeButton.Clicked += () =>
{
if (_window.IsMaximized)
_window.Restore();
else
_window.Maximize();
};
_charChromeRestore = ((char)EditorAssets.SegMDL2Icons.ChromeRestore).ToString();
_charChromeMaximize = ((char)EditorAssets.SegMDL2Icons.ChromeMaximize).ToString();
}
else
#endif
{
BackgroundColor = Style.Current.LightBackground;
}
}
#if PLATFORM_WINDOWS
/// <inheritdoc />
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (_maximizeButton != null)
{
_maximizeButton.Text = _window.IsMaximized ? _charChromeRestore : _charChromeMaximize;
}
}
private void OnWindowClosed()
{
if (_window != null)
{
_window.HitTest = null;
_window = null;
}
}
private WindowHitCodes OnHitTest(ref Float2 mouse)
{
var dpiScale = _window.DpiScale;
if (_window.IsMinimized)
return WindowHitCodes.NoWhere;
if (!_window.IsMaximized)
{
var pos = _window.ScreenToClient(mouse * dpiScale); // pos is not DPI adjusted
var winSize = _window.Size;
// Distance from which the mouse is considered to be on the border/corner
float distance = 5.0f * dpiScale;
if (pos.Y > winSize.Y - distance && pos.X < distance)
return WindowHitCodes.BottomLeft;
if (pos.X > winSize.X - distance && pos.Y > winSize.Y - distance)
return WindowHitCodes.BottomRight;
if (pos.Y < distance && pos.X < distance)
return WindowHitCodes.TopLeft;
if (pos.Y < distance && pos.X > winSize.X - distance)
return WindowHitCodes.TopRight;
if (pos.X > winSize.X - distance)
return WindowHitCodes.Right;
if (pos.X < distance)
return WindowHitCodes.Left;
if (pos.Y < distance)
return WindowHitCodes.Top;
if (pos.Y > winSize.Y - distance)
return WindowHitCodes.Bottom;
}
var mousePos = PointFromScreen(mouse * dpiScale);
var controlUnderMouse = GetChildAt(mousePos);
var isMouseOverSth = controlUnderMouse != null && controlUnderMouse != _title;
var rb = GetRightButton();
if (rb != null && _minimizeButton != null && new Rectangle(rb.UpperRight, _minimizeButton.BottomLeft - rb.UpperRight).Contains(ref mousePos) && !isMouseOverSth)
return WindowHitCodes.Caption;
return WindowHitCodes.Client;
}
#endif
/// <summary>
/// Return the rightmost button.
/// </summary>
/// <returns>Rightmost button, null if there is no <see cref="MainMenuButton"/></returns>
private MainMenuButton GetRightButton()
{
MainMenuButton b = null;
foreach (var control in Children)
{
if (b == null && control is MainMenuButton)
b = (MainMenuButton)control;
if (control is MainMenuButton && control.Right > b.Right)
b = (MainMenuButton)control;
}
return b;
} }
/// <summary> /// <summary>
@@ -298,26 +100,6 @@ namespace FlaxEditor.GUI
return result; return result;
} }
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (base.OnMouseDoubleClick(location, button))
return true;
#if PLATFORM_WINDOWS
var child = GetChildAtRecursive(location);
if (_useCustomWindowSystem && child is not Button && child is not MainMenuButton)
{
if (_window.IsMaximized)
_window.Restore();
else
_window.Maximize();
}
#endif
return true;
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key) public override bool OnKeyDown(KeyboardKeys key)
{ {
@@ -333,16 +115,8 @@ namespace FlaxEditor.GUI
protected override void PerformLayoutAfterChildren() protected override void PerformLayoutAfterChildren()
{ {
float x = 0; float x = 0;
WindowDecorations decorations = Parent.GetChild<WindowDecorations>();
#if PLATFORM_WINDOWS x += decorations?.Icon?.Width ?? 0;
if (_useCustomWindowSystem)
{
// Icon
_icon.X = x;
_icon.Size = new Float2(Height);
x += _icon.Width;
}
#endif
// Arrange controls // Arrange controls
MainMenuButton rightMostButton = null; MainMenuButton rightMostButton = null;
@@ -361,37 +135,21 @@ namespace FlaxEditor.GUI
x += b.Width; x += b.Width;
} }
} }
#if PLATFORM_WINDOWS // Fill the right side if title and buttons are not present
if (_useCustomWindowSystem) if (decorations?.Title == null)
{ Width = Parent.Width;
// Buttons else
_closeButton.Height = Height; Width = x;
_closeButton.X = Width - _closeButton.Width;
_maximizeButton.Height = Height;
_maximizeButton.X = _closeButton.X - _maximizeButton.Width;
_minimizeButton.Height = Height;
_minimizeButton.X = _maximizeButton.X - _minimizeButton.Width;
// Title
_title.Bounds = new Rectangle(x + 2, 0, _minimizeButton.Left - x - 4, Height);
//_title.Text = _title.Width < 300.0f ? Editor.Instance.ProjectInfo.Name : _window.Title;
}
#endif
} }
#if PLATFORM_WINDOWS
/// <inheritdoc /> /// <inheritdoc />
public override void OnDestroy() public override void OnDestroy()
{ {
base.OnDestroy(); base.OnDestroy();
if (_window != null) if (_selected != null)
{ Selected = null;
_window.Closed -= OnWindowClosed;
OnWindowClosed();
}
} }
#endif
} }
} }

View File

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

View File

@@ -144,7 +144,7 @@ namespace FlaxEditor.GUI.Timeline
var k = keyframes[i]; var k = keyframes[i];
var sphere = new BoundingSphere(k.Value, KeyframeSize); var sphere = new BoundingSphere(k.Value, KeyframeSize);
if (sphere.Intersects(ref selectRay)) if (sphere.Intersects(selectRay))
{ {
SelectKeyframe(_track, i, 0); SelectKeyframe(_track, i, 0);
return; return;
@@ -154,7 +154,7 @@ namespace FlaxEditor.GUI.Timeline
{ {
var t = k.Value + k.TangentIn; var t = k.Value + k.TangentIn;
var box = BoundingBox.FromSphere(new BoundingSphere(t, TangentSize)); var box = BoundingBox.FromSphere(new BoundingSphere(t, TangentSize));
if (box.Intersects(ref selectRay)) if (box.Intersects(selectRay))
{ {
SelectKeyframe(_track, i, 1); SelectKeyframe(_track, i, 1);
return; return;
@@ -165,7 +165,7 @@ namespace FlaxEditor.GUI.Timeline
{ {
var t = k.Value + k.TangentOut; var t = k.Value + k.TangentOut;
var box = BoundingBox.FromSphere(new BoundingSphere(t, TangentSize)); var box = BoundingBox.FromSphere(new BoundingSphere(t, TangentSize));
if (box.Intersects(ref selectRay)) if (box.Intersects(selectRay))
{ {
SelectKeyframe(_track, i, 2); SelectKeyframe(_track, i, 2);
return; return;

View File

@@ -115,7 +115,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
/// <inheritdoc /> /// <inheritdoc />
public override void OnMouseMove(Float2 location) public override void OnMouseMove(Float2 location)
{ {
if (_isMoving && Float2.DistanceSquared(ref location, ref _startMovePos) > 25.0f) if (_isMoving && Float2.DistanceSquared(location, _startMovePos) > 25.0f)
{ {
_startMovePos = Float2.Minimum; _startMovePos = Float2.Minimum;
var x = PointToParent(location).X; var x = PointToParent(location).X;
@@ -387,7 +387,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
{ {
// Push clipping mask // Push clipping mask
GetDesireClientArea(out var clientArea); GetDesireClientArea(out var clientArea);
Render2D.PushClip(ref clientArea); Render2D.PushClip(clientArea);
var style = Style.Current; var style = Style.Current;
var bounds = new Rectangle(Float2.Zero, Size); var bounds = new Rectangle(Float2.Zero, Size);

View File

@@ -115,7 +115,7 @@ namespace FlaxEditor.GUI
{ {
if (Children[i] is KeyframePoint p) if (Children[i] is KeyframePoint p)
{ {
p.IsSelected = p.Bounds.Intersects(ref selectionRect); p.IsSelected = p.Bounds.Intersects(selectionRect);
} }
} }
} }
@@ -401,7 +401,7 @@ namespace FlaxEditor.GUI
Cursor = CursorType.Default; Cursor = CursorType.Default;
// Check if no move has been made at all // Check if no move has been made at all
if (Float2.Distance(ref location, ref _rightMouseDownPos) < 2.0f) if (Float2.Distance(location, _rightMouseDownPos) < 2.0f)
{ {
var selectionCount = _editor.SelectionCount; var selectionCount = _editor.SelectionCount;
var point = GetChildAt(location) as KeyframePoint; var point = GetChildAt(location) as KeyframePoint;

View File

@@ -50,14 +50,14 @@ namespace FlaxEditor.GUI.Timeline.GUI
var color = (_timeline.IsMovingPositionHandle ? style.SelectionBorder : style.Foreground).AlphaMultiplied(0.6f); var color = (_timeline.IsMovingPositionHandle ? style.SelectionBorder : style.Foreground).AlphaMultiplied(0.6f);
Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1); Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1);
var m2 = Matrix3x3.Translation2D(0, timeAxisHeaderOffset); var m2 = Matrix3x3.Translation2D(0, timeAxisHeaderOffset);
Matrix3x3.Multiply(ref m1, ref m2, out var m3); Matrix3x3.Multiply(m1, m2, out var m3);
Render2D.PushTransform(ref m3); Render2D.PushTransform(m3);
// TODO: Convert to its own sprite or 9 slice // TODO: Convert to its own sprite or 9 slice
Render2D.DrawSprite(icon, new Rectangle(new Float2(10, -icon.Size.X * 0.5f - 1), Size + new Float2(0, 1)), color); Render2D.DrawSprite(icon, new Rectangle(new Float2(10, -icon.Size.X * 0.5f - 1), Size + new Float2(0, 1)), color);
Render2D.FillRectangle(new Rectangle(new Float2(-6, -icon.Size.Y * 0.5f + 7), new Float2(timeAxisOverlap, 5)), color); Render2D.FillRectangle(new Rectangle(new Float2(-6, -icon.Size.Y * 0.5f + 7), new Float2(timeAxisOverlap, 5)), color);
Render2D.PopTransform(); Render2D.PopTransform();
var textMatrix = Matrix3x3.Translation2D(12, timeAxisHeaderOffset); var textMatrix = Matrix3x3.Translation2D(12, timeAxisHeaderOffset);
Render2D.PushTransform(ref textMatrix); Render2D.PushTransform(textMatrix);
Render2D.DrawText(style.FontSmall, labelText, style.Foreground, new Float2(2, -6)); Render2D.DrawText(style.FontSmall, labelText, style.Foreground, new Float2(2, -6));
Render2D.PopTransform(); Render2D.PopTransform();

View File

@@ -356,7 +356,7 @@ namespace FlaxEditor.GUI.Timeline
{ {
Render2D.DrawLine(bounds.UpperLeft, bounds.BottomLeft, moveColor, moveThickness); Render2D.DrawLine(bounds.UpperLeft, bounds.BottomLeft, moveColor, moveThickness);
} }
else if (IsMouseOver && CanResize && MoveLeftEdgeRect.Contains(ref _mouseLocation)) else if (IsMouseOver && CanResize && MoveLeftEdgeRect.Contains(_mouseLocation))
{ {
Render2D.DrawLine(bounds.UpperLeft, bounds.BottomLeft, Color.Yellow); Render2D.DrawLine(bounds.UpperLeft, bounds.BottomLeft, Color.Yellow);
} }
@@ -364,7 +364,7 @@ namespace FlaxEditor.GUI.Timeline
{ {
Render2D.DrawLine(bounds.UpperRight, bounds.BottomRight, moveColor, moveThickness); Render2D.DrawLine(bounds.UpperRight, bounds.BottomRight, moveColor, moveThickness);
} }
else if (IsMouseOver && CanResize && MoveRightEdgeRect.Contains(ref _mouseLocation)) else if (IsMouseOver && CanResize && MoveRightEdgeRect.Contains(_mouseLocation))
{ {
Render2D.DrawLine(bounds.UpperRight, bounds.BottomRight, Color.Yellow); Render2D.DrawLine(bounds.UpperRight, bounds.BottomRight, Color.Yellow);
} }
@@ -384,8 +384,8 @@ namespace FlaxEditor.GUI.Timeline
_startMoveLocation = Root.MousePosition; _startMoveLocation = Root.MousePosition;
_startMoveStartFrame = StartFrame; _startMoveStartFrame = StartFrame;
_startMoveDuration = DurationFrames; _startMoveDuration = DurationFrames;
_startMoveLeftEdge = MoveLeftEdgeRect.Contains(ref location) && CanResize; _startMoveLeftEdge = MoveLeftEdgeRect.Contains(location) && CanResize;
_startMoveRightEdge = MoveRightEdgeRect.Contains(ref location) && CanResize; _startMoveRightEdge = MoveRightEdgeRect.Contains(location) && CanResize;
StartMouseCapture(true); StartMouseCapture(true);
if (_startMoveLeftEdge || _startMoveRightEdge) if (_startMoveLeftEdge || _startMoveRightEdge)
return true; return true;

View File

@@ -337,7 +337,7 @@ namespace FlaxEditor.GUI.Timeline
DebugDraw.DrawSphere(sphere, selected ? Color.Yellow : Color.Red); DebugDraw.DrawSphere(sphere, selected ? Color.Yellow : Color.Red);
sphere.Radius *= 0.95f; sphere.Radius *= 0.95f;
DebugDraw.DrawSphere(sphere, new Color(1, 0, 0, coveredAlpha), 0, false); DebugDraw.DrawSphere(sphere, new Color(1, 0, 0, coveredAlpha), 0, false);
if (select && sphere.Intersects(ref selectRay)) if (select && sphere.Intersects(selectRay))
SelectKeyframeGizmo(curveTrack, i, 0); SelectKeyframeGizmo(curveTrack, i, 0);
if (!k.TangentIn.IsZero) if (!k.TangentIn.IsZero)
@@ -349,7 +349,7 @@ namespace FlaxEditor.GUI.Timeline
var box = BoundingBox.FromSphere(new BoundingSphere(t, EditCurveTrackGizmo.TangentSize)); var box = BoundingBox.FromSphere(new BoundingSphere(t, EditCurveTrackGizmo.TangentSize));
DebugDraw.DrawBox(box, selected ? Color.Yellow : Color.AliceBlue); DebugDraw.DrawBox(box, selected ? Color.Yellow : Color.AliceBlue);
DebugDraw.DrawBox(box, Color.AliceBlue.AlphaMultiplied(coveredAlpha), 0, false); DebugDraw.DrawBox(box, Color.AliceBlue.AlphaMultiplied(coveredAlpha), 0, false);
if (select && box.Intersects(ref selectRay)) if (select && box.Intersects(selectRay))
SelectKeyframeGizmo(curveTrack, i, 2); SelectKeyframeGizmo(curveTrack, i, 2);
} }
@@ -362,7 +362,7 @@ namespace FlaxEditor.GUI.Timeline
var box = BoundingBox.FromSphere(new BoundingSphere(t, EditCurveTrackGizmo.TangentSize)); var box = BoundingBox.FromSphere(new BoundingSphere(t, EditCurveTrackGizmo.TangentSize));
DebugDraw.DrawBox(box, selected ? Color.Yellow : Color.AliceBlue); DebugDraw.DrawBox(box, selected ? Color.Yellow : Color.AliceBlue);
DebugDraw.DrawBox(box, Color.AliceBlue.AlphaMultiplied(coveredAlpha), 0, false); DebugDraw.DrawBox(box, Color.AliceBlue.AlphaMultiplied(coveredAlpha), 0, false);
if (select && box.Intersects(ref selectRay)) if (select && box.Intersects(selectRay))
SelectKeyframeGizmo(curveTrack, i, 2); SelectKeyframeGizmo(curveTrack, i, 2);
} }

View File

@@ -2078,7 +2078,7 @@ namespace FlaxEditor.GUI.Timeline
if (button == MouseButton.Right && _isRightMouseButtonDown) if (button == MouseButton.Right && _isRightMouseButtonDown)
{ {
_isRightMouseButtonDown = false; _isRightMouseButtonDown = false;
if (Float2.Distance(ref location, ref _rightMouseButtonDownPos) < 4.0f) if (Float2.Distance(location, _rightMouseButtonDownPos) < 4.0f)
ShowContextMenu(location); ShowContextMenu(location);
} }
@@ -2243,7 +2243,7 @@ namespace FlaxEditor.GUI.Timeline
foreach (var media in _tracks[i].Media) foreach (var media in _tracks[i].Media)
{ {
if (media.Bounds.Intersects(ref mediaRect)) if (media.Bounds.Intersects(mediaRect))
{ {
SelectedMedia.Add(media); SelectedMedia.Add(media);
selectionChanged = true; selectionChanged = true;

View File

@@ -810,7 +810,7 @@ namespace FlaxEditor.GUI.Timeline
/// <returns>True if hits it.</returns> /// <returns>True if hits it.</returns>
protected virtual bool TestHeaderHit(ref Float2 location) protected virtual bool TestHeaderHit(ref Float2 location)
{ {
return new Rectangle(0, 0, Width, HeaderHeight).Contains(ref location); return new Rectangle(0, 0, Width, HeaderHeight).Contains(location);
} }
/// <summary> /// <summary>

View File

@@ -208,7 +208,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
// Hit-test dot // Hit-test dot
var size = Height - 2.0f; var size = Height - 2.0f;
var rect = new Rectangle(new Float2(size * -0.5f) + Size * 0.5f, new Float2(size)); var rect = new Rectangle(new Float2(size * -0.5f) + Size * 0.5f, new Float2(size));
return rect.Contains(ref location); return rect.Contains(location);
} }
return base.ContainsPoint(ref location, precise); return base.ContainsPoint(ref location, precise);

View File

@@ -527,7 +527,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
{ {
_output = GPUDevice.Instance.CreateTexture("CameraCutMedia.Output"); _output = GPUDevice.Instance.CreateTexture("CameraCutMedia.Output");
var desc = GPUTextureDescription.New2D(Width, Height, PixelFormat.R8G8B8A8_UNorm); var desc = GPUTextureDescription.New2D(Width, Height, PixelFormat.R8G8B8A8_UNorm);
_output.Init(ref desc); _output.Init(desc);
} }
if (_task == null) if (_task == null)
{ {

View File

@@ -258,7 +258,7 @@ namespace FlaxEditor.GUI.Tree
} }
var nodeArea = new Rectangle(pos, child.Size); var nodeArea = new Rectangle(pos, child.Size);
if (child.IsExpanded && range.Intersects(ref nodeArea)) if (child.IsExpanded && range.Intersects(nodeArea))
WalkSelectRangeExpandedTree(selection, child, ref range); WalkSelectRangeExpandedTree(selection, child, ref range);
} }
} }

View File

@@ -555,7 +555,7 @@ namespace FlaxEditor.GUI.Tree
/// <returns>True if hits it.</returns> /// <returns>True if hits it.</returns>
protected virtual bool TestHeaderHit(ref Float2 location) protected virtual bool TestHeaderHit(ref Float2 location)
{ {
return _headerRect.Contains(ref location); return _headerRect.Contains(location);
} }
/// <summary> /// <summary>
@@ -864,14 +864,14 @@ namespace FlaxEditor.GUI.Tree
var child = children[i]; var child = children[i];
if (!child.Visible) if (!child.Visible)
continue; continue;
Render2D.PushTransform(ref child._cachedTransform); Render2D.PushTransform(child._cachedTransform);
child.Draw(); child.Draw();
Render2D.PopTransform(); Render2D.PopTransform();
} }
static Rectangle GetChildGlobalRectangle(Control control, ref Matrix3x3 globalTransform) static Rectangle GetChildGlobalRectangle(Control control, ref Matrix3x3 globalTransform)
{ {
Matrix3x3.Multiply(ref control._cachedTransform, ref globalTransform, out var globalChildTransform); Matrix3x3.Multiply(control._cachedTransform, globalTransform, out var globalChildTransform);
return new Rectangle(globalChildTransform.M31, globalChildTransform.M32, control.Width * globalChildTransform.M11, control.Height * globalChildTransform.M22); return new Rectangle(globalChildTransform.M31, globalChildTransform.M32, control.Width * globalChildTransform.M11, control.Height * globalChildTransform.M22);
} }
} }
@@ -882,7 +882,7 @@ namespace FlaxEditor.GUI.Tree
var child = children[i]; var child = children[i];
if (child.Visible) if (child.Visible)
{ {
Render2D.PushTransform(ref child._cachedTransform); Render2D.PushTransform(child._cachedTransform);
child.Draw(); child.Draw();
Render2D.PopTransform(); Render2D.PopTransform();
} }

View File

@@ -24,7 +24,7 @@ namespace FlaxEditor.GUI.Tree
foreach (var child in Addons) foreach (var child in Addons)
{ {
Render2D.PushTransform(ref child._cachedTransform); Render2D.PushTransform(child._cachedTransform);
child.Draw(); child.Draw();
Render2D.PopTransform(); Render2D.PopTransform();
} }

View File

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

View File

@@ -56,9 +56,9 @@ namespace FlaxEditor.Gizmo
var width = output.Width; var width = output.Width;
var height = output.Height; var height = output.Height;
var desc = GPUTextureDescription.New2D(width, height, format, GPUTextureFlags.RenderTarget | GPUTextureFlags.ShaderResource, 1, 1, msaaLevel); var desc = GPUTextureDescription.New2D(width, height, format, GPUTextureFlags.RenderTarget | GPUTextureFlags.ShaderResource, 1, 1, msaaLevel);
var target = RenderTargetPool.Get(ref desc); var target = RenderTargetPool.Get(desc);
desc = GPUTextureDescription.New2D(width, height, PixelFormat.D24_UNorm_S8_UInt, GPUTextureFlags.DepthStencil, 1, 1, msaaLevel); desc = GPUTextureDescription.New2D(width, height, PixelFormat.D24_UNorm_S8_UInt, GPUTextureFlags.DepthStencil, 1, 1, msaaLevel);
var targetDepth = RenderTargetPool.Get(ref desc); var targetDepth = RenderTargetPool.Get(desc);
// Copy frame and clear depth // Copy frame and clear depth
context.Draw(target, input); context.Draw(target, input);
@@ -81,16 +81,16 @@ namespace FlaxEditor.Gizmo
} }
// Sort draw calls // Sort draw calls
renderList.SortDrawCalls(ref renderContext, false, DrawCallsListType.GBuffer); renderList.SortDrawCalls(renderContext, false, DrawCallsListType.GBuffer);
renderList.SortDrawCalls(ref renderContext, false, DrawCallsListType.GBufferNoDecals); renderList.SortDrawCalls(renderContext, false, DrawCallsListType.GBufferNoDecals);
renderList.SortDrawCalls(ref renderContext, true, DrawCallsListType.Forward); renderList.SortDrawCalls(renderContext, true, DrawCallsListType.Forward);
// Perform the rendering // Perform the rendering
renderContext.View.Pass = DrawPass.GBuffer; renderContext.View.Pass = DrawPass.GBuffer;
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.GBuffer); renderList.ExecuteDrawCalls(renderContext, DrawCallsListType.GBuffer);
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.GBufferNoDecals); renderList.ExecuteDrawCalls(renderContext, DrawCallsListType.GBufferNoDecals);
renderContext.View.Pass = DrawPass.Forward; renderContext.View.Pass = DrawPass.Forward;
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.Forward); renderList.ExecuteDrawCalls(renderContext, DrawCallsListType.Forward);
// Resolve MSAA texture // Resolve MSAA texture
if (enableMsaa) if (enableMsaa)

View File

@@ -70,7 +70,7 @@ namespace FlaxEditor.Gizmo
_vertexBuffer = new GPUBuffer(); _vertexBuffer = new GPUBuffer();
var layout = GPUVertexLayout.Get([new VertexElement(VertexElement.Types.Position, 0, 0, false, PixelFormat.R32G32B32_Float)]); var layout = GPUVertexLayout.Get([new VertexElement(VertexElement.Types.Position, 0, 0, false, PixelFormat.R32G32B32_Float)]);
var desc = GPUBufferDescription.Vertex(layout, sizeof(Float3), 4); var desc = GPUBufferDescription.Vertex(layout, sizeof(Float3), 4);
_vertexBuffer.Init(ref desc); _vertexBuffer.Init(desc);
} }
if (_indexBuffer == null) if (_indexBuffer == null)
{ {
@@ -78,7 +78,7 @@ namespace FlaxEditor.Gizmo
fixed (uint* ptr = _triangles) fixed (uint* ptr = _triangles)
{ {
var desc = GPUBufferDescription.Index(sizeof(uint), _triangles.Length, new IntPtr(ptr)); var desc = GPUBufferDescription.Index(sizeof(uint), _triangles.Length, new IntPtr(ptr));
_indexBuffer.Init(ref desc); _indexBuffer.Init(desc);
} }
} }
if (_psGrid == null) if (_psGrid == null)
@@ -90,7 +90,7 @@ namespace FlaxEditor.Gizmo
desc.VS = _shader.GPU.GetVS("VS_Grid"); desc.VS = _shader.GPU.GetVS("VS_Grid");
desc.PS = _shader.GPU.GetPS("PS_Grid"); desc.PS = _shader.GPU.GetPS("PS_Grid");
desc.DepthWriteEnable = false; desc.DepthWriteEnable = false;
_psGrid.Init(ref desc); _psGrid.Init(desc);
} }
// Update vertices of the plane // Update vertices of the plane
@@ -113,8 +113,8 @@ namespace FlaxEditor.Gizmo
if (cb != IntPtr.Zero) if (cb != IntPtr.Zero)
{ {
var data = new Data(); var data = new Data();
Matrix.Multiply(ref renderContext.View.View, ref renderContext.View.Projection, out var viewProjection); Matrix.Multiply(renderContext.View.View, renderContext.View.Projection, out var viewProjection);
Matrix.Transpose(ref viewProjection, out data.ViewProjectionMatrix); Matrix.Transpose(viewProjection, out data.ViewProjectionMatrix);
data.ViewPos = renderContext.View.WorldPosition; data.ViewPos = renderContext.View.WorldPosition;
data.GridColor = options.Viewport.ViewportGridColor; data.GridColor = options.Viewport.ViewportGridColor;
data.Far = renderContext.View.Far; data.Far = renderContext.View.Far;

View File

@@ -128,7 +128,7 @@ namespace FlaxEditor.Gizmo
// Pick a temporary depth buffer // Pick a temporary depth buffer
var desc = GPUTextureDescription.New2D(input.Width, input.Height, PixelFormat.D32_Float, GPUTextureFlags.DepthStencil | GPUTextureFlags.ShaderResource); var desc = GPUTextureDescription.New2D(input.Width, input.Height, PixelFormat.D32_Float, GPUTextureFlags.DepthStencil | GPUTextureFlags.ShaderResource);
var customDepth = RenderTargetPool.Get(ref desc); var customDepth = RenderTargetPool.Get(desc);
context.ClearDepth(customDepth.View()); context.ClearDepth(customDepth.View());
// Draw objects to depth buffer // Draw objects to depth buffer
@@ -148,7 +148,7 @@ namespace FlaxEditor.Gizmo
_material.SetParameterValue("OutlineColor1", _color1); _material.SetParameterValue("OutlineColor1", _color1);
_material.SetParameterValue("CustomDepth", customDepth); _material.SetParameterValue("CustomDepth", customDepth);
_material.SetParameterValue("ViewInfo", new Float4(1.0f / projection.M11, 1.0f / projection.M22, far / (far - near), (-far * near) / (far - near) / far)); _material.SetParameterValue("ViewInfo", new Float4(1.0f / projection.M11, 1.0f / projection.M22, far / (far - near), (-far * near) / (far - near) / far));
Renderer.DrawPostFxMaterial(context, ref renderContext, _material, output, input.View()); Renderer.DrawPostFxMaterial(context, renderContext, _material, output, input.View());
// Cleanup // Cleanup
RenderTargetPool.Release(customDepth); RenderTargetPool.Release(customDepth);

View File

@@ -129,7 +129,7 @@ namespace FlaxEditor.Gizmo
if (_selectionParents[i] is ActorNode actorNode) if (_selectionParents[i] is ActorNode actorNode)
{ {
var b = actorNode.Actor.EditorBoxChildren; var b = actorNode.Actor.EditorBoxChildren;
BoundingBox.Merge(ref editorBounds, ref b, out editorBounds); BoundingBox.Merge(editorBounds, b, out editorBounds);
bottomToCenter = Mathf.Min(bottomToCenter, actorNode.Actor.Position.Y - editorBounds.Minimum.Y); bottomToCenter = Mathf.Min(bottomToCenter, actorNode.Actor.Position.Y - editorBounds.Minimum.Y);
} }
} }

View File

@@ -135,7 +135,7 @@ namespace FlaxEditor.Gizmo
Mesh sphereMesh = _modelSphere.LODs[0].Meshes[0]; Mesh sphereMesh = _modelSphere.LODs[0].Meshes[0];
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
Matrix.Multiply(ref m3, ref world, out m1); Matrix.Multiply(m3, world, out m1);
mx1 = m1; mx1 = m1;
mx1.M41 += 0.05f; mx1.M41 += 0.05f;
@@ -149,44 +149,44 @@ namespace FlaxEditor.Gizmo
// X axis // X axis
Matrix.RotationY(-Mathf.PiOverTwo, out m2); Matrix.RotationY(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance xAxisMaterialTransform = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; MaterialInstance xAxisMaterialTransform = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX;
transAxisMesh.Draw(ref renderContext, xAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); transAxisMesh.Draw(renderContext, xAxisMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Y axis // Y axis
Matrix.RotationX(Mathf.PiOverTwo, out m2); Matrix.RotationX(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance yAxisMaterialTransform = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; MaterialInstance yAxisMaterialTransform = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY;
transAxisMesh.Draw(ref renderContext, yAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); transAxisMesh.Draw(renderContext, yAxisMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Z axis // Z axis
Matrix.RotationX(Mathf.Pi, out m2); Matrix.RotationX(Mathf.Pi, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance zAxisMaterialTransform = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; MaterialInstance zAxisMaterialTransform = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ;
transAxisMesh.Draw(ref renderContext, zAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); transAxisMesh.Draw(renderContext, zAxisMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// XY plane // XY plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance xyPlaneMaterialTransform = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX; MaterialInstance xyPlaneMaterialTransform = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX;
cubeMesh.Draw(ref renderContext, xyPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, xyPlaneMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// ZX plane // ZX plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance zxPlaneMaterialTransform = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisY; MaterialInstance zxPlaneMaterialTransform = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisY;
cubeMesh.Draw(ref renderContext, zxPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, zxPlaneMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// YZ plane // YZ plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance yzPlaneMaterialTransform = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; MaterialInstance yzPlaneMaterialTransform = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisZ;
cubeMesh.Draw(ref renderContext, yzPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, yzPlaneMaterialTransform, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Center sphere // Center sphere
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2); Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); sphereMesh.Draw(renderContext, isCenter ? _materialAxisFocus : _materialSphere, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
break; break;
} }
@@ -199,24 +199,24 @@ namespace FlaxEditor.Gizmo
// X axis // X axis
Matrix.RotationZ(Mathf.PiOverTwo, out m2); Matrix.RotationZ(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX;
rotationAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); rotationAxisMesh.Draw(renderContext, xAxisMaterialRotate, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Y axis // Y axis
MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY;
rotationAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m1, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); rotationAxisMesh.Draw(renderContext, yAxisMaterialRotate, m1, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Z axis // Z axis
Matrix.RotationX(-Mathf.PiOverTwo, out m2); Matrix.RotationX(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ;
rotationAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); rotationAxisMesh.Draw(renderContext, zAxisMaterialRotate, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Center box // Center box
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2); Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); sphereMesh.Draw(renderContext, isCenter ? _materialAxisFocus : _materialSphere, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
break; break;
} }
@@ -229,44 +229,44 @@ namespace FlaxEditor.Gizmo
// X axis // X axis
Matrix.RotationY(-Mathf.PiOverTwo, out m2); Matrix.RotationY(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref mx1, out m3); Matrix.Multiply(m2, mx1, out m3);
MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX; MaterialInstance xAxisMaterialRotate = (isXAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisX;
scaleAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); scaleAxisMesh.Draw(renderContext, xAxisMaterialRotate, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Y axis // Y axis
Matrix.RotationX(Mathf.PiOverTwo, out m2); Matrix.RotationX(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY; MaterialInstance yAxisMaterialRotate = (isYAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisY;
scaleAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); scaleAxisMesh.Draw(renderContext, yAxisMaterialRotate, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Z axis // Z axis
Matrix.RotationX(Mathf.Pi, out m2); Matrix.RotationX(Mathf.Pi, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; MaterialInstance zAxisMaterialRotate = (isZAxis && !_isDisabled) ? _materialAxisFocus : _materialAxisZ;
scaleAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); scaleAxisMesh.Draw(renderContext, zAxisMaterialRotate, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// XY plane // XY plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance xyPlaneMaterialScale = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX; MaterialInstance xyPlaneMaterialScale = (_activeAxis == Axis.XY && !_isDisabled) ? _materialAxisFocus : _materialAxisX;
cubeMesh.Draw(ref renderContext, xyPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, xyPlaneMaterialScale, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// ZX plane // ZX plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance zxPlaneMaterialScale = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisZ; MaterialInstance zxPlaneMaterialScale = (_activeAxis == Axis.ZX && !_isDisabled) ? _materialAxisFocus : _materialAxisZ;
cubeMesh.Draw(ref renderContext, zxPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, zxPlaneMaterialScale, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// YZ plane // YZ plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale)); m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
MaterialInstance yzPlaneMaterialScale = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisY; MaterialInstance yzPlaneMaterialScale = (_activeAxis == Axis.YZ && !_isDisabled) ? _materialAxisFocus : _materialAxisY;
cubeMesh.Draw(ref renderContext, yzPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, yzPlaneMaterialScale, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
// Center box // Center box
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2); Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3); Matrix.Multiply(m2, m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); sphereMesh.Draw(renderContext, isCenter ? _materialAxisFocus : _materialSphere, m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
break; break;
} }
@@ -278,7 +278,7 @@ namespace FlaxEditor.Gizmo
Transform t = _vertexSnapObject?.Transform ?? _vertexSnapObjectTo.Transform; Transform t = _vertexSnapObject?.Transform ?? _vertexSnapObjectTo.Transform;
Vector3 p = t.LocalToWorld(_vertexSnapObject != null ? _vertexSnapPoint : _vertexSnapPointTo); Vector3 p = t.LocalToWorld(_vertexSnapObject != null ? _vertexSnapPoint : _vertexSnapPointTo);
Matrix matrix = new Transform(p, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld(); Matrix matrix = new Transform(p, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder); cubeMesh.Draw(renderContext, _materialSphere, matrix, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
} }
} }
} }

View File

@@ -36,7 +36,7 @@ namespace FlaxEditor.Gizmo
private bool IntersectsRotateCircle(Vector3 normal, ref Ray ray, out Real distance) private bool IntersectsRotateCircle(Vector3 normal, ref Ray ray, out Real distance)
{ {
var plane = new Plane(Vector3.Zero, normal); var plane = new Plane(Vector3.Zero, normal);
if (!plane.Intersects(ref ray, out distance)) if (!plane.Intersects(ray, out distance))
return false; return false;
Vector3 hitPoint = ray.Position + ray.Direction * distance; Vector3 hitPoint = ray.Position + ray.Direction * distance;
Real distanceNormalized = hitPoint.Length / RotateRadiusRaw; Real distanceNormalized = hitPoint.Length / RotateRadiusRaw;
@@ -50,8 +50,8 @@ namespace FlaxEditor.Gizmo
// Transform ray into local space of the gizmo // Transform ray into local space of the gizmo
Ray localRay; Ray localRay;
_gizmoWorld.WorldToLocalVector(ref ray.Direction, out localRay.Direction); _gizmoWorld.WorldToLocalVector(ray.Direction, out localRay.Direction);
_gizmoWorld.WorldToLocal(ref ray.Position, out localRay.Position); _gizmoWorld.WorldToLocal(ray.Position, out localRay.Position);
// Find gizmo collisions with mouse // Find gizmo collisions with mouse
Real closestIntersection = Real.MaxValue; Real closestIntersection = Real.MaxValue;
@@ -62,19 +62,19 @@ namespace FlaxEditor.Gizmo
case Mode.Translate: case Mode.Translate:
{ {
// Axis boxes collision // Axis boxes collision
if (XAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (XAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.X; _activeAxis = Axis.X;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (YAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (YAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.Y; _activeAxis = Axis.Y;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (ZAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (ZAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.Z; _activeAxis = Axis.Z;
closestIntersection = intersection; closestIntersection = intersection;
@@ -83,25 +83,25 @@ namespace FlaxEditor.Gizmo
// Quad planes collision // Quad planes collision
if (closestIntersection >= float.MaxValue) if (closestIntersection >= float.MaxValue)
closestIntersection = float.MinValue; closestIntersection = float.MinValue;
if (XYBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (XYBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.XY; _activeAxis = Axis.XY;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (XZBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (XZBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.ZX; _activeAxis = Axis.ZX;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (YZBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (YZBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.YZ; _activeAxis = Axis.YZ;
closestIntersection = intersection; closestIntersection = intersection;
} }
/*// Center /*// Center
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (CenterBoxRaw.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.Center; _activeAxis = Axis.Center;
closestIntersection = intersection; closestIntersection = intersection;
@@ -133,17 +133,17 @@ namespace FlaxEditor.Gizmo
case Mode.Scale: case Mode.Scale:
{ {
// Boxes collision // Boxes collision
if (XAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (XAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.X; _activeAxis = Axis.X;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (YAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (YAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.Y; _activeAxis = Axis.Y;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (ZAxisBox.Intersects(ref localRay, out intersection) && intersection < closestIntersection) if (ZAxisBox.Intersects(localRay, out intersection) && intersection < closestIntersection)
{ {
_activeAxis = Axis.Z; _activeAxis = Axis.Z;
closestIntersection = intersection; closestIntersection = intersection;
@@ -153,24 +153,24 @@ namespace FlaxEditor.Gizmo
if (closestIntersection >= float.MaxValue) if (closestIntersection >= float.MaxValue)
closestIntersection = float.MinValue; closestIntersection = float.MinValue;
if (XYBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (XYBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.XY; _activeAxis = Axis.XY;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (XZBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (XZBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.ZX; _activeAxis = Axis.ZX;
closestIntersection = intersection; closestIntersection = intersection;
} }
if (YZBox.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (YZBox.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.YZ; _activeAxis = Axis.YZ;
closestIntersection = intersection; closestIntersection = intersection;
} }
// Center // Center
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection > closestIntersection) if (CenterBoxRaw.Intersects(localRay, out intersection) && intersection > closestIntersection)
{ {
_activeAxis = Axis.Center; _activeAxis = Axis.Center;
closestIntersection = intersection; closestIntersection = intersection;

View File

@@ -212,10 +212,10 @@ namespace FlaxEditor.Gizmo
Vector3 delta = Vector3.Zero; Vector3 delta = Vector3.Zero;
Ray ray = Owner.MouseRay; Ray ray = Owner.MouseRay;
Matrix.RotationQuaternion(ref _gizmoWorld.Orientation, out var rotationMatrix); Matrix.RotationQuaternion(_gizmoWorld.Orientation, out var rotationMatrix);
Matrix.Invert(ref rotationMatrix, out var invRotationMatrix); Matrix.Invert(rotationMatrix, out var invRotationMatrix);
ray.Position = Vector3.Transform(ray.Position, invRotationMatrix); ray.Position = Vector3.Transform(ray.Position, invRotationMatrix);
Vector3.TransformNormal(ref ray.Direction, ref invRotationMatrix, out ray.Direction); Vector3.TransformNormal(ray.Direction, invRotationMatrix, out ray.Direction);
var position = Position; var position = Position;
var planeXY = new Plane(Vector3.Backward, Vector3.Transform(position, invRotationMatrix).Z); var planeXY = new Plane(Vector3.Backward, Vector3.Transform(position, invRotationMatrix).Z);
@@ -232,7 +232,7 @@ namespace FlaxEditor.Gizmo
case Axis.X: case Axis.X:
{ {
var plane = planeDotXY > planeDotZX ? planeXY : planeZX; var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
if (ray.Intersects(ref plane, out intersection)) if (ray.Intersects(plane, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -244,7 +244,7 @@ namespace FlaxEditor.Gizmo
case Axis.Y: case Axis.Y:
{ {
var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ; var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
if (ray.Intersects(ref plane, out intersection)) if (ray.Intersects(plane, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -256,7 +256,7 @@ namespace FlaxEditor.Gizmo
case Axis.Z: case Axis.Z:
{ {
var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ; var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
if (ray.Intersects(ref plane, out intersection)) if (ray.Intersects(plane, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -267,7 +267,7 @@ namespace FlaxEditor.Gizmo
} }
case Axis.YZ: case Axis.YZ:
{ {
if (ray.Intersects(ref planeYZ, out intersection)) if (ray.Intersects(planeYZ, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -288,7 +288,7 @@ namespace FlaxEditor.Gizmo
} }
case Axis.XY: case Axis.XY:
{ {
if (ray.Intersects(ref planeXY, out intersection)) if (ray.Intersects(planeXY, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -309,7 +309,7 @@ namespace FlaxEditor.Gizmo
} }
case Axis.ZX: case Axis.ZX:
{ {
if (ray.Intersects(ref planeZX, out intersection)) if (ray.Intersects(planeZX, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -332,7 +332,7 @@ namespace FlaxEditor.Gizmo
{ {
var gizmoToView = Position - Owner.ViewPosition; var gizmoToView = Position - Owner.ViewPosition;
var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length); var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
if (ray.Intersects(ref plane, out intersection)) if (ray.Intersects(plane, out intersection))
{ {
_intersectPosition = ray.GetPoint(intersection); _intersectPosition = ray.GetPoint(intersection);
if (!_lastIntersectionPosition.IsZero) if (!_lastIntersectionPosition.IsZero)
@@ -473,11 +473,11 @@ namespace FlaxEditor.Gizmo
dir = Float3.Forward * _gizmoWorld.Orientation; dir = Float3.Forward * _gizmoWorld.Orientation;
Float3 viewDir = Owner.ViewPosition - Position; Float3 viewDir = Owner.ViewPosition - Position;
Float3.Dot(ref viewDir, ref dir, out float dot); Float3.Dot(viewDir, dir, out float dot);
if (dot < 0.0f) if (dot < 0.0f)
delta *= -1; delta *= -1;
Quaternion.RotationAxis(ref dir, delta, out _rotationDelta); Quaternion.RotationAxis(dir, delta, out _rotationDelta);
break; break;
} }

View File

@@ -240,7 +240,7 @@ namespace FlaxEditor
{ {
foreach (var widget in _widgets) foreach (var widget in _widgets)
{ {
if (widget.Bounds.Contains(ref location)) if (widget.Bounds.Contains(location))
{ {
// Initialize widget movement // Initialize widget movement
_activeWidget = widget; _activeWidget = widget;
@@ -326,7 +326,7 @@ namespace FlaxEditor
{ {
foreach (var widget in _widgets) foreach (var widget in _widgets)
{ {
if (widget.Bounds.Contains(ref location)) if (widget.Bounds.Contains(location))
{ {
Cursor = widget.Cursor; Cursor = widget.Cursor;
cursorChanged = true; cursorChanged = true;
@@ -499,7 +499,7 @@ namespace FlaxEditor
var min = Float2.Min(upperLeft, bottomRight); var min = Float2.Min(upperLeft, bottomRight);
var max = Float2.Max(upperLeft, bottomRight); var max = Float2.Max(upperLeft, bottomRight);
var pixelRange = (max - min) * ViewScale; var pixelRange = (max - min) * ViewScale;
Render2D.PushClip(ref viewRect); Render2D.PushClip(viewRect);
DrawAxis(Float2.UnitX, viewRect, min.X, max.X, pixelRange.X); DrawAxis(Float2.UnitX, viewRect, min.X, max.X, pixelRange.X);
DrawAxis(Float2.UnitY, viewRect, min.Y, max.Y, pixelRange.Y); DrawAxis(Float2.UnitY, viewRect, min.Y, max.Y, pixelRange.Y);
Render2D.PopClip(); Render2D.PopClip();
@@ -605,7 +605,7 @@ namespace FlaxEditor
if (!drawAnySelectedControl) if (!drawAnySelectedControl)
{ {
drawAnySelectedControl = true; drawAnySelectedControl = true;
Render2D.PushTransform(ref _cachedTransform); Render2D.PushTransform(_cachedTransform);
} }
var options = Editor.Instance.Options.Options.Visual; var options = Editor.Instance.Options.Options.Visual;
@@ -643,10 +643,10 @@ namespace FlaxEditor
DrawControlWidget(uiControl, ref ur, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, -1), CursorType.SizeNESW); DrawControlWidget(uiControl, ref ur, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, -1), CursorType.SizeNESW);
DrawControlWidget(uiControl, ref bl, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 1), CursorType.SizeNESW); DrawControlWidget(uiControl, ref bl, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 1), CursorType.SizeNESW);
DrawControlWidget(uiControl, ref br, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 1), CursorType.SizeNWSE); DrawControlWidget(uiControl, ref br, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 1), CursorType.SizeNWSE);
Float2.Lerp(ref ul, ref bl, 0.5f, out var el); Float2.Lerp(ul, bl, 0.5f, out var el);
Float2.Lerp(ref ur, ref br, 0.5f, out var er); Float2.Lerp(ur, br, 0.5f, out var er);
Float2.Lerp(ref ul, ref ur, 0.5f, out var eu); Float2.Lerp(ul, ur, 0.5f, out var eu);
Float2.Lerp(ref bl, ref br, 0.5f, out var eb); Float2.Lerp(bl, br, 0.5f, out var eb);
DrawControlWidget(uiControl, ref el, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 0), CursorType.SizeWE); DrawControlWidget(uiControl, ref el, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, 0), CursorType.SizeWE);
DrawControlWidget(uiControl, ref er, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 0), CursorType.SizeWE); DrawControlWidget(uiControl, ref er, ref mousePos, ref widgetHandleSize, viewScale, new Float2(1, 0), CursorType.SizeWE);
DrawControlWidget(uiControl, ref eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS); DrawControlWidget(uiControl, ref eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS);
@@ -749,7 +749,7 @@ namespace FlaxEditor
default: break; default: break;
} }
} }
if (rect.Contains(ref mousePos)) if (rect.Contains(mousePos))
{ {
Render2D.FillRectangle(rect, style.Foreground); Render2D.FillRectangle(rect, style.Foreground);
Render2D.DrawRectangle(rect, style.SelectionBorder); Render2D.DrawRectangle(rect, style.SelectionBorder);

View File

@@ -124,7 +124,7 @@ public sealed class ViewportRubberBandSelector
public void ProjectPoint(Vector3 worldSpaceLocation, out Float2 viewportSpaceLocation) public void ProjectPoint(Vector3 worldSpaceLocation, out Float2 viewportSpaceLocation)
{ {
worldSpaceLocation -= _origin; worldSpaceLocation -= _origin;
_viewport.Project(ref worldSpaceLocation, ref _viewProjection, out var projected); _viewport.Project(worldSpaceLocation, _viewProjection, out var projected);
viewportSpaceLocation = new Float2((float)projected.X, (float)projected.Y); viewportSpaceLocation = new Float2((float)projected.X, (float)projected.Y);
} }
@@ -132,7 +132,7 @@ public sealed class ViewportRubberBandSelector
{ {
bounds.Minimum -= _origin; bounds.Minimum -= _origin;
bounds.Maximum -= _origin; bounds.Maximum -= _origin;
return _frustum.Contains(ref bounds); return _frustum.Contains(bounds);
} }
} }

View File

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

View File

@@ -334,7 +334,7 @@ Window* ManagedEditor::GetMainWindow()
ASSERT(HasManagedInstance()); ASSERT(HasManagedInstance());
const auto method = GetClass()->GetMethod("GetMainWindowPtr"); const auto method = GetClass()->GetMethod("GetMainWindowPtr");
ASSERT(method); ASSERT(method);
return (Window*)MUtils::Unbox<void*>(method->Invoke(GetManagedInstance(), nullptr, nullptr)); return (Window*)MUtils::Unbox<void*>(method->Invoke(GetManagedInstance(), nullptr, nullptr), true);
} }
bool ManagedEditor::CanReloadScripts() bool ManagedEditor::CanReloadScripts()
@@ -346,7 +346,7 @@ bool ManagedEditor::CanReloadScripts()
Internal_CanReloadScripts = GetClass()->GetMethod("Internal_CanReloadScripts"); Internal_CanReloadScripts = GetClass()->GetMethod("Internal_CanReloadScripts");
ASSERT(Internal_CanReloadScripts); ASSERT(Internal_CanReloadScripts);
} }
return MUtils::Unbox<bool>(Internal_CanReloadScripts->Invoke(GetManagedInstance(), nullptr, nullptr)); return MUtils::Unbox<bool>(Internal_CanReloadScripts->Invoke(GetManagedInstance(), nullptr, nullptr), true);
} }
bool ManagedEditor::CanAutoBuildCSG() bool ManagedEditor::CanAutoBuildCSG()
@@ -365,7 +365,7 @@ bool ManagedEditor::CanAutoBuildCSG()
Internal_CanAutoBuildCSG = GetClass()->GetMethod("Internal_CanAutoBuildCSG"); Internal_CanAutoBuildCSG = GetClass()->GetMethod("Internal_CanAutoBuildCSG");
ASSERT(Internal_CanAutoBuildCSG); ASSERT(Internal_CanAutoBuildCSG);
} }
return MUtils::Unbox<bool>(Internal_CanAutoBuildCSG->Invoke(GetManagedInstance(), nullptr, nullptr)); return MUtils::Unbox<bool>(Internal_CanAutoBuildCSG->Invoke(GetManagedInstance(), nullptr, nullptr), true);
} }
bool ManagedEditor::CanAutoBuildNavMesh() bool ManagedEditor::CanAutoBuildNavMesh()
@@ -384,7 +384,7 @@ bool ManagedEditor::CanAutoBuildNavMesh()
Internal_CanAutoBuildNavMesh = GetClass()->GetMethod("Internal_CanAutoBuildNavMesh"); Internal_CanAutoBuildNavMesh = GetClass()->GetMethod("Internal_CanAutoBuildNavMesh");
ASSERT(Internal_CanAutoBuildNavMesh); ASSERT(Internal_CanAutoBuildNavMesh);
} }
return MUtils::Unbox<bool>(Internal_CanAutoBuildNavMesh->Invoke(GetManagedInstance(), nullptr, nullptr)); return MUtils::Unbox<bool>(Internal_CanAutoBuildNavMesh->Invoke(GetManagedInstance(), nullptr, nullptr), true);
} }
bool ManagedEditor::HasGameViewportFocus() const bool ManagedEditor::HasGameViewportFocus() const
@@ -397,7 +397,8 @@ bool ManagedEditor::HasGameViewportFocus() const
Internal_HasGameViewportFocus = GetClass()->GetMethod("Internal_HasGameViewportFocus"); Internal_HasGameViewportFocus = GetClass()->GetMethod("Internal_HasGameViewportFocus");
ASSERT(Internal_HasGameViewportFocus); ASSERT(Internal_HasGameViewportFocus);
} }
result = MUtils::Unbox<bool>(Internal_HasGameViewportFocus->Invoke(GetManagedInstance(), nullptr, nullptr)); auto invk = Internal_HasGameViewportFocus->Invoke(GetManagedInstance(), nullptr, nullptr);
result = MUtils::Unbox<bool>(invk, true);
} }
return result; return result;
} }
@@ -495,7 +496,7 @@ bool ManagedEditor::OnAppExit()
Internal_OnAppExit = GetClass()->GetMethod("Internal_OnAppExit"); Internal_OnAppExit = GetClass()->GetMethod("Internal_OnAppExit");
ASSERT(Internal_OnAppExit); ASSERT(Internal_OnAppExit);
} }
return MUtils::Unbox<bool>(Internal_OnAppExit->Invoke(GetManagedInstance(), nullptr, nullptr)); return MUtils::Unbox<bool>(Internal_OnAppExit->Invoke(GetManagedInstance(), nullptr, nullptr), true);
} }
void ManagedEditor::RequestStartPlayOnEditMode() void ManagedEditor::RequestStartPlayOnEditMode()

View File

@@ -1013,7 +1013,7 @@ namespace FlaxEditor.Modules
ContentItem item; ContentItem item;
if (path.EndsWith(".cs")) if (path.EndsWith(".cs"))
item = new CSharpScriptItem(path); item = new CSharpScriptItem(path);
else if (path.EndsWith(".cpp") || path.EndsWith(".h")) else if (path.EndsWith(".cpp") || path.EndsWith(".h") || path.EndsWith(".c") || path.EndsWith(".hpp"))
item = new CppScriptItem(path); item = new CppScriptItem(path);
else if (path.EndsWith(".shader") || path.EndsWith(".hlsl")) else if (path.EndsWith(".shader") || path.EndsWith(".hlsl"))
item = new ShaderSourceItem(path); item = new ShaderSourceItem(path);

View File

@@ -222,7 +222,7 @@ namespace FlaxEditor.Modules
outputExtension = extension; outputExtension = extension;
// Check if can place source files here // Check if can place source files here
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h")) if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h" || extension == ".c" || extension == ".hpp"))
{ {
// Error // Error
Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path)); Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path));

View File

@@ -267,7 +267,7 @@ namespace FlaxEditor.Modules
} }
/// <inheritdoc /> /// <inheritdoc />
public override void OnPlayBegin() public override void OnPlayBeginning()
{ {
Editor.Windows.FlashMainWindow(); Editor.Windows.FlashMainWindow();

View File

@@ -334,6 +334,9 @@ namespace FlaxEditor.Modules.SourceCodeEditing
} }
} }
} }
if (editor == null)
editor = Editor.Instance.CodeEditing.Editors[0];
Editor.Instance.CodeEditing.SelectedEditor = editor; Editor.Instance.CodeEditing.SelectedEditor = editor;
} }

View File

@@ -41,9 +41,9 @@ namespace FlaxEditor.Modules.SourceCodeEditing
var vsCode = codeEditing.GetInBuildEditor(CodeEditorTypes.VSCode); var vsCode = codeEditing.GetInBuildEditor(CodeEditorTypes.VSCode);
var rider = codeEditing.GetInBuildEditor(CodeEditorTypes.Rider); var rider = codeEditing.GetInBuildEditor(CodeEditorTypes.Rider);
#if PLATFORM_WINDOW #if PLATFORM_WINDOWS
// Favor the newest Visual Studio // Favor the newest Visual Studio
for (int i = (int)CodeEditorTypes.VS2019; i >= (int)CodeEditorTypes.VS2008; i--) for (int i = (int)CodeEditorTypes.VS2026; i >= (int)CodeEditorTypes.VS2008; i--)
{ {
var visualStudio = codeEditing.GetInBuildEditor((CodeEditorTypes)i); var visualStudio = codeEditing.GetInBuildEditor((CodeEditorTypes)i);
if (visualStudio != null) if (visualStudio != null)
@@ -74,7 +74,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
public string Name => "Default"; public string Name => "Default";
/// <inheritdoc /> /// <inheritdoc />
public string GenerateProjectCustomArgs => null; public string GenerateProjectCustomArgs => _currentEditor?.GenerateProjectCustomArgs;
/// <inheritdoc /> /// <inheritdoc />
public void OpenSolution() public void OpenSolution()

View File

@@ -22,71 +22,14 @@ namespace FlaxEditor.Modules.SourceCodeEditing
public InBuildSourceCodeEditor(CodeEditorTypes type) public InBuildSourceCodeEditor(CodeEditorTypes type)
{ {
Type = type; Type = type;
switch (type) Name = CodeEditingManager.GetName(type);
{
case CodeEditorTypes.Custom:
Name = "Custom";
break;
case CodeEditorTypes.SystemDefault:
Name = "System Default";
break;
case CodeEditorTypes.VS2008:
Name = "Visual Studio 2008";
break;
case CodeEditorTypes.VS2010:
Name = "Visual Studio 2010";
break;
case CodeEditorTypes.VS2012:
Name = "Visual Studio 2012";
break;
case CodeEditorTypes.VS2013:
Name = "Visual Studio 2013";
break;
case CodeEditorTypes.VS2015:
Name = "Visual Studio 2015";
break;
case CodeEditorTypes.VS2017:
Name = "Visual Studio 2017";
break;
case CodeEditorTypes.VS2019:
Name = "Visual Studio 2019";
break;
case CodeEditorTypes.VS2022:
Name = "Visual Studio 2022";
break;
case CodeEditorTypes.VS2026:
Name = "Visual Studio 2026";
break;
case CodeEditorTypes.VSCode:
Name = "Visual Studio Code";
break;
case CodeEditorTypes.VSCodeInsiders:
Name = "Visual Studio Code - Insiders";
break;
case CodeEditorTypes.Rider:
Name = "Rider";
break;
default: throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
} }
/// <inheritdoc /> /// <inheritdoc />
public string Name { get; set; } public string Name { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public string GenerateProjectCustomArgs public string GenerateProjectCustomArgs => CodeEditingManager.GetGenerateProjectCustomArgs(Type);
{
get
{
switch (Type)
{
case CodeEditorTypes.VSCodeInsiders:
case CodeEditorTypes.VSCode: return "-vscode -vs2022";
case CodeEditorTypes.Rider: return "-vs2022";
default: return null;
}
}
}
/// <inheritdoc /> /// <inheritdoc />
public void OpenSolution() public void OpenSolution()

View File

@@ -16,7 +16,6 @@ using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;
using FlaxEngine.Json; using FlaxEngine.Json;
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel; using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
using FlaxEditor.Content.Settings; using FlaxEditor.Content.Settings;
using FlaxEditor.Options; using FlaxEditor.Options;
@@ -29,6 +28,40 @@ namespace FlaxEditor.Modules
/// <seealso cref="FlaxEditor.Modules.EditorModule" /> /// <seealso cref="FlaxEditor.Modules.EditorModule" />
public sealed class UIModule : EditorModule public sealed class UIModule : EditorModule
{ {
private class MainWindowDecorations : WindowDecorations
{
public MainWindowDecorations(RootControl window, bool iconOnly)
: base(window, iconOnly)
{
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
// Fallback to the edit window for shortcuts
var editor = Editor.Instance;
return editor.Windows.EditWin.InputActions.Process(editor, this, key);
}
/// <inheritdoc />
public override void DrawBorders()
{
// Draw main window borders if using a custom style
var win = RootWindow.Window;
if (win.IsMaximized)
return;
var color = Editor.Instance.UI.StatusBar.StatusColor;
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
}
}
private Label _progressLabel; private Label _progressLabel;
private ProgressBar _progressBar; private ProgressBar _progressBar;
private Button _outputLogButton; private Button _outputLogButton;
@@ -144,6 +177,11 @@ namespace FlaxEditor.Modules
/// </summary> /// </summary>
public MainMenu MainMenu; public MainMenu MainMenu;
/// <summary>
/// The window decorations (title bar with buttons)
/// </summary>
public WindowDecorations WindowDecorations;
/// <summary> /// <summary>
/// The tool strip control. /// The tool strip control.
/// </summary> /// </summary>
@@ -426,19 +464,11 @@ namespace FlaxEditor.Modules
InitToolstrip(mainWindow); InitToolstrip(mainWindow);
InitStatusBar(mainWindow); InitStatusBar(mainWindow);
InitDockPanel(mainWindow); InitDockPanel(mainWindow);
InitWindowDecorations(mainWindow);
Editor.Options.OptionsChanged += OnOptionsChanged; Editor.Options.OptionsChanged += OnOptionsChanged;
// Add dummy control for drawing the main window borders if using a custom style mainWindow.PerformLayout(true);
#if PLATFORM_WINDOWS
if (!Editor.Options.Options.Interface.UseNativeWindowSystem)
#endif
{
mainWindow.AddChild(new CustomWindowBorderControl
{
Size = Float2.Zero,
});
}
} }
private void InitViewportScaleOptions() private void InitViewportScaleOptions()
@@ -510,23 +540,6 @@ namespace FlaxEditor.Modules
} }
} }
private class CustomWindowBorderControl : Control
{
/// <inheritdoc />
public override void Draw()
{
var win = RootWindow.Window;
if (win.IsMaximized)
return;
var color = Editor.Instance.UI.StatusBar.StatusColor;
var rect = new Rectangle(0.5f, 0.5f, Parent.Width - 1.0f, Parent.Height - 1.0f - StatusBar.DefaultHeight);
Render2D.DrawLine(rect.UpperLeft, rect.UpperRight, color);
Render2D.DrawLine(rect.UpperLeft, rect.BottomLeft, color);
Render2D.DrawLine(rect.UpperRight, rect.BottomRight, color);
}
}
/// <inheritdoc /> /// <inheritdoc />
public override void OnEndInit() public override void OnEndInit()
{ {
@@ -558,13 +571,6 @@ namespace FlaxEditor.Modules
UpdateToolstrip(); UpdateToolstrip();
} }
/// <inheritdoc />
public override void OnExit()
{
// Cleanup dock panel hint proxy windows (Flax will destroy them by var but it's better to clear them earlier)
DockHintWindow.Proxy.Dispose();
}
private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing) private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing)
{ {
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing); var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);
@@ -618,10 +624,12 @@ namespace FlaxEditor.Modules
private void InitMainMenu(RootControl mainWindow) private void InitMainMenu(RootControl mainWindow)
{ {
MainMenu = new MainMenu(mainWindow) MainMenu = new MainMenu()
{ {
Parent = mainWindow Parent = mainWindow
}; };
if (Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
MainMenu.Height = 28;
var inputOptions = Editor.Options.Options.Input; var inputOptions = Editor.Options.Options.Input;
@@ -763,6 +771,20 @@ namespace FlaxEditor.Modules
cm.AddButton("Information about Flax", () => new AboutDialog().Show()); cm.AddButton("Information about Flax", () => new AboutDialog().Show());
} }
private void InitWindowDecorations(RootControl mainWindow)
{
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
var driver = Platform.DisplayServer;
if (!string.IsNullOrEmpty(driver))
driver = $" ({driver})";
WindowDecorations = new MainWindowDecorations(mainWindow, !Utilities.Utils.UseCustomWindowDecorations(isMainWindow: true))
{
Parent = mainWindow,
IconTooltipText = $"{mainWindow.RootWindow.Title}\nVersion {Globals.EngineVersion}\nConfiguration {configuration}\nGraphics {GPUDevice.Instance.RendererType}{driver}",
};
}
private void OnOptionsChanged(EditorOptions options) private void OnOptionsChanged(EditorOptions options)
{ {
var inputOptions = options.Input; var inputOptions = options.Input;
@@ -1183,6 +1205,7 @@ namespace FlaxEditor.Modules
{ {
// Clear UI references (GUI cannot be used after window closing) // Clear UI references (GUI cannot be used after window closing)
MainMenu = null; MainMenu = null;
WindowDecorations = null;
ToolStrip = null; ToolStrip = null;
MasterPanel = null; MasterPanel = null;
StatusBar = null; StatusBar = null;

View File

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

View File

@@ -179,6 +179,34 @@ namespace FlaxEditor.Options
GameWindowThenRestore, GameWindowThenRestore,
} }
/// <summary>
/// Options for type of window decorations to use.
/// </summary>
public enum WindowDecorationsType
{
/// <summary>
/// Determined automatically based on the system and any known compatibility issues with native decorations.
/// </summary>
Auto,
/// <summary>
/// Automatically choose most compatible window decorations for child windows, prefer custom decorations on main window.
/// </summary>
[EditorDisplay(Name = "Auto (Child Only)")]
AutoChildOnly,
/// <summary>
/// Use native system window decorations on all windows.
/// </summary>
Native,
/// <summary>
/// Use custom client-side window decorations on all windows.
/// </summary>
[EditorDisplay(Name = "Client-side")]
ClientSide,
}
/// <summary> /// <summary>
/// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required. /// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.
/// </summary> /// </summary>
@@ -268,7 +296,14 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(322)] [EditorDisplay("Interface"), EditorOrder(322)]
public bool ScrollToScriptOnAdd { get; set; } = true; public bool ScrollToScriptOnAdd { get; set; } = true;
#if PLATFORM_WINDOWS #if PLATFORM_SDL
/// <summary>
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
#elif PLATFORM_WINDOWS
/// <summary> /// <summary>
/// Gets or sets a value indicating whether use native window title bar. Editor restart required. /// Gets or sets a value indicating whether use native window title bar. Editor restart required.
/// </summary> /// </summary>
@@ -277,7 +312,7 @@ namespace FlaxEditor.Options
public bool UseNativeWindowSystem { get; set; } = false; public bool UseNativeWindowSystem { get; set; } = false;
#endif #endif
#if PLATFORM_WINDOWS #if PLATFORM_SDL || PLATFORM_WINDOWS
/// <summary> /// <summary>
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended. /// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
/// </summary> /// </summary>

View File

@@ -36,8 +36,8 @@ namespace FlaxEditor.SceneGraph
} }
var center = _actor.Transform.Translation; var center = _actor.Transform.Translation;
ViewportIconsRenderer.GetBounds(ref center, ref ray.Ray.Position, out var sphere); ViewportIconsRenderer.GetBounds(center, ray.Ray.Position, out var sphere);
return CollisionsHelper.RayIntersectsSphere(ref ray.Ray, ref sphere, out distance); return CollisionsHelper.RayIntersectsSphere(ray.Ray, sphere, out distance);
} }
} }
} }

View File

@@ -109,10 +109,10 @@ namespace FlaxEditor.SceneGraph.Actors
// Skin vertex position with the current pose // Skin vertex position with the current pose
var position = positionStream.GetFloat3(j); var position = positionStream.GetFloat3(j);
Float3.Transform(ref position, ref skinningMatrices[indices[0]], out Float3 pos0); Float3.Transform(position, skinningMatrices[indices[0]], out Float3 pos0);
Float3.Transform(ref position, ref skinningMatrices[indices[1]], out Float3 pos1); Float3.Transform(position, skinningMatrices[indices[1]], out Float3 pos1);
Float3.Transform(ref position, ref skinningMatrices[indices[2]], out Float3 pos2); Float3.Transform(position, skinningMatrices[indices[2]], out Float3 pos2);
Float3.Transform(ref position, ref skinningMatrices[indices[3]], out Float3 pos3); Float3.Transform(position, skinningMatrices[indices[3]], out Float3 pos3);
position = pos0 * weights[0] + pos1 * weights[1] + pos2 * weights[2] + pos3 * weights[3]; position = pos0 * weights[0] + pos1 * weights[1] + pos2 * weights[2] + pos3 * weights[3];
// Add vertex to the bone list // Add vertex to the bone list
@@ -269,8 +269,8 @@ namespace FlaxEditor.SceneGraph.Actors
for (int i = 0; i < boneVertices.Count; i++) for (int i = 0; i < boneVertices.Count; i++)
{ {
var pos = boneTransform.WorldToLocal(boneVertices[i]); var pos = boneTransform.WorldToLocal(boneVertices[i]);
Vector3.Min(ref boneLocalBounds.Minimum, ref pos, out boneLocalBounds.Minimum); Vector3.Min(boneLocalBounds.Minimum, pos, out boneLocalBounds.Minimum);
Vector3.Max(ref boneLocalBounds.Maximum, ref pos, out boneLocalBounds.Maximum); Vector3.Max(boneLocalBounds.Maximum, pos, out boneLocalBounds.Maximum);
} }
// Add collision shape // Add collision shape
@@ -415,7 +415,7 @@ namespace FlaxEditor.SceneGraph.Actors
float bkLength = bk.Length; float bkLength = bk.Length;
if (bkLength > 0.0f) if (bkLength > 0.0f)
{ {
Float3.Transform(ref bk, ref matrix, out Float3 bkA); Float3.Transform(bk, matrix, out Float3 bkA);
bk = bkA / bkLength; bk = bkA / bkLength;
} }
} }

View File

@@ -184,7 +184,7 @@ namespace FlaxEditor.SceneGraph.Actors
/// <inheritdoc /> /// <inheritdoc />
public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal)
{ {
return Brush.Intersects(Index, ref ray.Ray, out distance, out normal); return Brush.Intersects(Index, ray.Ray, out distance, out normal);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -207,7 +207,7 @@ namespace FlaxEditor.SceneGraph.Actors
/// <inheritdoc /> /// <inheritdoc />
public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal)
{ {
if (((BoxBrush)_actor).OrientedBox.Intersects(ref ray.Ray)) if (((BoxBrush)_actor).OrientedBox.Intersects(ray.Ray))
{ {
for (int i = 0; i < ChildNodes.Count; i++) for (int i = 0; i < ChildNodes.Count; i++)
{ {

View File

@@ -107,7 +107,7 @@ namespace FlaxEditor.SceneGraph.Actors
{ {
normal = Vector3.Up; normal = Vector3.Up;
var sphere = new BoundingSphere(Transform.Translation, 10.0f); var sphere = new BoundingSphere(Transform.Translation, 10.0f);
return sphere.Intersects(ref ray.Ray, out distance); return sphere.Intersects(ray.Ray, out distance);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -56,7 +56,7 @@ namespace FlaxEditor.SceneGraph.Actors
return false; return false;
} }
return Camera.Internal_IntersectsItselfEditor(FlaxEngine.Object.GetUnmanagedPtr(_actor), ref ray.Ray, out distance); return Camera.Internal_IntersectsItselfEditor(FlaxEngine.Object.GetUnmanagedPtr(_actor), ray.Ray, out distance);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -58,7 +58,7 @@ namespace FlaxEditor.SceneGraph.Actors
public override Transform Transform public override Transform Transform
{ {
get => Actor.GetInstance(Index).Transform; get => Actor.GetInstance(Index).Transform;
set => Actor.SetInstanceTransform(Index, ref value); set => Actor.SetInstanceTransform(Index, value);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -63,7 +63,7 @@ namespace FlaxEditor.SceneGraph.Actors
{ {
normal = Vector3.Up; normal = Vector3.Up;
var sphere = new BoundingSphere(Transform.Translation, 10.0f); var sphere = new BoundingSphere(Transform.Translation, 10.0f);
return sphere.Intersects(ref ray.Ray, out distance); return sphere.Intersects(ray.Ray, out distance);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -177,7 +177,7 @@ namespace FlaxEditor.SceneGraph.Actors
var actor = (Spline)_node.Actor; var actor = (Spline)_node.Actor;
var pos = actor.GetSplinePoint(Index); var pos = actor.GetSplinePoint(Index);
var nodeSize = NodeSizeByDistance(Transform.Translation, PointNodeSize, ray.View.Position); var nodeSize = NodeSizeByDistance(Transform.Translation, PointNodeSize, ray.View.Position);
return new BoundingSphere(pos, nodeSize).Intersects(ref ray.Ray, out distance); return new BoundingSphere(pos, nodeSize).Intersects(ray.Ray, out distance);
} }
public override void OnDebugDraw(ViewportDebugDrawData data) public override void OnDebugDraw(ViewportDebugDrawData data)
@@ -264,7 +264,7 @@ namespace FlaxEditor.SceneGraph.Actors
var actor = (Spline)_node.Actor; var actor = (Spline)_node.Actor;
var pos = actor.GetSplineTangent(_index, _isIn).Translation; var pos = actor.GetSplineTangent(_index, _isIn).Translation;
var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize, ray.View.Position); var tangentSize = NodeSizeByDistance(Transform.Translation, TangentNodeSize, ray.View.Position);
return new BoundingSphere(pos, tangentSize).Intersects(ref ray.Ray, out distance); return new BoundingSphere(pos, tangentSize).Intersects(ray.Ray, out distance);
} }
public override void OnDebugDraw(ViewportDebugDrawData data) public override void OnDebugDraw(ViewportDebugDrawData data)

View File

@@ -37,15 +37,15 @@ namespace FlaxEditor.SceneGraph.Actors
{ {
var up = Float3.Up; var up = Float3.Up;
Float3 translation = transform.Translation; Float3 translation = transform.Translation;
Matrix.Billboard(ref translation, ref viewPosition, ref up, ref viewDirection, out m2); Matrix.Billboard(translation, viewPosition, up, viewDirection, out m2);
Matrix.Multiply(ref m1, ref m2, out m3); Matrix.Multiply(m1, m2, out m3);
Matrix.Scaling(ref transform.Scale, out m1); Matrix.Scaling(transform.Scale, out m1);
Matrix.Multiply(ref m1, ref m3, out world); Matrix.Multiply(m1, m3, out world);
} }
else else
{ {
transform.GetWorld(out m2); transform.GetWorld(out m2);
Matrix.Multiply(ref m1, ref m2, out world); Matrix.Multiply(m1, m2, out world);
} }
OrientedBoundingBox bounds; OrientedBoundingBox bounds;
@@ -53,7 +53,7 @@ namespace FlaxEditor.SceneGraph.Actors
world.Decompose(out bounds.Transformation); world.Decompose(out bounds.Transformation);
normal = -ray.Ray.Direction; normal = -ray.Ray.Direction;
return bounds.Intersects(ref ray.Ray, out distance); return bounds.Intersects(ray.Ray, out distance);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -96,7 +96,7 @@ namespace FlaxEditor.SceneGraph.Actors
for (int i = 0; i < verts.Length; i++) for (int i = 0; i < verts.Length; i++)
{ {
ref var v = ref verts[i]; ref var v = ref verts[i];
var distance = Float3.DistanceSquared(ref pointLocal, ref v); var distance = Float3.DistanceSquared(pointLocal, v);
if (distance <= minDistance) if (distance <= minDistance)
{ {
hit = true; hit = true;

View File

@@ -64,7 +64,7 @@ namespace FlaxEditor.SceneGraph.Actors
normal = Vector3.Up; normal = Vector3.Up;
if (Actor is UICanvas uiCanvas && uiCanvas.Is3D) if (Actor is UICanvas uiCanvas && uiCanvas.Is3D)
return uiCanvas.Bounds.Intersects(ref ray.Ray, out distance); return uiCanvas.Bounds.Intersects(ray.Ray, out distance);
distance = 0; distance = 0;
return false; return false;

View File

@@ -352,7 +352,7 @@ namespace FlaxEditor.SceneGraph
for (int i = 0; i < ChildNodes.Count; i++) for (int i = 0; i < ChildNodes.Count; i++)
{ {
ChildNodes[i].GetEditorSphere(out var childSphere); ChildNodes[i].GetEditorSphere(out var childSphere);
BoundingSphere.Merge(ref sphere, ref childSphere, out sphere); BoundingSphere.Merge(sphere, childSphere, out sphere);
} }
} }

View File

@@ -139,6 +139,34 @@ CodeEditor* CodeEditingManager::GetCodeEditor(CodeEditorTypes editorType)
return nullptr; return nullptr;
} }
String CodeEditingManager::GetName(CodeEditorTypes editorType)
{
const auto editor = GetCodeEditor(editorType);
if (editor)
{
return editor->GetName();
}
else
{
LOG(Warning, "Missing code editor type {0}", (int32)editorType);
return String::Empty;
}
}
String CodeEditingManager::GetGenerateProjectCustomArgs(CodeEditorTypes editorType)
{
const auto editor = GetCodeEditor(editorType);
if (editor)
{
return editor->GetGenerateProjectCustomArgs();
}
else
{
LOG(Warning, "Missing code editor type {0}", (int32)editorType);
return String::Empty;
}
}
void CodeEditingManager::OpenFile(CodeEditorTypes editorType, const String& path, int32 line) void CodeEditingManager::OpenFile(CodeEditorTypes editorType, const String& path, int32 line)
{ {
const auto editor = GetCodeEditor(editorType); const auto editor = GetCodeEditor(editorType);

View File

@@ -109,9 +109,18 @@ public:
/// <summary> /// <summary>
/// Gets the name of the editor. /// Gets the name of the editor.
/// </summary> /// </summary>
/// <returns>The name</returns> /// <returns>The name.</returns>
virtual String GetName() const = 0; virtual String GetName() const = 0;
/// <summary>
/// Gets the custom arguments for the Flax.Build tool to add when generating project files for this code editor.
/// </summary>
/// <returns>The custom arguments to generate project files.</returns>
virtual String GetGenerateProjectCustomArgs() const
{
return String::Empty;
}
/// <summary> /// <summary>
/// Opens the file. /// Opens the file.
/// </summary> /// </summary>
@@ -169,6 +178,20 @@ public:
/// <returns>The editor object or null if not found.</returns> /// <returns>The editor object or null if not found.</returns>
static CodeEditor* GetCodeEditor(CodeEditorTypes editorType); static CodeEditor* GetCodeEditor(CodeEditorTypes editorType);
/// <summary>
/// Gets the name of the editor.
/// </summary>
/// <param name="editorType">The code editor type.</param>
/// <returns>The name.</returns>
API_FUNCTION() static String GetName(CodeEditorTypes editorType);
/// <summary>
/// Gets the custom arguments for the Flax.Build tool to add when generating project files for this code editor.
/// </summary>
/// <param name="editorType">The code editor type.</param>
/// <returns>The custom arguments to generate project files.</returns>
API_FUNCTION() static String GetGenerateProjectCustomArgs(CodeEditorTypes editorType);
/// <summary> /// <summary>
/// Opens the file. Handles async opening. /// Opens the file. Handles async opening.
/// </summary> /// </summary>

View File

@@ -257,12 +257,17 @@ String RiderCodeEditor::GetName() const
return TEXT("Rider"); return TEXT("Rider");
} }
String RiderCodeEditor::GetGenerateProjectCustomArgs() const
{
return TEXT("-vs2022");
}
void RiderCodeEditor::OpenFile(const String& path, int32 line) void RiderCodeEditor::OpenFile(const String& path, int32 line)
{ {
// Generate project files if solution is missing // Generate project files if solution is missing
if (!FileSystem::FileExists(_solutionPath)) if (!FileSystem::FileExists(_solutionPath))
{ {
ScriptsBuilder::GenerateProject(TEXT("-vs2022")); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
} }
// Open file // Open file
@@ -290,7 +295,7 @@ void RiderCodeEditor::OpenSolution()
// Generate project files if solution is missing // Generate project files if solution is missing
if (!FileSystem::FileExists(_solutionPath)) if (!FileSystem::FileExists(_solutionPath))
{ {
ScriptsBuilder::GenerateProject(TEXT("-vs2022")); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
} }
// Open solution // Open solution
@@ -312,5 +317,5 @@ void RiderCodeEditor::OpenSolution()
void RiderCodeEditor::OnFileAdded(const String& path) void RiderCodeEditor::OnFileAdded(const String& path)
{ {
ScriptsBuilder::GenerateProject(); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
} }

View File

@@ -35,6 +35,7 @@ public:
// [CodeEditor] // [CodeEditor]
CodeEditorTypes GetType() const override; CodeEditorTypes GetType() const override;
String GetName() const override; String GetName() const override;
String GetGenerateProjectCustomArgs() const override;
void OpenFile(const String& path, int32 line) override; void OpenFile(const String& path, int32 line) override;
void OpenSolution() override; void OpenSolution() override;
void OnFileAdded(const String& path) override; void OnFileAdded(const String& path) override;

View File

@@ -148,12 +148,17 @@ String VisualStudioEditor::GetName() const
return String(ToString(_version)); return String(ToString(_version));
} }
String VisualStudioEditor::GetGenerateProjectCustomArgs() const
{
return String::Format(TEXT("-{0}"), String(ToString(_version)).ToLower());
}
void VisualStudioEditor::OpenFile(const String& path, int32 line) void VisualStudioEditor::OpenFile(const String& path, int32 line)
{ {
// Generate project files if solution is missing // Generate project files if solution is missing
if (!FileSystem::FileExists(_solutionPath)) if (!FileSystem::FileExists(_solutionPath))
{ {
ScriptsBuilder::GenerateProject(); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
} }
// Open file // Open file
@@ -172,7 +177,7 @@ void VisualStudioEditor::OpenSolution()
// Generate project files if solution is missing // Generate project files if solution is missing
if (!FileSystem::FileExists(_solutionPath)) if (!FileSystem::FileExists(_solutionPath))
{ {
ScriptsBuilder::GenerateProject(); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
} }
// Open solution // Open solution
@@ -187,7 +192,7 @@ void VisualStudioEditor::OpenSolution()
void VisualStudioEditor::OnFileAdded(const String& path) void VisualStudioEditor::OnFileAdded(const String& path)
{ {
// TODO: finish dynamic files adding to the project - for now just regenerate it // TODO: finish dynamic files adding to the project - for now just regenerate it
ScriptsBuilder::GenerateProject(); ScriptsBuilder::GenerateProject(GetGenerateProjectCustomArgs());
return; return;
if (!FileSystem::FileExists(_solutionPath)) if (!FileSystem::FileExists(_solutionPath))
{ {

View File

@@ -56,6 +56,7 @@ public:
// [CodeEditor] // [CodeEditor]
CodeEditorTypes GetType() const override; CodeEditorTypes GetType() const override;
String GetName() const override; String GetName() const override;
String GetGenerateProjectCustomArgs() const override;
void OpenFile(const String& path, int32 line) override; void OpenFile(const String& path, int32 line) override;
void OpenSolution() override; void OpenSolution() override;
void OnFileAdded(const String& path) override; void OnFileAdded(const String& path) override;

View File

@@ -128,6 +128,11 @@ String VisualStudioCodeEditor::GetName() const
return _isInsiders ? TEXT("Visual Studio Code - Insiders") : TEXT("Visual Studio Code"); return _isInsiders ? TEXT("Visual Studio Code - Insiders") : TEXT("Visual Studio Code");
} }
String VisualStudioCodeEditor::GetGenerateProjectCustomArgs() const
{
return TEXT("-vs2022 -vscode");
}
void VisualStudioCodeEditor::OpenFile(const String& path, int32 line) void VisualStudioCodeEditor::OpenFile(const String& path, int32 line)
{ {
// Generate VS solution files for intellisense // Generate VS solution files for intellisense

View File

@@ -37,6 +37,7 @@ public:
// [CodeEditor] // [CodeEditor]
CodeEditorTypes GetType() const override; CodeEditorTypes GetType() const override;
String GetName() const override; String GetName() const override;
String GetGenerateProjectCustomArgs() const override;
void OpenFile(const String& path, int32 line) override; void OpenFile(const String& path, int32 line) override;
void OpenSolution() override; void OpenSolution() override;
bool UseAsyncForOpen() const override; bool UseAsyncForOpen() const override;

View File

@@ -121,9 +121,13 @@ void ScriptsBuilderImpl::sourceDirEvent(const String& path, FileSystemAction act
// Discard non-source files or generated files // Discard non-source files or generated files
if ((!path.EndsWith(TEXT(".cs")) && if ((!path.EndsWith(TEXT(".cs")) &&
!path.EndsWith(TEXT(".cpp")) && !path.EndsWith(TEXT(".cpp")) &&
!path.EndsWith(TEXT(".c")) &&
!path.EndsWith(TEXT(".hpp")) &&
!path.EndsWith(TEXT(".h"))) || !path.EndsWith(TEXT(".h"))) ||
path.EndsWith(TEXT(".Gen.cs"))) path.EndsWith(TEXT(".Gen.cs")))
{
return; return;
}
ScopeLock scopeLock(_locker); ScopeLock scopeLock(_locker);
_lastSourceCodeEdited = DateTime::Now(); _lastSourceCodeEdited = DateTime::Now();

View File

@@ -479,7 +479,7 @@ namespace FlaxEditor.Surface.Archetypes
// Scale debug pointer when it moves to make it more visible when investigating blending // Scale debug pointer when it moves to make it more visible when investigating blending
const float debugMaxSize = 2.0f; const float debugMaxSize = 2.0f;
float debugScale = Mathf.Saturate(Float2.Distance(ref _debugPos, ref prev) / new Float2(_rangeX.Absolute.ValuesSum, _rangeY.Absolute.ValuesSum).Length * 100.0f) * debugMaxSize + 1.0f; float debugScale = Mathf.Saturate(Float2.Distance(_debugPos, prev) / new Float2(_rangeX.Absolute.ValuesSum, _rangeY.Absolute.ValuesSum).Length * 100.0f) * debugMaxSize + 1.0f;
float debugBlendSpeed = _debugScale <= debugScale ? 4.0f : 1.0f; float debugBlendSpeed = _debugScale <= debugScale ? 4.0f : 1.0f;
_debugScale = Mathf.Lerp(_debugScale, debugScale, deltaTime * debugBlendSpeed); _debugScale = Mathf.Lerp(_debugScale, debugScale, deltaTime * debugBlendSpeed);
} }
@@ -1189,9 +1189,9 @@ namespace FlaxEditor.Surface.Archetypes
_triangleColors = new Color[_triangles.Length]; _triangleColors = new Color[_triangles.Length];
for (int i = 0; i < _triangles.Length; i += 3) for (int i = 0; i < _triangles.Length; i += 3)
{ {
var is0 = Float2.NearEqual(ref _triangles[i + 0], ref pos); var is0 = Float2.NearEqual(_triangles[i + 0], pos);
var is1 = Float2.NearEqual(ref _triangles[i + 1], ref pos); var is1 = Float2.NearEqual(_triangles[i + 1], pos);
var is2 = Float2.NearEqual(ref _triangles[i + 2], ref pos); var is2 = Float2.NearEqual(_triangles[i + 2], pos);
if (is0 || is1 || is2) if (is0 || is1 || is2)
{ {
selectedTriangles.Add(_triangles[i + 0]); selectedTriangles.Add(_triangles[i + 0]);
@@ -1233,7 +1233,7 @@ namespace FlaxEditor.Surface.Archetypes
if (point != null) if (point != null)
{ {
var highlightColor = point.IsMouseDown ? style.SelectionBorder : style.BackgroundSelected; var highlightColor = point.IsMouseDown ? style.SelectionBorder : style.BackgroundSelected;
Render2D.PushTint(ref highlightColor); Render2D.PushTint(highlightColor);
Render2D.DrawTriangles(_selectedTriangles, _selectedColors); Render2D.DrawTriangles(_selectedTriangles, _selectedColors);
Render2D.PopTint(); Render2D.PopTint();
} }

View File

@@ -213,7 +213,7 @@ namespace FlaxEditor.Surface.Archetypes
if (base.OnMouseDoubleClick(location, button)) if (base.OnMouseDoubleClick(location, button))
return true; return true;
if (_headerRect.Contains(ref location)) if (_headerRect.Contains(location))
{ {
StartRenaming(); StartRenaming();
return true; return true;
@@ -364,7 +364,7 @@ namespace FlaxEditor.Surface.Archetypes
if (ClipChildren) if (ClipChildren)
{ {
GetDesireClientArea(out var clientArea); GetDesireClientArea(out var clientArea);
Render2D.PushClip(ref clientArea); Render2D.PushClip(clientArea);
} }
DrawChildren(); DrawChildren();
@@ -382,13 +382,13 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return _dragAreaRect.MakeOffsetted(Location).Contains(ref location); return _dragAreaRect.MakeOffsetted(Location).Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && !_dragAreaRect.Contains(ref location)) if (button == MouseButton.Left && !_dragAreaRect.Contains(location))
{ {
_isMouseDown = true; _isMouseDown = true;
Cursor = CursorType.Hand; Cursor = CursorType.Hand;
@@ -687,7 +687,7 @@ namespace FlaxEditor.Surface.Archetypes
var upperLeft = bounds.UpperLeft; var upperLeft = bounds.UpperLeft;
var bottomRight = bounds.BottomRight; var bottomRight = bounds.BottomRight;
bounds = Rectangle.FromPoints(PointToParent(ref upperLeft), PointToParent(ref bottomRight)); bounds = Rectangle.FromPoints(PointToParent(ref upperLeft), PointToParent(ref bottomRight));
CollisionsHelper.ClosestPointRectanglePoint(ref bounds, ref startPos, out endPos); CollisionsHelper.ClosestPointRectanglePoint(bounds, startPos, out endPos);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -731,15 +731,15 @@ namespace FlaxEditor.Surface.Archetypes
// Check click over the connection // Check click over the connection
var mousePosition = Surface.SurfaceRoot.PointFromParent(ref mouse); var mousePosition = Surface.SurfaceRoot.PointFromParent(ref mouse);
if (!TransitionsRectangle.Contains(ref mousePosition)) if (!TransitionsRectangle.Contains(mousePosition))
return; return;
for (int i = 0; i < Transitions.Count; i++) for (int i = 0; i < Transitions.Count; i++)
{ {
var t = Transitions[i]; var t = Transitions[i];
if (t.Bounds.Contains(ref mousePosition)) if (t.Bounds.Contains(mousePosition))
{ {
CollisionsHelper.ClosestPointPointLine(ref mousePosition, ref t.StartPos, ref t.EndPos, out var point); CollisionsHelper.ClosestPointPointLine(mousePosition, t.StartPos, t.EndPos, out var point);
if (Float2.DistanceSquared(ref mousePosition, ref point) < 25.0f) if (Float2.DistanceSquared(mousePosition, point) < 25.0f)
{ {
OnTransitionClicked(t, ref mouse, ref mousePosition, buttons); OnTransitionClicked(t, ref mouse, ref mousePosition, buttons);
handled = true; handled = true;
@@ -756,15 +756,15 @@ namespace FlaxEditor.Surface.Archetypes
// Check double click over the connection // Check double click over the connection
var mousePosition = Surface.SurfaceRoot.PointFromParent(ref mouse); var mousePosition = Surface.SurfaceRoot.PointFromParent(ref mouse);
if (!TransitionsRectangle.Contains(ref mousePosition)) if (!TransitionsRectangle.Contains(mousePosition))
return; return;
for (int i = 0; i < Transitions.Count; i++) for (int i = 0; i < Transitions.Count; i++)
{ {
var t = Transitions[i]; var t = Transitions[i];
if (t.Bounds.Contains(ref mousePosition)) if (t.Bounds.Contains(mousePosition))
{ {
CollisionsHelper.ClosestPointPointLine(ref mousePosition, ref t.StartPos, ref t.EndPos, out var point); CollisionsHelper.ClosestPointPointLine(mousePosition, t.StartPos, t.EndPos, out var point);
if (Float2.DistanceSquared(ref mousePosition, ref point) < 25.0f) if (Float2.DistanceSquared(mousePosition, point) < 25.0f)
{ {
t.EditRule(); t.EditRule();
handled = true; handled = true;
@@ -1007,7 +1007,7 @@ namespace FlaxEditor.Surface.Archetypes
var offset = diff ? -6.0f : 6.0f; var offset = diff ? -6.0f : 6.0f;
var dir = startPos - endPos; var dir = startPos - endPos;
dir.Normalize(); dir.Normalize();
Float2.Perpendicular(ref dir, out var nrm); Float2.Perpendicular(dir, out var nrm);
nrm *= offset; nrm *= offset;
startPos += nrm; startPos += nrm;
endPos += nrm; endPos += nrm;
@@ -1031,7 +1031,7 @@ namespace FlaxEditor.Surface.Archetypes
t.StartPos = startPos; t.StartPos = startPos;
t.EndPos = endPos; t.EndPos = endPos;
Rectangle.FromPoints(ref startPos, ref endPos, out t.Bounds); Rectangle.FromPoints(startPos, endPos, out t.Bounds);
t.Bounds.Expand(10.0f); t.Bounds.Expand(10.0f);
} }
@@ -1040,7 +1040,7 @@ namespace FlaxEditor.Surface.Archetypes
TransitionsRectangle = Transitions[0].Bounds; TransitionsRectangle = Transitions[0].Bounds;
for (int i = 1; i < Transitions.Count; i++) for (int i = 1; i < Transitions.Count; i++)
{ {
Rectangle.Union(ref TransitionsRectangle, ref Transitions[i].Bounds, out TransitionsRectangle); Rectangle.Union(TransitionsRectangle, Transitions[i].Bounds, out TransitionsRectangle);
} }
} }
else else
@@ -1095,7 +1095,7 @@ namespace FlaxEditor.Surface.Archetypes
if (ClipChildren) if (ClipChildren)
{ {
GetDesireClientArea(out var clientArea); GetDesireClientArea(out var clientArea);
Render2D.PushClip(ref clientArea); Render2D.PushClip(clientArea);
} }
DrawChildren(); DrawChildren();
@@ -1120,7 +1120,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return _dragAreaRect.MakeOffsetted(Location).Contains(ref location); return _dragAreaRect.MakeOffsetted(Location).Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -1129,7 +1129,7 @@ namespace FlaxEditor.Surface.Archetypes
if (base.OnMouseDoubleClick(location, button)) if (base.OnMouseDoubleClick(location, button))
return true; return true;
if (_renameButtonRect.Contains(ref location) || _closeButtonRect.Contains(ref location)) if (_renameButtonRect.Contains(location) || _closeButtonRect.Contains(location))
return true; return true;
return false; return false;
@@ -1138,7 +1138,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && !_dragAreaRect.Contains(ref location)) if (button == MouseButton.Left && !_dragAreaRect.Contains(location))
{ {
_isMouseDown = true; _isMouseDown = true;
Cursor = CursorType.Hand; Cursor = CursorType.Hand;
@@ -1271,11 +1271,11 @@ namespace FlaxEditor.Surface.Archetypes
for (int i = 0; i < Transitions.Count; i++) for (int i = 0; i < Transitions.Count; i++)
{ {
var t = Transitions[i]; var t = Transitions[i];
var isMouseOver = t.Bounds.Contains(ref mousePosition); var isMouseOver = t.Bounds.Contains(mousePosition);
if (isMouseOver) if (isMouseOver)
{ {
CollisionsHelper.ClosestPointPointLine(ref mousePosition, ref t.StartPos, ref t.EndPos, out var point); CollisionsHelper.ClosestPointPointLine(mousePosition, t.StartPos, t.EndPos, out var point);
isMouseOver = Float2.DistanceSquared(ref mousePosition, ref point) < 25.0f; isMouseOver = Float2.DistanceSquared(mousePosition, point) < 25.0f;
} }
var color = isMouseOver ? Color.Wheat : t.LineColor; var color = isMouseOver ? Color.Wheat : t.LineColor;
SurfaceStyle.DrawStraightConnection(t.StartPos, t.EndPos, color); SurfaceStyle.DrawStraightConnection(t.StartPos, t.EndPos, color);
@@ -1474,7 +1474,7 @@ namespace FlaxEditor.Surface.Archetypes
return true; return true;
// Rename // Rename
if (_renameButtonRect.Contains(ref location)) if (_renameButtonRect.Contains(location))
{ {
StartRenaming(); StartRenaming();
return true; return true;

View File

@@ -308,7 +308,7 @@ namespace FlaxEditor.Surface.Archetypes
if (base.OnMouseDoubleClick(location, button)) if (base.OnMouseDoubleClick(location, button))
return true; return true;
if (_nameField.Bounds.Contains(ref location) && Surface.CanEdit) if (_nameField.Bounds.Contains(location) && Surface.CanEdit)
{ {
StartRenaming(); StartRenaming();
return true; return true;
@@ -1128,7 +1128,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button) public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && _headerRect.Contains(ref location)) if (button == MouseButton.Left && _headerRect.Contains(location))
{ {
// Open function content item if exists // Open function content item if exists
var method = GetMethod(out var scriptType, out _, out _); var method = GetMethod(out var scriptType, out _, out _);
@@ -1759,7 +1759,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button) public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && _headerRect.Contains(ref location)) if (button == MouseButton.Left && _headerRect.Contains(location))
{ {
OnEditSignature(); OnEditSignature();
return true; return true;

View File

@@ -347,7 +347,7 @@ namespace FlaxEditor.Surface.Archetypes
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return base.CanSelect(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); return base.CanSelect(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(location);
} }
public override void OnSurfaceLoaded(SurfaceNodeActions action) public override void OnSurfaceLoaded(SurfaceNodeActions action)
@@ -414,7 +414,7 @@ namespace FlaxEditor.Surface.Archetypes
if (base.OnMouseDown(location, button)) if (base.OnMouseDown(location, button))
return true; return true;
if (button == MouseButton.Left && _resizeButtonRect.Contains(ref location) && Surface.CanEdit) if (button == MouseButton.Left && _resizeButtonRect.Contains(location) && Surface.CanEdit)
{ {
// Start sliding // Start sliding
_isResizing = true; _isResizing = true;

View File

@@ -182,7 +182,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button) public override bool OnMouseDown(Float2 location, MouseButton button)
{ {
if (button == MouseButton.Left && _arrangeButtonRect.Contains(ref location)) if (button == MouseButton.Left && _arrangeButtonRect.Contains(location))
{ {
_arrangeButtonInUse = true; _arrangeButtonInUse = true;
Focus(); Focus();

View File

@@ -191,7 +191,7 @@ namespace FlaxEditor.Surface.Archetypes
// Header // Header
var headerColor = style.BackgroundHighlighted; var headerColor = style.BackgroundHighlighted;
if (_headerRect.Contains(ref _mousePosition)) if (_headerRect.Contains(_mousePosition))
headerColor *= 1.07f; headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor); Render2D.FillRectangle(_headerRect, headerColor);
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center); Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);

View File

@@ -113,7 +113,7 @@ namespace FlaxEditor.Surface.Archetypes
var icons = Editor.Instance.Icons; var icons = Editor.Instance.Icons;
var icon = isSelected ? icons.VisjectArrowClosed32 : icons.VisjectArrowOpen32; var icon = isSelected ? icons.VisjectArrowClosed32 : icons.VisjectArrowOpen32;
Render2D.PushTransform(ref arrowTransform); Render2D.PushTransform(arrowTransform);
Render2D.DrawSprite(icon, arrowRect, color); Render2D.DrawSprite(icon, arrowRect, color);
Render2D.PopTransform(); Render2D.PopTransform();
} }
@@ -169,7 +169,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override void OnMouseMove(Float2 location) public override void OnMouseMove(Float2 location)
{ {
if (_isMoving && Float2.DistanceSquared(ref location, ref _startMovePos) > 25.0f) if (_isMoving && Float2.DistanceSquared(location, _startMovePos) > 25.0f)
{ {
_startMovePos = Float2.Minimum; _startMovePos = Float2.Minimum;
int index = Node._stops.IndexOf(this); int index = Node._stops.IndexOf(this);
@@ -1076,12 +1076,12 @@ namespace FlaxEditor.Surface.Archetypes
} }
/// <inheritdoc /> /// <inheritdoc />
protected override bool ShowTooltip => !string.IsNullOrEmpty(TooltipText) && _localBounds.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened; protected override bool ShowTooltip => !string.IsNullOrEmpty(TooltipText) && _localBounds.Contains(_mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
/// <inheritdoc /> /// <inheritdoc />
public override bool OnTestTooltipOverControl(ref Float2 location) public override bool OnTestTooltipOverControl(ref Float2 location)
{ {
return _localBounds.Contains(ref location) && ShowTooltip; return _localBounds.Contains(location) && ShowTooltip;
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -1150,7 +1150,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return new Rectangle(Location, DefaultSize).Contains(ref location); return new Rectangle(Location, DefaultSize).Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -1230,7 +1230,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc /> /// <inheritdoc />
public override void OnMouseMove(Float2 location) public override void OnMouseMove(Float2 location)
{ {
_isMouseInConnectingBounds = IsMouseOver && _localBounds.MakeExpanded(ConnectingBounds).Contains(ref location); // Inner area for connecting, outer area for moving _isMouseInConnectingBounds = IsMouseOver && _localBounds.MakeExpanded(ConnectingBounds).Contains(location); // Inner area for connecting, outer area for moving
if (!_isMouseInConnectingBounds && !_isMouseDown) if (!_isMouseInConnectingBounds && !_isMouseDown)
Cursor = CursorType.SizeAll; Cursor = CursorType.SizeAll;
else else

View File

@@ -156,7 +156,7 @@ namespace FlaxEditor.Surface.Elements
Bezier(ref offsetStart, ref control1, ref control2, ref offsetEnd, t, out p); Bezier(ref offsetStart, ref control1, ref control2, ref offsetEnd, t, out p);
// Maybe it would be reasonable to return the point? // Maybe it would be reasonable to return the point?
CollisionsHelper.ClosestPointPointLine(ref point, ref oldp, ref p, out var result); CollisionsHelper.ClosestPointPointLine(point, oldp, p, out var result);
if (Float2.DistanceSquared(point, result) <= squaredDistance) if (Float2.DistanceSquared(point, result) <= squaredDistance)
{ {
return true; return true;
@@ -167,12 +167,12 @@ namespace FlaxEditor.Surface.Elements
private static void Bezier(ref Float2 p0, ref Float2 p1, ref Float2 p2, ref Float2 p3, float alpha, out Float2 result) private static void Bezier(ref Float2 p0, ref Float2 p1, ref Float2 p2, ref Float2 p3, float alpha, out Float2 result)
{ {
Float2.Lerp(ref p0, ref p1, alpha, out var p01); Float2.Lerp(p0, p1, alpha, out var p01);
Float2.Lerp(ref p1, ref p2, alpha, out var p12); Float2.Lerp(p1, p2, alpha, out var p12);
Float2.Lerp(ref p2, ref p3, alpha, out var p23); Float2.Lerp(p2, p3, alpha, out var p23);
Float2.Lerp(ref p01, ref p12, alpha, out var p012); Float2.Lerp(p01, p12, alpha, out var p012);
Float2.Lerp(ref p12, ref p23, alpha, out var p123); Float2.Lerp(p12, p23, alpha, out var p123);
Float2.Lerp(ref p012, ref p123, alpha, out result); Float2.Lerp(p012, p123, alpha, out result);
} }
/// <summary> /// <summary>

View File

@@ -146,13 +146,13 @@ namespace FlaxEditor.Surface
/// <inheritdoc /> /// <inheritdoc />
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return _headerRect.MakeOffsetted(Location).Contains(ref location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(ref location); return _headerRect.MakeOffsetted(Location).Contains(location) && !_resizeButtonRect.MakeOffsetted(Location).Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
public override bool IsSelectionIntersecting(ref Rectangle selectionRect) public override bool IsSelectionIntersecting(ref Rectangle selectionRect)
{ {
return _headerRect.MakeOffsetted(Location).Intersects(ref selectionRect); return _headerRect.MakeOffsetted(Location).Intersects(selectionRect);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -287,7 +287,7 @@ namespace FlaxEditor.Surface
/// <inheritdoc /> /// <inheritdoc />
public override bool ContainsPoint(ref Float2 location, bool precise) public override bool ContainsPoint(ref Float2 location, bool precise)
{ {
return _headerRect.Contains(ref location) || _resizeButtonRect.Contains(ref location); return _headerRect.Contains(location) || _resizeButtonRect.Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -297,7 +297,7 @@ namespace FlaxEditor.Surface
return true; return true;
// Check if can start resizing // Check if can start resizing
if (button == MouseButton.Left && _resizeButtonRect.Contains(ref location) && Surface.CanEdit) if (button == MouseButton.Left && _resizeButtonRect.Contains(location) && Surface.CanEdit)
{ {
// Start sliding // Start sliding
_isResizing = true; _isResizing = true;
@@ -336,7 +336,7 @@ namespace FlaxEditor.Surface
return true; return true;
// Rename // Rename
if (_headerRect.Contains(ref location) && Surface.CanEdit) if (_headerRect.Contains(location) && Surface.CanEdit)
{ {
StartRenaming(); StartRenaming();
return true; return true;
@@ -404,14 +404,14 @@ namespace FlaxEditor.Surface
return true; return true;
// Close // Close
if (_closeButtonRect.Contains(ref location) && Surface.CanEdit) if (_closeButtonRect.Contains(location) && Surface.CanEdit)
{ {
Surface.Delete(this); Surface.Delete(this);
return true; return true;
} }
// Color // Color
if (_colorButtonRect.Contains(ref location) && Surface.CanEdit) if (_colorButtonRect.Contains(location) && Surface.CanEdit)
{ {
ColorValueBox.ShowPickColorDialog?.Invoke(this, Color, OnColorChanged); ColorValueBox.ShowPickColorDialog?.Invoke(this, Color, OnColorChanged);
return true; return true;

View File

@@ -93,7 +93,7 @@ namespace FlaxEditor.Surface
/// <returns><c>true</c> if the selection rectangle is intersecting with the selectable parts of the control ; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if the selection rectangle is intersecting with the selectable parts of the control ; otherwise, <c>false</c>.</returns>
public virtual bool IsSelectionIntersecting(ref Rectangle selectionRect) public virtual bool IsSelectionIntersecting(ref Rectangle selectionRect)
{ {
return Bounds.Intersects(ref selectionRect); return Bounds.Intersects(selectionRect);
} }
/// <summary> /// <summary>

View File

@@ -868,7 +868,7 @@ namespace FlaxEditor.Surface
} }
/// <inheritdoc /> /// <inheritdoc />
protected override bool ShowTooltip => base.ShowTooltip && _headerRect.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened; protected override bool ShowTooltip => base.ShowTooltip && _headerRect.Contains(_mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
/// <inheritdoc /> /// <inheritdoc />
public override bool OnShowTooltip(out string text, out Float2 location, out Rectangle area) public override bool OnShowTooltip(out string text, out Float2 location, out Rectangle area)
@@ -898,13 +898,13 @@ namespace FlaxEditor.Surface
/// <inheritdoc /> /// <inheritdoc />
public override bool OnTestTooltipOverControl(ref Float2 location) public override bool OnTestTooltipOverControl(ref Float2 location)
{ {
return _headerRect.Contains(ref location) && ShowTooltip && !Surface.IsConnecting && !Surface.IsSelecting; return _headerRect.Contains(location) && ShowTooltip && !Surface.IsConnecting && !Surface.IsSelecting;
} }
/// <inheritdoc /> /// <inheritdoc />
public override bool CanSelect(ref Float2 location) public override bool CanSelect(ref Float2 location)
{ {
return _headerRect.MakeOffsetted(Location).Contains(ref location); return _headerRect.MakeOffsetted(Location).Contains(location);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -1056,7 +1056,7 @@ namespace FlaxEditor.Surface
// Header // Header
var headerColor = style.BackgroundHighlighted; var headerColor = style.BackgroundHighlighted;
if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting) if (_headerRect.Contains(_mousePosition) && !Surface.IsConnecting && !Surface.IsSelecting)
headerColor *= 1.07f; headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor); Render2D.FillRectangle(_headerRect, headerColor);
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center); Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
@@ -1099,7 +1099,7 @@ namespace FlaxEditor.Surface
if (base.OnMouseDown(location, button)) if (base.OnMouseDown(location, button))
return true; return true;
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location)) if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(location))
return true; return true;
if (button == MouseButton.Right) if (button == MouseButton.Right)
mouseDownMousePosition = Input.Mouse.Position; mouseDownMousePosition = Input.Mouse.Position;
@@ -1115,7 +1115,7 @@ namespace FlaxEditor.Surface
// Close/ delete // Close/ delete
bool canDelete = !Surface.IsConnecting && !Surface.WasSelecting && !Surface.WasMovingSelection; bool canDelete = !Surface.IsConnecting && !Surface.WasSelecting && !Surface.WasMovingSelection;
if (button == MouseButton.Left && canDelete && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location)) if (button == MouseButton.Left && canDelete && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(location))
{ {
Surface.Delete(this); Surface.Delete(this);
return true; return true;

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