Compare commits

...

337 Commits

Author SHA1 Message Date
mafiesto4 c486577b07 Fix TAA in editor's debug view modes 2024-05-20 19:03:28 +02:00
mafiesto4 a69c8ce6a2 Revert 73f68c102d and reopen #2610 2024-05-20 18:37:15 +02:00
mafiesto4 e527783e55 Fix missing curve initialization when loading from json 2024-05-20 18:36:41 +02:00
mafiesto4 4d9c92dd49 Fix editor hang when scene deserialization fails 2024-05-20 18:24:20 +02:00
mafiesto4 9b01229e58 Fix regression in GPU Particle collisions in editor 2024-05-20 18:12:35 +02:00
mafiesto4 e3a030fad8 Update version 2024-05-20 17:10:23 +02:00
mafiesto4 cb878294ea Minor fixes 2024-05-20 17:09:59 +02:00
mafiesto4 1bd1aca0f0 Merge branch 'GoaLitiuM-richtextbox_fix' 2024-05-20 14:43:26 +02:00
mafiesto4 b433312042 Merge branch 'richtextbox_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-richtextbox_fix 2024-05-20 14:43:09 +02:00
mafiesto4 1041b1b86d Merge branch 'tecnessino-patch-2' 2024-05-20 14:23:20 +02:00
mafiesto4 1ace5fd10d Merge branch 'patch-2' of https://github.com/tecnessino/FlaxEngine into tecnessino-patch-2 2024-05-20 14:23:03 +02:00
mafiesto4 cfc9f73744 Fix deadlock between content storage and asset that is being updated during load
#2621
2024-05-20 14:22:03 +02:00
mafiesto4 2418167182 Merge branch 'Tryibion-update-cursor-unlock-text' 2024-05-20 11:47:07 +02:00
mafiesto4 52090d3a6b Merge branch 'update-cursor-unlock-text' of https://github.com/Tryibion/FlaxEngine into Tryibion-update-cursor-unlock-text 2024-05-20 11:47:01 +02:00
mafiesto4 73f68c102d Revert #2421 two bone ik to solve #2610 regression 2024-05-20 11:19:03 +02:00
tecnessino 862dd1e5f1 Change comment 2024-05-18 20:37:43 +02:00
GoaLitiuM 58351d1989 Fix RichTextBox not drawing the last character 2024-05-18 00:00:27 +03:00
Tryibion 6705205e2f Update cursor unlock text with correct input key bind. 2024-05-17 09:41:02 -05:00
mafiesto4 2cdd0ff644 Fix test compilation 2024-05-17 15:47:50 +02:00
mafiesto4 69ae841f64 Merge branch 'Tryibion-sel-prefab-clear-search' 2024-05-17 15:31:04 +02:00
mafiesto4 7f8700288f Merge branch 'sel-prefab-clear-search' of https://github.com/Tryibion/FlaxEngine into Tryibion-sel-prefab-clear-search 2024-05-17 15:30:59 +02:00
mafiesto4 f87dec6ca6 Merge branch 'Tryibion-edit-options-move' 2024-05-17 15:30:50 +02:00
mafiesto4 65a6c0aed5 Merge branch 'edit-options-move' of https://github.com/Tryibion/FlaxEngine into Tryibion-edit-options-move 2024-05-17 15:30:44 +02:00
mafiesto4 f6dd0decfb Merge branch 'Tryibion-prefab-camera' 2024-05-17 15:30:26 +02:00
mafiesto4 816984542a Merge branch 'prefab-camera' of https://github.com/Tryibion/FlaxEngine into Tryibion-prefab-camera 2024-05-17 15:30:18 +02:00
Tryibion 3837e8b263 Rename "Options" to "Editor Options" and move under the "Edit" menu. 2024-05-16 23:20:44 -05:00
Tryibion 47b3141f18 Clear item search on select prefab 2024-05-16 23:00:32 -05:00
Tryibion e10ee3e55a Force camera model to load in prefabs. 2024-05-16 16:49:56 -05:00
mafiesto4 0a4e89e29b Fix UI navigation when using multiple canvases
#2574
2024-05-16 16:12:53 +02:00
mafiesto4 0765fa92b5 Add option to move all selected UI Controls while holding Shift key 2024-05-16 14:11:11 +02:00
mafiesto4 2529312152 Refactor Color.FromRGBA and add matching old logic Color.FromARGB
2592
2024-05-16 13:45:29 +02:00
mafiesto4 3404643636 Add better error messages to NetworkReplicator::SetObjectOwnership for incorrect usage 2024-05-16 10:49:51 +02:00
mafiesto4 6b9f6ac82e Fix incorrect async methods used as RPCs (not supported now) 2024-05-16 10:35:17 +02:00
mafiesto4 ab5bb79754 Fix regression in collections editing after improving ReadOnly option 2024-05-16 10:34:57 +02:00
mafiesto4 58f95d6ce3 Simplify 6f2bd0e932 2024-05-15 23:49:46 +02:00
mafiesto4 1cd2f6a070 Fix compilation when using non-strongly typed enum as default value 2024-05-15 13:23:30 +02:00
mafiesto4 35ddfc2455 Add test case of nested types in scripting
#2582 #2591
2024-05-15 13:09:51 +02:00
mafiesto4 17d1d87268 Merge branch 'GoaLitiuM-nested_type_fixes' 2024-05-15 12:51:57 +02:00
mafiesto4 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
mafiesto4 b4a4a8a591 Minor code cleanup 2024-05-15 12:40:08 +02:00
mafiesto4 24e4015425 Merge branch 'Tryibion-font-case' 2024-05-15 12:30:43 +02:00
mafiesto4 c670887b1a Merge branch 'font-case' of https://github.com/Tryibion/FlaxEngine into Tryibion-font-case 2024-05-15 12:30:39 +02:00
mafiesto4 d3cd6a461b Merge branch 'Tryibion-ui-edit-handles' 2024-05-15 12:26:25 +02:00
mafiesto4 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
mafiesto4 4fdd9a242b Merge branch 'Tryibion-add-script' 2024-05-15 12:26:06 +02:00
mafiesto4 a6e8e6f749 Merge branch 'add-script' of https://github.com/Tryibion/FlaxEngine into Tryibion-add-script 2024-05-15 12:25:59 +02:00
mafiesto4 03eabbcf63 Merge branch 'Tryibion-control-trans-dup' 2024-05-15 12:25:34 +02:00
mafiesto4 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
mafiesto4 3b44062eb0 Merge branch 'Tryibion-checkerboard-colorpicker' 2024-05-15 12:25:13 +02:00
mafiesto4 1457637707 Merge branch 'checkerboard-colorpicker' of https://github.com/Tryibion/FlaxEngine into Tryibion-checkerboard-colorpicker 2024-05-15 12:25:08 +02:00
mafiesto4 d28567111f Merge branch 'Tryibion-treenode-guidelines' 2024-05-15 12:24:17 +02:00
mafiesto4 1c7f06e570 Merge branch 'treenode-guidelines' of https://github.com/Tryibion/FlaxEngine into Tryibion-treenode-guidelines 2024-05-15 12:24:12 +02:00
mafiesto4 63cc0fef2e Merge branch 'Tryibion-tooltip-text-padding' 2024-05-15 12:23:52 +02:00
mafiesto4 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
mafiesto4 fa23619f08 Merge branch 'Tryibion-scroll-colors' 2024-05-15 12:23:12 +02:00
mafiesto4 1f2456fc67 Merge branch 'scroll-colors' of https://github.com/Tryibion/FlaxEngine into Tryibion-scroll-colors 2024-05-15 12:23:08 +02:00
mafiesto4 0b71e906a6 Merge branch 'Tryibion-textbox-add' 2024-05-15 12:22:47 +02:00
mafiesto4 2e59c35a44 Merge branch 'textbox-add' of https://github.com/Tryibion/FlaxEngine into Tryibion-textbox-add 2024-05-15 12:22:40 +02:00
mafiesto4 6f2bd0e932 Another attempt on 6a883bc7c6 2024-05-15 11:22:07 +02:00
mafiesto4 6a883bc7c6 Revert file handles bug 2024-05-14 09:03:52 +02:00
Tryibion 17de6388ca Code fix 2024-05-13 17:42:37 -05:00
Tryibion e028d263f1 Remove unused include. 2024-05-13 16:38:38 -05:00
Tryibion 6962ed6730 Fix case spelling 2024-05-13 16:38:10 -05:00
Tryibion b66d50ae1b Add font and case options to Label and Textbox 2024-05-13 16:34:23 -05:00
Tryibion 675ce71935 Draw hover before selection so that way ui selection is drawn on top. 2024-05-13 12:45:59 -05:00
Tryibion 833f844d59 Minor improvements to ui editor widget drawing. 2024-05-13 12:38:11 -05:00
mafiesto4 af08dc1c69 Fix ReadOnly attribute handling in collection editors 2024-05-13 16:08:50 +02:00
Tryibion 07628d2ec7 Clean up code 2024-05-11 21:31:00 -05:00
Tryibion aac3dbfe09 Fix control transform duplicating when changing anchor. 2024-05-11 21:29:45 -05:00
Tryibion 185f24ce49 Fix value alpha transparency being applied twice to preview color. 2024-05-11 20:19:51 -05:00
GoaLitiuM 77e29109ee Fix native internal type name for deeply nested types 2024-05-11 15:48:49 +03:00
GoaLitiuM 8d89b9efb0 Fix internal type name for nested blittable element types 2024-05-11 15:48:43 +03:00
Tryibion b2fee31a13 Add checkerboard background to color picker dialog color. 2024-05-10 20:30:14 -05:00
Tryibion fc7628e2ee Add tree node guidlines 2024-05-10 19:22:23 -05:00
Tryibion 2e3e4959d6 Add width padding for tooltip 2024-05-10 17:18:10 -05:00
Tryibion f22105c2c3 Allow adding script via drag drop 2024-05-10 16:58:40 -05:00
Tryibion 533902d185 Change panel scroll bar style editor order. 2024-05-10 15:04:27 -05:00
mafiesto4 68653fa91f Add small code optimizations 2024-05-10 12:27:28 +02:00
Tryibion dc0aa61a14 Add scrollbar colors to Panel 2024-05-09 22:14:08 -05:00
Tryibion ee790ff3a9 Change colors for tabs to be seen better. 2024-05-09 21:53:22 -05:00
Tryibion a2a3926aee Expose colors in scrollbar 2024-05-09 21:53:04 -05:00
Tryibion 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
mafiesto4 44006dd533 Various code improvements 2024-05-09 18:59:09 +02:00
mafiesto4 f6aabf2d14 Optimize navmesh building and reduce scene lock time 2024-05-09 18:58:47 +02:00
mafiesto4 dc1f15f18d Add OnStaticFlagsChanged to Actor 2024-05-09 16:55:05 +02:00
mafiesto4 7d7808af8f Remove default value tooltips from post process docs to prevent errors 2024-05-09 10:56:42 +02:00
mafiesto4 5029584a9f Fix crash when Visual Script event binding instance is invalid
#2548
2024-05-09 10:17:23 +02:00
mafiesto4 f353d3f114 Fix looping root motion 2024-05-09 10:16:45 +02:00
mafiesto4 667e8bc293 Minor cleanup in anim code 2024-05-09 10:16:34 +02:00
mafiesto4 2edb9cc4d8 Fix compilation warnings when using 64-bit coords 2024-05-08 23:24:23 +02:00
mafiesto4 7018666a8c Add layer masking for PostFxVolume against Camera's RenderLayersMask
#2573
2024-05-08 22:42:35 +02:00
mafiesto4 f04926ad94 Merge branch 'GoaLitiuM-treenode_expanded_fix' 2024-05-08 19:30:55 +02:00
GoaLitiuM 50f5f0acd9 Fix TreeNode rendering issues with expanded nodes 2024-05-08 20:15:55 +03:00
mafiesto4 3745979b81 Add attributes for game into AndroidManifest 2024-05-08 18:49:16 +02:00
mafiesto4 db15f6f08a Add For Distribution to be enabled by default in Release builds
#2571
2024-05-08 18:48:55 +02:00
mafiesto4 e1a2f51d5a Merge branch 'GoaLitiuM-editor_font_validation' 2024-05-08 18:17:53 +02:00
mafiesto4 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
mafiesto4 d46ef6ac92 Merge branch 'Tryibion-add-shift-scroll' 2024-05-08 18:17:20 +02:00
mafiesto4 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
mafiesto4 b1636c27e7 Merge branch 'Tryibion-Move-control-transform' 2024-05-08 17:39:48 +02:00
mafiesto4 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
mafiesto4 065dc474c0 Merge branch 'Tryibion-game-window-focus-issue' 2024-05-08 17:31:16 +02:00
mafiesto4 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
mafiesto4 f0b72aa025 Merge branch 'Tryibion-color-picker' 2024-05-08 17:30:50 +02:00
mafiesto4 058077736b Merge branch 'color-picker' of https://github.com/Tryibion/FlaxEngine into Tryibion-color-picker 2024-05-08 17:30:45 +02:00
mafiesto4 b02f011627 Merge branch 'GoaLitiuM-drawtext_fix' 2024-05-08 10:34:33 +02:00
GoaLitiuM ea04c746fd Fix Editor not launching if custom interface fonts are missing 2024-05-07 21:18:09 +03:00
GoaLitiuM 97454fc82e Fix drawing an extra character with Render2D.DrawText 2024-05-07 20:10:05 +03:00
Tryibion 4a6afdb108 Small fixes for color picker. 2024-05-07 08:41:23 -05:00
mafiesto4 65e852600a Merge branch 'Tryibion-skip-empty-layers' 2024-05-05 22:56:47 +02:00
mafiesto4 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
mafiesto4 c0329abe40 Merge branch 'Tryibion-fix-properties-1st-offset' 2024-05-05 22:55:30 +02:00
mafiesto4 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
mafiesto4 e171bb06ec Merge branch 'GoaLitiuM-unbox_array_fix' 2024-05-05 22:54:18 +02:00
mafiesto4 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
mafiesto4 db8adf7d96 Fix creating virtual terrain collision of actor that is not in a game 2024-05-05 22:50:12 +02:00
GoaLitiuM e77ae12b9b Fix unboxing of array type Variants 2024-05-05 13:15:54 +03:00
Tryibion bf4e4aeaf6 Fix bottom offset for last property label and property 2024-05-04 22:32:00 -05:00
Tryibion 2107b069db Fix odd offset between 1st property and property label. 2024-05-04 19:25:56 -05:00
Tryibion ea2005dacb Add layer number to LayerMask UI 2024-05-04 18:08:53 -05:00
Tryibion d5cded8aaa Skip empty layers for LayerMask Editor 2024-05-04 17:51:27 -05:00
Tryibion 430b22d5d7 Dont unfocus game window while cursor is not visible unless the lock mode is none. 2024-05-04 17:37:32 -05:00
mafiesto4 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
mafiesto4 7e3f84f95e Merge branch 'Tryibion-gg-keep-last-type' 2024-05-02 15:57:50 +02:00
mafiesto4 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
mafiesto4 e030d0461b Merge branch 'Tryibion-smoothstep-node-width' 2024-05-02 15:57:31 +02:00
mafiesto4 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
mafiesto4 dc7b7e6e10 Merge branch 'Tryibion-rename-trim' 2024-05-02 15:56:33 +02:00
mafiesto4 1e3eb11b94 Merge branch 'rename-trim' of https://github.com/Tryibion/FlaxEngine into Tryibion-rename-trim 2024-05-02 15:56:25 +02:00
mafiesto4 b15b231b85 Merge branch 'Tryibion-windows-hide-cursor' 2024-05-02 15:55:56 +02:00
mafiesto4 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
mafiesto4 352bf3f9a7 Merge branch 'Tryibion-fix-toolbox-panel-size' 2024-05-02 15:55:29 +02:00
Tryibion 9683868767 Add shift scroll for panels and textbox 2024-05-01 16:12:53 -05:00
Tryibion 40284fbbf8 Fix smooth step visject node width 2024-05-01 14:05:10 -05:00
Tryibion 0c86a900da Default gameplay global type selection to last selected type. 2024-05-01 13:54:41 -05:00
Tryibion c1e3eaeab1 Force windows cursor to show or hide based on cursor hidden value 2024-05-01 13:23:56 -05:00
Tryibion 3c487dff47 Trim actor name on rename. 2024-05-01 12:01:01 -05:00
Tryibion 2260d79e26 Trim content item name on rename 2024-05-01 11:54:07 -05:00
Tryibion 3209320547 Add margin to item tree in toolbox 2024-04-30 15:05:58 -05:00
Tryibion d1db06a9bb Change text alignment to far on some control transform properties 2024-04-29 19:44:49 -05:00
Tryibion 1c1d2fd96f Fix still showing some control transform properties in wrong spot. 2024-04-29 19:38:36 -05:00
Tryibion 2e5ad8c48a Always set control transform under general tab 2024-04-29 18:28:04 -05:00
Tryibion 9a6f866956 Move control transform to be under general group in layout. 2024-04-29 18:24:01 -05:00
mafiesto4 c59bce3b58 Merge branch 'Tryibion-controls-toolbox' 2024-04-29 18:37:11 +02:00
mafiesto4 1185a9c06c Merge branch 'controls-toolbox' of https://github.com/Tryibion/FlaxEngine into Tryibion-controls-toolbox
# Conflicts:
#	Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
2024-04-29 18:37:04 +02:00
Tryibion 026b69c544 Merge branch 'master' into controls-toolbox 2024-04-29 11:34:03 -05:00
mafiesto4 df7ece7655 Merge branch 'Tryibion-controls-toolbox' 2024-04-29 18:24:36 +02:00
mafiesto4 7e8f20bd9b Merge branch 'controls-toolbox' of https://github.com/Tryibion/FlaxEngine into Tryibion-controls-toolbox
# Conflicts:
#	Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
2024-04-29 16:56:30 +02:00
mafiesto4 20aef27439 Merge branch 'Tryibion-watermark-attribute' 2024-04-29 12:23:06 +02:00
mafiesto4 12344cf725 Merge branch 'watermark-attribute' of https://github.com/Tryibion/FlaxEngine into Tryibion-watermark-attribute 2024-04-29 12:23:01 +02:00
mafiesto4 ebb2704726 Merge branch 'Tryibion-fix-caret' 2024-04-29 12:21:55 +02:00
mafiesto4 5f9d0140c7 Merge branch 'fix-caret' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-caret 2024-04-29 12:21:49 +02:00
mafiesto4 02a7f74993 Merge branch 'Tryibion-focus-window-on-spawn' 2024-04-29 10:44:16 +02:00
mafiesto4 452e12db45 Merge branch 'focus-window-on-spawn' of https://github.com/Tryibion/FlaxEngine into Tryibion-focus-window-on-spawn 2024-04-29 10:44:09 +02:00
mafiesto4 ac46c89904 Merge branch 'Tryibion-fix-actortype-drag-spawn' 2024-04-29 10:42:38 +02:00
mafiesto4 88acc772b3 Merge branch 'fix-actortype-drag-spawn' of https://github.com/Tryibion/FlaxEngine into Tryibion-fix-actortype-drag-spawn 2024-04-29 10:42:31 +02:00
mafiesto4 fbec80c801 Fix error when using undo after removing Multi Blend node 2024-04-29 10:35:32 +02:00
mafiesto4 1ef487a5cc Add removing selected blend space point with Delete key
#2505
2024-04-29 10:35:07 +02:00
mafiesto4 1e5861de25 Merge branch 'Tryibion-win-layout-name' 2024-04-29 10:19:48 +02:00
mafiesto4 07733a4efb Merge branch 'win-layout-name' of https://github.com/Tryibion/FlaxEngine into Tryibion-win-layout-name 2024-04-29 10:19:38 +02:00
mafiesto4 fee15846ba Merge branch 'GoaLitiuM-fix_treenode_rendering' 2024-04-29 10:18:06 +02:00
mafiesto4 7040da9a44 Merge branch 'fix_treenode_rendering' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-fix_treenode_rendering 2024-04-29 10:17:58 +02:00
GoaLitiuM a8a621df3b Fix TreeNode not rendering all nodes properly with invisible children 2024-04-28 20:30:41 +03:00
Tryibion 18660140b0 Add controls to the ActorToolbox in the GUI tab. Add dragging and dropping controls from toolbox into scene and prefab trees. 2024-04-27 15:55:25 -05:00
Tryibion 58cc53b44d Remove unused include 2024-04-27 11:10:27 -05:00
Tryibion d8bb831dd9 Add watermark attribute to add watermark to string fields in editor. Have watermark show even when textbox is focused . 2024-04-27 11:07:20 -05:00
Tryibion 0d770e3909 Focus prefab window on item spawn. 2024-04-27 09:56:51 -05:00
Tryibion 3641886ebf Fix textbox caret showing on empty string. 2024-04-27 09:16:03 -05:00
Tryibion 611dd7bad1 Change "Apply window layouts" to "Window layouts" 2024-04-27 09:01:46 -05:00
Tryibion 7db20e0411 Fix actor type drag spawn to correctly assign parent. 2024-04-27 08:44:20 -05:00
mafiesto4 e835b25637 Fix wired Vulkan validation cache errors on Linux
#2201 #1825
2024-04-26 21:47:51 +02:00
mafiesto4 c5520f2777 Update version 2024-04-26 19:12:40 +02:00
mafiesto4 4414398f09 Fix crash when accessing physics objects state in OnLateFixedUpdate
#2494
2024-04-26 19:08:25 +02:00
mafiesto4 5e5497ff18 Add Tags.Find utility
#2492
2024-04-26 19:06:39 +02:00
mafiesto4 aaadf3065d Use ARM64 on the latest macOS builds 2024-04-25 19:41:38 +02:00
mafiesto4 b134a5567d Format comments 2024-04-25 19:30:12 +02:00
mafiesto4 740a31b7a9 Merge branch 'duarteroso-bug/issue-2476' 2024-04-25 19:27:23 +02:00
mafiesto4 75e25bf1f7 Merge branch 'bug/issue-2476' of https://github.com/duarteroso/FlaxEngine into duarteroso-bug/issue-2476 2024-04-25 19:27:11 +02:00
mafiesto4 279c80a9ae Merge branch 'duarteroso-bug/issue-2477' 2024-04-25 19:25:55 +02:00
mafiesto4 4dbfc01715 Merge branch 'bug/issue-2477' of https://github.com/duarteroso/FlaxEngine into duarteroso-bug/issue-2477 2024-04-25 19:25:50 +02:00
mafiesto4 45706be3a6 Merge branch 'duarteroso-bug/issue-2475' 2024-04-25 19:25:29 +02:00
mafiesto4 723423a3fa Merge branch 'bug/issue-2475' of https://github.com/duarteroso/FlaxEngine into duarteroso-bug/issue-2475 2024-04-25 18:02:46 +02:00
mafiesto4 42de657629 Merge branch 'GoaLitiuM-release_prefab_fix' 2024-04-25 18:02:02 +02:00
mafiesto4 16f1e8a3e1 Merge branch 'release_prefab_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-release_prefab_fix 2024-04-25 18:01:57 +02:00
mafiesto4 2c1b2d2b7c Optimize ActorTreeNode reparent when it's not collapsed but one of the parents is 2024-04-25 18:01:06 +02:00
mafiesto4 19cc33b200 Merge branch 'GoaLitiuM-treenode_optimize' 2024-04-25 18:00:27 +02:00
mafiesto4 3641e156ee Merge branch 'treenode_optimize' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-treenode_optimize 2024-04-25 17:18:54 +02:00
mafiesto4 4413af5d20 Merge branch 'GoaLitiuM-modelprefab_freeze_fix' 2024-04-25 17:17:44 +02:00
GoaLitiuM 8c2e7bccaa Delete Prefab default instance when scripting unloads 2024-04-23 22:14:06 +03:00
GoaLitiuM 3e7ac04a88 Fix freeze when selecting ModelPrefab referencing a removed asset 2024-04-23 20:55:20 +03:00
Duarte Roso 9bc9d95a22 Revert "Add android settings"
This reverts commit b6692b4747.
2024-04-23 16:10:08 +02:00
Duarte Roso b6e36c0014 Add android settings
Added:
- version code
- minimum Sdk version
- target Sdk version
2024-04-23 16:09:10 +02:00
Duarte Roso b6692b4747 Add android settings
Added:
- version code
- minimum Sdk version
- target Sdk version
2024-04-23 15:58:36 +02:00
Duarte Roso 62c2e3b8f0 Add exported property to the activity element 2024-04-23 15:30:36 +02:00
Duarte Roso d4774a2bfe Change screen orientation enum 2024-04-23 15:13:04 +02:00
mafiesto4 705856da24 Fix crash when resizing window on Vulkan
Regression from 8488a8d387
#2356
2024-04-23 10:08:16 +02:00
mafiesto4 ab9cc16529 Fix EyeAdaptation bug to flash on play mode start in Editor when time gets reset 2024-04-23 00:03:21 +02:00
mafiesto4 203f03a597 Add Write/Read methods to NetworkStream for INetworkSerializable sending in C# api 2024-04-22 23:25:19 +02:00
mafiesto4 4fbe210730 Fix heightfield not saved when editing splatmap of terrain with physical materials in use
#2262
2024-04-22 23:20:44 +02:00
mafiesto4 6eb431d12c Fix rare error on drag&drop in Editor 2024-04-22 23:17:56 +02:00
mafiesto4 890569ea3b Add logging and cleaning up leaked scene objects after play mode in Editor 2024-04-22 22:59:38 +02:00
mafiesto4 d8a1de64d1 Fix surface node moving regression from f19977a956
#2466
2024-04-22 22:56:01 +02:00
mafiesto4 b92fbcb3bc Add more const correctness
#2467
2024-04-22 22:53:27 +02:00
mafiesto4 515ee96a31 Fix compilation regression 2024-04-22 19:10:06 +02:00
mafiesto4 f19977a956 Fix surface node context menu to not show when moving surface
#2466
2024-04-22 19:03:40 +02:00
mafiesto4 96f628429c Improve const correctness in Mesh and SkinnedMesh api
#2467i
2024-04-22 18:56:54 +02:00
mafiesto4 3ecbbcd0a0 Update Newtonsoft.Json 2024-04-22 18:44:50 +02:00
mafiesto4 a01495cde1 Merge similar source chunks
#2468
2024-04-22 18:36:25 +02:00
mafiesto4 b7dc0dd004 Fix crash when removing Anim Event visual script that is used in opened Animation timeline
#2471
2024-04-22 18:11:25 +02:00
mafiesto4 32b15f90ab Minor improvements 2024-04-22 18:10:58 +02:00
mafiesto4 e795a8b037 Fix compile warning 2024-04-22 15:29:25 +02:00
mafiesto4 e551eae30d Update engine assets 2024-04-22 13:32:09 +02:00
mafiesto4 5f02b4173a Fix nested animations sampling
#2472
2024-04-22 13:29:29 +02:00
mafiesto4 568a69081d Fix animated model skinning precision issues
#2460
2024-04-22 13:18:52 +02:00
GoaLitiuM 4dcdd8b5f7 Add Actor.HasScene and Script.HasScene
Useful in managed code to check the existence of the scene in hot paths
by avoiding expensive marshalling of the Scene object.
2024-04-20 20:58:55 +03:00
mafiesto4 1072b90c5b Fix blend shapes normals usage
#2459
2024-04-20 16:52:07 +02:00
mafiesto4 6aacea99ab Fix blend shapes transformation applying
#2459
2024-04-20 16:16:01 +02:00
mafiesto4 5e086809ae Fix crash on prefab preview with lightmap in use
#2454
2024-04-20 15:51:20 +02:00
GoaLitiuM 361e9a2929 Remove TreeNode text color caching
This is actually slower than just resolving the color before draw.
2024-04-20 16:26:29 +03:00
GoaLitiuM b25ee23b14 Optimize TreeNode rendering 2024-04-20 16:26:25 +03:00
mafiesto4 41ffc16b66 Fix FindRandomPointAroundCircle to always find a valid point on a NavMesh in the radius
#2398
2024-04-20 15:01:27 +02:00
mafiesto4 560cf65121 Add add/remove buttons to Multi Blend 2024-04-19 17:50:14 +02:00
mafiesto4 93e26afa05 Optimize Anim Graph node size and remove limit of max 64 state transitions 2024-04-19 16:31:11 +02:00
mafiesto4 7653fba381 Refactor Multi Blend nodes to support up to 255 blend points 2024-04-19 16:30:34 +02:00
mafiesto4 71fe280464 Refactor Visject Graph nodes data for unlimited size 2024-04-19 12:22:04 +02:00
mafiesto4 0845866c4d Add live debugging of blend position in Multi Blend 2024-04-18 18:42:31 +02:00
mafiesto4 a3b5f4b789 Add grid labels drawing to Multi Blend 2024-04-18 18:22:19 +02:00
mafiesto4 4b6b24f4c5 Fix precision of blend points moving in Multi Blend 2024-04-18 17:22:37 +02:00
mafiesto4 d8079367fd Add improved visuals of points in Multi Blend 2024-04-18 17:22:21 +02:00
mafiesto4 83b9e6e32a Add Ctrl to snap points to grid in Multi Blend editor 2024-04-18 17:04:23 +02:00
mafiesto4 f8f1c02338 Add context menu to Multi Blend node points 2024-04-18 15:27:23 +02:00
mafiesto4 285710360c Fix margins issues in context menus 2024-04-18 15:26:52 +02:00
mafiesto4 695c212cf0 Add tooltips to Multi Blend points 2024-04-18 13:10:33 +02:00
mafiesto4 05278ca418 Add undo for Multi Blend points moving
#1980
2024-04-17 23:28:10 +02:00
mafiesto4 e31ce787aa Add improved size of Multi Blend nodes
#1980
2024-04-17 23:04:09 +02:00
mafiesto4 d379b4c046 Fix missing UI Control preview when changing UI Widget type 2024-04-17 16:43:53 +02:00
mafiesto4 261faad93e Fix incorrect View Size for 2d character font material 2024-04-17 16:41:19 +02:00
mafiesto4 16554fe742 Fix cloning value utility for object references
#2399
2024-04-17 16:17:39 +02:00
mafiesto4 9f983cff49 Refactor engine loop to have better sync between game update, physics and drawing 2024-04-17 13:38:06 +02:00
mafiesto4 e53ab10145 Add Engine::UpdateCount to sync gameplay logic updates with game loop rather than draw frames 2024-04-17 13:31:12 +02:00
mafiesto4 692a61c948 Add Time.Synchronize to stabilize engine loop 2024-04-17 13:01:58 +02:00
mafiesto4 c83b74c85d Fix blending nested animations to properly handle it per-node
#2416
2024-04-16 23:25:37 +02:00
mafiesto4 171fc276fb Fix bug in ValueContainer.HasDifferentTypes causing incorrect editor setup
#2436
2024-04-16 22:32:10 +02:00
mafiesto4 446c1edafc Fix deselecting actors when using camera orbiting in viewport after releasing LMB when Alt is up
#2447
2024-04-16 21:00:54 +02:00
mafiesto4 03b498546d Refactor UpdateGraph to run after engine services and game scripts
#2413
2024-04-16 20:27:31 +02:00
mafiesto4 794b007170 Optimize draw calls sorting in opaque passes 2024-04-16 17:18:18 +02:00
mafiesto4 26c2b33fc0 Fix large world compile 2024-04-16 16:34:38 +02:00
mafiesto4 1a87e5a2ca Add support for importing .exr textures
#2375
2024-04-16 15:19:33 +02:00
mafiesto4 daf3671233 Fix model tool importing to use temp file only for Assimp 2024-04-16 14:38:12 +02:00
mafiesto4 5fd808af19 Update DirectXTex to mar2024 2024-04-16 13:40:42 +02:00
mafiesto4 ce67c3a98d Add ShowDebugDrawSkeleton to preview Animated Model skeleton via Debug Draw
#2443
2024-04-16 12:00:05 +02:00
mafiesto4 cd2f96e3c0 Add better anim events visuals in timeline editor
#2419
2024-04-16 10:17:30 +02:00
mafiesto4 9ad4997691 Add automatic restoring Anim Event tracks when reimporting animation asset
#2363
2024-04-15 19:27:28 +02:00
mafiesto4 37a02e3a7e Minor tweaks 2024-04-15 14:35:35 +02:00
mafiesto4 ed732a0189 Fix panning Visject Surface with middle mouse button (right button does it) to prevent missed connections removals
#2420
2024-04-15 14:34:53 +02:00
mafiesto4 00492a33a3 Fix crash when reimporting animation with translation set
#2445
2024-04-15 13:03:11 +02:00
mafiesto4 56d3b4f012 Fix deadlock when parsing invalid HTML text in RichTextBox
#2402
2024-04-15 12:44:42 +02:00
mafiesto4 85b9d93e91 Update to the latest ReSharper 2024-04-15 12:39:00 +02:00
mafiesto4 8584d51d9f Merge branch 'Tryibion-sort-search-toolbox' 2024-04-15 12:19:16 +02:00
mafiesto4 8714163ee4 Merge branch 'sort-search-toolbox' of https://github.com/Tryibion/FlaxEngine into Tryibion-sort-search-toolbox 2024-04-15 12:19:06 +02:00
mafiesto4 525c3a0f29 Fix terrain heightmap to use higher range format when decompressed
#2375
2024-04-15 12:16:50 +02:00
Tryibion 5acdff02cc Add sorting search actor toolbox 2024-04-14 20:39:15 -05:00
mafiesto4 0728637ce1 Fix using confirm via enter key in Create Terrain dialog 2024-04-15 00:17:21 +02:00
mafiesto4 9c3c4fbf54 Use uniform scale on new terrain to prevent artifacts in normal vectors 2024-04-15 00:13:54 +02:00
mafiesto4 d2508ad902 Merge branch 'Tryibion-actor-search' 2024-04-15 00:02:16 +02:00
mafiesto4 8a0cd7c30f Merge branch 'actor-search' of https://github.com/Tryibion/FlaxEngine into Tryibion-actor-search 2024-04-15 00:02:11 +02:00
mafiesto4 d729eb2b24 Fix crash when playing uninitialized audio source
#2441
2024-04-15 00:01:59 +02:00
mafiesto4 36ad821734 Fix 634b05fc16 2024-04-14 22:39:54 +02:00
Tryibion b66b85d5f4 Display all actors in Actor toolbox search tab when no filter is applied. 2024-04-14 14:03:51 -05:00
mafiesto4 778b967c61 Fix editor toolstrip by moving game cooking and building to the right for less missclicks
#2426
2024-04-14 15:05:25 +02:00
mafiesto4 3f6dd92a68 Fix crash when using old Blend with Mask node in Anim Graph
#2434
2024-04-14 14:51:40 +02:00
mafiesto4 80d7ac2581 Merge branch 'Muzz-IkFix' 2024-04-14 14:41:30 +02:00
mafiesto4 af91ce7f3f Merge branch 'IkFix' of https://github.com/Muzz/FlaxEngine into Muzz-IkFix 2024-04-14 14:39:57 +02:00
mafiesto4 5f7293d0a1 Merge branch 'Tryibion-lock-selection' 2024-04-14 14:34:26 +02:00
mafiesto4 5cdf1c5764 Merge branch 'lock-selection' of https://github.com/Tryibion/FlaxEngine into Tryibion-lock-selection 2024-04-14 14:34:10 +02:00
mafiesto4 e701cdbee5 Merge branch 'Menotdan-nav-mesh-init' 2024-04-14 14:31:25 +02:00
mafiesto4 dc45f46ff4 Merge branch 'nav-mesh-init' of https://github.com/Menotdan/FlaxEngine into Menotdan-nav-mesh-init 2024-04-14 14:31:20 +02:00
mafiesto4 634b05fc16 Fix code style 2024-04-14 13:31:32 +02:00
Menotdan db28afb591 Fix regression where if the navmesh was disabled on playmode beginning, the mesh would still exist in the backend. 2024-04-14 01:02:48 -04:00
Menotdan 84c1f6b5de Make NavMesh initialize earlier. 2024-04-14 00:58:11 -04:00
mafiesto4 53689063b9 Minor tweaks to Gameplay Globals
#2412
2024-04-14 00:09:29 +02:00
mafiesto4 c59e872ef2 Fix crash when loading invalid Variant structure 2024-04-14 00:09:01 +02:00
mafiesto4 2b95f11b1f Fixes to Vulkan backend 2024-04-13 23:55:39 +02:00
mafiesto4 fbfe77e386 Fix win32 compile 2024-04-13 21:44:16 +02:00
mafiesto4 60ccac31b5 Add more sanitizers 2024-04-13 19:20:49 +02:00
mafiesto4 d42e315e55 Fix atomics to accept constant 2024-04-13 19:20:49 +02:00
mafiesto4 9c2c02c1cf Fix various issues found with thread sanitizer on macOS 2024-04-13 19:20:49 +02:00
mafiesto4 8144db8e13 Fix various issues found with adrress sanitizer on macOS 2024-04-13 19:20:49 +02:00
mafiesto4 4ac6a292f7 Add option for using Address and Thread sanitizers 2024-04-13 19:20:49 +02:00
mafiesto4 3e475398e7 Optimize draw calls batching sorting with Merge Sort 2024-04-12 16:02:37 +02:00
Tryibion 81d4501868 Add locking selection in prefab window 2024-04-12 07:41:43 -05:00
Tryibion 1bc7455e09 Add locking scene selection in properties window. 2024-04-12 07:33:09 -05:00
mafiesto4 1e77f3aa5a Optimize DrawBatch for faster sorting 2024-04-12 13:46:20 +02:00
mafiesto4 e47e91c223 Merge branch 'Menotdan-hide-taa-settings' 2024-04-12 13:12:47 +02:00
mafiesto4 734f1ee4aa Improve doc comment 2024-04-12 13:09:24 +02:00
mafiesto4 6d38590ad4 Merge branch 'hide-taa-settings' of https://github.com/Menotdan/FlaxEngine into Menotdan-hide-taa-settings 2024-04-12 13:08:26 +02:00
mafiesto4 76becec094 Merge branch 'GoaLitiuM-dotnet_daily_runtime_fix' 2024-04-12 13:05:46 +02:00
mafiesto4 e7a6f39a72 Merge branch 'dotnet_daily_runtime_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-dotnet_daily_runtime_fix 2024-04-12 13:05:40 +02:00
mafiesto4 98c5cc2d0f Merge branch 'Menotdan-particle-clone-fix' 2024-04-12 13:03:21 +02:00
mafiesto4 c8ad3e3a51 Merge branch 'particle-clone-fix' of https://github.com/Menotdan/FlaxEngine into Menotdan-particle-clone-fix 2024-04-12 13:03:16 +02:00
mafiesto4 5b25aeda32 Merge branch 'Tryibion-underline-fix' 2024-04-12 13:01:18 +02:00
mafiesto4 e5d700692f Merge branch 'underline-fix' of https://github.com/Tryibion/FlaxEngine into Tryibion-underline-fix 2024-04-12 13:01:10 +02:00
mafiesto4 495378c94d Merge branch 'GoaLitiuM-editor_viewport_camera_scaling' 2024-04-12 12:59:54 +02:00
mafiesto4 bf9701e132 Merge branch 'editor_viewport_camera_scaling' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-editor_viewport_camera_scaling 2024-04-12 12:56:22 +02:00
mafiesto4 14881494b8 Merge branch 'GoaLitiuM-debuglog_scroll_fix' 2024-04-12 12:55:17 +02:00
Menotdan c914e33462 Hide TAA settings if TAA isn't enabled. 2024-04-12 02:29:45 -04:00
Muzz 35f33b6746 Fixed IK to have correct bone roll 2024-04-12 12:07:26 +08:00
Menotdan e137d31839 Enforce Content:CloneAssetFile() running on the main thread, to avoid a bug that occurs when a particle emitter is created from one of the templates due to the creation coming from the content thread. 2024-04-11 17:37:31 -04:00
Tryibion 2e643347ec Fix selection height 2024-04-11 10:16:20 -05:00
Tryibion fb1685fe81 Fix underline being in wrong spot on different DPIs 2024-04-11 09:56:59 -05:00
GoaLitiuM 1ddf9ab0e1 Fix high mouse sensitivity in rotation gizmos 2024-04-09 21:45:28 +03:00
GoaLitiuM 8af8d50de1 Remove Editor viewport aspect ratio scaling from camera mouse movement
Rescaled the final mouse delta values to roughly matching default
viewport width in 1080p resolution.
2024-04-09 20:06:35 +03:00
GoaLitiuM e3093e0e09 Fix Debug Log scrolling when many entries are added at once 2024-04-09 20:05:58 +03:00
GoaLitiuM 02d5609f66 Fix .NET runtime validity checks with daily runtime builds 2024-04-09 20:05:37 +03:00
mafiesto4 b2f9da4113 Fix default diffuse color value when importing material 2024-04-05 16:54:10 +02:00
mafiesto4 a83b589e12 Fix error when applying prefab changes with Spline
#2384
2024-04-05 16:43:18 +02:00
mafiesto4 7578e1dbe3 Fix errors on using spline editor in Prefab window
#2383
2024-04-05 16:37:11 +02:00
mafiesto4 ae79f3ef0b Merge branch 'Zode-master' 2024-04-05 15:49:29 +02:00
mafiesto4 f164626c41 Merge branch 'master' of https://github.com/Zode/FlaxEngine into Zode-master 2024-04-05 15:49:20 +02:00
mafiesto4 354972fd9c Merge branch 'rkrahn-master' 2024-04-05 15:47:01 +02:00
mafiesto4 082733cb97 Merge branch 'master' of https://github.com/rkrahn/FlaxEngine into rkrahn-master 2024-04-05 15:46:30 +02:00
mafiesto4 97bd90d4be Change default collision type to ConvexMesh from TriangleMesh 2024-04-05 15:23:09 +02:00
mafiesto4 e788be46af Merge branch 'GoaLitiuM-win_dev_build_speed_fix' 2024-04-04 18:35:37 +02:00
mafiesto4 afd56974ef Merge branch 'win_dev_build_speed_fix' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-win_dev_build_speed_fix 2024-04-04 18:35:31 +02:00
mafiesto4 84e04de23d Add more improvements to optional tess/geo shaders 2024-04-04 18:35:26 +02:00
rkrahn 07c0b4567e Merge branch 'master' of https://github.com/rkrahn/FlaxEngine 2024-04-01 09:54:34 -07:00
GoaLitiuM e25448e10e Trade minor optimizations in MSVC Development builds for compile speed
Enabled the disabled optimization flags with whole program optimization
flag where the compilation speed doesn't seem to be affected at all, but
binary size is slightly smaller.
2024-03-31 19:05:35 +03:00
mafiesto4 d12630d815 Fix 2024-03-31 00:03:45 +01:00
mafiesto4 fb0d70d555 Fix 2024-03-30 23:58:50 +01:00
mafiesto4 c5e1abb08c Add setter for crword agent position and velocity 2024-03-30 22:29:43 +01:00
mafiesto4 294b4c4006 Add CPU profiler events for UI drawing 2024-03-30 22:20:41 +01:00
mafiesto4 e1944bce96 Add statically disabled geometry shaders on mobile 2024-03-30 22:08:44 +01:00
mafiesto4 369c19bd5d Add statically disabled tessellation on macOS/iOS 2024-03-30 18:46:37 +01:00
Zode 55383c3fa4 Patch numpad enter to normal enter on Linux 2024-03-30 02:35:11 +02:00
rkrahn 926a81c84b Merge branch 'FlaxEngine:master' into master 2024-03-29 13:40:36 -07:00
rkrahn d331e6b848 Merge remote-tracking branch 'upstream/master' 2024-03-29 13:38:38 -07:00
rkrahn eac553a992 Add toggle orthographic view hotkey
Adds the Toggle Orthographic hotkey to the editor. Bound to 'NumpadDecimal' by default.
2024-03-10 13:49:14 -07:00
381 changed files with 14780 additions and 2510 deletions
+4 -4
View File
@@ -9,7 +9,7 @@ jobs:
# Editor
editor-mac:
name: Editor (Mac, Development x64)
name: Editor (Mac, Development ARM64)
runs-on: "macos-latest"
steps:
- name: Checkout repo
@@ -30,11 +30,11 @@ jobs:
git lfs pull
- name: Build
run: |
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=8 -arch=ARM64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
# Game
game-mac:
name: Game (Mac, Release x64)
name: Game (Mac, Release ARM64)
runs-on: "macos-latest"
steps:
- name: Checkout repo
@@ -55,4 +55,4 @@ jobs:
git lfs pull
- name: Build
run: |
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=8 -arch=x64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=8 -arch=ARM64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
+2 -2
View File
@@ -166,7 +166,7 @@ jobs:
dotnet workload --info
- name: Build
run: |
./PackageEditor.command -arch=x64 -platform=Mac -deployOutput=Output
./PackageEditor.command -arch=ARM64 -platform=Mac -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v3
with:
@@ -194,7 +194,7 @@ jobs:
dotnet workload --info
- name: Build
run: |
./PackagePlatforms.command -arch=x64 -platform=Mac -deployOutput=Output
./PackagePlatforms.command -arch=ARM64 -platform=Mac -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v3
with:
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.
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.
+15 -18
View File
@@ -430,7 +430,9 @@ float3x4 GetPrevBoneMatrix(int index)
float3 SkinPrevPosition(ModelInput_Skinned input)
{
float4 position = float4(input.Position.xyz, 1);
float3x4 boneMatrix = input.BlendWeights.x * GetPrevBoneMatrix(input.BlendIndices.x);
float weightsSum = input.BlendWeights.x + input.BlendWeights.y + input.BlendWeights.z + input.BlendWeights.w;
float mainWeight = input.BlendWeights.x + (1.0f - weightsSum); // Re-normalize to account for 16-bit weights encoding erros
float3x4 boneMatrix = mainWeight * GetPrevBoneMatrix(input.BlendIndices.x);
boneMatrix += input.BlendWeights.y * GetPrevBoneMatrix(input.BlendIndices.y);
boneMatrix += input.BlendWeights.z * GetPrevBoneMatrix(input.BlendIndices.z);
boneMatrix += input.BlendWeights.w * GetPrevBoneMatrix(input.BlendIndices.w);
@@ -439,12 +441,6 @@ float3 SkinPrevPosition(ModelInput_Skinned input)
#endif
// Cached skinning data to avoid multiple calculation
struct SkinningData
{
float3x4 BlendMatrix;
};
// Calculates the transposed transform matrix for the given bone index
float3x4 GetBoneMatrix(int index)
{
@@ -457,7 +453,9 @@ float3x4 GetBoneMatrix(int index)
// Calculates the transposed transform matrix for the given vertex (uses blending)
float3x4 GetBoneMatrix(ModelInput_Skinned input)
{
float3x4 boneMatrix = input.BlendWeights.x * GetBoneMatrix(input.BlendIndices.x);
float weightsSum = input.BlendWeights.x + input.BlendWeights.y + input.BlendWeights.z + input.BlendWeights.w;
float mainWeight = input.BlendWeights.x + (1.0f - weightsSum); // Re-normalize to account for 16-bit weights encoding erros
float3x4 boneMatrix = mainWeight * GetBoneMatrix(input.BlendIndices.x);
boneMatrix += input.BlendWeights.y * GetBoneMatrix(input.BlendIndices.y);
boneMatrix += input.BlendWeights.z * GetBoneMatrix(input.BlendIndices.z);
boneMatrix += input.BlendWeights.w * GetBoneMatrix(input.BlendIndices.w);
@@ -465,13 +463,13 @@ float3x4 GetBoneMatrix(ModelInput_Skinned input)
}
// Transforms the vertex position by weighted sum of the skinning matrices
float3 SkinPosition(ModelInput_Skinned input, SkinningData data)
float3 SkinPosition(ModelInput_Skinned input, float3x4 boneMatrix)
{
return mul(data.BlendMatrix, float4(input.Position.xyz, 1));
return mul(boneMatrix, float4(input.Position.xyz, 1));
}
// Transforms the vertex position by weighted sum of the skinning matrices
float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
float3x3 SkinTangents(ModelInput_Skinned input, float3x4 boneMatrix)
{
// Unpack vertex tangent frame
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
@@ -479,10 +477,10 @@ float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
// Apply skinning
tangent = mul(data.BlendMatrix, float4(tangent, 0));
normal = mul(data.BlendMatrix, float4(normal, 0));
tangent = normalize(mul(boneMatrix, float4(tangent, 0)));
normal = normalize(mul(boneMatrix, float4(normal, 0)));
float3 bitangent = cross(normal, tangent) * bitangentSign;
float3 bitangent = normalize(cross(normal, tangent) * bitangentSign);
return float3x3(tangent, bitangent, normal);
}
@@ -501,10 +499,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
VertexOutput output;
// Perform skinning
SkinningData data;
data.BlendMatrix = GetBoneMatrix(input);
float3 position = SkinPosition(input, data);
float3x3 tangentToLocal = SkinTangents(input, data);
float3x4 boneMatrix = GetBoneMatrix(input);
float3 position = SkinPosition(input, boneMatrix);
float3x3 tangentToLocal = SkinTangents(input, boneMatrix);
// Compute world space vertex position
CalculateInstanceTransform(input);
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -3,8 +3,8 @@
"Version": {
"Major": 1,
"Minor": 8,
"Revision": 0,
"Build": 6510
"Revision": 2,
"Build": 6512
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",
+6
View File
@@ -74,11 +74,15 @@
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDK/@EntryIndexedValue">SDK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VS/@EntryIndexedValue">VS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=53eecf85_002Dd821_002D40e8_002Dac97_002Dfdb734542b84/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=70345118_002D4b40_002D4ece_002D937c_002Dbbeb7a0b2e70/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
@@ -220,6 +224,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002EFunctionReturnStyleSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002ENamespaceIndentationSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
@@ -232,6 +237,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/GrammarAndSpelling/GrammarChecking/RulesStates/=LanguageTool_002EEN_002EE_005FG/@EntryIndexedValue">DisabledByUser</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/Color/@EntryValue">Blue</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/MatchComments/@EntryValue">True</s:Boolean>
@@ -133,6 +133,7 @@ namespace FlaxEditor.Content.Import
FileTypes["dds"] = ImportTexture;
FileTypes["hdr"] = ImportTexture;
FileTypes["raw"] = ImportTexture;
FileTypes["exr"] = ImportTexture;
// Models
FileTypes["obj"] = ImportModel;
@@ -128,6 +128,11 @@ namespace FlaxEditor.Content.Import
_settings.Settings.Type = TextureFormatType.HdrRGBA;
_settings.Settings.Compress = false;
}
else if (extension == ".exr")
{
// HDR image
_settings.Settings.Type = TextureFormatType.HdrRGBA;
}
else if (extension == ".hdr")
{
// HDR sky texture
@@ -249,6 +249,7 @@ namespace FlaxEditor.Content
private ScriptMemberInfo[] _parameters;
private ScriptMemberInfo[] _methods;
private object[] _attributes;
private List<Action<ScriptType>> _disposing;
/// <summary>
/// Gets the Visual Script asset that contains this type.
@@ -310,6 +311,13 @@ namespace FlaxEditor.Content
internal void Dispose()
{
if (_disposing != null)
{
foreach (var e in _disposing)
e(new ScriptType(this));
_disposing.Clear();
_disposing = null;
}
if (_parameters != null)
{
OnAssetReloading(_asset);
@@ -510,6 +518,14 @@ namespace FlaxEditor.Content
}
return _methods;
}
/// <inheritdoc />
public void TrackLifetime(Action<ScriptType> disposing)
{
if (_disposing == null)
_disposing = new List<Action<ScriptType>>();
_disposing.Add(disposing);
}
}
/// <summary>
@@ -135,7 +135,7 @@ namespace FlaxEditor.Content
}
Task.Run(() =>
{
Editor.CookMeshCollision(assetItem.Path, CollisionDataType.TriangleMesh, model);
Editor.CookMeshCollision(assetItem.Path, CollisionDataType.ConvexMesh, model);
if (created != null)
FlaxEngine.Scripting.InvokeOnUpdate(() => created(collisionData));
});
+1 -1
View File
@@ -89,7 +89,7 @@ namespace FlaxEditor.Content
// Cleanup it after usage
Object.Destroy(actor, 20.0f);
}
else if (actor.Scene != null)
else if (actor.HasScene)
{
// Create prefab with identity transform so the actor instance on a level will have it customized
resetTransform = true;
@@ -203,16 +203,16 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
switch (defaultOrienation)
{
case AndroidPlatformSettings::ScreenOrientation::Portrait:
orientation = String("portrait");
orientation = String("userPortrait");
break;
case AndroidPlatformSettings::ScreenOrientation::PortraitReverse:
orientation = String("reversePortrait");
case AndroidPlatformSettings::ScreenOrientation::Landscape:
orientation = String("userLandscape");
break;
case AndroidPlatformSettings::ScreenOrientation::LandscapeRight:
orientation = String("landscape");
case AndroidPlatformSettings::ScreenOrientation::SensorPortrait:
orientation = String("sensorPortrait");
break;
case AndroidPlatformSettings::ScreenOrientation::LandscapeLeft:
orientation = String("reverseLandscape");
case AndroidPlatformSettings::ScreenOrientation::SensorLandscape:
orientation = String("sensorLandscape");
break;
case AndroidPlatformSettings::ScreenOrientation::AutoRotation:
orientation = String("fullSensor");
@@ -266,9 +266,33 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
}
}
String versionCode = platformSettings->VersionCode;
if (versionCode.IsEmpty())
{
LOG(Error, "AndroidSettings: Invalid version code");
return true;
}
String minimumSdk = platformSettings->MinimumAPILevel;
if (minimumSdk.IsEmpty())
{
LOG(Error, "AndroidSettings: Invalid minimum API level");
return true;
}
String targetSdk = platformSettings->TargetAPILevel;
if (targetSdk.IsEmpty())
{
LOG(Error, "AndroidSettings: Invalid target API level");
return true;
}
// Format project template files
const String buildGradlePath = data.OriginalOutputPath / TEXT("app/build.gradle");
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${PackageName}"), packageName);
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${VersionCode}"), versionCode);
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${MinimumSdk}"), minimumSdk);
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${TargetSdk}"), targetSdk);
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${ProjectVersion}"), projectVersion);
EditorUtilities::ReplaceInFile(buildGradlePath, TEXT("${PackageAbi}"), abi);
const String manifestPath = data.OriginalOutputPath / TEXT("app/src/main/AndroidManifest.xml");
@@ -341,7 +365,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"));
+1 -1
View File
@@ -536,7 +536,7 @@ namespace FlaxEditor.CustomEditors
/// </summary>
public void ClearReferenceValueAll()
{
Values.ClearReferenceValue();
Values?.ClearReferenceValue();
for (int i = 0; i < ChildrenEditors.Count; i++)
{
@@ -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)
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.CustomEditors.Elements;
@@ -9,6 +10,8 @@ using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
@@ -72,7 +75,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Selecting actor prefab asset
var selectPrefab = panel.Button("Select Prefab");
selectPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Select(prefab);
selectPrefab.Button.Clicked += () =>
{
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
Editor.Instance.Windows.ContentWin.Select(prefab);
};
// Viewing changes applied to this actor
var viewChanges = panel.Button("View Changes");
@@ -111,6 +118,38 @@ namespace FlaxEditor.CustomEditors.Dedicated
var actor = (Actor)Values[0];
var scriptType = TypeUtils.GetType(actor.TypeName);
var item = scriptType.ContentItem;
if (Presenter.Owner is PropertiesWindow propertiesWindow)
{
var lockButton = cm.AddButton(propertiesWindow.LockObjects ? "Unlock" : "Lock");
lockButton.ButtonClicked += button =>
{
propertiesWindow.LockObjects = !propertiesWindow.LockObjects;
// Reselect current selection
if (!propertiesWindow.LockObjects && Editor.Instance.SceneEditing.SelectionCount > 0)
{
var cachedSelection = Editor.Instance.SceneEditing.Selection.ToArray();
Editor.Instance.SceneEditing.Select(null);
Editor.Instance.SceneEditing.Select(cachedSelection);
}
};
}
else if (Presenter.Owner is PrefabWindow prefabWindow)
{
var lockButton = cm.AddButton(prefabWindow.LockSelectedObjects ? "Unlock" : "Lock");
lockButton.ButtonClicked += button =>
{
prefabWindow.LockSelectedObjects = !prefabWindow.LockSelectedObjects;
// Reselect current selection
if (!prefabWindow.LockSelectedObjects && prefabWindow.Selection.Count > 0)
{
var cachedSelection = prefabWindow.Selection.ToList();
prefabWindow.Select(null);
prefabWindow.Select(cachedSelection);
}
};
}
cm.AddButton("Copy ID", OnClickCopyId);
cm.AddButton("Edit actor type", OnClickEditActorType).Enabled = item != null;
var showButton = cm.AddButton("Show in content window", OnClickShowActorType);
@@ -164,7 +203,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
//Presenter.BuildLayoutOnUpdate();
// Better way is to just update the reference value using the new default instance of the prefab, created after changes apply
if (prefab && !prefab.WaitForLoaded())
if (Values != null && prefab && !prefab.WaitForLoaded())
{
var actor = (Actor)Values[0];
var prefabObjectId = actor.PrefabObjectID;
@@ -256,7 +295,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (editor.ChildrenEditors.Count == 0 || (isRefEdited && editor is CollectionEditor))
result = CreateDiffNode(editor);
bool isScriptEditorWithRefValue = editor is ScriptsEditor && editor.Values.HasReferenceValue;
bool isActorEditorInLevel = editor is ActorEditor && editor.Values[0] is Actor actor && actor.IsPrefabRoot && actor.Scene != null;
bool isActorEditorInLevel = editor is ActorEditor && editor.Values[0] is Actor actor && actor.IsPrefabRoot && actor.HasScene;
for (int i = 0; i < editor.ChildrenEditors.Count; i++)
{
var childEditor = editor.ChildrenEditors[i];
@@ -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);
}
}
@@ -45,6 +45,12 @@ public class ModelPrefabEditor : GenericEditor
break;
_prefabId = prefabObject.PrefabID;
}
else
{
// The model was removed earlier
_prefabId = Guid.Empty;
break;
}
}
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
@@ -37,6 +37,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
EvaluateVisibleIf(itemLayout, item, GetLabelIndex(itemLayout, item));
// Add labels with a check box
var label = new CheckablePropertyNameLabel(item.DisplayName);
label.CheckBox.Tag = setting.Bit;
@@ -209,16 +209,15 @@ namespace FlaxEditor.CustomEditors.Dedicated
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
{
var result = base.OnDragMove(ref location, data);
if (result != DragDropEffect.None)
if (result != DragDropEffect.None || _dragHandlers == null)
return result;
return _dragHandlers.Effect;
}
/// <inheritdoc />
public override void OnDragLeave()
{
_dragHandlers.OnDragLeave();
_dragHandlers?.OnDragLeave();
base.OnDragLeave();
}
@@ -31,6 +31,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// </summary>
private class EditTangentOptionBase
{
/// <summary>
/// Spline editor reference.
/// </summary>
public SplineEditor Editor;
/// <summary>
/// Called when user set selected tangent mode.
/// </summary>
@@ -103,7 +108,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
SetKeyframeLinear(spline, index);
// change the selection to tangent parent (a spline point / keyframe)
SetSelectSplinePointNode(spline, index);
Editor.SetSelectSplinePointNode(spline, index);
}
}
@@ -172,7 +177,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
public override void OnSetMode(Spline spline, int index)
{
SetTangentSmoothIn(spline, index);
SetSelectTangentIn(spline, index);
Editor.SetSelectTangentIn(spline, index);
}
}
@@ -186,7 +191,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
public override void OnSetMode(Spline spline, int index)
{
SetTangentSmoothOut(spline, index);
SetSelectTangentOut(spline, index);
Editor.SetSelectTangentOut(spline, index);
}
}
@@ -281,7 +286,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
base.Initialize(layout);
_currentTangentMode = new FreeTangentMode();
_currentTangentMode = new FreeTangentMode { Editor = this };
if (Values.HasDifferentTypes || !(Values[0] is Spline spline))
return;
_selectedSpline = spline;
@@ -471,7 +476,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_currentTangentMode is LinearTangentMode)
return;
_currentTangentMode = new LinearTangentMode();
_currentTangentMode = new LinearTangentMode { Editor = this };
_currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index);
}
@@ -479,7 +484,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_currentTangentMode is FreeTangentMode)
return;
_currentTangentMode = new FreeTangentMode();
_currentTangentMode = new FreeTangentMode { Editor = this };
_currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index);
}
@@ -487,7 +492,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_currentTangentMode is AlignedTangentMode)
return;
_currentTangentMode = new AlignedTangentMode();
_currentTangentMode = new AlignedTangentMode { Editor = this };
_currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index);
}
@@ -495,7 +500,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_currentTangentMode is SmoothInTangentMode)
return;
_currentTangentMode = new SmoothInTangentMode();
_currentTangentMode = new SmoothInTangentMode { Editor = this };
_currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index);
}
@@ -503,17 +508,34 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
if (_currentTangentMode is SmoothOutTangentMode)
return;
_currentTangentMode = new SmoothOutTangentMode();
_currentTangentMode = new SmoothOutTangentMode { Editor = this };
_currentTangentMode.OnSetMode(_selectedSpline, _lastPointSelected.Index);
}
private List<SceneGraphNode> GetSelection()
{
if (Presenter.Owner is Windows.Assets.PrefabWindow prefabWindow)
return prefabWindow.Selection;
return Editor.Instance.SceneEditing.Selection;
}
private void Select(SceneGraphNode node)
{
if (Presenter.Owner is Windows.Assets.PrefabWindow prefabWindow)
{
prefabWindow.Select(node);
return;
}
Editor.Instance.SceneEditing.Select(node);
}
private void UpdateSelectedPoint()
{
// works only if select one spline
if (_selectedSpline)
{
var currentSelected = Editor.Instance.SceneEditing.Selection[0];
var selection = GetSelection();
var currentSelected = selection.Count != 0 ? selection[0] : null;
if (currentSelected == _selectedPoint)
return;
if (currentSelected is SplineNode.SplinePointNode selectedPoint)
@@ -540,15 +562,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void UpdateSelectedTangent()
{
// works only if select one spline
if (_lastPointSelected == null || Editor.Instance.SceneEditing.SelectionCount != 1)
var selection = GetSelection();
if (_lastPointSelected == null || selection.Count != 1)
{
_selectedTangentIn = null;
_selectedTangentOut = null;
return;
}
var currentSelected = Editor.Instance.SceneEditing.Selection[0];
var currentSelected = selection[0];
if (currentSelected is not SplineNode.SplinePointTangentNode selectedPoint)
{
_selectedTangentIn = null;
@@ -568,10 +589,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
_selectedTangentIn = selectedPoint;
_selectedTangentOut = null;
_currentTangentMode.OnSelectTangent(_selectedSpline, index);
return;
}
if (currentSelected.Transform == _selectedSpline.GetSplineTangent(index, false))
{
_selectedTangentOut = selectedPoint;
@@ -833,7 +852,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
return null;
}
private static SplineNode.SplinePointTangentNode GetSplineTangentOutNode(Spline spline, int index)
private SplineNode.SplinePointTangentNode GetSplineTangentOutNode(Spline spline, int index)
{
var point = GetSplinePointNode(spline, index);
var tangentOut = spline.GetSplineTangent(index, false);
@@ -851,19 +870,19 @@ namespace FlaxEditor.CustomEditors.Dedicated
return null;
}
private static void SetSelectSplinePointNode(Spline spline, int index)
private void SetSelectSplinePointNode(Spline spline, int index)
{
Editor.Instance.SceneEditing.Select(GetSplinePointNode(spline, index));
Select(GetSplinePointNode(spline, index));
}
private static void SetSelectTangentIn(Spline spline, int index)
private void SetSelectTangentIn(Spline spline, int index)
{
Editor.Instance.SceneEditing.Select(GetSplineTangentInNode(spline, index));
Select(GetSplineTangentInNode(spline, index));
}
private static void SetSelectTangentOut(Spline spline, int index)
private void SetSelectTangentOut(Spline spline, int index)
{
Editor.Instance.SceneEditing.Select(GetSplineTangentOutNode(spline, index));
Select(GetSplineTangentOutNode(spline, index));
}
}
}
@@ -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)
{
@@ -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;
@@ -224,7 +227,8 @@ namespace FlaxEditor.CustomEditors.Editors
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
if (collection != null)
{
_canResize = !collection.ReadOnly;
_canResize = collection.CanResize;
_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);
@@ -585,7 +598,7 @@ namespace FlaxEditor.CustomEditors.Editors
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
{
var result = base.OnDragMove(ref location, data);
if (result != DragDropEffect.None)
if (result != DragDropEffect.None || _dragHandlers == null)
return result;
return _dragHandlers.Effect;
@@ -594,7 +607,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void OnDragLeave()
{
_dragHandlers.OnDragLeave();
_dragHandlers?.OnDragLeave();
base.OnDragLeave();
}
@@ -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;
@@ -189,6 +189,7 @@ namespace FlaxEditor.CustomEditors.Editors
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
if (collection != null)
{
_canEditKeys &= collection.CanReorderItems;
_readOnly = collection.ReadOnly;
_notNullItems = collection.NotNullItems;
if (collection.BackgroundColor.HasValue)
@@ -197,6 +198,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 +245,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 +261,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;
@@ -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})");
}
}
}
@@ -581,56 +581,51 @@ 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>
/// Spawns the property for the given item.
/// Evaluate the <see cref="VisibleIfAttribute"/> cache for a given property item.
/// </summary>
/// <param name="itemLayout">The item layout.</param>
/// <param name="itemValues">The item values.</param>
/// <param name="item">The item.</param>
protected virtual void SpawnProperty(LayoutElementsContainer itemLayout, ValueContainer itemValues, ItemInfo item)
/// <param name="labelIndex">The label index.</param>
protected virtual void EvaluateVisibleIf(LayoutElementsContainer itemLayout, ItemInfo item, int labelIndex)
{
int labelIndex = 0;
if ((item.IsReadOnly || item.VisibleIfs.Length > 0) &&
itemLayout.Children.Count > 0 &&
itemLayout.Children[itemLayout.Children.Count - 1] is PropertiesListElement propertiesListElement)
{
labelIndex = propertiesListElement.Labels.Count;
}
itemLayout.Property(item.DisplayName, itemValues, item.OverrideEditor, item.TooltipText);
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;
}
}
}
if (item.VisibleIfs.Length > 0 && itemLayout.Children.Count > 0)
{
PropertiesListElement list = null;
@@ -669,6 +664,45 @@ namespace FlaxEditor.CustomEditors.Editors
}
}
/// <summary>
/// Get the label index.
/// </summary>
/// <param name="itemLayout">The item layout.</param>
/// <param name="item">The item.</param>
/// <returns>The label index.</returns>
protected virtual int GetLabelIndex(LayoutElementsContainer itemLayout, ItemInfo item)
{
int labelIndex = 0;
if ((item.IsReadOnly || item.VisibleIfs.Length > 0) &&
itemLayout.Children.Count > 0 &&
itemLayout.Children[itemLayout.Children.Count - 1] is PropertiesListElement propertiesListElement)
{
labelIndex = propertiesListElement.Labels.Count;
}
return labelIndex;
}
/// <summary>
/// Spawns the property for the given item.
/// </summary>
/// <param name="itemLayout">The item layout.</param>
/// <param name="itemValues">The item values.</param>
/// <param name="item">The item.</param>
protected virtual void SpawnProperty(LayoutElementsContainer itemLayout, ValueContainer itemValues, ItemInfo item)
{
int labelIndex = GetLabelIndex(itemLayout, item);
itemLayout.Property(item.DisplayName, itemValues, item.OverrideEditor, item.TooltipText);
if (item.IsReadOnly && itemLayout.Children.Count > 0)
{
OnReadOnlyProperty(itemLayout, labelIndex);
}
EvaluateVisibleIf(itemLayout, item, labelIndex);
}
/// <inheritdoc />
internal override void Initialize(CustomEditorPresenter presenter, LayoutElementsContainer layout, ValueContainer values)
{
@@ -38,7 +38,7 @@ namespace FlaxEditor.CustomEditors.Editors
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
}
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkedEditor)
{
var button = menu.AddButton("Set to null");
button.Clicked += () => _comboBox.SelectedItem = null;
@@ -106,7 +106,7 @@ namespace FlaxEditor.CustomEditors.Editors
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
}
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkedEditor)
{
var button = menu.AddButton("Set to null");
button.Clicked += () => _comboBox.SelectedItem = null;
@@ -13,6 +13,9 @@ namespace FlaxEditor.CustomEditors.Editors
public sealed class StringEditor : CustomEditor
{
private TextBoxElement _element;
private string _watermarkText;
private Color _watermarkColor;
private Color _defaultWatermarkColor;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
@@ -21,15 +24,26 @@ namespace FlaxEditor.CustomEditors.Editors
public override void Initialize(LayoutElementsContainer layout)
{
bool isMultiLine = false;
_watermarkText = string.Empty;
var attributes = Values.GetAttributes();
var multiLine = attributes?.FirstOrDefault(x => x is MultilineTextAttribute);
var watermarkAttribute = attributes?.FirstOrDefault(x => x is WatermarkAttribute);
if (multiLine != null)
{
isMultiLine = true;
}
_element = layout.TextBox(isMultiLine);
_defaultWatermarkColor = _element.TextBox.WatermarkTextColor;
if (watermarkAttribute is WatermarkAttribute watermark)
{
_watermarkText = watermark.WatermarkText;
var watermarkColor = watermark.WatermarkColor > 0 ? Color.FromRGB(watermark.WatermarkColor) : FlaxEngine.GUI.Style.Current.ForegroundDisabled;
_watermarkColor = watermarkColor;
_element.TextBox.WatermarkText = watermark.WatermarkText;
_element.TextBox.WatermarkTextColor = watermarkColor;
}
_element.TextBox.EditEnd += () => SetValue(_element.Text);
}
@@ -41,12 +55,14 @@ namespace FlaxEditor.CustomEditors.Editors
if (HasDifferentValues)
{
_element.TextBox.Text = string.Empty;
_element.TextBox.WatermarkTextColor = _defaultWatermarkColor;
_element.TextBox.WatermarkText = "Different values";
}
else
{
_element.TextBox.Text = (string)Values[0];
_element.TextBox.WatermarkText = string.Empty;
_element.TextBox.WatermarkTextColor = _watermarkColor;
_element.TextBox.WatermarkText = _watermarkText;
}
}
}
@@ -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];
@@ -318,7 +318,7 @@ namespace FlaxEditor.CustomEditors
if (header.FontSize > 0)
element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize);
if (header.Color > 0)
element.Label.TextColor = Color.FromRGBA(header.Color);
element.Label.TextColor = Color.FromRGB(header.Color);
return element;
}
@@ -79,7 +79,7 @@ namespace FlaxEditor.CustomEditors
var theFirstType = TypeUtils.GetObjectType(this[0]);
for (int i = 1; i < Count; i++)
{
if (theFirstType != TypeUtils.GetObjectType(this[1]))
if (theFirstType != TypeUtils.GetObjectType(this[i]))
return true;
}
return false;
+1 -1
View File
@@ -554,7 +554,7 @@ namespace FlaxEditor.GUI
// Check if has selected item
if (_selectedIndices != null && _selectedIndices.Count > 0)
{
string text = _selectedIndices.Count == 1 ? _items[_selectedIndices[0]] : "Multiple Values";
string text = _selectedIndices.Count == 1 ? (_selectedIndices[0] >= 0 && _selectedIndices[0] < _items.Count ? _items[_selectedIndices[0]] : "") : "Multiple Values";
// Draw text of the selected item
float textScale = Height / DefaultHeight;
+6 -5
View File
@@ -42,15 +42,14 @@ namespace FlaxEditor.GUI.ContextMenu
// Arrange controls
Margin margin = _menu._itemsMargin;
float y = margin.Top;
float x = margin.Left;
float y = 0;
float width = Width - margin.Width;
for (int i = 0; i < _children.Count; i++)
{
if (_children[i] is ContextMenuItem item && item.Visible)
{
var height = item.Height;
item.Bounds = new Rectangle(x, y, width, height);
item.Bounds = new Rectangle(margin.Left, y, width, height);
y += height + margin.Height;
}
}
@@ -300,7 +299,6 @@ namespace FlaxEditor.GUI.ContextMenu
if (_panel.Children[i] is ContextMenuChildMenu menu && menu.Text == text)
return menu;
}
return null;
}
@@ -319,7 +317,6 @@ namespace FlaxEditor.GUI.ContextMenu
Parent = _panel
};
}
return item;
}
@@ -396,10 +393,12 @@ namespace FlaxEditor.GUI.ContextMenu
float height = _itemsAreaMargin.Height;
int itemsLeft = MaximumItemsInViewCount;
int overflowItemCount = 0;
int itemsCount = 0;
for (int i = 0; i < _panel.Children.Count; i++)
{
if (_panel.Children[i] is ContextMenuItem item && item.Visible)
{
itemsCount++;
if (itemsLeft > 0)
{
height += item.Height + _itemsMargin.Height;
@@ -412,6 +411,8 @@ namespace FlaxEditor.GUI.ContextMenu
maxWidth = Mathf.Max(maxWidth, item.MinimumWidth);
}
}
if (itemsCount != 0)
height -= _itemsMargin.Height; // Remove item margin from top and bottom
maxWidth = Mathf.Max(maxWidth + 20, MinimumWidth);
// Move child arrows to accommodate scroll bar showing
@@ -29,6 +29,15 @@ namespace FlaxEditor.GUI.ContextMenu
CloseMenuOnClick = false;
}
private void ShowChild(ContextMenu parentContextMenu)
{
// Hide parent CM popups and set itself as child
var vAlign = parentContextMenu.ItemsAreaMargin.Top;
var location = new Float2(Width, -vAlign);
location = PointToParent(parentContextMenu, location);
parentContextMenu.ShowChild(ContextMenu, location);
}
/// <inheritdoc />
public override void Draw()
{
@@ -58,14 +67,12 @@ namespace FlaxEditor.GUI.ContextMenu
var parentContextMenu = ParentContextMenu;
if (parentContextMenu == ContextMenu)
return;
if (ContextMenu.IsOpened)
return;
base.OnMouseEnter(location);
// Hide parent CM popups and set itself as child
parentContextMenu.ShowChild(ContextMenu, PointToParent(ParentContextMenu, new Float2(Width, 0)));
ShowChild(parentContextMenu);
}
/// <inheritdoc />
@@ -78,8 +85,7 @@ namespace FlaxEditor.GUI.ContextMenu
if (ContextMenu.IsOpened)
return true;
// Hide parent CM popups and set itself as child
parentContextMenu.ShowChild(ContextMenu, PointToParent(ParentContextMenu, new Float2(Width, 0)));
ShowChild(parentContextMenu);
return base.OnMouseUp(location, button);
}
}
+21 -3
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);
+3 -1
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);
}
+107
View File
@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
namespace FlaxEditor.GUI.Drag;
/// <summary>
/// Control type drag handler.
/// </summary>
public sealed class DragControlType : DragActorType<DragEventArgs>
{
/// <summary>
/// Initializes a new instance of the <see cref="DragControlType"/> class.
/// </summary>
/// <param name="validateFunction">The validation function</param>
public DragControlType(Func<ScriptType, bool> validateFunction)
: base(validateFunction)
{
}
}
/// <summary>
/// Helper class for handling control type drag and drop (for spawning).
/// </summary>
/// <seealso cref="Control" />
/// <seealso cref="ActorNode" />
public class DragControlType<U> : DragHelper<ScriptType, U> where U : DragEventArgs
{
/// <summary>
/// The default prefix for drag data used for actor type drag and drop.
/// </summary>
public const string DragPrefix = "CTYPE!?";
/// <summary>
/// Creates a new DragHelper
/// </summary>
/// <param name="validateFunction">The validation function</param>
public DragControlType(Func<ScriptType, bool> validateFunction)
: base(validateFunction)
{
}
/// <inheritdoc/>
public override DragData ToDragData(ScriptType item) => GetDragData(item);
/// <inheritdoc/>
public override DragData ToDragData(IEnumerable<ScriptType> items)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets the drag data.
/// </summary>
/// <param name="item">The control type.</param>
/// <returns>The data</returns>
public static DragData GetDragData(Type item)
{
if (item == null)
throw new ArgumentNullException();
return new DragDataText(DragPrefix + item.FullName);
}
/// <summary>
/// Gets the drag data.
/// </summary>
/// <param name="item">The control type.</param>
/// <returns>The data</returns>
public static DragData GetDragData(ScriptType item)
{
if (item == ScriptType.Null)
throw new ArgumentNullException();
return new DragDataText(DragPrefix + item.TypeName);
}
/// <summary>
/// Tries to parse the drag data to extract <see cref="Type"/> collection.
/// </summary>
/// <param name="data">The data.</param>
/// <returns>Gathered objects or empty array if cannot get any valid.</returns>
public override IEnumerable<ScriptType> FromDragData(DragData data)
{
if (data is DragDataText dataText)
{
if (dataText.Text.StartsWith(DragPrefix))
{
// Remove prefix and parse spitted names
var types = dataText.Text.Remove(0, DragPrefix.Length).Split('\n');
var results = new List<ScriptType>(types.Length);
for (int i = 0; i < types.Length; i++)
{
// Find type
var obj = TypeUtils.GetType(types[i]);
if (obj)
results.Add(obj);
}
return results;
}
}
return Utils.GetEmptyArray<ScriptType>();
}
}
+10
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
@@ -47,7 +47,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
break;
default: throw new ArgumentOutOfRangeException();
}
var color = (_timeline.IsMovingPositionHandle ? style.ProgressNormal : style.Foreground).AlphaMultiplied(0.6f);
var color = (_timeline.IsMovingPositionHandle ? style.SelectionBorder : style.Foreground).AlphaMultiplied(0.6f);
Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1);
var m2 = Matrix3x3.Translation2D(0, timeAxisHeaderOffset);
Matrix3x3.Multiply(ref m1, ref m2, out var m3);
@@ -61,7 +61,8 @@ namespace FlaxEditor.GUI.Timeline.GUI
Render2D.DrawText(style.FontSmall, labelText, style.Foreground, new Float2(2, -6));
Render2D.PopTransform();
Render2D.FillRectangle(new Rectangle(Width * 0.5f, Height + timeAxisHeaderOffset, 1, _timeline.MediaPanel.Height - timeAxisHeaderOffset - timeAxisOverlap), _timeline.IsMovingPositionHandle ? style.ProgressNormal : style.Foreground.RGBMultiplied(0.8f));
color = _timeline.IsMovingPositionHandle ? style.SelectionBorder : style.Foreground.RGBMultiplied(0.8f);
Render2D.FillRectangle(new Rectangle(Width * 0.5f, Height + timeAxisHeaderOffset, 1, _timeline.MediaPanel.Height - timeAxisHeaderOffset - timeAxisOverlap), color);
base.Draw();
}
@@ -42,7 +42,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
var timeAxisOverlap = Timeline.HeaderTopAreaHeight * 0.5f;
var timeAxisHeaderOffset = -_timeline.MediaBackground.ViewOffset.Y - timeAxisOverlap;
var moveColor = style.ProgressNormal;
var moveColor = style.SelectionBorder;
var thickness = 2.0f;
var borderColor = _isMoving ? moveColor : (IsMouseOver && _canEdit ? Color.Yellow : style.BorderNormal);
Render2D.FillRectangle(new Rectangle((Width - thickness) * 0.5f, timeAxisHeaderOffset, thickness, Height - timeAxisHeaderOffset), borderColor);
+2 -2
View File
@@ -100,7 +100,7 @@ namespace FlaxEditor.GUI.Timeline
private Track _tack;
private int _startFrame, _durationFrames;
private Float2 _mouseLocation = Float2.Minimum;
private bool _isMoving;
internal bool _isMoving;
private Float2 _startMoveLocation;
private int _startMoveStartFrame;
private int _startMoveDuration;
@@ -347,7 +347,7 @@ namespace FlaxEditor.GUI.Timeline
var isMovingWholeMedia = _isMoving && !_startMoveRightEdge && !_startMoveLeftEdge;
var borderHighlightColor = style.BorderHighlighted;
var moveColor = style.ProgressNormal;
var moveColor = style.SelectionBorder;
var selectedColor = style.BackgroundSelected;
var moveThickness = 2.0f;
var borderColor = isMovingWholeMedia ? moveColor : (Timeline.SelectedMedia.Contains(this) ? selectedColor : (IsMouseOver ? borderHighlightColor : style.BorderNormal));
@@ -1,6 +1,5 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -100,6 +99,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (Type == ScriptType.Null)
{
Editor.LogError("Missing anim event type " + _instanceTypeName);
InitMissing();
return;
}
Instance = (AnimEvent)Type.CreateInstance();
@@ -126,20 +126,37 @@ namespace FlaxEditor.GUI.Timeline.Tracks
_isRegisteredForScriptsReload = true;
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
Type.TrackLifetime(OnTypeDisposing);
}
private void OnTypeDisposing(ScriptType type)
{
if (Type == type && !IsDisposing)
{
// Turn into missing script
OnScriptsReloadBegin();
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
InitMissing();
}
}
private void InitMissing()
{
CanDelete = true;
CanSplit = false;
CanResize = false;
TooltipText = $"Missing Anim Event Type '{_instanceTypeName}'";
BackgroundColor = Color.Red;
Type = ScriptType.Null;
Instance = null;
}
internal void InitMissing(string typeName, byte[] data)
{
Type = ScriptType.Null;
IsContinuous = false;
CanDelete = true;
CanSplit = false;
CanResize = false;
TooltipText = $"Missing Anim Event Type '{typeName}'";
Instance = null;
BackgroundColor = Color.Red;
_instanceTypeName = typeName;
_instanceData = data;
InitMissing();
}
internal void Load(BinaryReader stream)
@@ -183,6 +200,49 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.OnDurationFramesChanged();
}
/// <inheritdoc />
public override bool ContainsPoint(ref Float2 location, bool precise = false)
{
if (Timeline.Zoom > 0.5f && !IsContinuous)
{
// Hit-test dot
var size = Height - 2.0f;
var rect = new Rectangle(new Float2(size * -0.5f) + Size * 0.5f, new Float2(size));
return rect.Contains(ref location);
}
return base.ContainsPoint(ref location, precise);
}
/// <inheritdoc />
public override void Draw()
{
if (Timeline.Zoom > 0.5f && !IsContinuous)
{
// Draw more visible dot for the event that maintains size even when zooming out
var style = Style.Current;
var icon = Editor.Instance.Icons.VisjectBoxClosed32;
var size = Height - 2.0f;
var rect = new Rectangle(new Float2(size * -0.5f) + Size * 0.5f, new Float2(size));
var outline = Color.Black; // Shadow
if (_isMoving)
outline = style.SelectionBorder;
else if (IsMouseOver)
outline = style.BorderHighlighted;
else if (Timeline.SelectedMedia.Contains(this))
outline = style.BackgroundSelected;
Render2D.DrawSprite(icon, rect.MakeExpanded(6.0f), outline);
Render2D.DrawSprite(icon, rect, BackgroundColor);
DrawChildren();
}
else
{
// Default drawing
base.Draw();
}
}
/// <inheritdoc />
public override void OnDestroy()
{
@@ -130,7 +130,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The keyframes.
/// </summary>
[EditorDisplay("Keyframes", EditorDisplayAttribute.InlineStyle), ExpandGroups]
[Collection(CanReorderItems = false, ReadOnly = true)]
[Collection(CanReorderItems = false, CanResize = true)]
public List<KeyValuePair<string, object>> Keyframes;
/// <inheritdoc />
@@ -159,7 +159,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
/// The parameters values.
/// </summary>
[EditorDisplay("Parameters", EditorDisplayAttribute.InlineStyle), ExpandGroups]
[Collection(CanReorderItems = false, ReadOnly = true)]
[Collection(CanReorderItems = false, CanResize = true)]
public object[] Parameters;
/// <inheritdoc />
+106 -8
View File
@@ -38,7 +38,6 @@ namespace FlaxEditor.GUI.Tree
private bool _isMouseDown;
private float _mouseDownTime;
private Float2 _mouseDownPos;
private Color _cachedTextColor;
private DragItemPositioning _dragOverMode;
private bool _isDragOverHeader;
@@ -91,6 +90,11 @@ namespace FlaxEditor.GUI.Tree
}
}
/// <summary>
/// Gets a value indicating whether the node is collapsed in the hierarchy (is collapsed or any of its parents is collapsed).
/// </summary>
public bool IsCollapsedInHierarchy => IsCollapsed || (Parent is TreeNode parentNode && parentNode.IsCollapsedInHierarchy);
/// <summary>
/// Gets or sets the text margin.
/// </summary>
@@ -604,9 +608,6 @@ namespace FlaxEditor.GUI.Tree
/// <inheritdoc />
public override void Update(float deltaTime)
{
// Cache text color
_cachedTextColor = CacheTextColor();
// Drop/down animation
if (_animationProgress < 1.0f)
{
@@ -676,7 +677,8 @@ namespace FlaxEditor.GUI.Tree
}
// Draw text
Render2D.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
Color textColor = CacheTextColor();
Render2D.DrawText(TextFont.GetFont(), _text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
// Draw drag and drop effect
if (IsDragOver && _tree.DraggedOverNode == this)
@@ -696,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)
{
@@ -712,6 +746,72 @@ namespace FlaxEditor.GUI.Tree
}
}
/// <inheritdoc />
protected override void DrawChildren()
{
// Draw all visible child controls
var children = _children;
if (children.Count == 0)
return;
if (CullChildren)
{
Render2D.PeekClip(out var globalClipping);
Render2D.PeekTransform(out var globalTransform);
// 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) / _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
for (; firstVisibleChild > 0; firstVisibleChild--)
{
var child = children[firstVisibleChild];
if (!child.Visible)
continue;
if (GetChildGlobalRectangle(child, ref globalTransform).Top < globalClipping.Top)
break;
}
}
for (int i = firstVisibleChild; i < children.Count; i++)
{
var child = children[i];
if (!child.Visible)
continue;
var childGlobalRect = GetChildGlobalRectangle(child, ref globalTransform);
if (!globalClipping.Intersects(ref childGlobalRect))
break;
Render2D.PushTransform(ref child._cachedTransform);
child.Draw();
Render2D.PopTransform();
}
static Rectangle GetChildGlobalRectangle(Control control, ref Matrix3x3 globalTransform)
{
Matrix3x3.Multiply(ref control._cachedTransform, ref globalTransform, out var globalChildTransform);
return new Rectangle(globalChildTransform.M31, globalChildTransform.M32, control.Width * globalChildTransform.M11, control.Height * globalChildTransform.M22);
}
}
else
{
for (int i = 0; i < children.Count; i++)
{
var child = children[i];
if (child.Visible)
{
Render2D.PushTransform(ref child._cachedTransform);
child.Draw();
Render2D.PopTransform();
}
}
}
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
@@ -996,7 +1096,7 @@ namespace FlaxEditor.GUI.Tree
// Expand node if mouse goes over arrow
if (ArrowRect.Contains(location) && HasAnyVisibleChild)
Expand(true);
if (!_isDragOverHeader)
result = OnDragEnterHeader(data);
else
@@ -1104,7 +1204,6 @@ namespace FlaxEditor.GUI.Tree
{
// TODO: perform layout for any non-TreeNode controls
_cachedHeight = _headerHeight;
_cachedTextColor = CacheTextColor();
Size = new Float2(width, _headerHeight);
}
@@ -1154,7 +1253,6 @@ namespace FlaxEditor.GUI.Tree
}
_cachedHeight = height;
_cachedTextColor = CacheTextColor();
Height = Mathf.Max(_headerHeight, y);
}
+29 -25
View File
@@ -253,7 +253,11 @@ namespace FlaxEditor
{
// Select node (with additive mode)
var selection = new List<SceneGraphNode>();
if (Root.GetKey(KeyboardKeys.Control))
if (Root.GetKey(KeyboardKeys.Shift) && transformGizmo.Selection.Contains(uiControlNode))
{
// Move whole selection
}
else if (Root.GetKey(KeyboardKeys.Control))
{
// Add/remove from selection
selection.AddRange(transformGizmo.Selection);
@@ -261,13 +265,14 @@ namespace FlaxEditor
selection.Remove(uiControlNode);
else
selection.Add(uiControlNode);
owner.Select(selection);
}
else
{
// Select
selection.Add(uiControlNode);
owner.Select(selection);
}
owner.Select(selection);
// Initialize control movement
_mouseMovesControl = true;
@@ -499,6 +504,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 +525,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 +622,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
{
+24
View File
@@ -16,6 +16,7 @@
#include "Engine/Engine/CommandLine.h"
#include "Engine/Renderer/ProbesRenderer.h"
#include "Engine/Animations/Graph/AnimGraph.h"
#include "Engine/Core/ObjectsRemovalService.h"
ManagedEditor::InternalOptions ManagedEditor::ManagedEditorOptions;
@@ -572,6 +573,29 @@ bool ManagedEditor::EvaluateVisualScriptLocal(VisualScript* script, VisualScript
return false;
}
void ManagedEditor::WipeOutLeftoverSceneObjects()
{
Array<ScriptingObject*> objects = Scripting::GetObjects();
bool removedAny = false;
for (ScriptingObject* object : objects)
{
if (EnumHasAllFlags(object->Flags, ObjectFlags::IsDuringPlay) && EnumHasNoneFlags(object->Flags, ObjectFlags::WasMarkedToDelete))
{
if (auto* sceneObject = Cast<SceneObject>(object))
{
if (sceneObject->HasParent())
continue; // Skip sub-objects
LOG(Error, "Object '{}' (ID={}, Type={}) is still in memory after play end but should be destroyed (memory leak).", sceneObject->GetNamePath(), sceneObject->GetID(), sceneObject->GetType().ToString());
sceneObject->DeleteObject();
removedAny = true;
}
}
}
if (removedAny)
ObjectsRemovalService::Flush();
}
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
{
ASSERT(!HasManagedInstance());
+1
View File
@@ -241,6 +241,7 @@ public:
API_FUNCTION(Internal) static VisualScriptStackFrame GetVisualScriptPreviousScopeFrame();
API_FUNCTION(Internal) static Array<VisualScriptLocal> GetVisualScriptLocals();
API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local);
API_FUNCTION(Internal) static void WipeOutLeftoverSceneObjects();
private:
void OnEditorAssemblyLoaded(MAssembly* assembly);
+2 -1
View File
@@ -202,6 +202,7 @@ namespace FlaxEditor.Modules
var prefabId = ((ActorNode)selection[0]).Actor.PrefabID;
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(prefabId);
Editor.Windows.ContentWin.ClearItemsSearch();
Editor.Windows.ContentWin.Select(prefab);
}
@@ -227,7 +228,7 @@ namespace FlaxEditor.Modules
// When applying changes to prefab from actor in level ignore it's root transformation (see ActorEditor.ProcessDiff)
var originalTransform = instance.LocalTransform;
if (instance.IsPrefabRoot && instance.Scene != null)
if (instance.IsPrefabRoot && instance.HasScene)
instance.LocalTransform = prefab.GetDefaultInstance().Transform;
// Call backend
+16 -17
View File
@@ -565,6 +565,7 @@ namespace FlaxEditor.Modules
if (item != null)
Editor.ContentEditing.Open(item);
});
cm.AddButton("Editor Options", () => Editor.Windows.EditorOptionsWin.Show());
// Scene
MenuScene = MainMenu.AddButton("Scene");
@@ -619,7 +620,6 @@ namespace FlaxEditor.Modules
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
cm.AddSeparator();
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
cm.AddButton("Options", () => Editor.Windows.EditorOptionsWin.Show());
// Window
MenuWindow = MainMenu.AddButton("Window");
@@ -640,7 +640,7 @@ namespace FlaxEditor.Modules
cm.AddButton("Visual Script Debugger", Editor.Windows.VisualScriptDebuggerWin.FocusOrShow);
cm.AddSeparator();
cm.AddButton("Save window layout", Editor.Windows.SaveLayout);
_menuWindowApplyWindowLayout = cm.AddChildMenu("Apply window layout");
_menuWindowApplyWindowLayout = cm.AddChildMenu("Window layouts");
cm.AddButton("Restore default layout", Editor.Windows.LoadDefaultLayout);
// Help
@@ -717,19 +717,6 @@ namespace FlaxEditor.Modules
_toolStripScale = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Scale32, () => Editor.MainTransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale).LinkTooltip($"Change Gizmo tool mode to Scale ({inputOptions.ScaleMode})");
ToolStrip.AddSeparator();
// Build scenes
_toolStripBuildScenes = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Build64, Editor.BuildScenesOrCancel).LinkTooltip($"Build scenes data - CSG, navmesh, static lighting, env probes - configurable via Build Actions in editor options ({inputOptions.BuildScenesData})");
// Cook and run
_toolStripCook = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.ShipIt64, Editor.Windows.GameCookerWin.BuildAndRun).LinkTooltip($"Cook & Run - build game for the current platform and run it locally ({inputOptions.CookAndRun})");
_toolStripCook.ContextMenu = new ContextMenu();
_toolStripCook.ContextMenu.AddButton("Run cooked game", Editor.Windows.GameCookerWin.RunCooked);
_toolStripCook.ContextMenu.AddSeparator();
var numberOfClientsMenu = _toolStripCook.ContextMenu.AddChildMenu("Number of game clients");
_numberOfClientsGroup.AddItemsToContextMenu(numberOfClientsMenu.ContextMenu);
ToolStrip.AddSeparator();
// Play
_toolStripPlay = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Play64, Editor.Simulation.DelegatePlayOrStopPlayInEditor).LinkTooltip($"Play In Editor ({inputOptions.Play})");
_toolStripPlay.ContextMenu = new ContextMenu();
@@ -741,7 +728,6 @@ namespace FlaxEditor.Modules
playActionGroup.Selected = Editor.Options.Options.Interface.PlayButtonAction;
playActionGroup.SelectedChanged = SetPlayAction;
Editor.Options.OptionsChanged += options => { playActionGroup.Selected = options.Interface.PlayButtonAction; };
var windowModesGroup = new ContextMenuSingleSelectGroup<InterfaceOptions.GameWindowMode>();
var windowTypeMenu = _toolStripPlay.ContextMenu.AddChildMenu("Game window mode");
windowModesGroup.AddItem("Docked", InterfaceOptions.GameWindowMode.Docked, null, "Shows the game window docked, inside the editor");
@@ -754,7 +740,20 @@ namespace FlaxEditor.Modules
Editor.Options.OptionsChanged += options => { windowModesGroup.Selected = options.Interface.DefaultGameWindowMode; };
_toolStripPause = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Pause64, Editor.Simulation.RequestResumeOrPause).LinkTooltip($"Pause/Resume game ({inputOptions.Pause})");
_toolStripStep = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Skip64, Editor.Simulation.RequestPlayOneFrame).LinkTooltip("Step one frame in game");
_toolStripStep = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Skip64, Editor.Simulation.RequestPlayOneFrame).LinkTooltip($"Step one frame in game ({inputOptions.StepFrame})");
ToolStrip.AddSeparator();
// Build scenes
_toolStripBuildScenes = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Build64, Editor.BuildScenesOrCancel).LinkTooltip($"Build scenes data - CSG, navmesh, static lighting, env probes - configurable via Build Actions in editor options ({inputOptions.BuildScenesData})");
// Cook and run
_toolStripCook = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.ShipIt64, Editor.Windows.GameCookerWin.BuildAndRun).LinkTooltip($"Cook & Run - build game for the current platform and run it locally ({inputOptions.CookAndRun})");
_toolStripCook.ContextMenu = new ContextMenu();
_toolStripCook.ContextMenu.AddButton("Run cooked game", Editor.Windows.GameCookerWin.RunCooked);
_toolStripCook.ContextMenu.AddSeparator();
var numberOfClientsMenu = _toolStripCook.ContextMenu.AddChildMenu("Number of game clients");
_numberOfClientsGroup.AddItemsToContextMenu(numberOfClientsMenu.ContextMenu);
UpdateToolstrip();
}
+4
View File
@@ -320,6 +320,10 @@ namespace FlaxEditor.Options
[EditorDisplay("Viewport"), EditorOrder(1750)]
public InputBinding ViewpointBottom = new InputBinding(KeyboardKeys.Numpad2);
[DefaultValue(typeof(InputBinding), "NumpadDecimal")]
[EditorDisplay("Viewport"), EditorOrder(1760)]
public InputBinding ToggleOrthographic = new InputBinding(KeyboardKeys.NumpadDecimal);
#endregion
#region Interface
@@ -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>
+11
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))
@@ -49,12 +49,14 @@ namespace FlaxEditor.SceneGraph.Actors
{
get
{
var actor = (Spline)_node.Actor;
return actor.GetSplineTransform(Index);
var actor = (Spline)_node?.Actor;
return actor?.GetSplineTransform(Index) ?? Transform.Identity;
}
set
{
var actor = (Spline)_node.Actor;
var actor = (Spline)_node?.Actor;
if (actor == null)
return;
actor.SetSplineTransform(Index, value);
OnSplineEdited(actor);
}
@@ -91,15 +91,11 @@ namespace FlaxEditor.SceneGraph.Actors
private void OnAddMeshCollider(EditorWindow window)
{
// Allow collider to be added to evey static model selection
SceneGraphNode[] selection = Array.Empty<SceneGraphNode>();
var selection = Array.Empty<SceneGraphNode>();
if (window is SceneTreeWindow)
{
selection = Editor.Instance.SceneEditing.Selection.ToArray();
}
else if (window is PrefabWindow prefabWindow)
{
selection = prefabWindow.Selection.ToArray();
}
var createdNodes = new List<SceneGraphNode>();
foreach (var node in selection)
+68 -13
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
{
@@ -29,6 +30,7 @@ namespace FlaxEditor.SceneGraph.GUI
private DragScripts _dragScripts;
private DragAssets _dragAssets;
private DragActorType _dragActorType;
private DragControlType _dragControlType;
private DragScriptItems _dragScriptItems;
private DragHandlers _dragHandlers;
private List<Rectangle> _highlights;
@@ -68,7 +70,7 @@ namespace FlaxEditor.SceneGraph.GUI
Visible = (actor.HideFlags & HideFlags.HideInHierarchy) == 0;
// Pick the correct id when inside a prefab window.
var id = actor.HasPrefabLink && actor.Scene == null ? actor.PrefabObjectID : actor.ID;
var id = actor.HasPrefabLink && !actor.HasScene ? actor.PrefabObjectID : actor.ID;
if (Editor.Instance.ProjectCache.IsExpandedActor(ref id))
{
Expand(true);
@@ -97,7 +99,7 @@ namespace FlaxEditor.SceneGraph.GUI
parentTreeNode.IsLayoutLocked = false;
// Skip UI update if node won't be in a view
if (parentTreeNode.IsCollapsed)
if (parentTreeNode.IsCollapsedInHierarchy)
{
UnlockChildrenRecursive();
}
@@ -291,7 +293,7 @@ namespace FlaxEditor.SceneGraph.GUI
return Style.Current.ForegroundGrey;
}
if (actor.Scene != null && Editor.Instance.StateMachine.IsPlayMode && actor.IsStatic)
if (actor.HasScene && Editor.Instance.StateMachine.IsPlayMode && actor.IsStatic)
{
// Static
return color * 0.85f;
@@ -354,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 />
@@ -366,7 +368,7 @@ namespace FlaxEditor.SceneGraph.GUI
if (!IsLayoutLocked && actor)
{
// Pick the correct id when inside a prefab window.
var id = actor.HasPrefabLink && actor.Scene == null ? actor.PrefabObjectID : actor.ID;
var id = actor.HasPrefabLink && !actor.HasScene ? actor.PrefabObjectID : actor.ID;
Editor.Instance.ProjectCache.SetExpandedActor(ref id, IsExpanded);
}
}
@@ -439,6 +441,17 @@ namespace FlaxEditor.SceneGraph.GUI
}
if (_dragActorType.OnDragEnter(data))
return _dragActorType.Effect;
// Check if drag control type
if (_dragControlType == null)
{
_dragControlType = new DragControlType(ValidateDragControlType);
_dragHandlers.Add(_dragControlType);
}
if (_dragControlType.OnDragEnter(data))
return _dragControlType.Effect;
// Check if drag script item
if (_dragScriptItems == null)
{
_dragScriptItems = new DragScriptItems(ValidateDragScriptItem);
@@ -572,10 +585,33 @@ namespace FlaxEditor.SceneGraph.GUI
Editor.LogWarning("Failed to spawn actor of type " + item.TypeName);
continue;
}
actor.StaticFlags = Actor.StaticFlags;
actor.StaticFlags = newParent.StaticFlags;
actor.Name = item.Name;
actor.Transform = Actor.Transform;
ActorNode.Root.Spawn(actor, Actor);
ActorNode.Root.Spawn(actor, newParent);
actor.OrderInParent = newOrder;
}
result = DragDropEffect.Move;
}
// Drag control type
else if (_dragControlType != null && _dragControlType.HasValidDrag)
{
for (int i = 0; i < _dragControlType.Objects.Count; i++)
{
var item = _dragControlType.Objects[i];
var control = item.CreateInstance() as Control;
if (control == null)
{
Editor.LogWarning("Failed to spawn UIControl with control type " + item.TypeName);
continue;
}
var uiControl = new UIControl
{
Control = control,
StaticFlags = newParent.StaticFlags,
Name = item.Name,
};
ActorNode.Root.Spawn(uiControl, newParent);
uiControl.OrderInParent = newOrder;
}
result = DragDropEffect.Move;
}
@@ -590,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;
@@ -604,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;
}
@@ -640,8 +689,8 @@ namespace FlaxEditor.SceneGraph.GUI
private bool ValidateDragScript(Script script)
{
// Reject dragging scripts not linked to scene (eg. from prefab) or in the opposite way
var thisHasScene = Actor.Scene != null;
var otherHasScene = script.Scene != null;
var thisHasScene = Actor.HasScene;
var otherHasScene = script.HasScene;
if (thisHasScene != otherHasScene)
return false;
@@ -656,12 +705,17 @@ namespace FlaxEditor.SceneGraph.GUI
private static bool ValidateDragActorType(ScriptType actorType)
{
return true;
return Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
}
private static bool ValidateDragScriptItem(ScriptItem script)
private static bool ValidateDragControlType(ScriptType controlType)
{
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType);
}
private bool ValidateDragScriptItem(ScriptItem script)
{
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null || Editor.Instance.CodeEditing.Scripts.Get(script) != ScriptType.Null;
}
/// <inheritdoc />
@@ -704,6 +758,7 @@ namespace FlaxEditor.SceneGraph.GUI
_dragScripts = null;
_dragAssets = null;
_dragActorType = null;
_dragControlType = null;
_dragScriptItems = null;
_dragHandlers?.Clear();
_dragHandlers = null;
+1 -1
View File
@@ -91,7 +91,7 @@ namespace FlaxEditor.SceneGraph
private void OnActorSpawned(Actor actor)
{
// Skip actors from game
if (actor.Scene != null)
if (actor.HasScene)
return;
// Check if it has parent
@@ -144,5 +144,11 @@ namespace FlaxEditor.Scripting
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
/// <inheritdoc />
public void TrackLifetime(Action<ScriptType> disposing)
{
ElementType.TrackLifetime(disposing);
}
}
}
@@ -167,6 +167,12 @@ namespace FlaxEditor.Scripting
/// <param name="bindingAttr">A bitmask comprised of one or more <see cref="T:System.Reflection.BindingFlags" /> that specify how the search is conducted.-or- Zero (<see cref="F:System.Reflection.BindingFlags.Default" />), to return an empty array.</param>
/// <returns>An array of member objects representing all methods defined for the current type that match the specified binding constraints.-or- An empty array of type member, if no methods are defined for the current type, or if none of the defined methods match the binding constraints.</returns>
ScriptMemberInfo[] GetMethods(BindingFlags bindingAttr);
/// <summary>
/// Registers delegate to be invoked upon script type disposal (except hot-reload in Editor via <see cref="ScriptsBuilder.ScriptsReload"/>). For example, can happen when user deleted Visual Script asset.
/// </summary>
/// <param name="disposing">Event to call when script type gets disposed (eg. removed asset).</param>
void TrackLifetime(Action<ScriptType> disposing);
}
/// <summary>
+14 -4
View File
@@ -1395,11 +1395,21 @@ namespace FlaxEditor.Scripting
}
/// <summary>
/// Basic check to see if a type could be casted to another type
/// Registers delegate to be invoked upon script type disposal (except hot-reload in Editor via <see cref="ScriptsBuilder.ScriptsReload"/>). For example, can happen when user deleted Visual Script asset.
/// </summary>
/// <param name="disposing">Event to call when script type gets disposed (eg. removed asset).</param>
public void TrackLifetime(Action<ScriptType> disposing)
{
if (_custom != null)
_custom.TrackLifetime(disposing);
}
/// <summary>
/// Basic check to see if a type could be cast to another type
/// </summary>
/// <param name="from">Source type</param>
/// <param name="to">Target type</param>
/// <returns>True if the type can be casted</returns>
/// <returns>True if the type can be cast.</returns>
public static bool CanCast(ScriptType from, ScriptType to)
{
if (from == to)
@@ -1412,10 +1422,10 @@ namespace FlaxEditor.Scripting
}
/// <summary>
/// Basic check to see if this type could be casted to another type
/// Basic check to see if this type could be cast to another type
/// </summary>
/// <param name="to">Target type</param>
/// <returns>True if the type can be casted</returns>
/// <returns>True if the type can be cast.</returns>
public bool CanCastTo(ScriptType to)
{
return CanCast(this, to);
+5 -1
View File
@@ -163,6 +163,8 @@ namespace FlaxEditor.States
Editor.OnPlayBegin();
IsPlayModeStarting = false;
Profiler.EndEvent();
Time.Synchronize();
}
private void SetupEditorEnvOptions()
@@ -192,7 +194,7 @@ namespace FlaxEditor.States
// Restore editor scene
SceneRestoring?.Invoke();
_duplicateScenes.DeletedScenes();
_duplicateScenes.UnloadScenes();
PluginManager.Internal_DeinitializeGamePlugins();
Editor.Internal_SetPlayMode(false);
_duplicateScenes.RestoreSceneData();
@@ -209,6 +211,8 @@ namespace FlaxEditor.States
Editor.OnPlayEnd();
IsPlayModeEnding = false;
Profiler.EndEvent();
Time.Synchronize();
}
}
}
@@ -6,6 +6,7 @@ using System.IO;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Input;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Undo;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -16,14 +17,13 @@ namespace FlaxEditor.Surface.Archetypes
/// </summary>
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
[HideInEditor]
public abstract class BlendPointsEditor : ContainerControl
public class BlendPointsEditor : ContainerControl
{
private readonly Animation.MultiBlend _node;
private readonly bool _is2D;
private Float2 _rangeX;
private Float2 _rangeY;
private readonly BlendPoint[] _blendPoints = new BlendPoint[Animation.MultiBlend.MaxAnimationsCount];
private readonly Guid[] _pointsAnims = new Guid[Animation.MultiBlend.MaxAnimationsCount];
private readonly Float2[] _pointsLocations = new Float2[Animation.MultiBlend.MaxAnimationsCount];
private Float2 _rangeX, _rangeY;
private Float2 _debugPos = Float2.Minimum;
private readonly List<BlendPoint> _blendPoints = new List<BlendPoint>();
/// <summary>
/// Represents single blend point.
@@ -31,16 +31,22 @@ namespace FlaxEditor.Surface.Archetypes
/// <seealso cref="FlaxEngine.GUI.Control" />
protected class BlendPoint : Control
{
private static Matrix3x3 _transform = Matrix3x3.RotationZ(45.0f * Mathf.DegreesToRadians) * Matrix3x3.Translation2D(4.0f, 0.5f);
private readonly BlendPointsEditor _editor;
private readonly int _index;
private bool _isMouseDown;
private Float2 _mousePosOffset;
private bool _isMouseDown, _mouseMoved;
private object[] _mouseMoveStartValues;
/// <summary>
/// The default size for the blend points.
/// </summary>
public const float DefaultSize = 8.0f;
/// <summary>
/// Blend point index.
/// </summary>
public int Index => _index;
/// <summary>
/// Initializes a new instance of the <see cref="BlendPoint"/> class.
/// </summary>
@@ -53,24 +59,45 @@ namespace FlaxEditor.Surface.Archetypes
_index = index;
}
private void EndMove()
{
_isMouseDown = false;
EndMouseCapture();
if (_mouseMoveStartValues != null)
{
// Add undo action
_editor._node.Surface.AddBatchedUndoAction(new EditNodeValuesAction(_editor._node, _mouseMoveStartValues, true));
_mouseMoveStartValues = null;
}
if (_mouseMoved)
_editor._node.Surface.MarkAsEdited();
}
/// <inheritdoc />
public override void OnGotFocus()
{
base.OnGotFocus();
_editor.SelectedIndex = _index;
_editor._node.SelectedAnimationIndex = _index;
}
/// <inheritdoc />
public override void Draw()
{
// Cache data
var isSelected = _editor.SelectedIndex == _index;
// Draw rotated rectangle
Render2D.PushTransform(ref _transform);
Render2D.FillRectangle(new Rectangle(0, 0, 5, 5), isSelected ? Color.Orange : Color.BlueViolet);
Render2D.PopTransform();
// Draw dot with outline
var style = Style.Current;
var icon = Editor.Instance.Icons.VisjectBoxClosed32;
var size = Height;
var rect = new Rectangle(new Float2(size * -0.5f) + Size * 0.5f, new Float2(size));
var outline = Color.Black; // Shadow
if (_isMouseDown)
outline = style.SelectionBorder;
else if (IsMouseOver)
outline = style.BorderHighlighted;
else if (_editor._node.SelectedAnimationIndex == _index)
outline = style.BackgroundSelected;
Render2D.DrawSprite(icon, rect.MakeExpanded(4.0f), outline);
Render2D.DrawSprite(icon, rect, style.Foreground);
}
/// <inheritdoc />
@@ -80,6 +107,9 @@ namespace FlaxEditor.Surface.Archetypes
{
Focus();
_isMouseDown = true;
_mouseMoved = false;
_mouseMoveStartValues = null;
_mousePosOffset = -location;
StartMouseCapture();
return true;
}
@@ -92,8 +122,7 @@ namespace FlaxEditor.Surface.Archetypes
{
if (button == MouseButton.Left && _isMouseDown)
{
_isMouseDown = false;
EndMouseCapture();
EndMove();
return true;
}
@@ -103,9 +132,26 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc />
public override void OnMouseMove(Float2 location)
{
if (_isMouseDown)
if (_isMouseDown && (_mouseMoved || Float2.DistanceSquared(location, _mousePosOffset) > 16.0f))
{
_editor.SetLocation(_index, _editor.BlendPointPosToBlendSpacePos(Location + location));
if (!_mouseMoved)
{
// Capture initial state for undo
_mouseMoved = true;
_mouseMoveStartValues = _editor._node.Surface.Undo != null ? (object[])_editor._node.Values.Clone() : null;
}
var newLocation = Location + location + _mousePosOffset;
newLocation = _editor.BlendPointPosToBlendSpacePos(newLocation);
if (Root != null && Root.GetKey(KeyboardKeys.Control))
{
var data0 = (Float4)_editor._node.Values[0];
var rangeX = new Float2(data0.X, data0.Y);
var rangeY = _editor._is2D ? new Float2(data0.Z, data0.W) : Float2.One;
var grid = new Float2(Mathf.Abs(rangeX.Y - rangeX.X) * 0.01f, Mathf.Abs(rangeY.X - rangeY.Y) * 0.01f);
newLocation = Float2.SnapToGrid(newLocation, grid);
}
_editor.SetLocation(_index, newLocation);
}
base.OnMouseMove(location);
@@ -116,8 +162,7 @@ namespace FlaxEditor.Surface.Archetypes
{
if (_isMouseDown)
{
_isMouseDown = false;
EndMouseCapture();
EndMove();
}
base.OnMouseLeave();
@@ -128,8 +173,7 @@ namespace FlaxEditor.Surface.Archetypes
{
if (_isMouseDown)
{
_isMouseDown = false;
EndMouseCapture();
EndMove();
}
base.OnLostFocus();
@@ -142,6 +186,18 @@ namespace FlaxEditor.Surface.Archetypes
base.OnEndMouseCapture();
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
switch (key)
{
case KeyboardKeys.Delete:
_editor.SetAsset(_index, Guid.Empty);
return true;
}
return base.OnKeyDown(key);
}
}
/// <summary>
@@ -149,40 +205,130 @@ namespace FlaxEditor.Surface.Archetypes
/// </summary>
public bool Is2D => _is2D;
/// <summary>
/// Blend points count.
/// </summary>
public int PointsCount => (_node.Values.Length - 4) / 2; // 4 node values + 2 per blend point
/// <summary>
/// Initializes a new instance of the <see cref="BlendPointsEditor"/> class.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="is2D">The value indicating whether blend space is 2D, otherwise it is 1D.</param>
/// <param name="x">The X location.</param>
/// <param name="y">The Y location.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public BlendPointsEditor(bool is2D, float x, float y, float width, float height)
public BlendPointsEditor(Animation.MultiBlend node, bool is2D, float x, float y, float width, float height)
: base(x, y, width, height)
{
_node = node;
_is2D = is2D;
}
/// <summary>
/// Gets the blend space data.
/// </summary>
/// <param name="rangeX">The space range for X axis (X-width, Y-height).</param>
/// <param name="rangeY">The space range for Y axis (X-width, Y-height).</param>
/// <param name="pointsAnims">The points anims (input array to fill of size equal 14).</param>
/// <param name="pointsLocations">The points locations (input array to fill of size equal 14).</param>
public abstract void GetData(out Float2 rangeX, out Float2 rangeY, Guid[] pointsAnims, Float2[] pointsLocations);
internal void AddPoint()
{
// Add random point within range
var rand = new Float2(Mathf.Frac((float)Platform.TimeSeconds), (Platform.TimeCycles % 10000) / 10000.0f);
AddPoint(Float2.Lerp(new Float2(_rangeX.X, _rangeY.X), new Float2(_rangeX.Y, _rangeY.Y), rand));
}
private void AddPoint(Float2 location)
{
// Reuse existing animation
var count = PointsCount;
Guid id = Guid.Empty;
for (int i = 0; i < count; i++)
{
id = (Guid)_node.Values[5 + i * 2];
if (id != Guid.Empty)
break;
}
if (id == Guid.Empty)
{
// Just use the first anim from project, user will change it
var ids = FlaxEngine.Content.GetAllAssetsByType(typeof(FlaxEngine.Animation));
if (ids.Length != 0)
id = ids[0];
else
return;
}
AddPoint(id, location);
}
/// <summary>
/// Gets or sets the index of the selected blend point.
/// Sets the blend point asset.
/// </summary>
public abstract int SelectedIndex { get; set; }
/// <param name="asset">The asset.</param>
/// <param name="location">The location.</param>
public void AddPoint(Guid asset, Float2 location)
{
// Find the first free slot
var count = PointsCount;
if (count == Animation.MultiBlend.MaxAnimationsCount)
return;
var values = (object[])_node.Values.Clone();
var index = 0;
for (; index < count; index++)
{
var dataB = (Guid)_node.Values[5 + index * 2];
if (dataB == Guid.Empty)
break;
}
if (index == count)
{
// Add another blend point
Array.Resize(ref values, values.Length + 2);
}
values[4 + index * 2] = new Float4(location.X, _is2D ? location.Y : 0.0f, 0, 1.0f);
values[5 + index * 2] = asset;
_node.SetValues(values);
// Auto-select
_node.SelectedAnimationIndex = index;
}
/// <summary>
/// Sets the blend point asset.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="asset">The asset.</param>
/// <param name="withUndo">True to use undo action.</param>
public void SetAsset(int index, Guid asset, bool withUndo = true)
{
if (withUndo)
{
_node.SetValue(5 + index * 2, asset);
}
else
{
_node.Values[5 + index * 2] = asset;
_node.Surface.MarkAsEdited();
}
_node.UpdateUI();
}
/// <summary>
/// Sets the blend point location.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="location">The location.</param>
public abstract void SetLocation(int index, Float2 location);
public void SetLocation(int index, Float2 location)
{
var dataA = (Float4)_node.Values[4 + index * 2];
var ranges = (Float4)_node.Values[0];
dataA.X = Mathf.Clamp(location.X, ranges.X, ranges.Y);
if (_is2D)
dataA.Y = Mathf.Clamp(location.Y, ranges.Z, ranges.W);
_node.Values[4 + index * 2] = dataA;
_node.UpdateUI();
}
/// <summary>
/// Gets the blend points area.
@@ -249,10 +395,23 @@ namespace FlaxEditor.Surface.Archetypes
public override void Update(float deltaTime)
{
// Synchronize blend points collection
GetData(out _rangeX, out _rangeY, _pointsAnims, _pointsLocations);
for (int i = 0; i < Animation.MultiBlend.MaxAnimationsCount; i++)
var data0 = (Float4)_node.Values[0];
_rangeX = new Float2(data0.X, data0.Y);
_rangeY = _is2D ? new Float2(data0.Z, data0.W) : Float2.Zero;
var count = PointsCount;
while (_blendPoints.Count > count)
{
if (_pointsAnims[i] != Guid.Empty)
_blendPoints[count].Dispose();
_blendPoints.RemoveAt(count);
}
while (_blendPoints.Count < count)
_blendPoints.Add(null);
for (int i = 0; i < count; i++)
{
var animId = (Guid)_node.Values[5 + i * 2];
var dataA = (Float4)_node.Values[4 + i * 2];
var location = new Float2(Mathf.Clamp(dataA.X, _rangeX.X, _rangeX.Y), _is2D ? Mathf.Clamp(dataA.Y, _rangeY.X, _rangeY.Y) : 0.0f);
if (animId != Guid.Empty)
{
if (_blendPoints[i] == null)
{
@@ -264,7 +423,13 @@ namespace FlaxEditor.Surface.Archetypes
}
// Update blend point
_blendPoints[i].Location = BlendSpacePosToBlendPointPos(_pointsLocations[i]);
_blendPoints[i].Location = BlendSpacePosToBlendPointPos(location);
var asset = Editor.Instance.ContentDatabase.FindAsset(animId);
var tooltip = asset?.ShortName ?? string.Empty;
tooltip += "\nX: " + location.X;
if (_is2D)
tooltip += "\nY: " + location.Y;
_blendPoints[i].TooltipText = tooltip;
}
else
{
@@ -277,6 +442,26 @@ namespace FlaxEditor.Surface.Archetypes
}
}
// Debug current playback position
if (((AnimGraphSurface)_node.Surface).TryGetTraceEvent(_node, out var traceEvent))
{
if (_is2D)
{
unsafe
{
// Unpack xy from 32-bits
Half2 packed = *(Half2*)&traceEvent.Value;
_debugPos = (Float2)packed;
}
}
else
_debugPos = new Float2(traceEvent.Value, 0.0f);
}
else
{
_debugPos = Float2.Minimum;
}
base.Update(deltaTime);
}
@@ -293,14 +478,90 @@ namespace FlaxEditor.Surface.Archetypes
}
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (base.OnMouseDown(location, button))
return true;
Focus();
return true;
}
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
if (base.OnMouseUp(location, button))
return true;
if (button == MouseButton.Right)
{
// Show context menu
var menu = new FlaxEditor.GUI.ContextMenu.ContextMenu();
var b = menu.AddButton("Add point", OnAddPoint);
b.Tag = location;
b.Enabled = PointsCount < Animation.MultiBlend.MaxAnimationsCount;
if (GetChildAt(location) is BlendPoint blendPoint)
{
b = menu.AddButton("Remove point", OnRemovePoint);
b.Tag = blendPoint.Index;
b.TooltipText = blendPoint.TooltipText;
}
menu.Show(this, location);
}
return true;
}
private void OnAddPoint(FlaxEditor.GUI.ContextMenu.ContextMenuButton b)
{
AddPoint(BlendPointPosToBlendSpacePos((Float2)b.Tag));
}
private void OnRemovePoint(FlaxEditor.GUI.ContextMenu.ContextMenuButton b)
{
SetAsset((int)b.Tag, Guid.Empty);
}
private void DrawAxis(bool vertical, Float2 start, Float2 end, ref Color gridColor, ref Color labelColor, Font labelFont, float value, bool isLast)
{
// Draw line
Render2D.DrawLine(start, end, gridColor);
// Draw label
var labelWidth = 50.0f;
var labelHeight = 10.0f;
var labelMargin = 2.0f;
string label = Utils.RoundTo2DecimalPlaces(value).ToString(System.Globalization.CultureInfo.InvariantCulture);
var hAlign = TextAlignment.Near;
Rectangle labelRect;
if (vertical)
{
labelRect = new Rectangle(start.X + labelMargin * 2, start.Y, labelWidth, labelHeight);
if (isLast)
return; // Don't overlap with the first horizontal label
}
else
{
labelRect = new Rectangle(start.X + labelMargin, start.Y - labelHeight - labelMargin, labelWidth, labelHeight);
if (isLast)
{
labelRect.X = start.X - labelMargin - labelRect.Width;
hAlign = TextAlignment.Far;
}
}
Render2D.DrawText(labelFont, label, labelRect, labelColor, hAlign, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.7f);
}
/// <inheritdoc />
public override void Draw()
{
// Cache data
var style = Style.Current;
var rect = new Rectangle(Float2.Zero, Size);
var containsFocus = ContainsFocus;
GetPointsArea(out var pointsArea);
var data0 = (Float4)_node.Values[0];
var rangeX = new Float2(data0.X, data0.Y);
// Background
Render2D.DrawRectangle(rect, IsMouseOver ? style.TextBoxBackgroundSelected : style.TextBoxBackground);
@@ -309,19 +570,27 @@ namespace FlaxEditor.Surface.Archetypes
// Grid
int splits = 10;
var gridColor = style.TextBoxBackgroundSelected * 1.1f;
var labelColor = style.ForegroundDisabled;
var labelFont = style.FontSmall;
//var blendArea = BlendAreaRect;
var blendArea = pointsArea;
for (int i = 0; i < splits; i++)
for (int i = 0; i <= splits; i++)
{
float x = blendArea.Left + blendArea.Width * i / splits;
Render2D.DrawLine(new Float2(x, 1), new Float2(x, rect.Height - 2), gridColor);
float alpha = (float)i / splits;
float x = blendArea.Left + blendArea.Width * alpha;
float value = Mathf.Lerp(rangeX.X, rangeX.Y, alpha);
DrawAxis(false, new Float2(x, rect.Height - 2), new Float2(x, 1), ref gridColor, ref labelColor, labelFont, value, i == splits);
}
if (_is2D)
{
for (int i = 0; i < splits; i++)
var rangeY = new Float2(data0.Z, data0.W);
for (int i = 0; i <= splits; i++)
{
float y = blendArea.Top + blendArea.Height * i / splits;
Render2D.DrawLine(new Float2(1, y), new Float2(rect.Width - 2, y), gridColor);
float alpha = (float)i / splits;
float y = blendArea.Top + blendArea.Height * alpha;
float value = Mathf.Lerp(rangeY.X, rangeY.Y, alpha);
DrawAxis(true, new Float2(1, y), new Float2(rect.Width - 2, y), ref gridColor, ref labelColor, labelFont, value, i == splits);
}
}
else
@@ -330,11 +599,24 @@ namespace FlaxEditor.Surface.Archetypes
Render2D.DrawLine(new Float2(1, y), new Float2(rect.Width - 2, y), gridColor);
}
// Base
base.Draw();
// Draw debug position
if (_debugPos.X > float.MinValue)
{
// Draw dot with outline
var icon = Editor.Instance.Icons.VisjectBoxOpen32;
var size = BlendPoint.DefaultSize;
var debugPos = BlendSpacePosToBlendPointPos(_debugPos);
var debugRect = new Rectangle(debugPos + new Float2(size * -0.5f) + size * 0.5f, new Float2(size));
var outline = Color.Black; // Shadow
Render2D.DrawSprite(icon, debugRect.MakeExpanded(2.0f), outline);
Render2D.DrawSprite(icon, debugRect, style.ProgressNormal);
}
// Frame
Render2D.DrawRectangle(new Rectangle(1, 1, rect.Width - 2, rect.Height - 2), containsFocus ? style.ProgressNormal : style.BackgroundSelected);
var frameColor = containsFocus ? style.BackgroundSelected : (IsMouseOver ? style.ForegroundGrey : style.ForegroundDisabled);
Render2D.DrawRectangle(new Rectangle(1, 1, rect.Width - 2, rect.Height - 2), frameColor);
}
}
@@ -346,6 +628,14 @@ namespace FlaxEditor.Surface.Archetypes
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
public abstract class MultiBlend : SurfaceNode
{
private Button _addButton;
private Button _removeButton;
/// <summary>
/// The blend space editor.
/// </summary>
protected BlendPointsEditor _editor;
/// <summary>
/// The selected animation label.
/// </summary>
@@ -379,7 +669,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <summary>
/// The maximum animations amount to blend per node.
/// </summary>
public const int MaxAnimationsCount = 14;
public const int MaxAnimationsCount = 255;
/// <summary>
/// Gets or sets the index of the selected animation.
@@ -387,7 +677,12 @@ namespace FlaxEditor.Surface.Archetypes
public int SelectedAnimationIndex
{
get => _selectedAnimation.SelectedIndex;
set => _selectedAnimation.SelectedIndex = value;
set
{
OnSelectedAnimationPopupShowing(_selectedAnimation);
_selectedAnimation.SelectedIndex = value;
UpdateUI();
}
}
/// <inheritdoc />
@@ -402,20 +697,14 @@ namespace FlaxEditor.Surface.Archetypes
Text = "Selected Animation:",
Parent = this
};
_selectedAnimation = new ComboBox(_selectedAnimationLabel.X, 4 * layoutOffsetY, _selectedAnimationLabel.Width)
{
TooltipText = "Select blend point to view and edit it",
Parent = this
};
_selectedAnimation.PopupShowing += OnSelectedAnimationPopupShowing;
_selectedAnimation.SelectedIndexChanged += OnSelectedAnimationChanged;
var items = new List<string>(MaxAnimationsCount);
while (items.Count < MaxAnimationsCount)
items.Add(string.Empty);
_selectedAnimation.Items = items;
_animationPicker = new AssetPicker(new ScriptType(typeof(FlaxEngine.Animation)), new Float2(_selectedAnimation.Left, _selectedAnimation.Bottom + 4))
{
Parent = this
@@ -428,20 +717,36 @@ namespace FlaxEditor.Surface.Archetypes
Text = "Speed:",
Parent = this
};
_animationSpeed = new FloatValueBox(1.0f, _animationSpeedLabel.Right + 4, _animationSpeedLabel.Y, _selectedAnimation.Right - _animationSpeedLabel.Right - 4)
{
SlideSpeed = 0.01f,
Parent = this
};
_animationSpeed.ValueChanged += OnAnimationSpeedValueChanged;
var buttonsSize = 12;
_addButton = new Button(_selectedAnimation.Right - buttonsSize, _selectedAnimation.Bottom + 4, buttonsSize, buttonsSize)
{
Text = "+",
TooltipText = "Add a new blend point",
Parent = this
};
_addButton.Clicked += OnAddButtonClicked;
_removeButton = new Button(_addButton.Left - buttonsSize - 4, _addButton.Y, buttonsSize, buttonsSize)
{
Text = "-",
TooltipText = "Remove selected blend point",
Parent = this
};
_removeButton.Clicked += OnRemoveButtonClicked;
}
private void OnSelectedAnimationPopupShowing(ComboBox comboBox)
{
var items = comboBox.Items;
items.Clear();
for (var i = 0; i < MaxAnimationsCount; i++)
var count = _editor.PointsCount;
for (var i = 0; i < count; i++)
{
var animId = (Guid)Values[5 + i * 2];
var path = string.Empty;
@@ -484,6 +789,16 @@ namespace FlaxEditor.Surface.Archetypes
}
}
private void OnAddButtonClicked()
{
_editor.AddPoint();
}
private void OnRemoveButtonClicked()
{
_editor.SetAsset(SelectedAnimationIndex, Guid.Empty);
}
/// <summary>
/// Updates the editor UI.
/// </summary>
@@ -491,7 +806,7 @@ namespace FlaxEditor.Surface.Archetypes
/// <param name="isValid">if set to <c>true</c> is selection valid.</param>
/// <param name="data0">The packed data 0.</param>
/// <param name="data1">The packed data 1.</param>
protected virtual void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
public virtual void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
{
if (isValid)
{
@@ -511,19 +826,21 @@ namespace FlaxEditor.Surface.Archetypes
_animationPicker.Enabled = isValid;
_animationSpeedLabel.Enabled = isValid;
_animationSpeed.Enabled = isValid;
_addButton.Enabled = _editor.PointsCount < MaxAnimationsCount;
_removeButton.Enabled = isValid && data1 != Guid.Empty;
}
/// <summary>
/// Updates the editor UI.
/// </summary>
protected void UpdateUI()
public void UpdateUI()
{
if (_isUpdatingUI)
return;
_isUpdatingUI = true;
var selectedIndex = _selectedAnimation.SelectedIndex;
var isValid = selectedIndex != -1;
var isValid = selectedIndex >= 0 && selectedIndex < _editor.PointsCount;
Float4 data0;
Guid data1;
if (isValid)
@@ -549,6 +866,16 @@ namespace FlaxEditor.Surface.Archetypes
UpdateUI();
}
/// <inheritdoc />
public override void OnSpawned(SurfaceNodeActions action)
{
base.OnSpawned(action);
// Select the first animation to make setup easier
OnSelectedAnimationPopupShowing(_selectedAnimation);
_selectedAnimation.SelectedIndex = 0;
}
/// <inheritdoc />
public override void OnValuesChanged()
{
@@ -566,67 +893,6 @@ namespace FlaxEditor.Surface.Archetypes
{
private readonly Label _animationXLabel;
private readonly FloatValueBox _animationX;
private readonly Editor _editor;
/// <summary>
/// The Multi Blend 1D blend space editor.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.Archetypes.BlendPointsEditor" />
protected class Editor : BlendPointsEditor
{
private MultiBlend1D _node;
/// <summary>
/// Initializes a new instance of the <see cref="Editor"/> class.
/// </summary>
/// <param name="node">The parent Visject Node node.</param>
/// <param name="x">The X location.</param>
/// <param name="y">The Y location.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public Editor(MultiBlend1D node, float x, float y, float width, float height)
: base(false, x, y, width, height)
{
_node = node;
}
/// <inheritdoc />
public override void GetData(out Float2 rangeX, out Float2 rangeY, Guid[] pointsAnims, Float2[] pointsLocations)
{
var data0 = (Float4)_node.Values[0];
rangeX = new Float2(data0.X, data0.Y);
rangeY = Float2.Zero;
for (int i = 0; i < MaxAnimationsCount; i++)
{
var dataA = (Float4)_node.Values[4 + i * 2];
var dataB = (Guid)_node.Values[5 + i * 2];
pointsAnims[i] = dataB;
pointsLocations[i] = new Float2(Mathf.Clamp(dataA.X, rangeX.X, rangeX.Y), 0.0f);
}
}
/// <inheritdoc />
public override int SelectedIndex
{
get => _node.SelectedAnimationIndex;
set => _node.SelectedAnimationIndex = value;
}
/// <inheritdoc />
public override void SetLocation(int index, Float2 location)
{
var dataA = (Float4)_node.Values[4 + index * 2];
var ranges = (Float4)_node.Values[0];
dataA.X = Mathf.Clamp(location.X, ranges.X, ranges.Y);
_node.Values[4 + index * 2] = dataA;
_node.Surface.MarkAsEdited();
_node.UpdateUI();
}
}
/// <inheritdoc />
public MultiBlend1D(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
@@ -646,11 +912,8 @@ namespace FlaxEditor.Surface.Archetypes
};
_animationX.ValueChanged += OnAnimationXChanged;
_editor = new Editor(this,
FlaxEditor.Surface.Constants.NodeMarginX,
_animationX.Bottom + 4.0f,
Width - FlaxEditor.Surface.Constants.NodeMarginX * 2.0f,
120.0f);
var size = Width - FlaxEditor.Surface.Constants.NodeMarginX * 2.0f;
_editor = new BlendPointsEditor(this, false, FlaxEditor.Surface.Constants.NodeMarginX, _animationX.Bottom + 4.0f, size, 120.0f);
_editor.Parent = this;
}
@@ -670,7 +933,7 @@ namespace FlaxEditor.Surface.Archetypes
}
/// <inheritdoc />
protected override void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
public override void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
{
base.UpdateUI(selectedIndex, isValid, ref data0, ref data1);
@@ -700,68 +963,6 @@ namespace FlaxEditor.Surface.Archetypes
private readonly FloatValueBox _animationX;
private readonly Label _animationYLabel;
private readonly FloatValueBox _animationY;
private readonly Editor _editor;
/// <summary>
/// The Multi Blend 2D blend space editor.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.Archetypes.BlendPointsEditor" />
protected class Editor : BlendPointsEditor
{
private MultiBlend2D _node;
/// <summary>
/// Initializes a new instance of the <see cref="Editor"/> class.
/// </summary>
/// <param name="node">The parent Visject Node node.</param>
/// <param name="x">The X location.</param>
/// <param name="y">The Y location.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public Editor(MultiBlend2D node, float x, float y, float width, float height)
: base(true, x, y, width, height)
{
_node = node;
}
/// <inheritdoc />
public override void GetData(out Float2 rangeX, out Float2 rangeY, Guid[] pointsAnims, Float2[] pointsLocations)
{
var data0 = (Float4)_node.Values[0];
rangeX = new Float2(data0.X, data0.Y);
rangeY = new Float2(data0.Z, data0.W);
for (int i = 0; i < MaxAnimationsCount; i++)
{
var dataA = (Float4)_node.Values[4 + i * 2];
var dataB = (Guid)_node.Values[5 + i * 2];
pointsAnims[i] = dataB;
pointsLocations[i] = new Float2(Mathf.Clamp(dataA.X, rangeX.X, rangeX.Y), Mathf.Clamp(dataA.Y, rangeY.X, rangeY.Y));
}
}
/// <inheritdoc />
public override int SelectedIndex
{
get => _node.SelectedAnimationIndex;
set => _node.SelectedAnimationIndex = value;
}
/// <inheritdoc />
public override void SetLocation(int index, Float2 location)
{
var dataA = (Float4)_node.Values[4 + index * 2];
var ranges = (Float4)_node.Values[0];
dataA.X = Mathf.Clamp(location.X, ranges.X, ranges.Y);
dataA.Y = Mathf.Clamp(location.Y, ranges.Z, ranges.W);
_node.Values[4 + index * 2] = dataA;
_node.Surface.MarkAsEdited();
_node.UpdateUI();
}
}
/// <inheritdoc />
public MultiBlend2D(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
@@ -795,11 +996,8 @@ namespace FlaxEditor.Surface.Archetypes
};
_animationY.ValueChanged += OnAnimationYChanged;
_editor = new Editor(this,
FlaxEditor.Surface.Constants.NodeMarginX,
_animationY.Bottom + 4.0f,
Width - FlaxEditor.Surface.Constants.NodeMarginX * 2.0f,
120.0f);
var size = Width - FlaxEditor.Surface.Constants.NodeMarginX * 2.0f;
_editor = new BlendPointsEditor(this, true, FlaxEditor.Surface.Constants.NodeMarginX, _animationY.Bottom + 4.0f, size, size);
_editor.Parent = this;
}
@@ -834,7 +1032,7 @@ namespace FlaxEditor.Surface.Archetypes
}
/// <inheritdoc />
protected override void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
public override void UpdateUI(int selectedIndex, bool isValid, ref Float4 data0, ref Guid data1)
{
base.UpdateUI(selectedIndex, isValid, ref data0, ref data1);
+15 -41
View File
@@ -621,7 +621,7 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new MultiBlend1D(id, context, arch, groupArch),
Title = "Multi Blend 1D",
Description = "Animation blending in 1D",
Flags = NodeFlags.AnimGraph,
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize,
Size = new Float2(420, 300),
DefaultValues = new object[]
{
@@ -633,19 +633,6 @@ namespace FlaxEditor.Surface.Archetypes
// Per blend sample data
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
},
Elements = new[]
{
@@ -658,10 +645,10 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(2, "Start Position", true, typeof(float), 3, 3),
// Axis X
NodeElementArchetype.Factory.Input(4, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 4 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 4 * Surface.Constants.LayoutOffsetY, 0, 0),
NodeElementArchetype.Factory.Float(145, 4 * Surface.Constants.LayoutOffsetY, 0, 1),
NodeElementArchetype.Factory.Input(3, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 3 * Surface.Constants.LayoutOffsetY + 2, 0, 0),
NodeElementArchetype.Factory.Float(145, 3 * Surface.Constants.LayoutOffsetY + 2, 0, 1),
}
},
new NodeArchetype
@@ -670,8 +657,8 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new MultiBlend2D(id, context, arch, groupArch),
Title = "Multi Blend 2D",
Description = "Animation blending in 2D",
Flags = NodeFlags.AnimGraph,
Size = new Float2(420, 320),
Flags = NodeFlags.AnimGraph | NodeFlags.VariableValuesSize,
Size = new Float2(420, 620),
DefaultValues = new object[]
{
// Node data
@@ -682,19 +669,6 @@ namespace FlaxEditor.Surface.Archetypes
// Per blend sample data
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
new Float4(0, 0, 0, 1.0f), Guid.Empty,
},
Elements = new[]
{
@@ -707,16 +681,16 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(2, "Start Position", true, typeof(float), 3, 3),
// Axis X
NodeElementArchetype.Factory.Input(4, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 4 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 4 * Surface.Constants.LayoutOffsetY, 0, 0),
NodeElementArchetype.Factory.Float(145, 4 * Surface.Constants.LayoutOffsetY, 0, 1),
NodeElementArchetype.Factory.Input(3, "X", true, typeof(float), 4),
NodeElementArchetype.Factory.Text(30, 3 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 3 * Surface.Constants.LayoutOffsetY + 2, 0, 0),
NodeElementArchetype.Factory.Float(145, 3 * Surface.Constants.LayoutOffsetY + 2, 0, 1),
// Axis Y
NodeElementArchetype.Factory.Input(5, "Y", true, typeof(float), 5),
NodeElementArchetype.Factory.Text(30, 5 * Surface.Constants.LayoutOffsetY, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 5 * Surface.Constants.LayoutOffsetY, 0, 2),
NodeElementArchetype.Factory.Float(145, 5 * Surface.Constants.LayoutOffsetY, 0, 3),
NodeElementArchetype.Factory.Input(4, "Y", true, typeof(float), 5),
NodeElementArchetype.Factory.Text(30, 4 * Surface.Constants.LayoutOffsetY + 2, "(min: max: )"),
NodeElementArchetype.Factory.Float(60, 4 * Surface.Constants.LayoutOffsetY + 2, 0, 2),
NodeElementArchetype.Factory.Float(145, 4 * Surface.Constants.LayoutOffsetY + 2, 0, 3),
}
},
new NodeArchetype
@@ -104,6 +104,16 @@ namespace FlaxEditor.Surface.Archetypes
}
}
private void OnTypeDisposing(ScriptType type)
{
if (_type == type && !IsDisposing)
{
// Turn into missing script
_type = ScriptType.Null;
Instance = null;
}
}
public override void OnLoaded(SurfaceNodeActions action)
{
base.OnLoaded(action);
@@ -113,6 +123,7 @@ namespace FlaxEditor.Surface.Archetypes
_type = TypeUtils.GetType(typeName);
if (_type != null)
{
_type.TrackLifetime(OnTypeDisposing);
TooltipText = Editor.Instance.CodeDocs.GetTooltip(_type);
try
{
+1 -1
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 },
+5
View File
@@ -73,6 +73,11 @@ namespace FlaxEditor.Surface
/// </summary>
BehaviorTreeGraph = 1024,
/// <summary>
/// Node can have different amount of items in values array.
/// </summary>
VariableValuesSize = 2048,
/// <summary>
/// Node can be used in the all visual graphs.
/// </summary>
+25 -9
View File
@@ -951,15 +951,20 @@ namespace FlaxEditor.Surface
{
if (_isDuringValuesEditing || !Surface.CanEdit)
return;
if (values == null || Values == null || values.Length != Values.Length)
if (values == null || Values == null)
throw new ArgumentException();
bool resize = values.Length != Values.Length;
if (resize && (Archetype.Flags & NodeFlags.VariableValuesSize) == 0)
throw new ArgumentException();
_isDuringValuesEditing = true;
var before = Surface.Undo != null ? (object[])Values.Clone() : null;
Array.Copy(values, Values, values.Length);
if (resize)
Values = (object[])values.Clone();
else
Array.Copy(values, Values, values.Length);
OnValuesChanged();
Surface.MarkAsEdited(graphEdited);
@@ -1057,6 +1062,20 @@ namespace FlaxEditor.Surface
}
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
if (base.OnMouseDown(location, button))
return true;
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location))
return true;
if (button == MouseButton.Right)
return true;
return false;
}
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
@@ -1064,13 +1083,10 @@ namespace FlaxEditor.Surface
return true;
// Close
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0)
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location))
{
if (_closeButtonRect.Contains(ref location))
{
Surface.Delete(this);
return true;
}
Surface.Delete(this);
return true;
}
// Secondary Context Menu
@@ -66,6 +66,8 @@ namespace FlaxEditor.Surface.Undo
// Initialize
if (node.Values != null && node.Values.Length == _nodeValues.Length)
Array.Copy(_nodeValues, node.Values, _nodeValues.Length);
else if (_nodeValues != null && (node.Archetype.Flags & NodeFlags.VariableValuesSize) != 0)
node.Values = (object[])_nodeValues.Clone();
else if (_nodeValues != null && _nodeValues.Length != 0)
throw new InvalidOperationException("Invalid node values.");
node.Location = _nodeLocation;
@@ -14,6 +14,7 @@ namespace FlaxEditor.Surface.Undo
private ContextHandle _context;
private readonly uint _nodeId;
private readonly bool _graphEdited;
private readonly bool _resize;
private object[] _before;
private object[] _after;
@@ -23,7 +24,8 @@ namespace FlaxEditor.Surface.Undo
throw new ArgumentNullException(nameof(before));
if (node?.Values == null)
throw new ArgumentNullException(nameof(node));
if (before.Length != node.Values.Length)
_resize = before.Length != node.Values.Length;
if (_resize && (node.Archetype.Flags & NodeFlags.VariableValuesSize) == 0)
throw new ArgumentException(nameof(before));
_surface = node.Surface;
@@ -48,7 +50,10 @@ namespace FlaxEditor.Surface.Undo
throw new Exception("Missing node.");
node.SetIsDuringValuesEditing(true);
Array.Copy(_after, node.Values, _after.Length);
if (_resize)
node.Values = (object[])_after.Clone();
else
Array.Copy(_after, node.Values, _after.Length);
node.OnValuesChanged();
context.MarkAsModified(_graphEdited);
node.SetIsDuringValuesEditing(false);
@@ -65,7 +70,10 @@ namespace FlaxEditor.Surface.Undo
throw new Exception("Missing node.");
node.SetIsDuringValuesEditing(true);
Array.Copy(_before, node.Values, _before.Length);
if (_resize)
node.Values = (object[])_before.Clone();
else
Array.Copy(_before, node.Values, _before.Length);
node.OnValuesChanged();
context.MarkAsModified(_graphEdited);
node.SetIsDuringValuesEditing(false);
+25 -13
View File
@@ -17,6 +17,11 @@ namespace FlaxEditor.Surface
/// </summary>
public readonly InputActionsContainer InputActions;
/// <summary>
/// Optional feature.
/// </summary>
public bool PanWithMiddleMouse = false;
private string _currentInputText = string.Empty;
private Float2 _movingNodesDelta;
private HashSet<SurfaceNode> _movingNodes;
@@ -223,15 +228,18 @@ namespace FlaxEditor.Surface
if (_middleMouseDown)
{
// Calculate delta
var delta = location - _middleMouseDownPos;
if (delta.LengthSquared > 0.01f)
if (PanWithMiddleMouse)
{
// Move view
_mouseMoveAmount += delta.Length;
_rootControl.Location += delta;
_middleMouseDownPos = location;
Cursor = CursorType.SizeAll;
// Calculate delta
var delta = location - _middleMouseDownPos;
if (delta.LengthSquared > 0.01f)
{
// Move view
_mouseMoveAmount += delta.Length;
_rootControl.Location += delta;
_middleMouseDownPos = location;
Cursor = CursorType.SizeAll;
}
}
// Handled
@@ -300,7 +308,8 @@ namespace FlaxEditor.Surface
if (_middleMouseDown)
{
_middleMouseDown = false;
Cursor = CursorType.Default;
if (PanWithMiddleMouse)
Cursor = CursorType.Default;
}
_isMovingSelection = false;
ConnectingEnd(null);
@@ -483,7 +492,7 @@ namespace FlaxEditor.Surface
Focus();
return true;
}
if (_rightMouseDown || _middleMouseDown)
if (_rightMouseDown || (_middleMouseDown && _middleMouseDown))
{
// Start navigating
StartMouseCapture();
@@ -555,9 +564,12 @@ namespace FlaxEditor.Surface
if (_middleMouseDown && button == MouseButton.Middle)
{
_middleMouseDown = false;
EndMouseCapture();
Cursor = CursorType.Default;
if (_mouseMoveAmount > 0)
if (_middleMouseDown)
{
EndMouseCapture();
Cursor = CursorType.Default;
}
if (_mouseMoveAmount > 0 && _middleMouseDown)
_mouseMoveAmount = 0;
else if (CanEdit)
{
@@ -630,6 +630,15 @@ namespace FlaxEditor.Surface
stream.ReadCommonValue(ref node.Values[j]);
}
}
else if ((node.Archetype.Flags & NodeFlags.VariableValuesSize) != 0)
{
node.Values = new object[valuesCnt];
for (int j = firstValueReadIdx; j < valuesCnt; j++)
{
// ReSharper disable once PossibleNullReferenceException
stream.ReadCommonValue(ref node.Values[j]);
}
}
else
{
Editor.LogWarning(string.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));
@@ -795,6 +804,12 @@ namespace FlaxEditor.Surface
for (int j = firstValueReadIdx; j < valuesCnt; j++)
node.Values[j] = stream.ReadVariant();
}
else if ((node.Archetype.Flags & NodeFlags.VariableValuesSize) != 0)
{
node.Values = new object[valuesCnt];
for (int j = firstValueReadIdx; j < valuesCnt; j++)
node.Values[j] = stream.ReadVariant();
}
else
{
Editor.LogWarning(string.Format("Invalid node values. Loaded: {0}, expected: {1}. Type: {2}, {3}", valuesCnt, nodeValuesCnt, node.Archetype.Title, node.Archetype.TypeID));
@@ -82,7 +82,7 @@ namespace FlaxEditor.Tools.Foliage
}
}
[EditorOrder(20), EditorDisplay("Model"), Collection(ReadOnly = true), Tooltip("Model materials override collection. Can be used to change a specific material of the mesh to the custom one without editing the asset.")]
[EditorOrder(20), EditorDisplay("Model"), Collection(CanResize = true), Tooltip("Model materials override collection. Can be used to change a specific material of the mesh to the custom one without editing the asset.")]
public MaterialBase[] Materials
{
get
@@ -66,8 +66,8 @@ namespace FlaxEditor.Tools.Terrain
[EditorOrder(410), EditorDisplay("Transform", "Rotation"), DefaultValue(typeof(Quaternion), "0,0,0,1"), Tooltip("Orientation of the terrain")]
public Quaternion Orientation = Quaternion.Identity;
[EditorOrder(420), EditorDisplay("Transform", "Scale"), DefaultValue(typeof(Float3), "1,1,1"), Limit(float.MinValue, float.MaxValue, 0.01f), Tooltip("Scale of the terrain")]
public Float3 Scale = Float3.One;
[EditorOrder(420), EditorDisplay("Transform", "Scale"), DefaultValue(1.0f), Limit(0.0001f, float.MaxValue, 0.01f), Tooltip("Scale of the terrain")]
public float Scale = 1.0f;
}
private readonly Options _options = new Options();
@@ -147,7 +147,7 @@ namespace FlaxEditor.Tools.Terrain
// Create terrain object and setup some options
var terrain = new FlaxEngine.Terrain();
terrain.Setup(_options.LODCount, (int)_options.ChunkSize);
terrain.Transform = new Transform(_options.Position, _options.Orientation, _options.Scale);
terrain.Transform = new Transform(_options.Position, _options.Orientation, new Float3(_options.Scale));
terrain.Material = _options.Material;
terrain.CollisionLOD = _options.CollisionLOD;
if (_options.Heightmap)
@@ -238,24 +238,5 @@ namespace FlaxEditor.Tools.Terrain
return base.CanCloseWindow(reason);
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (_isWorking)
return true;
switch (key)
{
case KeyboardKeys.Escape:
OnCancel();
return true;
case KeyboardKeys.Return:
OnSubmit();
return true;
}
return base.OnKeyDown(key);
}
}
}

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