227 Commits

Author SHA1 Message Date
74dcea373c Allow reimporting model prefabs from Content window context menu
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
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2024-06-01 21:43:42 +03:00
70f8492c01 Fix missing vertices in some imported models
The Spatial Sort version was being too greedy when merging vertices
2024-06-01 21:43:42 +03:00
63acdccd43 Fix typos 2024-06-01 21:43:41 +03:00
03f74b0c50 Implement triangulation for non-convex polygons 2024-06-01 21:43:41 +03:00
0d21a3ba1b Fix compile errors in libdeflate 2024-06-01 21:43:41 +03:00
d85a5bcd36 Reapply OpenFBX patches 2024-06-01 21:43:40 +03:00
585ebceb6a Update OpenFBX
Updated to commit 365f52c1edad6bd283c8a645f1d8d2347dbd1e35
2024-06-01 21:43:40 +03:00
593c82543f Limit MSVC compiler code generation threads to one per file 2024-06-01 21:43:39 +03:00
7f1bcd91f5 Remove redundant asset waiting and reloading when saving materials 2024-06-01 21:43:39 +03:00
58214ffc35 Fix RichTextBox not drawing the last character 2024-06-01 21:43:39 +03:00
67b4b01697 _binaries 2024-06-01 21:43:21 +03:00
bd880c0e2f _lfsconfig 2024-06-01 21:43:20 +03:00
0bca21a1d4 Fix compilation errors with miniz 2024-06-01 21:28:23 +03:00
c5e3d4afd3 Update miniz for tinyexr 2024-06-01 21:28:21 +03:00
bb1bee40e4 Fix alignment issues in stack allocators 2024-05-19 23:58:44 +03:00
1b0b8998f9 Hide Visual Studio solution architectures not supported by main project 2024-05-19 23:58:43 +03:00
e4764c4d84 Skip setup of ARM64 configuration for Windows with no compiler support 2024-05-19 23:58:43 +03:00
2de756f761 Include configuration specific source files in solution configurations
Include only relevant generated source files for selected solution
configuration. Fixes Intellisense issues when both ARM64 and Win64
configurations are present in project.
2024-05-19 23:58:43 +03:00
83f40be4f5 Copy hostfxr from platform architecture specific dependencies folder 2024-05-19 23:58:43 +03:00
87a73c9b73 Add cooking support for Windows on ARM 2024-05-19 23:58:42 +03:00
7054f942f6 Update minimp3 2024-05-19 23:58:42 +03:00
227eaff9e2 Patch rapidjson for Windows on ARM 2024-05-19 23:58:42 +03:00
563a45633f Patch tracy for Windows on ARM 2024-05-19 23:58:42 +03:00
09e0754902 Compile glslang for Windows on ARM 2024-05-19 23:58:41 +03:00
3dfe0e6c5a Compile assimp for Windows on ARM 2024-05-19 23:58:41 +03:00
9e7af72046 Add dependencies to copy dbghelp and dxcompiler files from SDK 2024-05-19 23:58:41 +03:00
96eb8cb0ca Build astc for Windows on ARM 2024-05-19 23:58:41 +03:00
ff86057a0a Update OpenAL to use CMake for compilation on Windows 2024-05-19 23:58:40 +03:00
56abd82c9b Update ogg and vorbis to use CMake for compilation on Windows 2024-05-19 23:58:40 +03:00
9777bef9df Patch pix3.h for Windows on ARM 2024-05-19 23:58:40 +03:00
9fedacb404 Use VS2022 Win10 MSVC solutions in DirectX-related dependencies 2024-05-19 23:58:40 +03:00
84f7fde753 Build NvCloth for Windows on ARM 2024-05-19 23:58:39 +03:00
a5566d297f Update PhysX with Windows on ARM support 2024-05-19 23:58:39 +03:00
3f299f99cd Update curl to 7.88.1 2024-05-19 23:58:39 +03:00
741fc959e6 Update Freetype to 2.13.2 2024-05-19 23:58:38 +03:00
93fd560723 Fix rebuilding dependencies using Git with existing local folders 2024-05-19 23:58:38 +03:00
cf48ce6d93 Fallback to D3D11 devices without debug layers when unavailable 2024-05-19 23:58:38 +03:00
bdd3b754bd Support using native host MSVC binaries on ARM64 2024-05-19 23:58:38 +03:00
99c27c9c30 Support ARM64 architecture under Windows 2024-05-19 23:58:37 +03:00
Wojtek Figat
97be8ee8cc Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Source/Engine/Content/Storage/FlaxStorage.cpp
#	Source/Engine/Renderer/GBufferPass.cpp
2024-05-15 23:49:05 +02:00
Wojtek Figat
1d6e8c4b7c Add video support on Android 2024-05-15 23:39:10 +02:00
Wojtek Figat
1cd2f6a070 Fix compilation when using non-strongly typed enum as default value 2024-05-15 13:23:30 +02:00
Wojtek Figat
35ddfc2455 Add test case of nested types in scripting
#2582 #2591
2024-05-15 13:09:51 +02:00
Wojtek Figat
17d1d87268 Merge branch 'GoaLitiuM-nested_type_fixes' 2024-05-15 12:51:57 +02:00
Wojtek Figat
fd871ce830 Merge branch 'nested_type_fixes' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-nested_type_fixes 2024-05-15 12:50:44 +02:00
Wojtek Figat
b4a4a8a591 Minor code cleanup 2024-05-15 12:40:08 +02:00
Wojtek Figat
24e4015425 Merge branch 'Tryibion-font-case' 2024-05-15 12:30:43 +02:00
Wojtek Figat
c670887b1a Merge branch 'font-case' of https://github.com/Tryibion/FlaxEngine into Tryibion-font-case 2024-05-15 12:30:39 +02:00
Wojtek Figat
d3cd6a461b Merge branch 'Tryibion-ui-edit-handles' 2024-05-15 12:26:25 +02:00
Wojtek Figat
2625a9d762 Merge branch 'ui-edit-handles' of https://github.com/Tryibion/FlaxEngine into Tryibion-ui-edit-handles 2024-05-15 12:26:20 +02:00
Wojtek Figat
4fdd9a242b Merge branch 'Tryibion-add-script' 2024-05-15 12:26:06 +02:00
Wojtek Figat
a6e8e6f749 Merge branch 'add-script' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-script 2024-05-15 12:25:59 +02:00
Wojtek Figat
03eabbcf63 Merge branch 'Tryibion-control-trans-dup' 2024-05-15 12:25:34 +02:00
Wojtek Figat
13f94dcf11 Merge branch 'control-trans-dup' of https://github.com/Tryibion/FlaxEngine into Tryibion-control-trans-dup 2024-05-15 12:25:28 +02:00
Wojtek Figat
3b44062eb0 Merge branch 'Tryibion-checkerboard-colorpicker' 2024-05-15 12:25:13 +02:00
Wojtek Figat
1457637707 Merge branch 'checkerboard-colorpicker' of https://github.com/Tryibion/FlaxEngine into Tryibion-checkerboard-colorpicker 2024-05-15 12:25:08 +02:00
Wojtek Figat
d28567111f Merge branch 'Tryibion-treenode-guidelines' 2024-05-15 12:24:17 +02:00
Wojtek Figat
1c7f06e570 Merge branch 'treenode-guidelines' of https://github.com/Tryibion/FlaxEngine into Tryibion-treenode-guidelines 2024-05-15 12:24:12 +02:00
Wojtek Figat
63cc0fef2e Merge branch 'Tryibion-tooltip-text-padding' 2024-05-15 12:23:52 +02:00
Wojtek Figat
57084b3d6c Merge branch 'tooltip-text-padding' of https://github.com/Tryibion/FlaxEngine into Tryibion-tooltip-text-padding 2024-05-15 12:23:47 +02:00
Wojtek Figat
fa23619f08 Merge branch 'Tryibion-scroll-colors' 2024-05-15 12:23:12 +02:00
Wojtek Figat
1f2456fc67 Merge branch 'scroll-colors' of https://github.com/Tryibion/FlaxEngine into Tryibion-scroll-colors 2024-05-15 12:23:08 +02:00
Wojtek Figat
0b71e906a6 Merge branch 'Tryibion-textbox-add' 2024-05-15 12:22:47 +02:00
Wojtek Figat
2e59c35a44 Merge branch 'textbox-add' of https://github.com/Tryibion/FlaxEngine into Tryibion-textbox-add 2024-05-15 12:22:40 +02:00
Wojtek Figat
6f2bd0e932 Another attempt on 6a883bc7c6 2024-05-15 11:22:07 +02:00
Wojtek Figat
82bf4238df Add support for decoding NV12 into RGB image 2024-05-15 11:15:19 +02:00
Wojtek Figat
9d2dc91920 Add PixelFormat::NV12 2024-05-15 11:14:16 +02:00
Wojtek Figat
3ae30a59b3 Fix engine with c# scripting disabled 2024-05-14 13:13:37 +02:00
Wojtek Figat
6a883bc7c6 Revert file handles bug 2024-05-14 09:03:52 +02:00
Chandler Cox
17de6388ca Code fix 2024-05-13 17:42:37 -05:00
Chandler Cox
e028d263f1 Remove unused include. 2024-05-13 16:38:38 -05:00
Chandler Cox
6962ed6730 Fix case spelling 2024-05-13 16:38:10 -05:00
Chandler Cox
b66d50ae1b Add font and case options to Label and Textbox 2024-05-13 16:34:23 -05:00
Wojtek Figat
a742ce1d32 Optimize FileReadStream seeking if new position is within the cached buffer 2024-05-13 22:40:27 +02:00
Chandler Cox
675ce71935 Draw hover before selection so that way ui selection is drawn on top. 2024-05-13 12:45:59 -05:00
Chandler Cox
833f844d59 Minor improvements to ui editor widget drawing. 2024-05-13 12:38:11 -05:00
Wojtek Figat
af08dc1c69 Fix ReadOnly attribute handling in collection editors 2024-05-13 16:08:50 +02:00
Wojtek Figat
3593f835cd Remove unused property of video player 2024-05-13 15:03:55 +02:00
Wojtek Figat
df086f3b3b Add more backends 2024-05-13 15:03:44 +02:00
Chandler Cox
07628d2ec7 Clean up code 2024-05-11 21:31:00 -05:00
Chandler Cox
aac3dbfe09 Fix control transform duplicating when changing anchor. 2024-05-11 21:29:45 -05:00
Chandler Cox
185f24ce49 Fix value alpha transparency being applied twice to preview color. 2024-05-11 20:19:51 -05:00
77e29109ee Fix native internal type name for deeply nested types 2024-05-11 15:48:49 +03:00
8d89b9efb0 Fix internal type name for nested blittable element types 2024-05-11 15:48:43 +03:00
Chandler Cox
b2fee31a13 Add checkerboard background to color picker dialog color. 2024-05-10 20:30:14 -05:00
Chandler Cox
fc7628e2ee Add tree node guidlines 2024-05-10 19:22:23 -05:00
Chandler Cox
2e3e4959d6 Add width padding for tooltip 2024-05-10 17:18:10 -05:00
Chandler Cox
f22105c2c3 Allow adding script via drag drop 2024-05-10 16:58:40 -05:00
Chandler Cox
533902d185 Change panel scroll bar style editor order. 2024-05-10 15:04:27 -05:00
Wojtek Figat
6b31d51e31 Add volume, pan and spatial audio options for video playback 2024-05-10 13:54:52 +02:00
Wojtek Figat
f0d143ecaa Fix decoding 480p videos 2024-05-10 13:29:08 +02:00
Wojtek Figat
196aa020fd Fix video playback if fie has no audio track 2024-05-10 13:16:07 +02:00
Wojtek Figat
ffe5105602 Fixes for audio playback in videos 2024-05-10 13:12:07 +02:00
Wojtek Figat
4acaa62a07 Fix crash in AudioBackendOAL::Source_DequeueProcessedBuffers when buffer count is large 2024-05-10 12:52:07 +02:00
Wojtek Figat
68653fa91f Add small code optimizations 2024-05-10 12:27:28 +02:00
Chandler Cox
dc0aa61a14 Add scrollbar colors to Panel 2024-05-09 22:14:08 -05:00
Chandler Cox
ee790ff3a9 Change colors for tabs to be seen better. 2024-05-09 21:53:22 -05:00
Chandler Cox
a2a3926aee Expose colors in scrollbar 2024-05-09 21:53:04 -05:00
Chandler Cox
9a70344c1f Fix carrot location on text box with no text. Add vertical and horizontal alignment options to textbox. 2024-05-09 21:31:54 -05:00
Wojtek Figat
44006dd533 Various code improvements 2024-05-09 18:59:09 +02:00
Wojtek Figat
f6aabf2d14 Optimize navmesh building and reduce scene lock time 2024-05-09 18:58:47 +02:00
Wojtek Figat
dc1f15f18d Add OnStaticFlagsChanged to Actor 2024-05-09 16:55:05 +02:00
Wojtek Figat
7d7808af8f Remove default value tooltips from post process docs to prevent errors 2024-05-09 10:56:42 +02:00
Wojtek Figat
5029584a9f Fix crash when Visual Script event binding instance is invalid
#2548
2024-05-09 10:17:23 +02:00
Wojtek Figat
f353d3f114 Fix looping root motion 2024-05-09 10:16:45 +02:00
Wojtek Figat
667e8bc293 Minor cleanup in anim code 2024-05-09 10:16:34 +02:00
Wojtek Figat
2edb9cc4d8 Fix compilation warnings when using 64-bit coords 2024-05-08 23:24:23 +02:00
Wojtek Figat
7018666a8c Add layer masking for PostFxVolume against Camera's RenderLayersMask
#2573
2024-05-08 22:42:35 +02:00
Wojtek Figat
f04926ad94 Merge branch 'GoaLitiuM-treenode_expanded_fix' 2024-05-08 19:30:55 +02:00
Wojtek Figat
e7508538e0 Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Flax.flaxproj
2024-05-08 19:27:56 +02:00
50f5f0acd9 Fix TreeNode rendering issues with expanded nodes 2024-05-08 20:15:55 +03:00
Wojtek Figat
33202a74b0 Fix 2024-05-08 19:15:25 +02:00
Wojtek Figat
3745979b81 Add attributes for game into AndroidManifest 2024-05-08 18:49:16 +02:00
Wojtek Figat
db15f6f08a Add For Distribution to be enabled by default in Release builds
#2571
2024-05-08 18:48:55 +02:00
Wojtek Figat
e1a2f51d5a Merge branch 'GoaLitiuM-editor_font_validation' 2024-05-08 18:17:53 +02:00
Wojtek Figat
a8e1fd7a4a Merge branch 'editor_font_validation' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-editor_font_validation 2024-05-08 18:17:46 +02:00
Wojtek Figat
d46ef6ac92 Merge branch 'Tryibion-add-shift-scroll' 2024-05-08 18:17:20 +02:00
Wojtek Figat
36d21b27c7 Merge branch 'add-shift-scroll' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-shift-scroll 2024-05-08 18:17:13 +02:00
Wojtek Figat
b1636c27e7 Merge branch 'Tryibion-Move-control-transform' 2024-05-08 17:39:48 +02:00
Wojtek Figat
5d32fc6c5e Merge branch 'Move-control-transform' of https://github.com/Tryibion/FlaxEngine into Tryibion-Move-control-transform 2024-05-08 17:31:47 +02:00
Wojtek Figat
065dc474c0 Merge branch 'Tryibion-game-window-focus-issue' 2024-05-08 17:31:16 +02:00
Wojtek Figat
1fb7b24aad Merge branch 'game-window-focus-issue' of https://github.com/Tryibion/FlaxEngine into Tryibion-game-window-focus-issue 2024-05-08 17:31:08 +02:00
Wojtek Figat
f0b72aa025 Merge branch 'Tryibion-color-picker' 2024-05-08 17:30:50 +02:00
Wojtek Figat
058077736b Merge branch 'color-picker' of https://github.com/Tryibion/FlaxEngine into Tryibion-color-picker 2024-05-08 17:30:45 +02:00
Wojtek Figat
571ba6773d Optimize win32 filesystem access via static buffer or unlimited path len 2024-05-08 17:28:46 +02:00
Wojtek Figat
40652a0ebc Fix HashSet adding item via move operation 2024-05-08 17:28:14 +02:00
Wojtek Figat
481a6de821 Add support for cooking raw files referenced by assets 2024-05-08 17:27:46 +02:00
Wojtek Figat
66b828ae92 Refactor Asset::GetReferences to support file path references 2024-05-08 15:54:37 +02:00
Wojtek Figat
b91f51fb46 Add async videos update 2024-05-08 12:35:18 +02:00
Wojtek Figat
b02f011627 Merge branch 'GoaLitiuM-drawtext_fix' 2024-05-08 10:34:33 +02:00
Wojtek Figat
e51d2dda00 Fix playing 6-channel audio with XAudio2 backend 2024-05-08 10:20:04 +02:00
Wojtek Figat
a11fa46ee2 Add cpu profile events to GPU tasks executor queue 2024-05-08 10:19:39 +02:00
Wojtek Figat
47f3ecbde2 Fix video player shutdown on editor window close 2024-05-08 10:19:22 +02:00
Wojtek Figat
deb2319190 Add audio playback support to video player 2024-05-08 10:19:08 +02:00
ea04c746fd Fix Editor not launching if custom interface fonts are missing 2024-05-07 21:18:09 +03:00
97454fc82e Fix drawing an extra character with Render2D.DrawText 2024-05-07 20:10:05 +03:00
Chandler Cox
4a6afdb108 Small fixes for color picker. 2024-05-07 08:41:23 -05:00
Wojtek Figat
4b8970f674 Update assets 2024-05-06 10:41:07 +02:00
Wojtek Figat
f43cd97907 Refactor Audio Backend to not depend on AudioSource object 2024-05-06 10:36:36 +02:00
Wojtek Figat
65e852600a Merge branch 'Tryibion-skip-empty-layers' 2024-05-05 22:56:47 +02:00
Wojtek Figat
fedd990c13 Merge branch 'skip-empty-layers' of https://github.com/Tryibion/FlaxEngine into Tryibion-skip-empty-layers 2024-05-05 22:56:41 +02:00
Wojtek Figat
c0329abe40 Merge branch 'Tryibion-fix-properties-1st-offset' 2024-05-05 22:55:30 +02:00
Wojtek Figat
d8850a56a8 Merge branch 'fix-properties-1st-offset' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-properties-1st-offset 2024-05-05 22:55:26 +02:00
Wojtek Figat
e171bb06ec Merge branch 'GoaLitiuM-unbox_array_fix' 2024-05-05 22:54:18 +02:00
Wojtek Figat
3825e07adc Merge branch 'unbox_array_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-unbox_array_fix 2024-05-05 22:54:12 +02:00
Wojtek Figat
db8adf7d96 Fix creating virtual terrain collision of actor that is not in a game 2024-05-05 22:50:12 +02:00
e77ae12b9b Fix unboxing of array type Variants 2024-05-05 13:15:54 +03:00
Chandler Cox
bf4e4aeaf6 Fix bottom offset for last property label and property 2024-05-04 22:32:00 -05:00
Chandler Cox
2107b069db Fix odd offset between 1st property and property label. 2024-05-04 19:25:56 -05:00
Chandler Cox
ea2005dacb Add layer number to LayerMask UI 2024-05-04 18:08:53 -05:00
Chandler Cox
d5cded8aaa Skip empty layers for LayerMask Editor 2024-05-04 17:51:27 -05:00
Chandler Cox
430b22d5d7 Dont unfocus game window while cursor is not visible unless the lock mode is none. 2024-05-04 17:37:32 -05:00
Wojtek Figat
5b2af6b3d5 Refactor Audio Backend to not depend on AudioListener object 2024-05-04 22:16:20 +02:00
Wojtek Figat
f604503566 Refactor Audio Backend to support single listener only 2024-05-04 21:47:47 +02:00
Wojtek Figat
388a0f4196 Add initial audio buffer support in video player 2024-05-03 14:32:23 +02:00
Wojtek Figat
754ed56119 Add FilePathEditor custom editor for path-based editing asset/url refs with a file picker 2024-05-03 12:26:03 +02:00
Wojtek Figat
dca8e391fa Rollback video thumbnail as generic for now 2024-05-02 18:48:49 +02:00
Wojtek Figat
9d830eb1e2 Fix crash when using scripting object as interface implementation in object property displayed in Editor
#2493
2024-05-02 18:31:30 +02:00
Wojtek Figat
7e3f84f95e Merge branch 'Tryibion-gg-keep-last-type' 2024-05-02 15:57:50 +02:00
Wojtek Figat
cddee38d71 Merge branch 'gg-keep-last-type' of https://github.com/Tryibion/FlaxEngine into Tryibion-gg-keep-last-type 2024-05-02 15:57:45 +02:00
Wojtek Figat
e030d0461b Merge branch 'Tryibion-smoothstep-node-width' 2024-05-02 15:57:31 +02:00
Wojtek Figat
4978c8e0d9 Merge branch 'smoothstep-node-width' of https://github.com/Tryibion/FlaxEngine into Tryibion-smoothstep-node-width 2024-05-02 15:57:20 +02:00
Wojtek Figat
dc7b7e6e10 Merge branch 'Tryibion-rename-trim' 2024-05-02 15:56:33 +02:00
Wojtek Figat
1e3eb11b94 Merge branch 'rename-trim' of https://github.com/Tryibion/FlaxEngine into Tryibion-rename-trim 2024-05-02 15:56:25 +02:00
Wojtek Figat
b15b231b85 Merge branch 'Tryibion-windows-hide-cursor' 2024-05-02 15:55:56 +02:00
Wojtek Figat
262992571a Merge branch 'windows-hide-cursor' of https://github.com/Tryibion/FlaxEngine into Tryibion-windows-hide-cursor 2024-05-02 15:55:50 +02:00
Wojtek Figat
352bf3f9a7 Merge branch 'Tryibion-fix-toolbox-panel-size' 2024-05-02 15:55:29 +02:00
Chandler Cox
9683868767 Add shift scroll for panels and textbox 2024-05-01 16:12:53 -05:00
Chandler Cox
40284fbbf8 Fix smooth step visject node width 2024-05-01 14:05:10 -05:00
Chandler Cox
0c86a900da Default gameplay global type selection to last selected type. 2024-05-01 13:54:41 -05:00
Chandler Cox
c1e3eaeab1 Force windows cursor to show or hide based on cursor hidden value 2024-05-01 13:23:56 -05:00
Chandler Cox
3c487dff47 Trim actor name on rename. 2024-05-01 12:01:01 -05:00
Chandler Cox
2260d79e26 Trim content item name on rename 2024-05-01 11:54:07 -05:00
Wojtek Figat
863794d3c0 Add playback buttons and info label to Video Player actor editor 2024-05-01 01:30:03 +02:00
Wojtek Figat
0d8c9f6626 Add Video module 2024-05-01 01:25:16 +02:00
Wojtek Figat
8a45dda98c Add support for custom file proxies in Editor 2024-05-01 01:05:15 +02:00
Chandler Cox
3209320547 Add margin to item tree in toolbox 2024-04-30 15:05:58 -05:00
Chandler Cox
d1db06a9bb Change text alignment to far on some control transform properties 2024-04-29 19:44:49 -05:00
Chandler Cox
1c1d2fd96f Fix still showing some control transform properties in wrong spot. 2024-04-29 19:38:36 -05:00
Chandler Cox
2e5ad8c48a Always set control transform under general tab 2024-04-29 18:28:04 -05:00
Chandler Cox
9a6f866956 Move control transform to be under general group in layout. 2024-04-29 18:24:01 -05:00
Wojtek Figat
0cdce9dba2 Upgrade GDK to 230305 and support v143 MSVC toolset 2024-04-25 23:09:18 +02:00
Wojtek Figat
97078cda7e Fix GPU Tasks queue to be executed on frame start, rather than end 2024-04-25 17:10:39 +02:00
Wojtek Figat
10c47b8c2a Fix missing namespace 2024-04-25 17:09:54 +02:00
Wojtek Figat
3ebf73ec22 Add video texture format YUY2 2024-04-25 10:26:23 +02:00
Wojtek Figat
ebe05d4a51 Refactor RenderToolsDX to support new pixel formats properly 2024-04-24 17:35:58 +02:00
Wojtek Figat
cdeb9a3b15 Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Content/Editor/Camera/M_Camera.flax
#	Content/Editor/CubeTexturePreviewMaterial.flax
#	Content/Editor/DebugMaterials/DDGIDebugProbes.flax
#	Content/Editor/DebugMaterials/SingleColor/Decal.flax
#	Content/Editor/DebugMaterials/SingleColor/Particle.flax
#	Content/Editor/DebugMaterials/SingleColor/Surface.flax
#	Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
#	Content/Editor/DebugMaterials/SingleColor/Terrain.flax
#	Content/Editor/DefaultFontMaterial.flax
#	Content/Editor/Gizmo/FoliageBrushMaterial.flax
#	Content/Editor/Gizmo/Material.flax
#	Content/Editor/Gizmo/MaterialWire.flax
#	Content/Editor/Gizmo/SelectionOutlineMaterial.flax
#	Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
#	Content/Editor/Highlight Material.flax
#	Content/Editor/Icons/IconsMaterial.flax
#	Content/Editor/IesProfilePreviewMaterial.flax
#	Content/Editor/Particles/Particle Material Color.flax
#	Content/Editor/Particles/Smoke Material.flax
#	Content/Editor/SpriteMaterial.flax
#	Content/Editor/Terrain/Circle Brush Material.flax
#	Content/Editor/Terrain/Highlight Terrain Material.flax
#	Content/Editor/TexturePreviewMaterial.flax
#	Content/Editor/Wires Debug Material.flax
#	Content/Engine/DefaultDeformableMaterial.flax
#	Content/Engine/DefaultMaterial.flax
#	Content/Engine/DefaultTerrainMaterial.flax
#	Content/Engine/SingleColorMaterial.flax
#	Content/Engine/SkyboxMaterial.flax
#	Source/Engine/Graphics/Materials/MaterialShader.h
2024-04-23 10:30:01 +02:00
Wojtek Figat
60e8d73079 Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Source/Engine/Renderer/RenderList.cpp
#	Source/Engine/Renderer/RenderList.h
2024-04-17 09:58:59 +02:00
Wojtek Figat
cf23892bd4 Fix sun shadows invalidate when view rotates 2024-04-14 23:51:20 +02:00
Wojtek Figat
25f3cef8c3 Fix artifacts due to light shape culling and use depth test to improve perf 2024-04-14 23:44:08 +02:00
Wojtek Figat
00f2a0b825 Improve doc 2024-04-12 11:29:21 +02:00
Wojtek Figat
7342629a86 Add dynamic resolution for static shadow map tiles limited by current dynamic res 2024-04-11 18:47:32 +02:00
Wojtek Figat
5f860db6a5 Fix typo 2024-04-11 17:34:21 +02:00
Wojtek Figat
6233718b06 Update engine shaders 2024-04-11 17:33:42 +02:00
Wojtek Figat
62444315de Add METERS_TO_UNITS and impl metric units in shadows rendering 2024-04-11 16:38:43 +02:00
Wojtek Figat
a532ea7b42 Add InvalidateShadow for manual shadow cache refresh 2024-04-11 16:34:42 +02:00
Wojtek Figat
803249f126 Minor tweaks 2024-04-11 16:19:35 +02:00
Wojtek Figat
4e65b76b8c Optimize BoundingSphere.Intersects to be inlined by the compiler 2024-04-11 15:58:34 +02:00
Wojtek Figat
890b2da108 Add **shadows caching for static geometry** 2024-04-11 15:35:18 +02:00
Wojtek Figat
eac1d19a09 Add additional StaticFlagsCompare to Render View for dynamic or static only drawing 2024-04-11 10:21:13 +02:00
Wojtek Figat
c4949de28f Add new Static Flag Shadow for cached shadow maps 2024-04-11 10:20:21 +02:00
Wojtek Figat
340ef194d3 Add grey out to obsolete/deprecated members in properties panel 2024-04-10 13:36:59 +02:00
Wojtek Figat
b4547ec4d2 Minor fixes 2024-04-10 11:03:33 +02:00
Wojtek Figat
89f7e442f7 Fix point light seams due to missing shadow map borders 2024-04-10 11:03:18 +02:00
Wojtek Figat
e7bef5e880 Bring back Optimized PCF sampling for shadow maps
61323f8526
2024-04-09 17:55:29 +02:00
Wojtek Figat
ff7c986fb1 Add better stability to Cascaded Shadow Maps projection 2024-04-09 16:58:22 +02:00
Wojtek Figat
708fba5136 Add variable rate update for shadow maps atlas based on distance to light 2024-04-08 00:04:57 +02:00
Wojtek Figat
7d92779e99 Merge remote-tracking branch 'origin/master' into 1.9 2024-04-05 21:50:42 +02:00
Wojtek Figat
4c8528dcae Remove branch macro as it's just texture sample in lights shader 2024-04-05 12:48:34 +02:00
Wojtek Figat
3efd1e4e84 Optimize local lights sphere mesh rendering to match the area better 2024-04-05 12:48:09 +02:00
Wojtek Figat
0cc6669cbd Reimplement cascaded shadow maps blending via dithering 2024-04-05 10:59:34 +02:00
Wojtek Figat
8bd409e95d DIsable certain shader features in Volumetric Fog shader 2024-04-04 14:35:22 +02:00
Wojtek Figat
3d0d41ebff Add reducing shadows quality for smaller local lights 2024-04-04 13:29:38 +02:00
Wojtek Figat
61323f8526 Refactor shadows rendering to use Shadow Map Atlas 2024-04-04 12:54:07 +02:00
Wojtek Figat
017def29d4 Rename ShadowSamplerPCF to ShadowSamplerLinear 2024-04-03 13:29:45 +02:00
Wojtek Figat
13a04c2941 Add stencilValue for stencil buffer clearing 2024-04-02 14:56:26 +02:00
Wojtek Figat
bc9cdf5cdb Update version 2024-04-02 14:34:43 +02:00
Wojtek Figat
f7470af42d Optimize depth pass rendering to batch simple materials together 2024-03-26 18:04:08 +01:00
Wojtek Figat
5c356ec22a Fix Global Surface Atlas defragmentation flicker when atlas it nearly full 2024-03-26 16:50:58 +01:00
Wojtek Figat
06a35da0a8 Merge remote-tracking branch 'origin/master' into 1.9 2024-03-26 16:45:31 +01:00
Wojtek Figat
55af307c43 Optimize env probes data storage in renderer 2024-03-26 15:01:12 +01:00
Wojtek Figat
4ab572426d Various renamings 2024-03-26 14:27:10 +01:00
Wojtek Figat
01d91bf102 Optimize decals rendering 2024-03-26 14:05:24 +01:00
Wojtek Figat
2dfb1058b2 Optimize world matrix storage for drawable objects to use Matrix3x4 instead of full matrix 2024-03-26 11:29:01 +01:00
Wojtek Figat
cdbb2cc813 Refactor shader structures naming with a prefix 2024-03-25 17:52:48 +01:00
Wojtek Figat
0e00f1e0eb Refactor lights data in renderer storage 2024-03-25 17:13:40 +01:00
Wojtek Figat
d13621e631 Skip CloseFileHandles if file is not in use 2024-03-25 16:50:48 +01:00
650 changed files with 31172 additions and 11346 deletions

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server
[lfs]
url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

View File

@@ -16,7 +16,6 @@
#include "./Flax/ExponentialHeightFog.hlsl"
@2// Forward Shading: Constants
LightData DirectionalLight;
LightShadowData DirectionalLightShadow;
LightData SkyLight;
ProbeData EnvironmentProbe;
ExponentialHeightFogData ExponentialHeightFog;
@@ -26,9 +25,9 @@ LightData LocalLights[MAX_LOCAL_LIGHTS];
@3// Forward Shading: Resources
TextureCube EnvProbe : register(t__SRV__);
TextureCube SkyLightTexture : register(t__SRV__);
Texture2DArray DirectionalLightShadowMap : register(t__SRV__);
Buffer<float4> ShadowsBuffer : register(t__SRV__);
Texture2D<float> ShadowMap : register(t__SRV__);
@4// Forward Shading: Utilities
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
@5// Forward Shading: Shaders
// Pixel Shader function for Forward Pass
@@ -80,11 +79,8 @@ void PS_Forward(
// Calculate lighting from a single directional light
float4 shadowMask = 1.0f;
if (DirectionalLight.CastShadows > 0)
{
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
}
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
shadowMask = GetShadowMask(shadow);
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
// Calculate lighting from sky light

View File

@@ -26,7 +26,7 @@ struct RibbonInput
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x3 WorldMatrix;
uint SortedIndicesOffset;
float PerInstanceRandom;
int ParticleStride;
@@ -45,7 +45,7 @@ int RibbonWidthOffset;
int RibbonTwistOffset;
int RibbonFacingVectorOffset;
uint RibbonSegmentCount;
float4x4 WorldMatrixInverseTransposed;
float4x3 WorldMatrixInverseTransposed;
@1META_CB_END
// Particles attributes buffer
@@ -138,7 +138,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
#else
#define GetInstanceTransform(input) WorldMatrix;
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -264,12 +264,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input)
{
return mul(float4(input, 1.0f), WorldMatrix).xyz;
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
}
float3 TransformParticleVector(float3 input)
{
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
}
@8
@@ -333,7 +333,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
float4x4 world = WorldMatrix;
float4x4 world = ToMatrix4x4(WorldMatrix);
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
float3x3 viewRot = transpose((float3x3)ViewMatrix);
float3 position = mul(float4(particlePosition, 1), world).xyz;
@@ -463,11 +463,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
}
// Read particle data
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1;
float3 position = mul(float4(particlePosition, 1), WorldMatrix).xyz;
float3 position = mul(float4(particlePosition, 1), worldMatrix).xyz;
// Compute final vertex position in the world
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
@@ -506,7 +507,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
world = mul(world, scaleMatrix);
}
world = transpose(world);
world = mul(world, WorldMatrix);
world = mul(world, worldMatrix);
// Calculate the vertex position in world space
output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
@@ -520,12 +521,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
#if USE_VERTEX_COLOR
output.VertexColor = input.Color;
#endif
output.InstanceOrigin = WorldMatrix[3].xyz;
output.InstanceOrigin = worldMatrix[3].xyz;
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = CalcTangentToLocal(input);
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
half3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property
@@ -625,12 +626,13 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
#if USE_VERTEX_COLOR
output.VertexColor = 1;
#endif
output.InstanceOrigin = WorldMatrix[3].xyz;
float4x4 world = ToMatrix4x4(WorldMatrix);
output.InstanceOrigin = world[3].xyz;
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property

View File

@@ -10,8 +10,8 @@
@7
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x4 PrevWorldMatrix;
float4x3 WorldMatrix;
float4x3 PrevWorldMatrix;
float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
@@ -171,7 +171,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING
#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
#else
#define CalculateInstanceTransform(input) float4x4 world = WorldMatrix; output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#define CalculateInstanceTransform(input) float4x4 world = ToMatrix4x4(WorldMatrix); output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -328,7 +328,7 @@ VertexOutput VS(ModelInput input)
// Compute world space vertex position
CalculateInstanceTransform(input);
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
// Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -402,7 +402,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
#if USE_INSTANCING
float4x4 world = GetInstanceTransform(input);
#else
float4x4 world = WorldMatrix;
float4x4 world = ToMatrix4x4(WorldMatrix);
#endif
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
@@ -508,9 +508,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
#if PER_BONE_MOTION_BLUR
float3 prevPosition = SkinPrevPosition(input);
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#else
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(position, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#endif
// Compute clip space position

View File

@@ -17,7 +17,7 @@
@7
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x3 WorldMatrix;
float3 WorldInvScale;
float WorldDeterminantSign;
float PerInstanceRandom;
@@ -194,7 +194,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
// Transforms a vector from local space to world space
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
{
float3x3 localToWorld = (float3x3)WorldMatrix;
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localVector, localToWorld);
}
@@ -202,7 +202,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
// Transforms a vector from local space to world space
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
{
float3x3 localToWorld = (float3x3)WorldMatrix;
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localToWorld, worldVector);
}
@@ -210,7 +210,7 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
// Gets the current object position
float3 GetObjectPosition(MaterialInput input)
{
return WorldMatrix[3].xyz;
return ToMatrix4x4(WorldMatrix)[3].xyz;
}
// Gets the current object size
@@ -365,7 +365,8 @@ VertexOutput VS(TerrainVertexInput input)
float3 position = float3(positionXZ.x, height, positionXZ.y);
// Compute world space vertex position
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
// Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -389,7 +390,7 @@ VertexOutput VS(TerrainVertexInput input)
// Compute world space normal vector
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
float3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.Geometry.WorldNormal = tangentToWorld[2];
// Get material input params if need to evaluate any material property

View File

@@ -13,8 +13,8 @@
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 InverseViewProjectionMatrix;
float4x4 WorldMatrix;
float4x4 WorldMatrixInverseTransposed;
float4x3 WorldMatrix;
float4x3 WorldMatrixInverseTransposed;
float3 GridSize;
float PerInstanceRandom;
float Dummy0;
@@ -49,7 +49,7 @@ struct MaterialInput
#endif
};
#define GetInstanceTransform(input) WorldMatrix;
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
// Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
@@ -170,12 +170,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input)
{
return mul(float4(input, 1.0f), WorldMatrix).xyz;
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
}
float3 TransformParticleVector(float3 input)
{
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
}
@8
@@ -219,7 +219,7 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
materialInput.ParticleIndex = ParticleIndex;
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
materialInput.TwoSidedSign = 1.0f;
materialInput.InstanceOrigin = WorldMatrix[3].xyz;
materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz;
materialInput.InstanceParams = PerInstanceRandom;
materialInput.SvPosition = clipPos;
Material material = GetMaterialPS(materialInput);

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@@ -2,9 +2,9 @@
"Name": "Flax",
"Version": {
"Major": 1,
"Minor": 8,
"Revision": 1,
"Build": 6511
"Minor": 9,
"Revision": 0,
"Build": 6601
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",

View File

@@ -14,8 +14,8 @@ call "Development\Scripts\Windows\CallBuildTool.bat" -genproject %*
if errorlevel 1 goto BuildToolFailed
:: Build bindings for all editor configurations
echo Building C# bindings...
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
::echo Building C# bindings...
::Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
popd
echo Done!

View File

@@ -1,3 +1,5 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using FlaxEditor.Scripting;
@@ -94,30 +96,8 @@ public class AssetPickerValidator : IContentItemOwner
/// </summary>
public string SelectedPath
{
get
{
string path = _selectedItem?.Path ?? _selected?.Path;
if (path != null)
{
// Convert into path relative to the project (cross-platform)
var projectFolder = Globals.ProjectFolder;
if (path.StartsWith(projectFolder))
path = path.Substring(projectFolder.Length + 1);
}
return path;
}
set
{
if (string.IsNullOrEmpty(value))
{
SelectedItem = null;
}
else
{
var path = StringUtils.IsRelative(value) ? Path.Combine(Globals.ProjectFolder, value) : value;
SelectedItem = Editor.Instance.ContentDatabase.Find(path);
}
}
get => Utilities.Utils.ToPathProject(_selectedItem?.Path ?? _selected?.Path);
set => SelectedItem = string.IsNullOrEmpty(value) ? null : Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(value));
}
/// <summary>
@@ -242,7 +222,7 @@ public class AssetPickerValidator : IContentItemOwner
/// <summary>
/// Initializes a new instance of the <see cref="AssetPickerValidator"/> class.
/// </summary>
/// <param name="assetType">The assets types that this picker accepts.</param>
/// <param name="assetType">The asset types that this picker accepts.</param>
public AssetPickerValidator(ScriptType assetType)
{
_type = assetType;

View File

@@ -0,0 +1,28 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Content item that contains video media file.
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetItem" />
public sealed class VideoItem : FileItem
{
/// <summary>
/// Initializes a new instance of the <see cref="VideoItem"/> class.
/// </summary>
/// <param name="path">The file path.</param>
public VideoItem(string path)
: base(path)
{
}
/// <inheritdoc />
public override string TypeDescription => "Video";
/// <inheritdoc />
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
}
}

View File

@@ -30,9 +30,7 @@ namespace FlaxEditor.Content
/// <summary>
/// Determines whether [is virtual proxy].
/// </summary>
/// <returns>
/// <c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.
/// </returns>
/// <returns><c>true</c> if [is virtual proxy]; otherwise, <c>false</c>.</returns>
public bool IsVirtualProxy()
{
return IsVirtual && CanExport == false;

View File

@@ -29,6 +29,12 @@ namespace FlaxEditor.Content
return item is CSharpScriptItem;
}
/// <inheritdoc />
public override ContentItem ConstructItem(string path)
{
return new CSharpScriptItem(path);
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{

View File

@@ -39,6 +39,16 @@ namespace FlaxEditor.Content
return false;
}
/// <summary>
/// Constructs the item for the file.
/// </summary>
/// <param name="path">The file path.</param>
/// <returns>Created item or null.</returns>
public virtual ContentItem ConstructItem(string path)
{
return null;
}
/// <summary>
/// Gets a value indicating whether this proxy if for assets.
/// </summary>

View File

@@ -87,6 +87,12 @@ namespace FlaxEditor.Content
return item is CppScriptItem;
}
/// <inheritdoc />
public override ContentItem ConstructItem(string path)
{
return new CppScriptItem(path);
}
/// <inheritdoc />
protected override void GetTemplatePaths(out string headerTemplate, out string sourceTemplate)
{

View File

@@ -20,6 +20,12 @@ namespace FlaxEditor.Content
return item is FileItem;
}
/// <inheritdoc />
public override ContentItem ConstructItem(string path)
{
return new FileItem(path);
}
/// <inheritdoc />
public override string FileExtension => string.Empty;

View File

@@ -73,6 +73,16 @@ namespace FlaxEditor.Content
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
if (item is not PrefabItem prefabItem)
return base.CanReimport(item);
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
return prefab.GetDefaultInstance().GetScript<ModelPrefab>() != null;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{

View File

@@ -0,0 +1,48 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A video media file proxy object.
/// </summary>
public class VideoProxy : ContentProxy
{
private readonly string _extension;
internal VideoProxy(string extension)
{
_extension = extension;
}
/// <inheritdoc />
public override string Name => "Video";
/// <inheritdoc />
public override string FileExtension => _extension;
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x11f7f1);
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is VideoItem;
}
/// <inheritdoc />
public override ContentItem ConstructItem(string path)
{
return new VideoItem(path);
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new VideoWindow(editor, (VideoItem)item);
}
}
}

View File

@@ -134,6 +134,12 @@ API_ENUM() enum class BuildPlatform
/// </summary>
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
iOSARM64 = 14,
/// <summary>
/// Windows (ARM64)
/// </summary>
API_ENUM(Attributes = "EditorDisplay(null, \"Windows ARM64\")")
WindowsARM64 = 15,
};
/// <summary>
@@ -285,24 +291,22 @@ public:
/// <summary>
/// The total assets amount in the build.
/// </summary>
int32 TotalAssets;
int32 TotalAssets = 0;
/// <summary>
/// The cooked assets (TotalAssets - CookedAssets is amount of reused cached assets).
/// </summary>
int32 CookedAssets;
int32 CookedAssets = 0;
/// <summary>
/// The final output content size in MB.
/// The final output content size (in bytes).
/// </summary>
int32 ContentSizeMB;
uint64 ContentSize = 0;
/// <summary>
/// The asset type stats. Key is the asset typename, value is the stats container.
/// </summary>
Dictionary<String, AssetTypeStatistics> AssetStats;
Statistics();
};
/// <summary>
@@ -328,6 +332,11 @@ public:
/// </summary>
HashSet<Guid> Assets;
/// <summary>
/// The final files collection to include in build (valid only after CollectAssetsStep).
/// </summary>
HashSet<String> Files;
struct BinaryModuleInfo
{
String Name;

View File

@@ -148,6 +148,8 @@ const Char* ToString(const BuildPlatform platform)
return TEXT("Mac ARM64");
case BuildPlatform::iOSARM64:
return TEXT("iOS ARM64");
case BuildPlatform::WindowsARM64:
return TEXT("Windows ARM64");
default:
return TEXT("");
}
@@ -202,13 +204,6 @@ bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& othe
return Count > other.Count;
}
CookingData::Statistics::Statistics()
{
TotalAssets = 0;
CookedAssets = 0;
ContentSizeMB = 0;
}
CookingData::CookingData(const SpawnParams& params)
: ScriptingObject(params)
{
@@ -307,6 +302,10 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
platform = TEXT("iOS");
architecture = TEXT("ARM64");
break;
case BuildPlatform::WindowsARM64:
platform = TEXT("Windows");
architecture = TEXT("ARM64");
break;
default:
LOG(Fatal, "Unknown or unsupported build platform.");
}
@@ -393,6 +392,9 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
case BuildPlatform::Windows64:
result = New<WindowsPlatformTools>(ArchitectureType::x64);
break;
case BuildPlatform::WindowsARM64:
result = New<WindowsPlatformTools>(ArchitectureType::ARM64);
break;
#endif
#if PLATFORM_TOOLS_UWP
case BuildPlatform::UWPx86:
@@ -554,7 +556,12 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
switch (PLATFORM_TYPE)
{
case PlatformType::Windows:
buildPlatform = PLATFORM_64BITS ? BuildPlatform::Windows64 : BuildPlatform::Windows32;
if (PLATFORM_ARCH == ArchitectureType::x64)
buildPlatform = BuildPlatform::Windows64;
else if (PLATFORM_ARCH == ArchitectureType::ARM64)
buildPlatform = BuildPlatform::WindowsARM64;
else
buildPlatform = BuildPlatform::Windows32;
break;
case PlatformType::XboxOne:
buildPlatform = BuildPlatform::XboxOne;

View File

@@ -325,9 +325,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
const auto buildSettings = BuildSettings::Get();
if (buildSettings->SkipPackaging)
{
return false;
}
GameCooker::PackageFiles();
// Validate environment variables
@@ -365,7 +363,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
Platform::CreateProcess(procSettings);
}
#endif
const bool distributionPackage = buildSettings->ForDistribution;
const bool distributionPackage = buildSettings->ForDistribution || data.Configuration == BuildConfiguration::Release;
{
CreateProcessSettings procSettings;
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));

View File

@@ -10,47 +10,26 @@
#include "Engine/Content/Assets/Shader.h"
#include "Engine/Content/Cache/AssetsCache.h"
bool CollectAssetsStep::Process(CookingData& data, Asset* asset)
{
// Skip virtual/temporary assets
if (asset->IsVirtual())
return false;
// Keep reference to the asset
AssetReference<Asset> ref(asset);
// Asset should have loaded data
if (asset->WaitForLoaded())
return false;
// Gather asset references
_references.Clear();
asset->Locker.Lock();
asset->GetReferences(_references);
asset->Locker.Unlock();
_assetsQueue.Add(_references);
return false;
}
bool CollectAssetsStep::Perform(CookingData& data)
{
LOG(Info, "Searching for assets to include in a build. Using {0} root assets.", data.RootAssets.Count());
data.StepProgress(TEXT("Collecting assets"), 0);
// Initialize assets queue
_assetsQueue.Clear();
_assetsQueue.EnsureCapacity(1024);
Array<Guid> assetsQueue;
assetsQueue.Clear();
assetsQueue.EnsureCapacity(1024);
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
_assetsQueue.Add(i->Item);
assetsQueue.Add(i->Item);
// Iterate through the assets graph
AssetInfo assetInfo;
while (_assetsQueue.HasItems())
Array<Guid> references;
Array<String> files;
while (assetsQueue.HasItems())
{
BUILD_STEP_CANCEL_CHECK;
const auto assetId = _assetsQueue.Dequeue();
const Guid assetId = assetsQueue.Dequeue();
// Skip already processed or invalid assets
if (!assetId.IsValid()
@@ -69,14 +48,31 @@ bool CollectAssetsStep::Perform(CookingData& data)
}
// Load asset
const auto asset = Content::LoadAsync<Asset>(assetId);
AssetReference<Asset> asset = Content::LoadAsync<Asset>(assetId);
if (asset == nullptr)
continue;
// Process that asset
LOG_STR(Info, asset->GetPath());
data.Assets.Add(assetId);
Process(data, asset);
// Skip virtual/temporary assets
if (asset->IsVirtual())
continue;
// Asset should have loaded data
if (asset->WaitForLoaded())
continue;
// Gather asset references
references.Clear();
asset->Locker.Lock();
asset->GetReferences(references, files);
asset->Locker.Unlock();
assetsQueue.Add(references);
for (String& file : files)
{
if (file.HasChars())
data.Files.Add(MoveTemp(file));
}
}
data.Stats.TotalAssets = data.Assets.Count();

View File

@@ -12,15 +12,7 @@ class Asset;
/// <seealso cref="GameCooker::BuildStep" />
class CollectAssetsStep : public GameCooker::BuildStep
{
private:
Array<Guid> _assetsQueue;
Array<Guid> _references;
bool Process(CookingData& data, Asset* asset);
public:
// [BuildStep]
bool Perform(CookingData& data) override;
};

View File

@@ -447,6 +447,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
#if PLATFORM_TOOLS_WINDOWS
case BuildPlatform::Windows32:
case BuildPlatform::Windows64:
case BuildPlatform::WindowsARM64:
{
const char* platformDefineName = "PLATFORM_WINDOWS";
const auto settings = WindowsPlatformSettings::Get();
@@ -891,7 +892,6 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, JsonAssetBase*
class PackageBuilder : public NonCopyable
{
private:
int32 _packageIndex;
int32 MaxAssetsPerPackage;
int32 MaxPackageSize;
@@ -904,7 +904,6 @@ private:
uint64 packagesSizeTotal;
public:
/// <summary>
/// Initializes a new instance of the <see cref="PackageBuilder" /> class.
/// </summary>
@@ -933,7 +932,6 @@ public:
}
public:
uint64 GetPackagesSizeTotal() const
{
return packagesSizeTotal;
@@ -1042,8 +1040,11 @@ bool CookAssetsStep::Perform(CookingData& data)
float Step1ProgressEnd = 0.6f;
String Step1Info = TEXT("Cooking assets");
float Step2ProgressStart = Step1ProgressEnd;
float Step2ProgressEnd = 0.9f;
String Step2Info = TEXT("Packaging assets");
float Step2ProgressEnd = 0.8f;
String Step2Info = TEXT("Cooking files");
float Step3ProgressStart = Step2ProgressStart;
float Step3ProgressEnd = 0.9f;
String Step3Info = TEXT("Packaging assets");
data.StepProgress(TEXT("Loading build cache"), 0);
@@ -1100,11 +1101,14 @@ bool CookAssetsStep::Perform(CookingData& data)
#endif
int32 subStepIndex = 0;
AssetReference<Asset> assetRef;
assetRef.Unload.Bind([]() { LOG(Error, "Asset gets unloaded while cooking it!"); Platform::Sleep(100); });
assetRef.Unload.Bind([]
{
LOG(Error, "Asset got unloaded while cooking it!");
Platform::Sleep(100);
});
for (auto i = data.Assets.Begin(); i.IsNotEnd(); ++i)
{
BUILD_STEP_CANCEL_CHECK;
data.StepProgress(Step1Info, Math::Lerp(Step1ProgressStart, Step1ProgressEnd, static_cast<float>(subStepIndex++) / data.Assets.Count()));
const Guid assetId = i->Item;
@@ -1184,6 +1188,35 @@ bool CookAssetsStep::Perform(CookingData& data)
// Save build cache header
cache.Save(data);
// Process all files
for (auto i = data.Files.Begin(); i.IsNotEnd(); ++i)
{
BUILD_STEP_CANCEL_CHECK;
data.StepProgress(Step2Info, Math::Lerp(Step2ProgressStart, Step2ProgressEnd, (float)subStepIndex++ / data.Files.Count()));
const String& filePath = i->Item;
// Calculate destination path
String cookedPath = data.DataOutputPath;
if (FileSystem::IsRelative(filePath))
cookedPath /= filePath;
else
cookedPath /= String(TEXT("Content")) / StringUtils::GetFileName(filePath);
// Copy file
if (!FileSystem::FileExists(cookedPath) || FileSystem::GetFileLastEditTime(cookedPath) >= FileSystem::GetFileLastEditTime(filePath))
{
if (FileSystem::CreateDirectory(StringUtils::GetDirectoryName(cookedPath)))
return true;
if (FileSystem::CopyFile(cookedPath, filePath))
return true;
}
// Count stats of file extension
auto& assetStats = data.Stats.AssetStats[FileSystem::GetExtension(cookedPath)];
assetStats.Count++;
assetStats.ContentSize += FileSystem::GetFileSize(cookedPath);
}
// Create build game header
{
GameHeaderFlags gameFlags = GameHeaderFlags::None;
@@ -1229,13 +1262,11 @@ bool CookAssetsStep::Perform(CookingData& data)
for (auto i = AssetsRegistry.Begin(); i.IsNotEnd(); ++i)
{
BUILD_STEP_CANCEL_CHECK;
data.StepProgress(Step2Info, Math::Lerp(Step2ProgressStart, Step2ProgressEnd, static_cast<float>(subStepIndex++) / AssetsRegistry.Count()));
data.StepProgress(Step3Info, Math::Lerp(Step3ProgressStart, Step3ProgressEnd, (float)subStepIndex++ / AssetsRegistry.Count()));
const auto assetId = i->Key;
String cookedFilePath;
cache.GetFilePath(assetId, cookedFilePath);
if (!FileSystem::FileExists(cookedFilePath))
{
LOG(Warning, "Missing cooked file for asset \'{0}\'", assetId);
@@ -1253,12 +1284,12 @@ bool CookAssetsStep::Perform(CookingData& data)
return true;
for (auto& e : data.Stats.AssetStats)
e.Value.TypeName = e.Key;
data.Stats.ContentSizeMB = static_cast<int32>(packageBuilder.GetPackagesSizeTotal() / (1024 * 1024));
data.Stats.ContentSize += packageBuilder.GetPackagesSizeTotal();
}
BUILD_STEP_CANCEL_CHECK;
data.StepProgress(TEXT("Creating assets cache"), Step2ProgressEnd);
data.StepProgress(TEXT("Creating assets cache"), Step3ProgressEnd);
// Create asset paths mapping for the assets.
// Assets mapping is use to convert paths used in Content::Load(path) into the asset id.
@@ -1291,7 +1322,7 @@ bool CookAssetsStep::Perform(CookingData& data)
}
// Print stats
LOG(Info, "Cooked {0} assets, total assets: {1}, total content packages size: {2} MB", data.Stats.CookedAssets, AssetsRegistry.Count(), data.Stats.ContentSizeMB);
LOG(Info, "Cooked {0} assets, total assets: {1}, total content packages size: {2} MB", data.Stats.CookedAssets, AssetsRegistry.Count(), (int32)(data.Stats.ContentSize / (1024 * 1024)));
{
Array<CookingData::AssetTypeStatistics> assetTypes;
data.Stats.AssetStats.GetValues(assetTypes);

View File

@@ -73,6 +73,7 @@ bool DeployDataStep::Perform(CookingData& data)
{
case BuildPlatform::Windows32:
case BuildPlatform::Windows64:
case BuildPlatform::WindowsARM64:
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
break;
case BuildPlatform::LinuxX64:
@@ -159,7 +160,20 @@ bool DeployDataStep::Perform(CookingData& data)
}
else
{
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("host/fxr") / version, srcDotnet / TEXT("host/fxr") / version, true);
// TODO: hostfxr for target platform should be copied from nuget package location: microsoft.netcore.app.runtime.<RID>/<VERSION>/runtimes/<RID>/native/hostfxr.dll
String dstHostfxr = dstDotnet / TEXT("host/fxr") / version;
if (!FileSystem::DirectoryExists(dstHostfxr))
FileSystem::CreateDirectory(dstHostfxr);
const Char *platformName, *archName;
data.GetBuildPlatformName(platformName, archName);
if (data.Platform == BuildPlatform::Windows64 || data.Platform == BuildPlatform::WindowsARM64 || data.Platform == BuildPlatform::Windows32)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dll"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dll"));
else if (data.Platform == BuildPlatform::LinuxX64)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.so"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.so"));
else if (data.Platform == BuildPlatform::MacOSx64 || data.Platform == BuildPlatform::MacOSARM64)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dylib"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dylib"));
else
failed |= true;
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
}
if (failed)

View File

@@ -377,6 +377,10 @@ namespace FlaxEditor.CustomEditors
else if (Values.HasDefaultValue && CanRevertDefaultValue)
color = Color.Yellow * 0.8f;
LinkedLabel.HighlightStripColor = color;
// Grey out deprecated members
if (Values.IsObsolete)
LinkedLabel.TextColor = LinkedLabel.TextColorHighlighted = FlaxEngine.GUI.Style.Current.ForegroundGrey;
}
}

View File

@@ -52,13 +52,18 @@ namespace FlaxEditor.CustomEditors
// Check if use provided editor
if (overrideEditor != null)
return overrideEditor;
ScriptType targetType = values.Type;
// Special case if property is a pure object type and all values are the same type
if (values.Type.Type == typeof(object) && values.Count > 0 && values[0] != null && !values.HasDifferentTypes)
if (targetType.Type == typeof(object) && values.Count > 0 && values[0] != null && !values.HasDifferentTypes)
return CreateEditor(TypeUtils.GetObjectType(values[0]), canUseRefPicker);
// Special case if property is interface but the value is implemented as Scripting Object that should use reference picker
if (targetType.IsInterface && canUseRefPicker && values.Count > 0 && values[0] is FlaxEngine.Object)
return new DummyEditor();
// Use editor for the property type
return CreateEditor(values.Type, canUseRefPicker);
return CreateEditor(targetType, canUseRefPicker);
}
internal static CustomEditor CreateEditor(ScriptType targetType, bool canUseRefPicker = true)

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.Content.Settings;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -12,7 +13,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
[CustomEditor(typeof(LayersMask)), DefaultEditor]
internal class LayersMaskEditor : CustomEditor
{
private CheckBox[] _checkBoxes;
private List<CheckBox> _checkBoxes;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
@@ -24,16 +25,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
_checkBoxes = new CheckBox[layers.Length];
_checkBoxes = new List<CheckBox>();
for (int i = 0; i < layers.Length; i++)
{
var layer = layers[i];
var property = layout.AddPropertyItem(layer);
if (string.IsNullOrEmpty(layer))
continue;
var property = layout.AddPropertyItem($"{i}: {layer}");
var checkbox = property.Checkbox().CheckBox;
UpdateCheckbox(checkbox, i);
checkbox.Tag = i;
checkbox.StateChanged += OnCheckboxStateChanged;
_checkBoxes[i] = checkbox;
_checkBoxes.Add(checkbox);
}
}
@@ -50,9 +53,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_checkBoxes != null)
{
for (int i = 0; i < _checkBoxes.Length; i++)
for (int i = 0; i < _checkBoxes.Count; i++)
{
UpdateCheckbox(_checkBoxes[i], i);
UpdateCheckbox(_checkBoxes[i], (int)_checkBoxes[i].Tag);
}
}

View File

@@ -456,14 +456,57 @@ namespace FlaxEditor.CustomEditors.Dedicated
for (int i = 0; i < layout.Children.Count; i++)
{
if (layout.Children[i] is GroupElement group && group.Panel.HeaderText == "Transform")
if (layout.Children[i] is GroupElement group && group.Panel.HeaderText.Equals("Transform", StringComparison.Ordinal))
{
VerticalPanelElement mainHor = VerticalPanelWithoutMargin(group);
CreateTransformElements(mainHor, ValuesTypes);
group.ContainerControl.ChangeChildIndex(mainHor.Control, 0);
layout.Children.Remove(group);
layout.ContainerControl.Children.Remove(group.Panel);
break;
}
}
// Setup transform
if (Presenter is LayoutElementsContainer l)
{
for (int i = 0; i < l.Children.Count; i++)
{
if (l.Children[i] is GroupElement g && g.Panel.HeaderText.Equals("Transform", StringComparison.Ordinal))
{
l.Children.Remove(g);
l.ContainerControl.Children.Remove(g.Panel);
break;
}
}
var transformGroup = l.Group("Transform");
VerticalPanelElement mainHor = VerticalPanelWithoutMargin(transformGroup);
CreateTransformElements(mainHor, ValuesTypes);
ScriptMemberInfo scaleInfo = ValuesTypes[0].GetProperty("Scale");
ItemInfo scaleItem = new ItemInfo(scaleInfo);
transformGroup.Property("Scale", scaleItem.GetValues(Values));
ScriptMemberInfo pivotInfo = ValuesTypes[0].GetProperty("Pivot");
ItemInfo pivotItem = new ItemInfo(pivotInfo);
transformGroup.Property("Pivot", pivotItem.GetValues(Values));
ScriptMemberInfo shearInfo = ValuesTypes[0].GetProperty("Shear");
ItemInfo shearItem = new ItemInfo(shearInfo);
transformGroup.Property("Shear", shearItem.GetValues(Values));
ScriptMemberInfo rotationInfo = ValuesTypes[0].GetProperty("Rotation");
ItemInfo rotationItem = new ItemInfo(rotationInfo);
transformGroup.Property("Rotation", rotationItem.GetValues(Values));
// Get position of general tab
for (int i = 0; i < l.Children.Count; i++)
{
if (l.Children[i] is GroupElement g && g.Panel.HeaderText.Equals("General", StringComparison.Ordinal) && i + 1 <= l.Children.Count)
{
Presenter.ContainerControl.ChangeChildIndex(transformGroup.Control, i + 1);
break;
}
}
}
}
private void CreateTransformElements(LayoutElementsContainer main, ScriptType[] valueTypes)
@@ -645,7 +688,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
var grid = UniformGridTwoByOne(el);
grid.CustomControl.SlotPadding = new Margin(5, 5, 1, 1);
var label = grid.Label(text);
var label = grid.Label(text, TextAlignment.Far);
var editor = grid.Object(values);
if (editor is FloatEditor floatEditor && floatEditor.Element is FloatValueElement floatEditorElement)
{

View File

@@ -6,6 +6,7 @@ using FlaxEditor.Content;
using FlaxEditor.GUI;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
namespace FlaxEditor.CustomEditors.Editors
@@ -50,7 +51,6 @@ namespace FlaxEditor.CustomEditors.Editors
if (HasDifferentTypes)
return;
Picker = layout.Custom<AssetPicker>().CustomControl;
var value = Values[0];
_valueType = Values.Type.Type != typeof(object) || value == null ? Values.Type : TypeUtils.GetObjectType(value);
var assetType = _valueType;
@@ -58,37 +58,8 @@ namespace FlaxEditor.CustomEditors.Editors
assetType = new ScriptType(typeof(Asset));
else if (_valueType.Type != null && _valueType.Type.Name == typeof(JsonAssetReference<>).Name)
assetType = new ScriptType(_valueType.Type.GenericTypeArguments[0]);
float height = 48;
var attributes = Values.GetAttributes();
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
if (assetReference != null)
{
if (assetReference.UseSmallPicker)
height = 32;
if (string.IsNullOrEmpty(assetReference.TypeName))
{
}
else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
{
// Generic file picker
assetType = ScriptType.Null;
Picker.Validator.FileExtension = assetReference.TypeName;
}
else
{
var customType = TypeUtils.GetType(assetReference.TypeName);
if (customType != ScriptType.Null)
assetType = customType;
else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName))
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
else
assetType = ScriptType.Void;
}
}
Picker.Validator.AssetType = assetType;
ApplyAssetReferenceAttribute(Values, out var height, Picker.Validator);
Picker.Height = height;
Picker.SelectedItemChanged += OnSelectedItemChanged;
}
@@ -115,6 +86,37 @@ namespace FlaxEditor.CustomEditors.Editors
SetValue(Picker.Validator.SelectedAsset);
}
internal static void ApplyAssetReferenceAttribute(ValueContainer values, out float height, AssetPickerValidator validator)
{
height = 48;
var attributes = values.GetAttributes();
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
if (assetReference != null)
{
if (assetReference.UseSmallPicker)
height = 32;
if (string.IsNullOrEmpty(assetReference.TypeName))
{
}
else if (assetReference.TypeName.Length > 1 && assetReference.TypeName[0] == '.')
{
// Generic file picker
validator.AssetType = ScriptType.Null;
validator.FileExtension = assetReference.TypeName;
}
else
{
var customType = TypeUtils.GetType(assetReference.TypeName);
if (customType != ScriptType.Null)
validator.AssetType = customType;
else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName))
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
else
validator.AssetType = ScriptType.Void;
}
}
}
/// <inheritdoc />
public override void Refresh()
{
@@ -140,4 +142,155 @@ namespace FlaxEditor.CustomEditors.Editors
}
}
}
/// <summary>
/// Default implementation of the inspector used to edit reference to the files via path (absolute or relative to the project).
/// </summary>
/// <remarks>Supports editing reference to the asset via path using various containers: <see cref="Asset"/> or <see cref="AssetItem"/> or <see cref="System.String"/>.</remarks>
public class FilePathEditor : CustomEditor
{
private sealed class TextBoxWithPicker : TextBox
{
private const float DropdownIconMargin = 3.0f;
private const float DropdownIconSize = 12.0f;
private Rectangle DropdownRect => new Rectangle(Width - DropdownIconSize - DropdownIconMargin, DropdownIconMargin, DropdownIconSize, DropdownIconSize);
public Action ShowPicker;
public override void Draw()
{
base.Draw();
var style = FlaxEngine.GUI.Style.Current;
var dropdownRect = DropdownRect;
Render2D.DrawSprite(style.ArrowDown, dropdownRect, Enabled ? (DropdownRect.Contains(PointFromWindow(RootWindow.MousePosition)) ? style.BorderSelected : style.Foreground) : style.ForegroundDisabled);
}
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (DropdownRect.Contains(ref location))
{
Focus();
ShowPicker();
return true;
}
return base.OnMouseDown(location, button);
}
public override void OnMouseMove(Float2 location)
{
base.OnMouseMove(location);
if (DropdownRect.Contains(ref location))
Cursor = CursorType.Default;
else
Cursor = CursorType.IBeam;
}
protected override Rectangle TextRectangle
{
get
{
var result = base.TextRectangle;
result.Size.X -= DropdownIconSize + DropdownIconMargin * 2;
return result;
}
}
protected override Rectangle TextClipRectangle
{
get
{
var result = base.TextClipRectangle;
result.Size.X -= DropdownIconSize + DropdownIconMargin * 2;
return result;
}
}
}
private TextBoxWithPicker _textBox;
private AssetPickerValidator _validator;
private bool _isRefreshing;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
if (HasDifferentTypes)
return;
_textBox = layout.Custom<TextBoxWithPicker>().CustomControl;
_textBox.ShowPicker = OnShowPicker;
_textBox.EditEnd += OnEditEnd;
_validator = new AssetPickerValidator(ScriptType.Null);
AssetRefEditor.ApplyAssetReferenceAttribute(Values, out _, _validator);
}
private void OnShowPicker()
{
if (_validator.AssetType != ScriptType.Null)
AssetSearchPopup.Show(_textBox, _textBox.BottomLeft, _validator.IsValid, SetPickerPath);
else
ContentSearchPopup.Show(_textBox, _textBox.BottomLeft, _validator.IsValid, SetPickerPath);
}
private void SetPickerPath(ContentItem item)
{
var path = Utilities.Utils.ToPathProject(item.Path);
SetPath(path);
_isRefreshing = true;
_textBox.Defocus();
_textBox.Text = path;
_isRefreshing = false;
_textBox.RootWindow.Focus();
_textBox.Focus();
}
private void OnEditEnd()
{
SetPath(_textBox.Text);
}
private string GetPath()
{
var value = Values[0];
if (value is AssetItem assetItem)
return Utilities.Utils.ToPathProject(assetItem.Path);
if (value is Asset asset)
return Utilities.Utils.ToPathProject(asset.Path);
if (value is string str)
return str;
return null;
}
private void SetPath(string path)
{
if (_isRefreshing)
return;
var value = Values[0];
if (value is AssetItem)
SetValue(Editor.Instance.ContentDatabase.Find(Utilities.Utils.ToPathAbsolute(path)));
else if (value is Asset)
SetValue(FlaxEngine.Content.LoadAsync(path));
else if (value is string)
SetValue(path);
}
/// <inheritdoc />
public override void Refresh()
{
base.Refresh();
if (!HasDifferentValues)
{
_isRefreshing = true;
_textBox.Text = GetPath();
_isRefreshing = false;
}
}
}
}

View File

@@ -57,17 +57,18 @@ namespace FlaxEditor.CustomEditors.Editors
menu.ItemsContainer.RemoveChildren();
menu.AddButton("Copy", linkedEditor.Copy);
var paste = menu.AddButton("Paste", linkedEditor.Paste);
paste.Enabled = linkedEditor.CanPaste;
var b = menu.AddButton("Paste", linkedEditor.Paste);
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
menu.AddSeparator();
var moveUpButton = menu.AddButton("Move up", OnMoveUpClicked);
moveUpButton.Enabled = Index > 0;
b = menu.AddButton("Move up", OnMoveUpClicked);
b.Enabled = Index > 0 && !Editor._readOnly;
var moveDownButton = menu.AddButton("Move down", OnMoveDownClicked);
moveDownButton.Enabled = Index + 1 < Editor.Count;
menu.AddButton("Remove", OnRemoveClicked);
b = menu.AddButton("Move down", OnMoveDownClicked);
b.Enabled = Index + 1 < Editor.Count && !Editor._readOnly;
b = menu.AddButton("Remove", OnRemoveClicked);
b.Enabled = !Editor._readOnly;
}
private void OnMoveUpClicked()
@@ -177,6 +178,7 @@ namespace FlaxEditor.CustomEditors.Editors
private IntValueBox _sizeBox;
private Color _background;
private int _elementsCount, _minCount, _maxCount;
private bool _readOnly;
private bool _canResize;
private bool _canReorderItems;
private CollectionAttribute.DisplayType _displayType;
@@ -209,6 +211,7 @@ namespace FlaxEditor.CustomEditors.Editors
return;
var size = Count;
_readOnly = false;
_canResize = true;
_canReorderItems = true;
_minCount = 0;
@@ -225,6 +228,7 @@ namespace FlaxEditor.CustomEditors.Editors
if (collection != null)
{
_canResize = !collection.ReadOnly;
_readOnly = collection.ReadOnly;
_minCount = collection.MinCount;
_maxCount = collection.MaxCount;
_canReorderItems = collection.CanReorderItems;
@@ -235,6 +239,12 @@ namespace FlaxEditor.CustomEditors.Editors
spacing = collection.Spacing;
_displayType = collection.Display;
}
if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute))
{
_readOnly = true;
_canResize = false;
_canReorderItems = false;
}
if (_maxCount == 0)
_maxCount = ushort.MaxValue;
_canResize &= _minCount < _maxCount;
@@ -243,8 +253,7 @@ namespace FlaxEditor.CustomEditors.Editors
dragArea.CustomControl.Editor = this;
dragArea.CustomControl.ElementType = ElementType;
// Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter
// which scripts can be dragged over and dropped on this collection editor.
// Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter which scripts can be dragged over and dropped on this collection editor
var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute);
if (assetReference != null)
{
@@ -333,6 +342,8 @@ namespace FlaxEditor.CustomEditors.Editors
var property = panel.AddPropertyItem(itemLabel);
var itemLayout = (LayoutElementsContainer)property;
itemLabel.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
if (_readOnly && itemLayout.Children.Count > 0)
GenericEditor.OnReadOnlyProperty(itemLayout);
}
else if (_displayType == CollectionAttribute.DisplayType.Header || (_displayType == CollectionAttribute.DisplayType.Default && !single))
{
@@ -340,13 +351,15 @@ namespace FlaxEditor.CustomEditors.Editors
cdp.CustomControl.Setup(this, i, _canReorderItems);
var itemLayout = cdp.VerticalPanel();
cdp.CustomControl.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor);
if (_readOnly && itemLayout.Children.Count > 0)
GenericEditor.OnReadOnlyProperty(itemLayout);
}
}
}
_elementsCount = size;
// Add/Remove buttons
if (_canResize)
if (_canResize && !_readOnly)
{
var panel = dragArea.HorizontalPanel();
panel.Panel.Size = new Float2(0, 20);

View File

@@ -131,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (button == MouseButton.Left)
if (button == MouseButton.Left && _editor._canEditKeys)
{
OnEditClicked(null);
return true;
@@ -197,6 +197,11 @@ namespace FlaxEditor.CustomEditors.Editors
spacing = collection.Spacing;
_displayType = collection.Display;
}
if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute))
{
_readOnly = true;
_canEditKeys = false;
}
// Size
if (layout.ContainerControl is DropPanel dropPanel)
@@ -239,14 +244,6 @@ namespace FlaxEditor.CustomEditors.Editors
var keysEnumerable = ((IDictionary)Values[0]).Keys.OfType<object>();
var keys = keysEnumerable as object[] ?? keysEnumerable.ToArray();
var valuesType = new ScriptType(valueType);
bool single = valuesType.IsPrimitive ||
valuesType.Equals(new ScriptType(typeof(string))) ||
valuesType.IsEnum ||
(valuesType.GetFields().Length == 1 && valuesType.GetProperties().Length == 0) ||
(valuesType.GetProperties().Length == 1 && valuesType.GetFields().Length == 0) ||
valuesType.Equals(new ScriptType(typeof(JsonAsset))) ||
valuesType.Equals(new ScriptType(typeof(SettingsBase)));
// Use separate layout cells for each collection items to improve layout updates for them in separation
var useSharedLayout = valueType.IsPrimitive || valueType.IsEnum;
@@ -263,6 +260,8 @@ namespace FlaxEditor.CustomEditors.Editors
var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key));
var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel();
itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor);
if (_readOnly && itemLayout.Children.Count > 0)
GenericEditor.OnReadOnlyProperty(itemLayout);
}
}
_elementsCount = size;

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
namespace FlaxEditor.CustomEditors.Editors
{
internal sealed class DummyEditor : CustomEditor
{
public override void Initialize(LayoutElementsContainer layout)
{
string valueName;
if (Values.Count != 0 && Values[0] != null)
valueName = Values[0].ToString();
else
valueName = "null";
layout.Label($"{valueName} ({Values.Type})");
}
}
}

View File

@@ -581,6 +581,43 @@ namespace FlaxEditor.CustomEditors.Editors
return layout;
}
internal static void OnReadOnlyProperty(LayoutElementsContainer itemLayout, int labelIndex = -1)
{
PropertiesListElement list = null;
int firstChildControlIndex = 0;
bool disableSingle = true;
var control = itemLayout.Children[itemLayout.Children.Count - 1];
if (control is GroupElement group && group.Children.Count > 0)
{
list = group.Children[0] as PropertiesListElement;
disableSingle = false; // Disable all nested editors
}
else if (control is PropertiesListElement list1 && labelIndex != -1)
{
list = list1;
firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex;
}
else if (control?.Control != null)
{
control.Control.Enabled = false;
}
if (list != null)
{
// Disable controls added to the editor
var count = list.Properties.Children.Count;
for (int j = firstChildControlIndex; j < count; j++)
{
var child = list.Properties.Children[j];
if (disableSingle && child is PropertyNameLabel)
break;
if (child != null)
child.Enabled = false;
}
}
}
/// <summary>
/// Evaluate the <see cref="VisibleIfAttribute"/> cache for a given property item.
/// </summary>
@@ -660,35 +697,7 @@ namespace FlaxEditor.CustomEditors.Editors
if (item.IsReadOnly && itemLayout.Children.Count > 0)
{
PropertiesListElement list = null;
int firstChildControlIndex = 0;
bool disableSingle = true;
var control = itemLayout.Children[itemLayout.Children.Count - 1];
if (control is GroupElement group && group.Children.Count > 0)
{
list = group.Children[0] as PropertiesListElement;
disableSingle = false; // Disable all nested editors
}
else if (control is PropertiesListElement list1)
{
list = list1;
firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex;
}
if (list != null)
{
// Disable controls added to the editor
var count = list.Properties.Children.Count;
for (int j = firstChildControlIndex; j < count; j++)
{
var child = list.Properties.Children[j];
if (disableSingle && child is PropertyNameLabel)
break;
if (child != null)
child.Enabled = false;
}
}
OnReadOnlyProperty(itemLayout, labelIndex);
}
EvaluateVisibleIf(itemLayout, item, labelIndex);

View File

@@ -25,6 +25,7 @@ namespace FlaxEditor.CustomEditors.Editors
new OptionType("Linear Gradient", typeof(LinearGradientBrush)),
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
new OptionType("Video", typeof(VideoBrush)),
};
}
}

View File

@@ -242,7 +242,7 @@ namespace FlaxEditor.CustomEditors.GUI
float namesWidth = _splitterValue * Width;
int count = _element.Labels.Count;
float[] yStarts = new float[count + 1];
for (int i = 1; i < count; i++)
for (int i = 0; i < count; i++)
{
var label = _element.Labels[i];
@@ -251,9 +251,13 @@ namespace FlaxEditor.CustomEditors.GUI
else if (_children.Count <= label.FirstChildControlIndex)
yStarts[i] = y;
else
{
yStarts[i] = _children[label.FirstChildControlIndex].Top;
if (i == count - 1)
yStarts[i + 1] = _children[label.FirstChildControlIndex].Bottom;
}
}
yStarts[count] = y;
for (int i = 0; i < count; i++)
{
var label = _element.Labels[i];

View File

@@ -139,6 +139,11 @@ namespace FlaxEditor.CustomEditors
/// </summary>
public bool IsArray => Type != ScriptType.Null && Type.IsArray;
/// <summary>
/// True if member or type has <see cref="System.ObsoleteAttribute"/> that marks it as obsolete.
/// </summary>
public bool IsObsolete { get; }
/// <summary>
/// Gets the values types array (without duplicates).
/// </summary>
@@ -160,6 +165,7 @@ namespace FlaxEditor.CustomEditors
{
Info = info;
Type = Info.ValueType;
IsObsolete = Info.HasAttribute(typeof(ObsoleteAttribute), true);
}
/// <summary>

View File

@@ -5,10 +5,8 @@ using System.IO;
using FlaxEditor.Content;
using FlaxEditor.GUI.Drag;
using FlaxEditor.Scripting;
using FlaxEditor.Utilities;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
namespace FlaxEditor.GUI
{

View File

@@ -264,6 +264,7 @@ namespace FlaxEditor.GUI.Dialogs
{
Text = "+",
Parent = this,
TooltipText = "Save Color.",
Tag = null,
};
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);
@@ -370,9 +371,25 @@ namespace FlaxEditor.GUI.Dialogs
Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
// Color difference
var newRect = new Rectangle(_cOK.X, _cHex.Bottom + PickerMargin, _cCancel.Right - _cOK.Left, 0);
newRect.Size.Y = _cValue.Bottom - newRect.Y;
Render2D.FillRectangle(newRect, _value * _value.A);
var newRect = new Rectangle(_cOK.X - 3, _cHex.Bottom + PickerMargin, 130, 0);
newRect.Size.Y = 50;
Render2D.FillRectangle(newRect, Color.White);
var smallRectSize = 10;
var numHor = Mathf.FloorToInt(newRect.Width / smallRectSize);
var numVer = Mathf.FloorToInt(newRect.Height / smallRectSize);
// Draw checkerboard for background of color to help with transparency
for (int i = 0; i < numHor; i++)
{
for (int j = 0; j < numVer; j++)
{
if ((i + j) % 2 == 0 )
{
var rect = new Rectangle(newRect.X + smallRectSize * i, newRect.Y + smallRectSize * j, new Float2(smallRectSize));
Render2D.FillRectangle(rect, Color.Gray);
}
}
}
Render2D.FillRectangle(newRect, _value);
}
/// <inheritdoc />
@@ -498,6 +515,7 @@ namespace FlaxEditor.GUI.Dialogs
{
Text = "+",
Parent = this,
TooltipText = "Save Color.",
Tag = null,
};
savedColorButton.ButtonClicked += (b) => OnSavedColorButtonClicked(b);

View File

@@ -311,7 +311,9 @@ namespace FlaxEditor.GUI.Dialogs
// Alpha
float alphaY = _slider2Rect.Height * (1 - _color.A);
var alphaR = new Rectangle(_slider2Rect.X - slidersOffset, _slider2Rect.Y + alphaY - slidersThickness / 2, _slider2Rect.Width + slidersOffset * 2, slidersThickness);
Render2D.FillRectangle(_slider2Rect, _color, _color, Color.Transparent, Color.Transparent);
var color = _color;
color.A = 1; // Keep slider 2 fill rect from changing color alpha while selecting.
Render2D.FillRectangle(_slider2Rect, color, color, Color.Transparent, Color.Transparent);
Render2D.DrawRectangle(_slider2Rect, _isMouseDownSlider2 ? style.BackgroundSelected : Color.Black);
Render2D.DrawRectangle(alphaR, _isMouseDownSlider2 ? Color.White : Color.Gray);
}

View File

@@ -418,9 +418,19 @@ namespace FlaxEditor.GUI.Tabs
{
// If scroll bar is visible it covers part of the tab header so include this in tab size to improve usability
if (_orientation == Orientation.Horizontal && TabsPanel.HScrollBar.Visible)
{
tabsSize.Y += TabsPanel.HScrollBar.Height;
var style = Style.Current;
TabsPanel.HScrollBar.TrackColor = style.Background;
TabsPanel.HScrollBar.ThumbColor = style.ForegroundGrey;
}
else if (_orientation == Orientation.Vertical && TabsPanel.VScrollBar.Visible)
{
tabsSize.X += TabsPanel.VScrollBar.Width;
var style = Style.Current;
TabsPanel.VScrollBar.TrackColor = style.Background;
TabsPanel.VScrollBar.ThumbColor = style.ForegroundGrey;
}
}
// Fit the tabs panel

View File

@@ -698,6 +698,38 @@ namespace FlaxEditor.GUI.Tree
}
}
// Show tree guide lines
if (Editor.Instance.Options.Options.Interface.ShowTreeLines)
{
TreeNode parentNode = Parent as TreeNode;
bool thisNodeIsLast = false;
while (parentNode != null && parentNode != ParentTree.Children[0])
{
float bottomOffset = 0;
float topOffset = 0;
if (Parent == parentNode && this == Parent.Children[0])
topOffset = 2;
if (thisNodeIsLast && parentNode.Children.Count == 1)
bottomOffset = topOffset != 0 ? 4 : 2;
if (Parent == parentNode && this == Parent.Children[Parent.Children.Count - 1] && !_opened)
{
thisNodeIsLast = true;
bottomOffset = topOffset != 0 ? 4 : 2;
}
float leftOffset = 9;
// Adjust offset for icon image
if (_iconCollaped.IsValid)
leftOffset += 18;
var lineRect1 = new Rectangle(parentNode.TextRect.Left - leftOffset, parentNode.HeaderRect.Top + topOffset, 1, parentNode.HeaderRect.Height - bottomOffset);
Render2D.FillRectangle(lineRect1, isSelected ? style.ForegroundGrey : style.LightBackground);
parentNode = parentNode.Parent as TreeNode;
}
}
// Base
if (_opened)
{
@@ -729,7 +761,7 @@ namespace FlaxEditor.GUI.Tree
// Try to estimate the rough location of the first node, assuming the node height is constant
var firstChildGlobalRect = GetChildGlobalRectangle(children[0], ref globalTransform);
var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Y - firstChildGlobalRect.Top) / firstChildGlobalRect.Height) + 1, 0, children.Count - 1);
var firstVisibleChild = Math.Clamp((int)Math.Floor((globalClipping.Y - firstChildGlobalRect.Top) / _headerHeight) + 1, 0, children.Count - 1);
if (GetChildGlobalRectangle(children[firstVisibleChild], ref globalTransform).Top > globalClipping.Top || !children[firstVisibleChild].Visible)
{
// Estimate overshoot, either it's partially visible or hidden in the tree

View File

@@ -499,6 +499,15 @@ namespace FlaxEditor
bool drawAnySelectedControl = false;
var transformGizmo = TransformGizmo;
var mousePos = PointFromWindow(RootWindow.MousePosition);
if (EnableSelecting && !_mouseMovesControl && !_mouseMovesWidget && IsMouseOver)
{
// Highlight control under mouse for easier selecting (except if already selected)
if (RayCastControl(ref mousePos, out var hitControl) &&
(transformGizmo == null || !transformGizmo.Selection.Any(x => x.EditableObject is UIControl controlActor && controlActor.Control == hitControl)))
{
DrawControl(null, hitControl, false, ref mousePos, ref drawAnySelectedControl);
}
}
if (transformGizmo != null)
{
// Selected UI controls outline
@@ -511,15 +520,6 @@ namespace FlaxEditor
}
}
}
if (EnableSelecting && !_mouseMovesControl && !_mouseMovesWidget && IsMouseOver)
{
// Highlight control under mouse for easier selecting (except if already selected)
if (RayCastControl(ref mousePos, out var hitControl) &&
(transformGizmo == null || !transformGizmo.Selection.Any(x => x.EditableObject is UIControl controlActor && controlActor.Control == hitControl)))
{
DrawControl(null, hitControl, false, ref mousePos, ref drawAnySelectedControl);
}
}
if (drawAnySelectedControl)
Render2D.PopTransform();
@@ -617,40 +617,39 @@ namespace FlaxEditor
// Draw sizing widgets
if (_widgets == null)
_widgets = new List<Widget>();
var widgetSize = 8.0f;
var widgetSize = 10.0f;
var viewScale = ViewScale;
if (viewScale < 0.7f)
widgetSize *= viewScale;
var controlSize = control.Size.Absolute.MinValue / 50.0f;
if (controlSize < 1.0f)
widgetSize *= Mathf.Clamp(controlSize + 0.1f, 0.1f, 1.0f);
var cornerSize = new Float2(widgetSize);
DrawControlWidget(uiControl, ref ul, ref mousePos, ref cornerSize, new Float2(-1, -1), CursorType.SizeNWSE);
DrawControlWidget(uiControl, ref ur, ref mousePos, ref cornerSize, new Float2(1, -1), CursorType.SizeNESW);
DrawControlWidget(uiControl, ref bl, ref mousePos, ref cornerSize, new Float2(-1, 1), CursorType.SizeNESW);
DrawControlWidget(uiControl, ref br, ref mousePos, ref cornerSize, new Float2(1, 1), CursorType.SizeNWSE);
var edgeSizeV = new Float2(widgetSize * 2, widgetSize);
var edgeSizeH = new Float2(edgeSizeV.Y, edgeSizeV.X);
var widgetHandleSize = new Float2(widgetSize);
DrawControlWidget(uiControl, ref ul, ref mousePos, ref widgetHandleSize, viewScale, new Float2(-1, -1), CursorType.SizeNWSE);
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 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(ref ur, ref br, 0.5f, out var er);
Float2.Lerp(ref ul, ref ur, 0.5f, out var eu);
Float2.Lerp(ref bl, ref br, 0.5f, out var eb);
DrawControlWidget(uiControl, ref el, ref mousePos, ref edgeSizeH, new Float2(-1, 0), CursorType.SizeWE);
DrawControlWidget(uiControl, ref er, ref mousePos, ref edgeSizeH, new Float2(1, 0), CursorType.SizeWE);
DrawControlWidget(uiControl, ref eu, ref mousePos, ref edgeSizeV, new Float2(0, -1), CursorType.SizeNS);
DrawControlWidget(uiControl, ref eb, ref mousePos, ref edgeSizeV, new Float2(0, 1), CursorType.SizeNS);
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 eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS);
DrawControlWidget(uiControl, ref eb, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, 1), CursorType.SizeNS);
// TODO: draw anchors
}
}
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size, Float2 resizeAxis, CursorType cursor)
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size,float scale, Float2 resizeAxis, CursorType cursor)
{
var style = Style.Current;
var rect = new Rectangle(pos - size * 0.5f, size);
var rect = new Rectangle((pos + resizeAxis * 10 * scale) - size * 0.5f, size);
if (rect.Contains(ref mousePos))
{
Render2D.FillRectangle(rect, style.Foreground);
Render2D.DrawRectangle(rect, style.SelectionBorder);
}
else
{

View File

@@ -129,12 +129,9 @@ namespace FlaxEditor.Modules
for (int i = 0; i < Proxy.Count; i++)
{
if (Proxy[i].IsProxyFor(item))
{
return Proxy[i];
}
}
}
return null;
}
@@ -147,11 +144,8 @@ namespace FlaxEditor.Modules
for (int i = 0; i < Proxy.Count; i++)
{
if (Proxy[i].IsProxyFor<T>())
{
return Proxy[i];
}
}
return null;
}
@@ -164,17 +158,12 @@ namespace FlaxEditor.Modules
{
if (string.IsNullOrEmpty(extension))
throw new ArgumentNullException();
extension = StringUtils.NormalizeExtension(extension);
for (int i = 0; i < Proxy.Count; i++)
{
if (Proxy[i].FileExtension == extension)
{
if (string.Equals(Proxy[i].FileExtension, extension, StringComparison.Ordinal))
return Proxy[i];
}
}
return null;
}
@@ -189,30 +178,23 @@ namespace FlaxEditor.Modules
for (int i = 0; i < Proxy.Count; i++)
{
if (Proxy[i] is AssetProxy proxy && proxy.AcceptsAsset(typeName, path))
{
return proxy;
}
}
return null;
}
/// <summary>
/// Gets the virtual proxy object from given path.
/// <br></br>use case if the asset u trying to display is not a flax asset but u like to add custom functionality
/// <br></br>to context menu,or display it the asset
/// </summary>
/// <param name="path">The asset path.</param>
/// <returns>Asset proxy or null if cannot find.</returns>
public AssetProxy GetAssetVirtuallProxy(string path)
public AssetProxy GetAssetVirtualProxy(string path)
{
for (int i = 0; i < Proxy.Count; i++)
{
if (Proxy[i] is AssetProxy proxy && proxy.IsVirtualProxy() && path.EndsWith(proxy.FileExtension, StringComparison.OrdinalIgnoreCase))
{
return proxy;
}
}
return null;
}
@@ -1016,11 +998,13 @@ namespace FlaxEditor.Modules
}
if (item == null)
{
var proxy = GetAssetVirtuallProxy(path);
var proxy = GetAssetVirtualProxy(path);
item = proxy?.ConstructItem(path, assetInfo.TypeName, ref assetInfo.ID);
if (item == null)
{
item = new FileItem(path);
item = GetProxy(Path.GetExtension(path))?.ConstructItem(path);
if (item == null)
item = new FileItem(path);
}
}
@@ -1106,6 +1090,7 @@ namespace FlaxEditor.Modules
Proxy.Add(new VisualScriptProxy());
Proxy.Add(new BehaviorTreeProxy());
Proxy.Add(new LocalizedStringTableProxy());
Proxy.Add(new VideoProxy("mp4"));
Proxy.Add(new WidgetProxy());
Proxy.Add(new FileProxy());
Proxy.Add(new SpawnableJsonAssetProxy<PhysicalMaterial>());

View File

@@ -210,6 +210,13 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(310)]
public bool SeparateValueAndUnit { get; set; }
/// <summary>
/// Gets or sets the option to put a space between numbers and units for unit formatting.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Interface"), EditorOrder(320)]
public bool ShowTreeLines { get; set; } = true;
/// <summary>
/// Gets or sets the timestamps prefix mode for output log messages.
/// </summary>

View File

@@ -255,6 +255,17 @@ namespace FlaxEditor.Options
}
}
// Ensure custom fonts are valid, reset if not
var defaultInterfaceOptions = new InterfaceOptions();
if (Style.Current.FontTitle == null)
Style.Current.FontTitle = defaultInterfaceOptions.TitleFont.GetFont();
if (Style.Current.FontSmall == null)
Style.Current.FontSmall = defaultInterfaceOptions.SmallFont.GetFont();
if (Style.Current.FontMedium == null)
Style.Current.FontMedium = defaultInterfaceOptions.MediumFont.GetFont();
if (Style.Current.FontLarge == null)
Style.Current.FontLarge = defaultInterfaceOptions.LargeFont.GetFont();
// Set fallback fonts
var fallbackFonts = Options.Interface.FallbackFonts;
if (fallbackFonts == null || fallbackFonts.Length == 0 || fallbackFonts.All(x => x == null))

View File

@@ -0,0 +1,69 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.CustomEditors.Dedicated
{
/// <summary>
/// Custom editor for <see cref="VideoPlayer"/>.
/// </summary>
[CustomEditor(typeof(VideoPlayer)), DefaultEditor]
public class VideoPlayerEditor : ActorEditor
{
private Label _infoLabel;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
base.Initialize(layout);
// Show playback options during simulation
if (Editor.IsPlayMode)
{
var playbackGroup = layout.Group("Playback");
playbackGroup.Panel.Open();
_infoLabel = playbackGroup.Label(string.Empty).Label;
_infoLabel.AutoHeight = true;
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
var gridControl = grid.CustomControl;
gridControl.ClipChildren = false;
gridControl.Height = Button.DefaultHeight;
gridControl.SlotsHorizontally = 3;
gridControl.SlotsVertically = 1;
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
}
}
/// <inheritdoc />
public override void Refresh()
{
base.Refresh();
if (_infoLabel != null)
{
var text = string.Empty;
foreach (var value in Values)
{
if (value is VideoPlayer player)
text += $"Time: {player.Time:##0.0}s / {player.Duration:##0.0}s\nResolution: {player.Size.X}x{player.Size.Y}, Frame Rate: {player.FrameRate}";
}
_infoLabel.Text = text;
}
}
private void Foreach(Action<VideoPlayer> func)
{
foreach (var value in Values)
{
if (value is VideoPlayer player)
func(player);
}
}
}
}

View File

@@ -15,6 +15,7 @@ using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
using Object = FlaxEngine.Object;
namespace FlaxEditor.SceneGraph.GUI
{
@@ -355,7 +356,7 @@ namespace FlaxEditor.SceneGraph.GUI
private void OnRenamed(RenamePopup renamePopup)
{
using (new UndoBlock(ActorNode.Root.Undo, Actor, "Rename"))
Actor.Name = renamePopup.Text;
Actor.Name = renamePopup.Text.Trim();
}
/// <inheritdoc />
@@ -625,6 +626,7 @@ namespace FlaxEditor.SceneGraph.GUI
{
var item = _dragScriptItems.Objects[i];
var actorType = Editor.Instance.CodeEditing.Actors.Get(item);
var scriptType = Editor.Instance.CodeEditing.Scripts.Get(item);
if (actorType != ScriptType.Null)
{
var actor = actorType.CreateInstance() as Actor;
@@ -639,6 +641,18 @@ namespace FlaxEditor.SceneGraph.GUI
ActorNode.Root.Spawn(actor, spawnParent);
actor.OrderInParent = newOrder;
}
else if (scriptType != ScriptType.Null)
{
if (DragOverMode == DragItemPositioning.Above || DragOverMode == DragItemPositioning.Below)
{
Editor.LogWarning("Failed to spawn script of type " + actorType.TypeName);
continue;
}
IUndoAction action = new AddRemoveScript(true, newParent, scriptType);
Select();
ActorNode.Root.Undo?.AddAction(action);
action.Do();
}
}
result = DragDropEffect.Move;
}
@@ -699,9 +713,9 @@ namespace FlaxEditor.SceneGraph.GUI
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType);
}
private static bool ValidateDragScriptItem(ScriptItem script)
private bool ValidateDragScriptItem(ScriptItem script)
{
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null || Editor.Instance.CodeEditing.Scripts.Get(script) != ScriptType.Null;
}
/// <inheritdoc />

View File

@@ -430,7 +430,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Smoothstep",
Description = "Returns a smooth Hermite interpolation between 0 and 1, if value is in the range [min, max].",
Flags = NodeFlags.MaterialGraph,
Size = new Float2(120, 60),
Size = new Float2(200, 60),
ConnectionsHints = ConnectionsHint.Numeric,
IndependentBoxes = new[] { 0, 1, 2 },
DependentBoxes = new[] { 3 },

View File

@@ -1471,5 +1471,27 @@ namespace FlaxEditor.Utilities
inputActions.Add(options => options.GenerateScriptsProject, () => Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync());
inputActions.Add(options => options.RecompileScripts, ScriptsBuilder.Compile);
}
internal static string ToPathProject(string path)
{
if (path != null)
{
// Convert into path relative to the project (cross-platform)
var projectFolder = Globals.ProjectFolder;
if (path.StartsWith(projectFolder))
path = path.Substring(projectFolder.Length + 1);
}
return path;
}
internal static string ToPathAbsolute(string path)
{
if (path != null)
{
// Convert into global path to if relative to the project
path = StringUtils.IsRelative(path) ? Path.Combine(Globals.ProjectFolder, path) : path;
}
return path;
}
}
}

View File

@@ -21,6 +21,7 @@
#include "Engine/Level/Actors/Sky.h"
#include "Engine/Level/Actors/SkyLight.h"
#include "Engine/Level/Actors/SpotLight.h"
#include "Engine/Video/VideoPlayer.h"
#define ICON_RADIUS 7.0f
@@ -283,6 +284,7 @@ bool ViewportIconsRendererService::Init()
MAP_TYPE(Sky, Skybox);
MAP_TYPE(SkyLight, SkyLight);
MAP_TYPE(SpotLight, PointLight);
MAP_TYPE(VideoPlayer, SceneAnimationPlayer);
#undef MAP_TYPE
return false;

View File

@@ -351,6 +351,8 @@ namespace FlaxEditor.Viewport
private void OnCollectDrawCalls(ref RenderContext renderContext)
{
if (renderContext.View.Pass == DrawPass.Depth)
return;
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
if (ShowNavigation)
Editor.Internal_DrawNavMesh();
@@ -620,12 +622,12 @@ namespace FlaxEditor.Viewport
private static bool ValidateDragActorType(ScriptType actorType)
{
return Level.IsAnySceneLoaded;
return Level.IsAnySceneLoaded && Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
}
private static bool ValidateDragScriptItem(ScriptItem script)
{
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
return Level.IsAnySceneLoaded && Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
}
/// <inheritdoc />

View File

@@ -98,7 +98,6 @@ namespace FlaxEditor.Viewport
ShowDebugDraw = true;
ShowEditorPrimitives = true;
Gizmos = new GizmosCollection(this);
var inputOptions = window.Editor.Options.Options.Input;
// Prepare rendering task
Task.ActorsSource = ActorsSources.CustomActors;
@@ -219,6 +218,8 @@ namespace FlaxEditor.Viewport
private void OnCollectDrawCalls(ref RenderContext renderContext)
{
if (renderContext.View.Pass == DrawPass.Depth)
return;
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
_debugDrawData.OnDraw(ref renderContext);
}
@@ -498,7 +499,7 @@ namespace FlaxEditor.Viewport
private static bool ValidateDragActorType(ScriptType actorType)
{
return true;
return Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
}
private static bool ValidateDragScriptItem(ScriptItem script)

View File

@@ -459,8 +459,7 @@ namespace FlaxEditor.Windows.Assets
/// <returns>True if failed, otherwise false.</returns>
protected virtual bool SaveToOriginal()
{
// Wait until temporary asset file be fully loaded
if (_asset.WaitForLoaded())
if (_asset.LastLoadFailed)
{
Editor.LogError(string.Format("Cannot save asset {0}. Wait for temporary asset loaded failed.", _item.Path));
return true;
@@ -494,12 +493,6 @@ namespace FlaxEditor.Windows.Assets
return true;
}
// Reload original asset
if (originalAsset)
{
originalAsset.Reload();
}
// Refresh thumbnail
_item.RefreshThumbnail();

View File

@@ -302,8 +302,17 @@ namespace FlaxEditor.Windows.Assets
// TODO: improve the UI
layout.Space(40);
var addParamType = layout.ComboBox().ComboBox;
addParamType.Items = AllowedTypes.Select(CustomEditorsUtil.GetTypeNameUI).ToList();
addParamType.SelectedIndex = 0;
object lastValue = null;
foreach (var e in _proxy.DefaultValues)
lastValue = e.Value;
var allowedTypes = AllowedTypes.Select(CustomEditorsUtil.GetTypeNameUI).ToList();
int index = 0;
if (lastValue != null)
index = allowedTypes.FindIndex(x => x.Equals(CustomEditorsUtil.GetTypeNameUI(lastValue.GetType()), StringComparison.Ordinal));
addParamType.Items = allowedTypes;
addParamType.SelectedIndex = index;
_addParamType = addParamType;
var addParamButton = layout.Button("Add").Button;
addParamButton.Clicked += OnAddParamButtonClicked;

View File

@@ -355,7 +355,6 @@ namespace FlaxEditor.Windows.Assets
Editor.LogError("Failed to save surface data");
}
_asset.Reload();
_asset.WaitForLoaded();
}
}

View File

@@ -0,0 +1,234 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using FlaxEditor.Content;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Windows.Assets
{
/// <summary>
/// Editor window to view video media.
/// </summary>
public sealed class VideoWindow : EditorWindow, IContentItemOwner
{
private VideoItem _item;
private Image _frame;
private VideoPlayer _videoPlayer;
private Image _seekBegin, _seekEnd, _seekLeft, _seekRight, _playPause, _stop;
/// <inheritdoc />
public VideoWindow(Editor editor, VideoItem item)
: base(editor, false, ScrollBars.None)
{
_item = item;
_item.AddReference(this);
Title = _item.ShortName;
// Setup video player
_videoPlayer = new VideoPlayer
{
PlayOnStart = false,
Url = item.Path,
};
// Setup UI
var style = Style.Current;
var icons = Editor.Icons;
var playbackButtonsSize = 24.0f;
var playbackButtonsMouseOverColor = Color.FromBgra(0xFFBBBBBB);
_frame = new Image
{
Brush = new VideoBrush(_videoPlayer),
AnchorPreset = AnchorPresets.StretchAll,
Offsets = new Margin(0.0f, 0.0f, 0.0f, playbackButtonsSize),
Parent = this,
};
var playbackButtonsArea = new ContainerControl
{
AutoFocus = false,
ClipChildren = false,
BackgroundColor = style.LightBackground,
AnchorPreset = AnchorPresets.HorizontalStretchBottom,
Offsets = new Margin(0, 0, -playbackButtonsSize, playbackButtonsSize),
Parent = this
};
var playbackButtonsPanel = new ContainerControl
{
AutoFocus = false,
ClipChildren = false,
AnchorPreset = AnchorPresets.VerticalStretchCenter,
Offsets = Margin.Zero,
Parent = playbackButtonsArea,
};
_seekBegin = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Rewind to timeline start (Home)",
Brush = new SpriteBrush(icons.Skip64),
MouseOverColor = playbackButtonsMouseOverColor,
Rotation = 180.0f,
Parent = playbackButtonsPanel
};
_seekBegin.Clicked += (image, button) => SeekBegin();
playbackButtonsPanel.Width += playbackButtonsSize;
_seekLeft = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Move one frame back (Left Arrow)",
Brush = new SpriteBrush(icons.Left32),
MouseOverColor = playbackButtonsMouseOverColor,
Parent = playbackButtonsPanel
};
_seekLeft.Clicked += (image, button) => SeekLeft();
playbackButtonsPanel.Width += playbackButtonsSize;
_stop = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Stop playback",
Brush = new SpriteBrush(icons.Stop64),
MouseOverColor = playbackButtonsMouseOverColor,
Parent = playbackButtonsPanel
};
_stop.Clicked += (image, button) => Stop();
playbackButtonsPanel.Width += playbackButtonsSize;
_playPause = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Play/pause playback (Space)",
Brush = new SpriteBrush(icons.Play64),
MouseOverColor = playbackButtonsMouseOverColor,
Parent = playbackButtonsPanel
};
_playPause.Clicked += (image, button) => PlayPause();
playbackButtonsPanel.Width += playbackButtonsSize;
_seekRight = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Move one frame forward (Right Arrow)",
Brush = new SpriteBrush(icons.Right32),
MouseOverColor = playbackButtonsMouseOverColor,
Parent = playbackButtonsPanel
};
_seekRight.Clicked += (image, button) => SeekRight();
playbackButtonsPanel.Width += playbackButtonsSize;
_seekEnd = new Image(playbackButtonsPanel.Width, 0, playbackButtonsSize, playbackButtonsSize)
{
TooltipText = "Rewind to timeline end (End)",
Brush = new SpriteBrush(icons.Skip64),
MouseOverColor = playbackButtonsMouseOverColor,
Parent = playbackButtonsPanel
};
_seekEnd.Clicked += (image, button) => SeekEnd();
playbackButtonsPanel.Width += playbackButtonsSize;
playbackButtonsPanel.X = (playbackButtonsPanel.Parent.Width - playbackButtonsPanel.Width) * 0.5f;
}
private void PlayPause()
{
if (_videoPlayer.State == VideoPlayer.States.Playing)
_videoPlayer.Pause();
else
_videoPlayer.Play();
}
private void Stop()
{
_videoPlayer.Stop();
}
private void SeekBegin()
{
_videoPlayer.Time = 0.0f;
}
private void SeekEnd()
{
_videoPlayer.Time = _videoPlayer.Duration;
}
private void SeekLeft()
{
if (_videoPlayer.State == VideoPlayer.States.Paused)
_videoPlayer.Time -= 1.0f / _videoPlayer.FrameRate;
}
private void SeekRight()
{
if (_videoPlayer.State == VideoPlayer.States.Paused)
_videoPlayer.Time += 1.0f / _videoPlayer.FrameRate;
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
switch (key)
{
case KeyboardKeys.ArrowLeft:
SeekLeft();
return true;
case KeyboardKeys.ArrowRight:
SeekRight();
return true;
case KeyboardKeys.Home:
SeekBegin();
return true;
case KeyboardKeys.End:
SeekEnd();
return true;
case KeyboardKeys.Spacebar:
PlayPause();
return true;
}
return false;
}
/// <inheritdoc />
public override void Update(float deltaTime)
{
base.Update(deltaTime);
// Update UI
var state = _videoPlayer.State;
var icons = Editor.Icons;
_stop.Enabled = state != VideoPlayer.States.Stopped;
_seekLeft.Enabled = _seekRight.Enabled = state != VideoPlayer.States.Playing;
((SpriteBrush)_playPause.Brush).Sprite = state == VideoPlayer.States.Playing ? icons.Pause64 : icons.Play64;
}
/// <inheritdoc />
public override void OnDestroy()
{
if (IsDisposing)
return;
_videoPlayer.Stop();
Object.Destroy(ref _videoPlayer);
_item.RemoveReference(this);
_item = null;
base.OnDestroy();
}
/// <inheritdoc />
public void OnItemDeleted(ContentItem item)
{
if (item == _item)
Close();
}
/// <inheritdoc />
public void OnItemRenamed(ContentItem item)
{
}
/// <inheritdoc />
public void OnItemReimported(ContentItem item)
{
}
/// <inheritdoc />
public void OnItemDispose(ContentItem item)
{
if (item == _item)
Close();
}
}
}

View File

@@ -311,6 +311,23 @@ namespace FlaxEditor.Windows
{
if (selection[i] is BinaryAssetItem binaryAssetItem)
Editor.ContentImporting.Reimport(binaryAssetItem);
else if (selection[i] is PrefabItem prefabItem)
{
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
var modelPrefab = prefab.GetDefaultInstance().GetScript<ModelPrefab>();
if (!modelPrefab)
continue;
var importPath = modelPrefab.ImportPath;
var editor = Editor.Instance;
if (editor.ContentImporting.GetReimportPath("Model Prefab", ref importPath))
continue;
var folder = editor.ContentDatabase.Find(Path.GetDirectoryName(prefab.Path)) as ContentFolder;
if (folder == null)
continue;
var importOptions = modelPrefab.ImportOptions;
importOptions.Type = FlaxEngine.Tools.ModelTool.ModelType.Prefab;
editor.ContentImporting.Import(importPath, folder, true, importOptions);
}
}
}

View File

@@ -542,6 +542,8 @@ namespace FlaxEditor.Windows
return;
}
newShortName = newShortName.Trim();
// Cache data
string extension = item.IsFolder ? "" : Path.GetExtension(item.Path);
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);

View File

@@ -767,13 +767,6 @@ namespace FlaxEditor.Windows
Platform = BuildPlatform.Windows64,
Mode = BuildConfiguration.Development,
},
new BuildTarget
{
Name = "Windows 32bit",
Output = "Output\\Win32",
Platform = BuildPlatform.Windows32,
Mode = BuildConfiguration.Development,
},
}
};
_data = presets;
@@ -793,9 +786,9 @@ namespace FlaxEditor.Windows
Array.Copy(_data[_selectedPresetIndex].Targets, targets, count);
targets[count] = new BuildTarget
{
Name = "Xbox One",
Output = "Output\\XboxOne",
Platform = BuildPlatform.XboxOne,
Name = "Windows 64bit",
Output = "Output\\Win64",
Platform = BuildPlatform.Windows64,
Mode = BuildConfiguration.Development,
};
_data[_selectedPresetIndex].Targets = targets;

View File

@@ -470,6 +470,10 @@ namespace FlaxEditor.Windows
IsMaximized = false;
IsBorderless = false;
Cursor = CursorType.Default;
Screen.CursorLock = CursorLockMode.None;
if (Screen.MainWindow.IsMouseTracking)
Screen.MainWindow.EndTrackingMouse();
RootControl.GameRoot.EndMouseCapture();
}
/// <inheritdoc />
@@ -478,7 +482,7 @@ namespace FlaxEditor.Windows
base.OnMouseLeave();
// Remove focus from game window when mouse moves out and the cursor is hidden during game
if ((IsFocused || ContainsFocus) && Parent != null && Editor.IsPlayMode && !Screen.CursorVisible)
if (ContainsFocus && Parent != null && Editor.IsPlayMode && !Screen.CursorVisible && Screen.CursorLock == CursorLockMode.None)
{
Parent.Focus();
}

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using System.ComponentModel;
using FlaxEditor.CustomEditors;
using FlaxEngine;
@@ -96,14 +95,6 @@ namespace FlaxEditor.Windows
set => Graphics.ShadowMapsQuality = value;
}
[DefaultValue(false)]
[EditorOrder(1320), EditorDisplay("Quality", "Allow CSM Blending"), Tooltip("Enables cascades splits blending for directional light shadows.")]
public bool AllowCSMBlending
{
get => Graphics.AllowCSMBlending;
set => Graphics.AllowCSMBlending = value;
}
[NoSerialize, DefaultValue(1.0f), Limit(0.05f, 5, 0)]
[EditorOrder(1400), EditorDisplay("Quality")]
[Tooltip("The scale of the rendering resolution relative to the output dimensions. If lower than 1 the scene and postprocessing will be rendered at a lower resolution and upscaled to the output backbuffer.")]

View File

@@ -281,7 +281,7 @@ namespace FlaxEditor.Windows
if (IsLayoutLocked)
return;
_hScroll.Maximum = _output.TextSize.X;
_hScroll.Maximum = Mathf.Max(_output.TextSize.X, _hScroll.Minimum);
_vScroll.Maximum = Mathf.Max(_output.TextSize.Y - _output.Height, _vScroll.Minimum);
}

View File

@@ -367,6 +367,7 @@ namespace FlaxEditor.Windows
var tree = new Tree(false)
{
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Margin = new Margin(0, 0, 0, panel.ScrollBarsSize),
IsScrollable = true,
Parent = panel
};

View File

@@ -232,12 +232,12 @@ void BehaviorTree::OnScriptsReloadEnd()
Graph.Setup(this);
}
void BehaviorTree::GetReferences(Array<Guid>& output) const
void BehaviorTree::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
Graph.GetReferences(output);
Graph.GetReferences(assets);
// Extract refs from serialized nodes data
for (const BehaviorTreeGraphNode& n : Graph.Nodes)
@@ -246,7 +246,7 @@ void BehaviorTree::GetReferences(Array<Guid>& output) const
continue;
const Variant& data = n.Values[1];
if (data.Type == VariantType::Blob)
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), output);
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), assets);
}
}

View File

@@ -98,7 +98,7 @@ public:
// [BinaryAsset]
void OnScriptingDispose() override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
protected:

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