From 3fcad4bbbea0455588843799c67861f7b9eb3825 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Thu, 18 Nov 2021 12:23:33 +0000 Subject: [PATCH] Unity 2022.1.0a15 C# reference source code --- .../BeeBuildProgramCommon.Data.gen.csproj | 111 +--- .../PlayerBuildProgramLibrary.Data.gen.csproj | 117 +--- ...iptCompilationBuildProgram.Data.gen.csproj | 116 +--- .../SpriteAtlas/SpriteAtlasAsset.bindings.cs | 35 +- .../SpriteAtlasImporter.bindings.cs | 13 +- .../SpriteAtlasImporterInspector.cs | 241 +++++--- .../AnimationWindow/AnimationRecording.cs | 18 +- Editor/Mono/AssemblyHelper.cs | 25 +- .../TextureImporterTypes.bindings.cs | 10 +- .../AssetStoreCachePathManager.bindings.cs | 4 +- Editor/Mono/AssetStoreCachePathManager.cs | 2 +- .../AndroidPostGenerateGradleProject.cs | 39 -- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 13 +- .../BuildPipeline/BuildPipelineInterfaces.cs | 8 + .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 7 +- Editor/Mono/BuildPlayerWindow.cs | 14 +- Editor/Mono/BuildPlayerWindowBuildMethods.cs | 10 +- Editor/Mono/Clipboard/ClipboardParser.cs | 20 +- Editor/Mono/ConsoleWindow.cs | 1 + Editor/Mono/DragAndDrop.bindings.cs | 1 + Editor/Mono/EditorApplication.bindings.cs | 15 +- Editor/Mono/EditorApplication.cs | 56 +- Editor/Mono/EditorGUI.cs | 81 ++- Editor/Mono/EditorHandles/FreeMove.cs | 6 + Editor/Mono/EditorHandles/PositionHandle.cs | 2 +- Editor/Mono/EditorSceneManager.bindings.cs | 12 +- Editor/Mono/EditorSettings.bindings.cs | 16 +- Editor/Mono/EditorUIService.cs | 2 + .../Mono/EditorUserBuildSettings.bindings.cs | 8 +- Editor/Mono/EditorUtility.cs | 14 +- Editor/Mono/EditorWindow.cs | 1 - Editor/Mono/GUI/AboutWindow.cs | 14 +- Editor/Mono/GUI/DockArea.cs | 7 + Editor/Mono/GUI/EditorCache.cs | 18 +- Editor/Mono/GUI/PopupWindowWithoutFocus.cs | 2 +- Editor/Mono/GUI/SearchField.cs | 1 - .../Mono/GUI/Toolbars/Core/EditorToolbar.cs | 155 ++--- .../GUI/Toolbars/Core/EditorToolbarManager.cs | 14 + .../GUI/Toolbars/Core/EditorToolbarUtility.cs | 3 - Editor/Mono/GUI/Tools/BuiltinTools.cs | 25 +- Editor/Mono/GUI/Tools/EditorToolCache.cs | 20 + Editor/Mono/GUI/Tools/EditorToolContext.cs | 22 + Editor/Mono/GUI/Tools/EditorToolManager.cs | 47 +- .../GUI/Tools/EditorToolSettingsOverlay.cs | 168 +++-- Editor/Mono/GUI/Tools/EditorToolUtility.cs | 32 +- Editor/Mono/GUI/Tools/ToolManager.cs | 21 +- Editor/Mono/GUIDebugger/StylePicker.cs | 1 - Editor/Mono/GlobalObjectId.bindings.cs | 15 +- .../Graphics/StaticBatchingEditorHelper.cs | 2 +- Editor/Mono/HandleUtility.cs | 17 +- Editor/Mono/Handles.cs | 13 + .../AdvancedDropdown/AdvancedDropdownGUI.cs | 33 +- Editor/Mono/Inspector/AvatarPreview.cs | 45 +- Editor/Mono/Inspector/EditorElementUpdater.cs | 133 ++++ .../Mono/Inspector/EditorSettingsInspector.cs | 42 +- Editor/Mono/Inspector/GameObjectInspector.cs | 6 +- Editor/Mono/Inspector/GenericInspector.cs | 6 +- Editor/Mono/Inspector/IEditorElement.cs | 1 + Editor/Mono/Inspector/InspectorWindowUtils.cs | 2 +- Editor/Mono/Inspector/LODGroupEditor.cs | 22 +- Editor/Mono/Inspector/LightEditor.cs | 6 +- .../Inspector/LightProbeGroupInspector.cs | 8 +- .../Mono/Inspector/LightingSettingsEditor.cs | 2 + Editor/Mono/Inspector/MaskFieldDropdown.cs | 2 +- .../PlayerSettingsEditor.cs | 79 ++- Editor/Mono/Inspector/PreviewRenderUtility.cs | 4 +- Editor/Mono/Inspector/PropertyEditor.cs | 49 +- .../Mono/Inspector/ReflectionProbeEditor.cs | 35 +- Editor/Mono/Inspector/RenderTextureEditor.cs | 2 +- .../Mono/Inspector/ReorderableListWrapper.cs | 6 +- Editor/Mono/Inspector/RootEditor.cs | 16 + Editor/Mono/Inspector/SortingGroupEditor.cs | 10 + Editor/Mono/Inspector/SpriteFrameInspector.cs | 14 +- Editor/Mono/InternalEditorUtility.bindings.cs | 37 +- Editor/Mono/LogEntries.bindings.cs | 1 + Editor/Mono/Macros/MethodEvaluator.cs | 84 ++- Editor/Mono/Modules/BeeBuildPostprocessor.cs | 14 +- Editor/Mono/Modules/ModuleManager.cs | 143 ----- Editor/Mono/ObjectListLocalGroup.cs | 2 +- Editor/Mono/Overlays/ICreateToolbar.cs | 15 +- Editor/Mono/Overlays/Overlay.cs | 42 +- Editor/Mono/Overlays/OverlayAttribute.cs | 107 +++- Editor/Mono/Overlays/OverlayCanvas.cs | 99 ++- Editor/Mono/Overlays/OverlayContainer.cs | 7 + Editor/Mono/Overlays/OverlayToolbar.cs | 24 + Editor/Mono/Overlays/OverlayUtilities.cs | 30 +- Editor/Mono/Overlays/ToolbarOverlay.cs | 27 +- Editor/Mono/PlayerSettings.bindings.cs | 16 + Editor/Mono/PostprocessScene.cs | 2 +- .../Prefabs/PrefabOverrides/PrefabOverride.cs | 6 +- .../PrefabOverridesTreeView.cs | 43 +- .../PrefabOverrides/PrefabOverridesUtility.cs | 11 - .../PrefabOverrides/PrefabOverridesWindow.cs | 41 +- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 24 +- Editor/Mono/Prefabs/PrefabUtility.cs | 154 +++-- Editor/Mono/SceneHierarchy.cs | 2 +- .../StageManager/PrefabStage/PrefabStage.cs | 3 +- Editor/Mono/SceneView/SceneView.cs | 76 ++- Editor/Mono/SceneView/SceneViewToolbars.cs | 22 +- .../ScriptAttributeGUI/PropertyHandler.cs | 42 +- .../APIUpdater/APIUpdaterAssemblyHelper.cs | 31 +- .../APIUpdater/AssemblyDependencyGraph.cs | 4 + .../BeeDriver/UnityBeeDriver.cs | 93 ++- .../ScriptCompilation/EditorCompilation.cs | 4 +- Editor/Mono/SerializedObject.bindings.cs | 4 +- Editor/Mono/SerializedProperty.bindings.cs | 225 ++++++- Editor/Mono/Settings/SettingsWindow.cs | 25 + .../SettingsWindow/GraphicsSettingsEditors.cs | 4 + .../Mono/UnityConnect/CloudProjectSettings.cs | 60 ++ .../CloudProjectSettingsEventManager.cs | 63 ++ Editor/Mono/UnityConnect/CoppaCompliance.cs | 37 ++ .../UnityConnect/UnityConnect.bindings.cs | 17 +- Editor/Mono/Unsupported.bindings.cs | 7 +- Editor/Mono/Utils/AssemblyReferenceChecker.cs | 34 +- Editor/Mono/Utils/MathUtils.cs | 59 +- Editor/Mono/Utils/NetCoreProgram.cs | 9 +- Editor/Mono/VisualStudioUtil.bindings.cs | 3 + .../Editor/Builder/Builder.cs | 5 + .../Inspector/BuilderInspectorAttributes.cs | 82 ++- .../Builder/Library/BuilderLibraryContent.cs | 6 +- .../Builder/Library/BuilderLibraryTreeView.cs | 2 +- .../Builder/Utilities/BuilderConstants.cs | 1 + .../StyleField/DimensionStyleField.cs | 18 +- .../Utilities/StyleField/NumericStyleField.cs | 13 +- .../Utilities/StyleField/ScaleStyleField.cs | 5 +- .../Editor/Utilities/StyleField/StyleField.cs | 2 +- .../StyleField/StyleVariableUtilities.cs | 158 ++--- .../Utilities/StyleField/VariableCompleter.cs | 2 +- .../StyleField/VariableEditingHandler.cs | 6 +- .../Utilities/StyleField/VariableInfo.cs | 38 +- .../Utilities/StyleField/VariableInfoView.cs | 90 +-- .../StyleSheetExtensions/StyleSheetToUss.cs | 2 +- .../TwoPaneSplitView/TwoPaneSplitView.cs | 459 -------------- .../TwoPaneSplitViewResizer.cs | 144 ----- .../TwoPaneSplitViewTestWindow.cs | 27 - .../NetStandardExtensions/System.CodeDom.dll | Bin 0 -> 183176 bytes .../builds/lib/net35/Unity.Cecil.Mdb.dll | Bin 44544 -> 0 bytes .../builds/lib/net35/Unity.Cecil.Pdb.dll | Bin 87552 -> 0 bytes .../builds/lib/net35/Unity.Cecil.Rocks.dll | Bin 28672 -> 0 bytes .../builds/lib/net35/Unity.Cecil.dll | Bin 350720 -> 0 bytes .../builds/lib/net40/Unity.Cecil.Mdb.dll | Bin 0 -> 44544 bytes .../builds/lib/net40/Unity.Cecil.Pdb.dll | Bin 0 -> 88064 bytes .../builds/lib/net40/Unity.Cecil.Rocks.dll | Bin 0 -> 28672 bytes .../builds/lib/net40/Unity.Cecil.dll | Bin 0 -> 350720 bytes .../com.unity.ui/Core/ClickDetector.cs | 12 +- .../com.unity.ui/Core/Clickable.cs | 19 +- .../Controls/BaseCompositeField.cs | 51 +- .../Core/Controls/BasePopupField.cs | 2 +- .../{Editor => Core}/Controls/BoundsField.cs | 5 +- .../Controls/BoundsIntField.cs | 7 +- .../Controls/CompoundFields.cs | 26 +- .../{Editor => Core}/Controls/DoubleField.cs | 19 +- .../com.unity.ui/Core/Controls/EnumField.cs | 39 +- .../{Editor => Core}/Controls/FloatField.cs | 24 +- .../Core/Controls/GenericDropdownMenu.cs | 3 + .../{Editor => Core}/Controls/Hash128Field.cs | 9 +- .../{Editor => Core}/Controls/IntegerField.cs | 22 +- .../{Editor => Core}/Controls/LongField.cs | 14 +- .../Core/Controls/MinMaxSlider.cs | 16 +- .../com.unity.ui/Core/Controls/PopupField.cs | 5 +- .../com.unity.ui/Core/Controls/ProgressBar.cs | 2 +- .../com.unity.ui/Core/Controls/ScrollView.cs | 40 +- .../Controls/TextValueField.cs | 9 +- ModuleOverrides/com.unity.ui/Core/Cursor.cs | 8 + .../com.unity.ui/Core/DefaultEventSystem.cs | 60 +- .../com.unity.ui/Core/EventDispatcher.cs | 9 +- .../com.unity.ui/Core/Events/CaptureEvents.cs | 7 +- .../Events/CommandEventDispatchingStrategy.cs | 2 +- .../Core/Events/DefaultDispatchingStrategy.cs | 4 +- .../com.unity.ui/Core/Events/EventBase.cs | 17 + .../Core/Events/EventCallbackRegistry.cs | 6 +- .../Core/Events/IEventDispatchingStrategy.cs | 18 +- .../Events/MouseEventDispatchingStrategy.cs | 5 +- .../com.unity.ui/Core/Events/MouseEvents.cs | 4 +- .../Events/PointerEventDispatchingStrategy.cs | 6 +- .../com.unity.ui/Core/Events/PointerEvents.cs | 262 +++++++- .../Core/Events/PropagationPaths.cs | 2 +- .../{Editor => Core}/FieldMouseDragger.cs | 65 +- ModuleOverrides/com.unity.ui/Core/Panel.cs | 25 + .../com.unity.ui/Core/PenButton.cs | 25 + .../com.unity.ui/Core/Style/Background.cs | 11 + .../com.unity.ui/Core/Style/CustomStyle.cs | 26 +- .../com.unity.ui/Core/Style/FontDefinition.cs | 9 + .../Core/Style/Generated/StylePropertyUtil.cs | 19 + .../Core/StyleSheets/StyleVariable.cs | 2 + .../com.unity.ui/Core/UIElementsBridge.cs | 18 + .../com.unity.ui/Core/UIElementsUtility.cs | 3 + .../Core/UXML/UxmlAttributeDescription.cs | 34 +- .../Core/UXML/VisualElementFactoryRegistry.cs | 16 +- .../com.unity.ui/Core/UXML/VisualTreeAsset.cs | 23 + .../com.unity.ui/Core/UpgradeConstants.cs | 12 + .../com.unity.ui/Core/VisualElement.cs | 84 ++- .../Core/VisualElementFocusRing.cs | 1 + .../Core/VisualElementHierarchy.cs | 5 +- .../Core/VisualElementStyleAccess.cs | 26 + .../Core/VisualTreeStyleUpdater.cs | 2 +- .../Editor/Bindings/BindingExtensions.cs | 32 +- .../Editor/Controls/EnumFlagsField.cs | 4 +- .../Editor/Controls/PropertyField.cs | 14 +- .../Editor/Debugger/PanelDebugger.cs | 15 +- .../com.unity.ui/Editor/EditorPanel.cs | 1 + .../Editor/EditorUIElementsBridge.cs | 49 ++ .../Editor/Inspector/EditorElement.cs | 132 ++-- .../Editor/Inspector/InspectorElement.cs | 38 +- .../com.unity.ui/Editor/RetainedMode.cs | 8 + .../StyleSheets/StyleSheetImportErrors.cs | 1 - .../StyleSheets/StyleSheetImportGlossary.cs | 2 +- .../StyleSheets/StyleSheetImporterImpl.cs | 60 +- .../Editor/UIElementsEditorUtility.cs | 6 +- .../ScriptBindings/Animator.bindings.cs | 9 + .../ScriptBindings/AssetDatabase.bindings.cs | 13 +- .../AssetDatabaseExperimental.bindings.cs | 12 +- .../ModelImporterModelEditor.cs | 7 + .../ModelImporting/ModelImporter.bindings.cs | 6 + .../Public/VideoImporter.bindings.cs | 15 + .../Public/ScriptBindings/Audio.bindings.cs | 16 + .../AudioSampleProviderExtensions.bindings.cs | 24 + .../Public/ScriptBindings/ExposeVivox.cs | 5 + .../Editor/Managed/BuildUsageTagGlobal.cs | 2 + .../Managed/BuildReport.bindings.cs | 5 +- .../ClusterSerialization.bindings.cs | 12 +- .../DeviceInfo/DeviceLoader.cs | 88 +-- Modules/GraphViewEditor/Elements/Node.cs | 2 +- Modules/GraphViewEditor/Elements/Port.cs | 2 + Modules/IMGUI/Event.bindings.cs | 3 + Modules/Input/Private/InputModule.bindings.cs | 3 + Modules/InputLegacy/Input.bindings.cs | 44 ++ .../Editor/Managed/PackageInfo.cs | 18 +- .../Editor/Managed/SignatureInfo.cs | 38 ++ .../Editor/Managed/SignatureStatus.cs | 15 + .../Editor/Extensions/ExtensionManager.cs | 6 + .../Editor/Extensions/PackageSelectionArgs.cs | 9 +- .../External/EditorGameServiceExtension.cs | 223 +++++++ .../ServicesTab/ServiceGroupingsWrapper.cs | 17 + .../ServicesTab/ServicesTabConfiguration.cs | 16 + .../Services/AssetStore/AssetStoreCache.cs | 6 +- .../Services/AssetStore/AssetStoreClient.cs | 9 +- .../AssetStore/AssetStoreDownloadManager.cs | 38 +- .../AssetStore/AssetStoreDownloadOperation.cs | 48 +- .../Services/AssetStore/AssetStoreOAuth.cs | 72 +-- .../Services/AssetStore/AssetStorePackage.cs | 10 +- .../Editor/Services/Common/BasePackage.cs | 37 +- .../Services/Common/BasePackageVersion.cs | 19 + .../Services/Common/PlaceholderPackage.cs | 5 +- .../Editor/Services/Common/UIError.cs | 22 +- .../Editor/Services/Common/UIErrorCode.cs | 4 +- .../Services/Interfaces/IPackageVersion.cs | 10 + .../Packages/PackageAndVersionIdPair.cs | 21 + .../Services/Packages/PackageDatabase.cs | 119 ++-- .../Services/Proxies/ApplicationProxy.cs | 7 +- .../Proxies/AssetStoreCachePathProxy.cs | 54 ++ .../Editor/Services/Proxies/ClientProxy.cs | 15 + .../Editor/Services/Proxies/SelectionProxy.cs | 6 + .../Editor/Services/ServicesContainer.cs | 13 +- .../Services/Upm/UpmAddAndRemoveOperation.cs | 18 + .../Editor/Services/Upm/UpmBaseOperation.cs | 4 +- .../Editor/Services/Upm/UpmCache.cs | 1 + .../Editor/Services/Upm/UpmCacheRootClient.cs | 87 +++ .../Upm/UpmClearCacheRootOperation.cs | 25 + .../Editor/Services/Upm/UpmClient.cs | 77 +-- .../Services/Upm/UpmGetCacheRootOperation.cs | 25 + .../Services/Upm/UpmGetRegistriesOperation.cs | 5 - .../Editor/Services/Upm/UpmListOperation.cs | 5 - .../Editor/Services/Upm/UpmPackage.cs | 16 +- .../Editor/Services/Upm/UpmPackageDocs.cs | 31 + .../Editor/Services/Upm/UpmPackageVersion.cs | 40 +- .../Editor/Services/Upm/UpmSearchOperation.cs | 5 - .../Services/Upm/UpmSetCacheRootOperation.cs | 31 + .../PackageManagerUserSettingsProvider.cs | 323 ++++++++++ .../Editor/UI/Common/Alert.cs | 40 +- .../Editor/UI/Common/BasePage.cs | 102 ++-- .../Editor/UI/Common/LoadingSpinner.cs | 9 + .../Editor/UI/Common/PageManager.cs | 256 ++++---- .../Editor/UI/Common/PageSelection.cs | 136 +++++ .../Editor/UI/Common/PaginatedPage.cs | 20 +- .../Editor/UI/Common/SimplePage.cs | 31 +- .../Editor/UI/Common/VisualState.cs | 8 +- .../Editor/UI/Interfaces/IPage.cs | 15 +- .../UI/MultiSelect/CheckUpdateFoldout.cs | 32 + .../UI/MultiSelect/DownloadFoldoutGroup.cs | 19 + .../MultiSelect/DownloadUpdateFoldoutGroup.cs | 19 + .../MultiSelect/IMultiSelectFoldoutElement.cs | 13 + .../UI/MultiSelect/InstallFoldoutGroup.cs | 31 + .../UI/MultiSelect/MultiSelectDetails.cs | 218 +++++++ .../UI/MultiSelect/MultiSelectFoldout.cs | 95 +++ .../UI/MultiSelect/MultiSelectFoldoutGroup.cs | 50 ++ .../Editor/UI/MultiSelect/MultiSelectItem.cs | 94 +++ .../Editor/UI/MultiSelect/NoActionsFoldout.cs | 15 + .../UI/MultiSelect/RemoveFoldoutGroup.cs | 34 ++ .../Editor/UI/MultiSelect/UnlockFoldout.cs | 21 + .../Editor/UI/MultiSelect/UpdateFoldout.cs | 24 + .../UI/MultiSelect/UpdateFoldoutGroup.cs | 18 + .../Editor/UI/PackageDependencies.cs | 17 +- .../UI/PackageDependencySampleItemLowWidth.cs | 17 +- .../Editor/UI/PackageDetails.cs | 85 ++- .../Editor/UI/PackageDetailsBody.cs | 18 +- .../Editor/UI/PackageDetailsHeader.cs | 16 +- .../Editor/UI/PackageDetailsLinks.cs | 18 + .../PackageManagerUI/Editor/UI/PackageItem.cs | 40 +- .../PackageManagerUI/Editor/UI/PackageList.cs | 6 +- .../Editor/UI/PackageListScrollView.cs | 220 +++++-- .../Editor/UI/PackageListView.cs | 54 +- .../Editor/UI/PackageLoadBar.cs | 8 +- .../Editor/UI/PackageManagerPrefs.cs | 7 + .../Editor/UI/PackageManagerToolbar.cs | 28 +- .../Editor/UI/PackageManagerWindow.cs | 3 +- .../Editor/UI/PackageManagerWindowRoot.cs | 38 +- .../UI/PackageManifestImporterEditor.cs | 17 +- .../Editor/UI/PackageSampleItem.cs | 4 + .../Editor/UI/PackageSampleList.cs | 41 +- .../Editor/UI/PackageSelectionEditor.cs | 38 +- .../Editor/UI/PackageSelectionObject.cs | 2 + .../Editor/UI/PackageSubPageFilterBar.cs | 24 +- .../Editor/UI/PackageVersionItem.cs | 10 +- .../Editor/UI/ToolBar/PackageAddButton.cs | 110 ++-- .../UI/ToolBar/PackageCancelDownloadButton.cs | 41 +- .../UI/ToolBar/PackageDeselectButton.cs | 44 ++ .../UI/ToolBar/PackageDownloadButton.cs | 80 +-- .../UI/ToolBar/PackageDownloadUpdateButton.cs | 80 +++ .../UI/ToolBar/PackageGitUpdateButton.cs | 12 +- .../Editor/UI/ToolBar/PackageImportButton.cs | 47 +- .../UI/ToolBar/PackagePauseDownloadButton.cs | 27 +- .../UI/ToolBar/PackageRedownloadButton.cs | 76 +++ .../Editor/UI/ToolBar/PackageRemoveButton.cs | 102 +++- .../Editor/UI/ToolBar/PackageResetButton.cs | 57 +- .../UI/ToolBar/PackageResumeDownloadButton.cs | 27 +- .../Editor/UI/ToolBar/PackageSignInButton.cs | 12 +- .../Editor/UI/ToolBar/PackageToolBar.cs | 79 ++- .../Editor/UI/ToolBar/PackageToolBarButton.cs | 151 ++++- .../Editor/UI/ToolBar/PackageUnlockButton.cs | 23 +- .../Editor/UI/ToolBar/PackageUpdateButton.cs | 144 +++++ .../ParticleSystemForceField.bindings.cs | 2 +- .../CollisionModuleUI.cs | 2 +- .../ParticleSystemEditor/ParticleSystemUI.cs | 26 +- .../ScriptBindings/Dynamics.bindings.cs | 13 +- .../ScriptBindings/QueryCommand.bindings.cs | 43 ++ .../ScriptBindings/Physics2D.bindings.cs | 27 +- Modules/PhysicsEditor/PhysicsDebugWindow.cs | 364 ++++++++--- .../PhysicsDebugWindowContactsTab.cs | 189 ++++++ .../PhysicsDebugWindowInfoTab.cs | 203 +++--- .../PhysicsDebugWindowQueries.cs | 478 +++++++++++++++ .../ScriptBindings/PhysicsDebug.bindings.cs | 159 +++++ .../FileIO/AssetMarkerTreeView.cs | 9 +- .../Editor/Indexing/ObjectIndexer.cs | 5 +- .../Editor/Indexing/SearchIndexer.cs | 13 +- .../Editor/Providers/AssetProvider.cs | 39 +- .../Editor/Providers/Calculator.cs | 2 +- .../Editor/Providers/FindProvider.cs | 9 +- .../Editor/Providers/MenuProvider.cs | 2 +- .../Editor/Providers/ObjectQueryEngine.cs | 22 +- .../Editor/Providers/PerformanceProvider.cs | 5 +- .../Editor/Providers/SceneProvider.cs | 20 +- .../Editor/Providers/SceneQueryEngine.cs | 4 +- .../QueryBuilder/Blocks/QueryAddNewBlock.cs | 22 +- .../QueryBuilder/Blocks/QueryAreaBlock.cs | 4 +- .../QueryBuilder/Blocks/QueryBlockEditor.cs | 46 -- .../Blocks/QueryExpressionBlock.cs | 167 +++++ .../QueryBuilder/Blocks/QueryFilterBlock.cs | 67 +- .../QueryBuilder/Blocks/QueryListBlock.cs | 6 +- .../QueryBuilder/Blocks/QueryWordBlock.cs | 5 +- .../Editor/QueryBuilder/IBlockEditor.cs | 1 + .../Editor/QueryBuilder/QueryBlock.cs | 51 +- .../Editor/QueryBuilder/QueryBuilder.cs | 96 ++- .../Editor/QueryBuilder/QueryContent.cs | 3 +- .../Editor/QueryBuilder/QueryHelperWidget.cs | 5 + .../Editor/QueryBuilder/QuerySelector.cs | 157 ++++- .../Editor/QueryEngine/QueryEngine.cs | 4 +- .../Editor/QueryEngine/QueryToken.cs | 2 +- Modules/QuickSearch/Editor/SearchAnalytics.cs | 10 +- Modules/QuickSearch/Editor/SearchContext.cs | 9 +- Modules/QuickSearch/Editor/SearchEngines.cs | 18 +- .../Evaluators/SelectEvaluator.cs | 2 +- .../SearchExpression/TaskEvaluatorManager.cs | 16 + Modules/QuickSearch/Editor/SearchItem.cs | 2 +- Modules/QuickSearch/Editor/SearchProvider.cs | 2 +- .../Editor/SearchQuery/SearchQuery.cs | 30 +- .../Editor/SearchQuery/SearchQueryAsset.cs | 2 +- Modules/QuickSearch/Editor/SearchService.cs | 2 + Modules/QuickSearch/Editor/SearchSession.cs | 17 + Modules/QuickSearch/Editor/SearchUtils.cs | 32 +- .../Editor/Selectors/AssetSelectors.cs | 8 +- .../Editor/Selectors/SceneSelectors.cs | 17 + .../Editor/Selectors/SearchColumn.cs | 56 +- .../Editor/Selectors/SearchSelector.cs | 1 + Modules/QuickSearch/Editor/UI/QuickSearch.cs | 88 ++- .../Editor/UI/SearchPickerWindow.cs | 10 - .../Editor/UI/SearchProposition.cs | 38 +- .../QuickSearch/Editor/UI/SearchViewState.cs | 14 +- Modules/QuickSearch/Editor/UI/Styles.cs | 44 +- Modules/QuickSearch/Editor/Utilities/Utils.cs | 15 +- .../SceneTemplateEditor/DependencyListView.cs | 12 +- Modules/SceneTemplateEditor/DropdownWindow.cs | 52 -- Modules/SceneTemplateEditor/GridView.cs | 54 +- .../ListSelectionWindow.cs | 172 ++++-- Modules/SceneTemplateEditor/ReferenceUtils.cs | 15 + Modules/SceneTemplateEditor/ScenePicker.cs | 6 +- .../SceneTemplateAnalytics.cs | 2 +- .../SceneTemplateEditor/SceneTemplateAsset.cs | 2 + .../SceneTemplateAssetInspectorWindow.cs | 79 +-- .../SceneTemplateDialog.cs | 99 ++- .../SceneTemplatePreferences.cs | 86 +++ .../SceneTemplatePreviewArea.cs | 65 +- .../SceneTemplateProjectSettings.cs | 177 +++--- .../SceneTemplateService.cs | 336 ++++++++-- .../SceneTemplateEditor/SceneTemplateUtils.cs | 41 +- Modules/SceneTemplateEditor/StringListView.cs | 70 --- Modules/SceneTemplateEditor/Styles.cs | 2 + Modules/SceneTemplateEditor/VisualSplitter.cs | 1 - Modules/StyleSheetsEditor/StylePainter.cs | 8 +- Modules/Terrain/Public/PaintContext.cs | 2 + Modules/Tilemap/Managed/Tilemap.cs | 69 ++- .../ScriptBindings/Tilemap.bindings.cs | 22 +- Modules/TreeEditor/TreeEditor.cs | 8 +- .../Controls/ComponentToolButton.cs | 2 + .../Controls/EditorToolbarDropdownToggle.cs | 25 + .../Controls/LastCustomToolButton.cs | 32 +- .../Controls/ToolContextButton.cs | 71 ++- .../EditorToolbar/DefaultMainToolbar.cs | 60 +- .../ToolbarElements/AccountDropdown.cs | 15 +- .../ToolbarElements/BuiltinToolSettings.cs | 1 - .../ToolbarElements/BuiltinTools.cs | 62 +- .../ToolbarElements/CloudButton.cs | 17 +- .../ToolbarElements/SnapSettings.cs | 6 +- .../GridAndSnap/SnapSettingsWindow.cs | 14 +- .../SceneView/SceneViewLightingOverlays.cs | 18 +- .../SceneView/SceneViewToolbarElements.cs | 37 +- .../Analytics/EditorGameServicesAnalytics.cs | 77 +++ .../UnityConnectEditor/Common/CoppaDrawer.cs | 86 +++ .../UnityConnectEditor/Common/CoppaManager.cs | 18 +- .../Common/IProjectEditorDrawer.cs | 27 + .../Common/PackageHelper.cs | 58 ++ .../Common/ProjectBindDrawer.cs | 87 +++ .../Common/ProjectBindManager.cs | 3 +- .../Common/ServicesConstants.cs | 14 + .../ProjectSettings/AdsProjectSettings.cs | 15 +- .../AnalyticsProjectSettings.cs | 30 +- .../CloudBuildProjectSettings.cs | 14 +- .../CloudDiagProjectSettings.cs | 14 +- .../ProjectSettings/CollabProjectSettings.cs | 14 +- .../Fallback/FallbackProjectSettings.cs | 74 +++ .../Fallback/InstallPackageSection.cs | 149 +++++ .../Fallback/PackageInstallationHandler.cs | 139 +++++ .../Fallback/VisualElementConstants.cs | 28 + .../Fallback/VisualElementUtils.cs | 20 + .../ProjectSettings/GeneralProjectSettings.cs | 10 +- .../PurchasingProjectSettings.cs | 33 +- .../UnityConnectEditor/Services/AdsService.cs | 10 +- .../Services/AnalyticsService.cs | 11 +- .../Services/BuildService.cs | 13 +- .../Services/CollabService.cs | 10 +- .../Services/CrashService.cs | 12 +- .../Services/PurchasingService.cs | 9 +- .../Services/ServicesUtils.cs | 21 +- .../Services/SingleService.cs | 13 +- .../Services/UDPServices.cs | 12 +- .../ServicesEditorWindow.cs | 363 ----------- .../UnityConnectEditor/ServicesExploreMenu.cs | 18 + .../ServicesProjectSettings.cs | 17 +- .../UnityConnectEditor/ServicesRepository.cs | 17 +- .../BuildEventsHandler.cs | 2 +- .../EditorAnalytics.bindings.cs | 16 + .../ScriptBindings/VFXEnums.bindings.cs | 15 +- .../VFXExpressionMesh.bindings.cs | 42 -- .../ScriptBindings/VideoPlayer.bindings.cs | 15 + Projects/CSharp/UnityEditor.csproj | 304 +++++---- Projects/CSharp/UnityEngine.csproj | 117 ++-- Projects/CSharp/UnityReferenceSource.sln | 20 +- README.md | 2 +- .../ScriptBindings/SortingGroup.bindings.cs | 1 + .../Application/Application.bindings.cs | 2 +- .../Export}/ExpressionEvaluator.cs | 4 +- .../Export/GI/LightingSettings.bindings.cs | 4 + Runtime/Export/Graphics/Graphics.bindings.cs | 42 +- Runtime/Export/Graphics/Graphics.cs | 22 + Runtime/Export/Graphics/GraphicsEnums.cs | 2 + .../GraphicsFormatUtility.bindings.cs | 13 +- Runtime/Export/Graphics/Texture.bindings.cs | 3 + Runtime/Export/Graphics/Texture.cs | 7 +- Runtime/Export/Input/KeyCode.cs | 63 +- Runtime/Export/Math/Mathf.cs | 91 +++ .../Export}/NumericFieldDraggerUtility.cs | 5 +- .../RenderPipeline/CullingParameters.cs | 3 + .../Rendering/BatchRendererGroup.bindings.cs | 577 ++++++++++++------ Runtime/Export/SceneManager/Scene.bindings.cs | 3 + Runtime/Export/SceneManager/Scene.cs | 5 + .../Scripting/ClassLibraryInitializer.cs | 14 + Runtime/Export/Shaders/HybridV2.bindings.cs | 104 ---- .../Export/Shaders/LocalKeyword.bindings.cs | 2 + Runtime/Export/UINumericFieldsUtils.cs | 45 ++ .../Export/Windows/VideoCapture.bindings.cs | 3 - .../Export/Windows/WindowsInput.bindings.cs | 6 + Runtime/Export/Windows/WindowsInput.cs | 27 + Runtime/Export/iOS/iOS.deprecated.cs | 92 --- .../Export/iOS/iOSNotifications.bindings.cs | 225 ------- .../ScriptBindings/Profiler.bindings.cs | 5 +- .../Unity.CecilTools.gen.csproj | 63 +- .../Unity.SerializationLogic.gen.csproj | 68 +-- .../bee_530d/BeeAsALibrary/Bee.BeeDriver.dll | Bin 81920 -> 0 bytes .../bee_bcfb/BeeAsALibrary/Bee.BeeDriver.dll | Bin 0 -> 87552 bytes 499 files changed, 12956 insertions(+), 6353 deletions(-) create mode 100644 Editor/Mono/Inspector/EditorElementUpdater.cs create mode 100644 Editor/Mono/Overlays/OverlayToolbar.cs create mode 100644 Editor/Mono/UnityConnect/CloudProjectSettingsEventManager.cs create mode 100644 Editor/Mono/UnityConnect/CoppaCompliance.cs delete mode 100644 External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitView.cs delete mode 100644 External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewResizer.cs delete mode 100644 External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewTestWindow.cs create mode 100644 External/NetStandardExtensions/System.CodeDom.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Mdb.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Pdb.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Rocks.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.dll create mode 100644 External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Mdb.dll create mode 100644 External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Pdb.dll create mode 100644 External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Rocks.dll create mode 100644 External/Unity.Cecil/builds/lib/net40/Unity.Cecil.dll rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/BaseCompositeField.cs (89%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/BoundsField.cs (97%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/BoundsIntField.cs (96%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/CompoundFields.cs (96%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/DoubleField.cs (90%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/FloatField.cs (86%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/Hash128Field.cs (96%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/IntegerField.cs (87%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/LongField.cs (92%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/Controls/TextValueField.cs (96%) rename ModuleOverrides/com.unity.ui/{Editor => Core}/FieldMouseDragger.cs (75%) create mode 100644 ModuleOverrides/com.unity.ui/Core/PenButton.cs create mode 100644 ModuleOverrides/com.unity.ui/Core/UIElementsBridge.cs create mode 100644 ModuleOverrides/com.unity.ui/Core/UpgradeConstants.cs create mode 100644 ModuleOverrides/com.unity.ui/Editor/EditorUIElementsBridge.cs create mode 100644 Modules/Audio/Public/ScriptBindings/AudioSampleProviderExtensions.bindings.cs create mode 100644 Modules/Audio/Public/ScriptBindings/ExposeVivox.cs create mode 100644 Modules/PackageManager/Editor/Managed/SignatureInfo.cs create mode 100644 Modules/PackageManager/Editor/Managed/SignatureStatus.cs create mode 100644 Modules/PackageManagerUI/Editor/External/EditorGameServiceExtension.cs create mode 100644 Modules/PackageManagerUI/Editor/External/ServicesTab/ServiceGroupingsWrapper.cs create mode 100644 Modules/PackageManagerUI/Editor/External/ServicesTab/ServicesTabConfiguration.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Packages/PackageAndVersionIdPair.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Proxies/AssetStoreCachePathProxy.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Upm/UpmCacheRootClient.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Upm/UpmClearCacheRootOperation.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Upm/UpmGetCacheRootOperation.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/Upm/UpmSetCacheRootOperation.cs create mode 100644 Modules/PackageManagerUI/Editor/Services/UserSettings/PackageManagerUserSettingsProvider.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/Common/PageSelection.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/CheckUpdateFoldout.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/DownloadFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/DownloadUpdateFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/IMultiSelectFoldoutElement.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/InstallFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/MultiSelectDetails.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/MultiSelectFoldout.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/MultiSelectFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/MultiSelectItem.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/NoActionsFoldout.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/RemoveFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/UnlockFoldout.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/UpdateFoldout.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/MultiSelect/UpdateFoldoutGroup.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/ToolBar/PackageDeselectButton.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/ToolBar/PackageDownloadUpdateButton.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/ToolBar/PackageRedownloadButton.cs create mode 100644 Modules/PackageManagerUI/Editor/UI/ToolBar/PackageUpdateButton.cs create mode 100644 Modules/PhysicsEditor/PhysicsDebugWindowContactsTab.cs create mode 100644 Modules/PhysicsEditor/PhysicsDebugWindowQueries.cs create mode 100644 Modules/QuickSearch/Editor/QueryBuilder/Blocks/QueryExpressionBlock.cs delete mode 100644 Modules/SceneTemplateEditor/DropdownWindow.cs create mode 100644 Modules/SceneTemplateEditor/SceneTemplatePreferences.cs delete mode 100644 Modules/SceneTemplateEditor/StringListView.cs create mode 100644 Modules/UnityConnectEditor/Analytics/EditorGameServicesAnalytics.cs create mode 100644 Modules/UnityConnectEditor/Common/CoppaDrawer.cs create mode 100644 Modules/UnityConnectEditor/Common/IProjectEditorDrawer.cs create mode 100644 Modules/UnityConnectEditor/Common/PackageHelper.cs create mode 100644 Modules/UnityConnectEditor/Common/ProjectBindDrawer.cs create mode 100644 Modules/UnityConnectEditor/Common/ServicesConstants.cs create mode 100644 Modules/UnityConnectEditor/ProjectSettings/Fallback/FallbackProjectSettings.cs create mode 100644 Modules/UnityConnectEditor/ProjectSettings/Fallback/InstallPackageSection.cs create mode 100644 Modules/UnityConnectEditor/ProjectSettings/Fallback/PackageInstallationHandler.cs create mode 100644 Modules/UnityConnectEditor/ProjectSettings/Fallback/VisualElementConstants.cs create mode 100644 Modules/UnityConnectEditor/ProjectSettings/Fallback/VisualElementUtils.cs delete mode 100644 Modules/UnityConnectEditor/ServicesEditorWindow.cs create mode 100644 Modules/UnityConnectEditor/ServicesExploreMenu.cs rename {Editor/Mono/Utils => Runtime/Export}/ExpressionEvaluator.cs (99%) rename {Editor/Mono => Runtime/Export}/NumericFieldDraggerUtility.cs (94%) delete mode 100644 Runtime/Export/Shaders/HybridV2.bindings.cs create mode 100644 Runtime/Export/UINumericFieldsUtils.cs create mode 100644 Runtime/Export/Windows/WindowsInput.bindings.cs create mode 100644 Runtime/Export/Windows/WindowsInput.cs delete mode 100644 Runtime/Export/iOS/iOSNotifications.bindings.cs delete mode 100644 artifacts/Stevedore/bee_530d/BeeAsALibrary/Bee.BeeDriver.dll create mode 100644 artifacts/Stevedore/bee_bcfb/BeeAsALibrary/Bee.BeeDriver.dll diff --git a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj index 597465a2ce..7ff0a1d95a 100644 --- a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj @@ -1,113 +1,14 @@  - - + - Debug - AnyCPU - {236F6903-2F21-1CCA-571E-C6D1D859E1EA} - Library - BeeBuildProgramCommon.Data - BeeBuildProgramCommon.Data - 512 - true + netstandard2.1 + false + false + false latest + - - AnyCPU - true - full - false - ..\..\..\artifacts\BeeBuildProgramCommon.Data.dll\Debug - - prompt - 4 - - false - false - v4.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj index 8ed951461d..5d8e5ddc83 100644 --- a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj @@ -1,117 +1,16 @@  - - + - Debug - AnyCPU - {0B340C5C-3844-3B45-E3FD-DA591C333973} - Library - PlayerBuildProgramLibrary.Data - PlayerBuildProgramLibrary.Data - 512 - true + netstandard2.1 + false + false + false latest + + PlayerBuildProgramLibrary.Data + - - AnyCPU - true - full - false - ..\..\..\artifacts\PlayerBuildProgramLibrary.Data.dll\Debug - - prompt - 4 - - false - false - v4.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {236F6903-2F21-1CCA-571E-C6D1D859E1EA} - BeeBuildProgramCommon.Data - - - - diff --git a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj index a1e8a6751b..a84a752587 100644 --- a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj @@ -1,117 +1,15 @@  - - + - Debug - AnyCPU - {2BA9D0ED-D2EF-DA84-1599-37A046A44915} - Library - ScriptCompilationBuildProgram.Data - ScriptCompilationBuildProgram.Data - 512 - true + netstandard2.1 + false + false + false latest + + - - AnyCPU - true - full - false - ..\..\..\artifacts\ScriptCompilationBuildProgram.Data.dll\Debug - - prompt - 4 - - false - false - v4.6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {236F6903-2F21-1CCA-571E-C6D1D859E1EA} - BeeBuildProgramCommon.Data - - - - diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasAsset.bindings.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasAsset.bindings.cs index 0164fda16e..08c25e6de6 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasAsset.bindings.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasAsset.bindings.cs @@ -25,28 +25,29 @@ public class SpriteAtlasAsset : UnityEngine.Object extern public bool isVariant { [NativeMethod("GetIsVariant")] get; } extern public void SetIsVariant(bool value); extern public void SetMasterAtlas(SpriteAtlas atlas); - extern public void SetIncludeInBuild(bool value); - extern public bool IsIncludeInBuild(); extern public SpriteAtlas GetMasterAtlas(); - extern public void SetVariantScale(float value); - extern public void SetPlatformSettings(TextureImporterPlatformSettings src); - extern public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget); - extern public SpriteAtlasTextureSettings GetTextureSettings(); - extern public void SetTextureSettings(SpriteAtlasTextureSettings src); - extern public SpriteAtlasPackingSettings GetPackingSettings(); - extern public void SetPackingSettings(SpriteAtlasPackingSettings src); - extern public void Add(UnityEngine.Object[] objects); extern public void Remove(UnityEngine.Object[] objects); extern internal void RemoveAt(int index); - extern internal TextureFormat GetTextureFormat(BuildTarget target); - extern internal void CopyMasterAtlasSettings(); - extern internal TextureImporterPlatformSettings GetSecondaryPlatformSettings(string buildTarget, string secondaryTextureName); - extern internal void SetSecondaryPlatformSettings(TextureImporterPlatformSettings src, string secondaryTextureName); - extern internal bool GetSecondaryColorSpace(string secondaryTextureName); - extern internal void SetSecondaryColorSpace(string secondaryTextureName, bool srGB); - extern internal void DeleteSecondaryPlatformSettings(string secondaryTextureName); + [Obsolete("SetVariantScale is no longer supported and will be removed. Use SpriteAtlasImporter.SetVariantScale instead.")] + public void SetVariantScale(float value) { } + [Obsolete("SetIncludeInBuild is no longer supported and will be removed. Use SpriteAtlasImporter.SetIncludeInBuild instead.")] + public void SetIncludeInBuild(bool value) { } + [Obsolete("IsIncludeInBuild is no longer supported and will be removed. Use SpriteAtlasImporter.IsIncludeInBuild instead.")] + public bool IsIncludeInBuild() { return true; } + [Obsolete("SetPlatformSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetPlatformSettings instead.")] + public void SetPlatformSettings(TextureImporterPlatformSettings src) { } + [Obsolete("SetTextureSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetTextureSettings instead.")] + public void SetTextureSettings(SpriteAtlasTextureSettings src) { } + [Obsolete("SetPackingSettings is no longer supported and will be removed. Use SpriteAtlasImporter.SetPackingSettings instead.")] + public void SetPackingSettings(SpriteAtlasPackingSettings src) { } + [Obsolete("GetPackingSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetPackingSettings instead.")] + public SpriteAtlasPackingSettings GetPackingSettings() { return new SpriteAtlasPackingSettings(); } + [Obsolete("GetTextureSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetTextureSettings instead.")] + public SpriteAtlasTextureSettings GetTextureSettings() { return new SpriteAtlasTextureSettings(); } + [Obsolete("GetPlatformSettings is no longer supported and will be removed. Use SpriteAtlasImporter.GetPlatformSettingss instead.")] + public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget) { return new TextureImporterPlatformSettings(); } // Load SpriteAtlasAsset public static SpriteAtlasAsset Load(string assetPath) diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs index 07d68da288..d174d50f38 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs @@ -16,9 +16,20 @@ namespace UnityEditor.U2D { // SpriteAtlas Importer lets you modify [[SpriteAtlas]] [NativeHeader("Editor/Src/2D/SpriteAtlas/SpriteAtlasImporter.h")] - [ExcludeFromPreset] public sealed partial class SpriteAtlasImporter : AssetImporter { extern internal static void MigrateAllSpriteAtlases(); + extern public float variantScale { get; set; } + extern public bool includeInBuild { get; set; } + extern public SpriteAtlasPackingSettings packingSettings { get; set; } + extern public SpriteAtlasTextureSettings textureSettings { get; set; } + extern public void SetPlatformSettings(TextureImporterPlatformSettings src); + extern public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget); + extern internal TextureFormat GetTextureFormat(BuildTarget target); + extern internal TextureImporterPlatformSettings GetSecondaryPlatformSettings(string buildTarget, string secondaryTextureName); + extern internal void SetSecondaryPlatformSettings(TextureImporterPlatformSettings src, string secondaryTextureName); + extern internal bool GetSecondaryColorSpace(string secondaryTextureName); + extern internal void SetSecondaryColorSpace(string secondaryTextureName, bool srGB); + extern internal void DeleteSecondaryPlatformSettings(string secondaryTextureName); } }; diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs index 0eec9fa010..a0d7556217 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs @@ -11,12 +11,12 @@ using UnityEditor.U2D.Common; using UnityEditor.U2D.Interface; using UnityEditorInternal; +using UnityEditor.AssetImporters; namespace UnityEditor.U2D { [CustomEditor(typeof(SpriteAtlasImporter))] - [ExcludeFromPreset] - internal class SpriteAtlasImporterInspector : Editor + internal class SpriteAtlasImporterInspector : AssetImporterEditor { class SpriteAtlasInspectorPlatformSettingView : TexturePlatformSettingsView { @@ -116,6 +116,10 @@ private SpriteAtlasAsset spriteAtlasAsset { get { return m_TargetAsset; } } + private SpriteAtlasImporter spriteAtlasImporter + { + get { return target as SpriteAtlasImporter; } + } private enum AtlasType { Undefined = -1, Master = 0, Variant = 1 } private SerializedProperty m_FilterMode; @@ -148,11 +152,11 @@ private enum AtlasType { Undefined = -1, Master = 0, Variant = 1 } private float m_MipLevel = 0; private bool m_ShowAlpha; - private bool m_HasChanged = false; private List m_PlatformSettingsOptions; private int m_SelectedPlatformSettings = 0; + private int m_ContentHash = 0; private List m_ValidPlatforms; private Dictionary> m_TempPlatformSettings; @@ -180,19 +184,21 @@ static Object ValidateObjectForPackableFieldAssignment(Object[] references, Syst bool IsTargetVariant() { - return spriteAtlasAsset.isVariant; + return spriteAtlasAsset ? spriteAtlasAsset.isVariant : false; } bool IsTargetMaster() { - return !spriteAtlasAsset.isVariant; + return spriteAtlasAsset ? !spriteAtlasAsset.isVariant : true; } + protected override bool needsApplyRevert => false; + internal override string targetTitle { get { - return Path.GetFileNameWithoutExtension(m_AssetPath) + " (Sprite Atlas)"; + return spriteAtlasAsset ? ( Path.GetFileNameWithoutExtension(m_AssetPath) + " (Sprite Atlas)" ) : "SpriteAtlasImporter Settings"; } } @@ -212,6 +218,43 @@ private SerializedObject serializedAssetObject return GetSerializedAssetObject(); } } + + internal static int SpriteAtlasAssetHash(SerializedObject obj) + { + int hashCode = 0; + if (obj == null) + return 0; + unchecked + { + hashCode = (int)2166136261 ^ (int) obj.FindProperty("m_MasterAtlas").contentHash; + hashCode = hashCode * 16777619 ^ (int) obj.FindProperty("m_ImporterData").contentHash; + hashCode = hashCode * 16777619 ^ (int) obj.FindProperty("m_IsVariant").contentHash; + } + return hashCode; + } + + internal static int SpriteAtlasImporterHash(SerializedObject obj) + { + int hashCode = 0; + if (obj == null) + return 0; + unchecked + { + hashCode = (int)2166136261 ^ (int)obj.FindProperty("m_PackingSettings").contentHash; + hashCode = hashCode * 16777619 ^ (int)obj.FindProperty("m_TextureSettings").contentHash; + hashCode = hashCode * 16777619 ^ (int)obj.FindProperty("m_PlatformSettings").contentHash; + hashCode = hashCode * 16777619 ^ (int)obj.FindProperty("m_SecondaryTextureSettings").contentHash; + hashCode = hashCode * 16777619 ^ (int)obj.FindProperty("m_BindAsDefault").contentHash; + hashCode = hashCode * 16777619 ^ (int)obj.FindProperty("m_VariantMultiplier").contentHash; + } + return hashCode; + } + + internal int GetInspectorHash() + { + return SpriteAtlasAssetHash(m_SerializedAssetObject) * 16777619 ^ SpriteAtlasImporterHash(m_SerializedObject); + } + private SerializedObject GetSerializedAssetObject() { if (m_SerializedAssetObject == null) @@ -220,6 +263,7 @@ private SerializedObject GetSerializedAssetObject() { m_SerializedAssetObject = new SerializedObject(spriteAtlasAsset, m_Context); m_SerializedAssetObject.inspectorMode = inspectorMode; + m_ContentHash = GetInspectorHash(); m_EnabledProperty = m_SerializedAssetObject.FindProperty("m_Enabled"); } catch (System.ArgumentException e) @@ -232,37 +276,24 @@ private SerializedObject GetSerializedAssetObject() return m_SerializedAssetObject; } - void OnEnable() + public override void OnEnable() { - m_AssetPath = LoadSourceAsset(); - if (spriteAtlasAsset == null) - return; + base.OnEnable(); - m_FilterMode = serializedAssetObject.FindProperty("m_ImporterData.textureSettings.filterMode"); - m_AnisoLevel = serializedAssetObject.FindProperty("m_ImporterData.textureSettings.anisoLevel"); - m_GenerateMipMaps = serializedAssetObject.FindProperty("m_ImporterData.textureSettings.generateMipMaps"); - m_Readable = serializedAssetObject.FindProperty("m_ImporterData.textureSettings.readable"); - m_UseSRGB = serializedAssetObject.FindProperty("m_ImporterData.textureSettings.sRGB"); - - m_EnableTightPacking = serializedAssetObject.FindProperty("m_ImporterData.packingSettings.enableTightPacking"); - m_EnableRotation = serializedAssetObject.FindProperty("m_ImporterData.packingSettings.enableRotation"); - m_EnableAlphaDilation = serializedAssetObject.FindProperty("m_ImporterData.packingSettings.enableAlphaDilation"); - m_Padding = serializedAssetObject.FindProperty("m_ImporterData.packingSettings.padding"); - - m_MasterAtlas = serializedAssetObject.FindProperty("m_MasterAtlas"); - m_BindAsDefault = serializedAssetObject.FindProperty("m_ImporterData.bindAsDefault"); - m_VariantScale = serializedAssetObject.FindProperty("m_ImporterData.variantMultiplier"); + m_FilterMode = serializedObject.FindProperty("m_TextureSettings.filterMode"); + m_AnisoLevel = serializedObject.FindProperty("m_TextureSettings.anisoLevel"); + m_GenerateMipMaps = serializedObject.FindProperty("m_TextureSettings.generateMipMaps"); + m_Readable = serializedObject.FindProperty("m_TextureSettings.readable"); + m_UseSRGB = serializedObject.FindProperty("m_TextureSettings.sRGB"); + m_EnableTightPacking = serializedObject.FindProperty("m_PackingSettings.enableTightPacking"); + m_EnableRotation = serializedObject.FindProperty("m_PackingSettings.enableRotation"); + m_EnableAlphaDilation = serializedObject.FindProperty("m_PackingSettings.enableAlphaDilation"); + m_Padding = serializedObject.FindProperty("m_PackingSettings.padding"); + m_BindAsDefault = serializedObject.FindProperty("m_BindAsDefault"); + m_VariantScale = serializedObject.FindProperty("m_VariantMultiplier"); PopulatePlatformSettingsOptions(); - m_Packables = serializedAssetObject.FindProperty("m_ImporterData.packables"); - m_PackableList = new ReorderableList(serializedAssetObject, m_Packables, true, true, true, true); - m_PackableList.onAddCallback = AddPackable; - m_PackableList.onRemoveCallback = RemovePackable; - m_PackableList.drawElementCallback = DrawPackableElement; - m_PackableList.elementHeight = EditorGUIUtility.singleLineHeight; - m_PackableList.headerHeight = 0f; - SyncPlatformSettings(); m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(IsTargetMaster()); @@ -271,13 +302,25 @@ void OnEnable() // Don't show max size option for secondary textures as they must have the same size as the main texture. m_SecondaryTexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(false); + + m_AssetPath = LoadSourceAsset(); + if (spriteAtlasAsset == null) + return; + + m_MasterAtlas = serializedAssetObject.FindProperty("m_MasterAtlas"); + m_Packables = serializedAssetObject.FindProperty("m_ImporterData.packables"); + m_PackableList = new ReorderableList(serializedAssetObject, m_Packables, true, true, true, true); + m_PackableList.onAddCallback = AddPackable; + m_PackableList.drawElementCallback = DrawPackableElement; + m_PackableList.elementHeight = EditorGUIUtility.singleLineHeight; + m_PackableList.headerHeight = 0f; } // Populate the platform settings dropdown list with secondary texture names found through serialized properties of the Sprite Atlas assets. private void PopulatePlatformSettingsOptions() { m_PlatformSettingsOptions = new List { L10n.Tr("Main Texture"), "", "", L10n.Tr("New Secondary Texture settings.") }; - SerializedProperty secondaryPlatformSettings = serializedAssetObject.FindProperty("m_ImporterData.secondaryTextureSettings"); + SerializedProperty secondaryPlatformSettings = serializedObject.FindProperty("m_SecondaryTextureSettings"); if (secondaryPlatformSettings != null && !secondaryPlatformSettings.hasMultipleDifferentValues) { int numSecondaryTextures = secondaryPlatformSettings.arraySize; @@ -305,8 +348,8 @@ void SyncPlatformSettings() var defaultSettings = new List(); m_TempPlatformSettings.Add(TextureImporterInspector.s_DefaultPlatformName, defaultSettings); var settings = secondaryTextureSelected - ? spriteAtlasAsset.GetSecondaryPlatformSettings(TextureImporterInspector.s_DefaultPlatformName, secondaryTextureName) - : spriteAtlasAsset.GetPlatformSettings(TextureImporterInspector.s_DefaultPlatformName); + ? spriteAtlasImporter.GetSecondaryPlatformSettings(TextureImporterInspector.s_DefaultPlatformName, secondaryTextureName) + : spriteAtlasImporter.GetPlatformSettings(TextureImporterInspector.s_DefaultPlatformName); defaultSettings.Add(settings); m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms(); @@ -314,7 +357,7 @@ void SyncPlatformSettings() { var platformSettings = new List(); m_TempPlatformSettings.Add(platform.name, platformSettings); - var perPlatformSettings = secondaryTextureSelected ? spriteAtlasAsset.GetSecondaryPlatformSettings(platform.name, secondaryTextureName) : spriteAtlasAsset.GetPlatformSettings(platform.name); + var perPlatformSettings = secondaryTextureSelected ? spriteAtlasImporter.GetSecondaryPlatformSettings(platform.name, secondaryTextureName) : spriteAtlasImporter.GetPlatformSettings(platform.name); // setting will be in default state if copy failed platformSettings.Add(perPlatformSettings); } @@ -322,15 +365,15 @@ void SyncPlatformSettings() void RenameSecondaryPlatformSettings(string oldName, string newName) { - spriteAtlasAsset.DeleteSecondaryPlatformSettings(oldName); + spriteAtlasImporter.DeleteSecondaryPlatformSettings(oldName); var defaultPlatformSettings = m_TempPlatformSettings[TextureImporterInspector.s_DefaultPlatformName]; - spriteAtlasAsset.SetSecondaryPlatformSettings(defaultPlatformSettings[0], newName); + spriteAtlasImporter.SetSecondaryPlatformSettings(defaultPlatformSettings[0], newName); foreach (var buildPlatform in m_ValidPlatforms) { var platformSettings = m_TempPlatformSettings[buildPlatform.name]; - spriteAtlasAsset.SetSecondaryPlatformSettings(platformSettings[0], newName); + spriteAtlasImporter.SetSecondaryPlatformSettings(platformSettings[0], newName); } } @@ -341,13 +384,6 @@ void AddPackable(ReorderableList list) ObjectSelector.get.objectSelectorID = styles.packableSelectorHash; } - void RemovePackable(ReorderableList list) - { - var index = list.index; - if (index != -1) - spriteAtlasAsset.RemoveAt(index); - } - void DrawPackableElement(Rect rect, int index, bool selected, bool focused) { var property = m_Packables.GetArrayElementAtIndex(index); @@ -357,11 +393,7 @@ void DrawPackableElement(Rect rect, int index, bool selected, bool focused) var changedObject = EditorGUI.DoObjectField(rect, rect, controlID, previousObject, target, typeof(Object), ValidateObjectForPackableFieldAssignment, false); if (changedObject != previousObject) { - // Always call Remove() on the previous object if we swapping the object field item. - // This ensure the Sprites was pack in this atlas will be refreshed of it unbound. Undo.RegisterCompleteObjectUndo(spriteAtlasAsset, styles.swapObjectRegisterUndo); - if (previousObject != null) - spriteAtlasAsset.Remove(new Object[] { previousObject }); property.objectReferenceValue = changedObject; } @@ -369,30 +401,24 @@ void DrawPackableElement(Rect rect, int index, bool selected, bool focused) m_PackableList.index = index; } - public virtual void OnDestroy() - { - if (HasModified()) - { - ApplyAndImport(); - } - } - - protected void Apply() + protected override void Apply() { if (HasModified()) { - serializedAssetObject.ApplyModifiedPropertiesWithoutUndo(); - SpriteAtlasAsset.Save(spriteAtlasAsset, m_AssetPath); + if (spriteAtlasAsset) + SpriteAtlasAsset.Save(spriteAtlasAsset, m_AssetPath); + m_ContentHash = GetInspectorHash(); } + base.Apply(); } - public void ApplyAndImport() + public void ApplyAndImportSpriteAtlas() { Apply(); - AssetDatabase.ImportAsset(m_AssetPath); + base.ApplyAndImport(); } - protected void ApplyRevertGUI() + protected void PackPreviewGUI() { EditorGUILayout.Space(); @@ -406,9 +432,8 @@ protected void ApplyRevertGUI() { GUI.FocusControl(null); SpriteAtlasUtility.EnableV2Import(true); - ApplyAndImport(); + ApplyAndImportSpriteAtlas(); SpriteAtlasUtility.EnableV2Import(false); - m_HasChanged = false; } } } @@ -422,9 +447,29 @@ private bool IsValidAtlas() return true; } - public bool HasModified() + public override void OnDisable() + { + + if (Unsupported.IsDestroyScriptableObject(this)) + { + if (spriteAtlasAsset && HasModified()) + { + if (EditorUtility.DisplayDialog("Unapplied import settings", "Unapplied import settings for \'" + m_AssetPath + "\'", "Apply", "Revert")) + { + ApplyAndImportSpriteAtlas(); + } + else + { + ResetValues(); + } + } + } + base.OnDisable(); + } + + public override bool HasModified() { - return m_HasChanged; + return base.HasModified() || m_ContentHash != GetInspectorHash(); } private void ValidateMasterAtlas() @@ -451,24 +496,27 @@ private void ValidateMasterAtlas() public override void OnInspectorGUI() { - if (spriteAtlasAsset == null) - return; - - EditorGUI.BeginChangeCheck(); - // Ensure changes done through script are reflected immediately in Inspector by Syncing m_TempPlatformSettings with Actual Settings. SyncPlatformSettings(); - serializedAssetObject.Update(); - - HandleCommonSettingUI(); + serializedObject.Update(); + if (spriteAtlasAsset) + { + serializedAssetObject.Update(); + HandleCommonSettingUI(); + } + EditorGUILayout.PropertyField(m_BindAsDefault, styles.bindAsDefaultLabel); GUILayout.Space(EditorGUI.kSpacing); - if (IsTargetVariant()) - HandleVariantSettingUI(); - else if (IsTargetMaster()) + bool isTargetMaster = true; + if (spriteAtlasAsset) + isTargetMaster = IsTargetMaster(); + + if (isTargetMaster) HandleMasterSettingUI(); + if (!spriteAtlasAsset || IsTargetVariant()) + HandleVariantSettingUI(); GUILayout.Space(EditorGUI.kSpacing); @@ -478,16 +526,15 @@ public override void OnInspectorGUI() // Only show the packable object list when: // - This is a master atlas. - if (targets.Length == 1 && IsTargetMaster()) + if (targets.Length == 1 && IsTargetMaster() && spriteAtlasAsset) HandlePackableListUI(); - serializedAssetObject.ApplyModifiedPropertiesWithoutUndo(); - - if (EditorGUI.EndChangeCheck()) + serializedObject.ApplyModifiedProperties(); + if (spriteAtlasAsset) { - m_HasChanged = true; + serializedAssetObject.ApplyModifiedProperties(); + PackPreviewGUI(); } - ApplyRevertGUI(); } private void HandleCommonSettingUI() @@ -520,13 +567,10 @@ private void HandleCommonSettingUI() ValidateMasterAtlas(); // Apply modified properties here to have latest master atlas reflected in native codes. serializedAssetObject.ApplyModifiedPropertiesWithoutUndo(); - spriteAtlasAsset.CopyMasterAtlasSettings(); PopulatePlatformSettingsOptions(); SyncPlatformSettings(); } } - - EditorGUILayout.PropertyField(m_BindAsDefault, styles.bindAsDefaultLabel); } private void HandleVariantSettingUI() @@ -594,7 +638,6 @@ private void HandleTextureSettingUI() m_SelectedPlatformSettings--; EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName); } - m_HasChanged = true; SyncPlatformSettings(); } @@ -605,7 +648,7 @@ private void HandleTextureSettingUI() { EditorGUI.EndEditingActiveTextField(); - spriteAtlasAsset.DeleteSecondaryPlatformSettings(m_PlatformSettingsOptions[m_SelectedPlatformSettings]); + spriteAtlasImporter.DeleteSecondaryPlatformSettings(m_PlatformSettingsOptions[m_SelectedPlatformSettings]); m_PlatformSettingsOptions.RemoveAt(m_SelectedPlatformSettings); @@ -613,7 +656,6 @@ private void HandleTextureSettingUI() if (m_SelectedPlatformSettings == 1) m_SelectedPlatformSettings = 0; - m_HasChanged = true; SyncPlatformSettings(); } } @@ -654,14 +696,13 @@ private void HandleTextureSettingUI() Debug.LogWarning(s_Styles.nameUniquenessWarning); EditorGUI.FocusTextInControl(s_Styles.secondaryTextureNameTextControlName); } - m_HasChanged = true; } string secondaryTextureName = m_PlatformSettingsOptions[m_SelectedPlatformSettings]; EditorGUI.BeginChangeCheck(); - bool value = EditorGUILayout.Toggle(s_Styles.sRGBLabel, spriteAtlasAsset.GetSecondaryColorSpace(secondaryTextureName)); + bool value = EditorGUILayout.Toggle(s_Styles.sRGBLabel, spriteAtlasImporter.GetSecondaryColorSpace(secondaryTextureName)); if (EditorGUI.EndChangeCheck()) - spriteAtlasAsset.SetSecondaryColorSpace(secondaryTextureName, value); + spriteAtlasImporter.SetSecondaryColorSpace(secondaryTextureName, value); HandlePlatformSettingUI(textFieldText); } @@ -684,11 +725,10 @@ private void HandlePlatformSettingUI(string secondaryTextureName) for (var i = 0; i < defaultPlatformSettings.Count; ++i) { if (isSecondary) - spriteAtlasAsset.SetSecondaryPlatformSettings(defaultPlatformSettings[i], secondaryTextureName); + spriteAtlasImporter.SetSecondaryPlatformSettings(defaultPlatformSettings[i], secondaryTextureName); else - spriteAtlasAsset.SetPlatformSettings(defaultPlatformSettings[i]); + spriteAtlasImporter.SetPlatformSettings(defaultPlatformSettings[i]); } - m_HasChanged = true; } } else @@ -704,7 +744,7 @@ private void HandlePlatformSettingUI(string secondaryTextureName) { if (defaultPlatformSettings[0].format == TextureImporterFormat.Automatic) { - settings.format = (TextureImporterFormat)spriteAtlasAsset.GetTextureFormat(buildPlatform.defaultTarget); + settings.format = (TextureImporterFormat)spriteAtlasImporter.GetTextureFormat(buildPlatform.defaultTarget); } else { @@ -723,11 +763,10 @@ private void HandlePlatformSettingUI(string secondaryTextureName) for (var i = 0; i < platformSettings.Count; ++i) { if (isSecondary) - spriteAtlasAsset.SetSecondaryPlatformSettings(platformSettings[i], secondaryTextureName); + spriteAtlasImporter.SetSecondaryPlatformSettings(platformSettings[i], secondaryTextureName); else - spriteAtlasAsset.SetPlatformSettings(platformSettings[i]); + spriteAtlasImporter.SetPlatformSettings(platformSettings[i]); } - m_HasChanged = true; } } diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs index dab131fbe2..81c8f4cd83 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs @@ -475,10 +475,14 @@ static bool ValueFromPropertyModification(PropertyModification modification, Edi } else { - float temp; - if (float.TryParse(modification.value, NumberStyles.Float, CultureInfo.InvariantCulture, out temp)) + if(binding.isDiscreteCurve && int.TryParse(modification.value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int tempInt)) { - outObject = temp; + outObject = tempInt; + return true; + } + else if (float.TryParse(modification.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempFloat)) + { + outObject = tempFloat; return true; } else @@ -505,7 +509,15 @@ static void AddKey(IAnimationRecordingState state, EditorCurveBinding binding, T if (curve.length == 0) { if (state.currentFrame != 0) + { + // case 1373924 + // In the case of a new curve, we also have to convert the previousValue to float for a discrete int + if(binding.isDiscreteCurve) + { + previousValue = UnityEngine.Animations.DiscreteEvaluationAttributeUtilities.ConvertDiscreteIntToFloat((int)previousValue); + } AnimationWindowUtility.AddKeyframeToCurve(curve, previousValue, type, AnimationKeyTime.Frame(0, clip.frameRate)); + } } } diff --git a/Editor/Mono/AssemblyHelper.cs b/Editor/Mono/AssemblyHelper.cs index a2c80f0eea..3aa7261772 100644 --- a/Editor/Mono/AssemblyHelper.cs +++ b/Editor/Mono/AssemblyHelper.cs @@ -26,22 +26,6 @@ internal partial class AssemblyHelper static Dictionary managedToDllType = new Dictionary(); static BuildPlayerDataExtractor m_BuildPlayerDataExtractor = new BuildPlayerDataExtractor(); - // Check if assmebly internal name doesn't match file name, and show the warning. - [RequiredByNativeCode] - static public void CheckForAssemblyFileNameMismatch(string assemblyPath) - { - string fileName = Path.GetFileNameWithoutExtension(assemblyPath); - string assemblyName = ExtractInternalAssemblyName(assemblyPath); - - if (string.IsNullOrEmpty(assemblyName)) - return; - - if (fileName != assemblyName) - { - Debug.LogWarning("Assembly '" + assemblyName + "' has non matching file name: '" + Path.GetFileName(assemblyPath) + "'. This can cause build issues on some platforms."); - } - } - static public string[] GetNamesOfAssembliesLoadedInCurrentDomain() { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); @@ -253,14 +237,11 @@ public static string[] GetDefaultAssemblySearchPaths() // Add the path to all available precompiled assemblies var group = EditorUserBuildSettings.activeBuildTargetGroup; var target = EditorUserBuildSettings.activeBuildTarget; - var precompiledAssemblies = InternalEditorUtility.GetPrecompiledAssemblies(true, group, target); + var precompiledAssemblyPaths = InternalEditorUtility.GetPrecompiledAssemblyPaths(); - HashSet searchPaths = new HashSet(); - - foreach (var asm in precompiledAssemblies) - searchPaths.Add(Path.GetDirectoryName(asm.Path)); + HashSet searchPaths = new HashSet(precompiledAssemblyPaths); - precompiledAssemblies = InternalEditorUtility.GetUnityAssemblies(true, group, target); + var precompiledAssemblies = InternalEditorUtility.GetUnityAssemblies(true, group, target); foreach (var asm in precompiledAssemblies) searchPaths.Add(Path.GetDirectoryName(asm.Path)); diff --git a/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs index 34240c99ce..b3cb72d8c6 100644 --- a/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs @@ -27,14 +27,14 @@ public struct SpriteMetaData [NativeType(CodegenOptions.Custom, "TextureImporterSettings")] [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h")] [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h")] - public sealed partial class TextureImporterSettings + public sealed class TextureImporterSettings { [SerializeField] - int m_AlphaSource; + int m_AlphaSource = (int)TextureImporterAlphaSource.FromInput; [SerializeField] int m_MipMapMode; [SerializeField] - int m_EnableMipMap; + int m_EnableMipMap = 1; [SerializeField] int m_FadeOut; [SerializeField] @@ -59,7 +59,7 @@ public sealed partial class TextureImporterSettings [SerializeField] int m_FlipGreenChannel; [SerializeField] - uint m_Swizzle; + uint m_Swizzle = 0x03020100; [SerializeField] int m_IsReadable; @@ -76,7 +76,7 @@ public sealed partial class TextureImporterSettings [SerializeField] int m_NPOTScale; [SerializeField] - int m_sRGBTexture; + int m_sRGBTexture = 1; [SerializeField] int m_SpriteMode; diff --git a/Editor/Mono/AssetStoreCachePathManager.bindings.cs b/Editor/Mono/AssetStoreCachePathManager.bindings.cs index 8077e2518c..5af3259549 100644 --- a/Editor/Mono/AssetStoreCachePathManager.bindings.cs +++ b/Editor/Mono/AssetStoreCachePathManager.bindings.cs @@ -9,10 +9,12 @@ namespace UnityEditorInternal [NativeHeader("Editor/Src/AssetStore/AssetStoreCachePathManager.h")] internal partial class AssetStoreCachePathManager { + [FreeFunction("AssetStoreCachePathManager::GetDefaultConfig")] + public static extern CachePathConfig GetDefaultConfig(); + [FreeFunction("AssetStoreCachePathManager::GetConfig")] public static extern CachePathConfig GetConfig(); - // Int return the status of setting the config [FreeFunction("AssetStoreCachePathManager::SetConfig")] public static extern ConfigStatus SetConfig(string newPath); diff --git a/Editor/Mono/AssetStoreCachePathManager.cs b/Editor/Mono/AssetStoreCachePathManager.cs index 8868a9ce75..6cf4345d18 100644 --- a/Editor/Mono/AssetStoreCachePathManager.cs +++ b/Editor/Mono/AssetStoreCachePathManager.cs @@ -17,7 +17,7 @@ public enum ConfigStatus { Success = 0, InvalidPath, - WritePermissionError, + ReadOnly, EnvironmentOverride, NotFound, Failed diff --git a/Editor/Mono/BuildPipeline/Android/AndroidPostGenerateGradleProject.cs b/Editor/Mono/BuildPipeline/Android/AndroidPostGenerateGradleProject.cs index cd67b1b6dd..bbf1321fdc 100644 --- a/Editor/Mono/BuildPipeline/Android/AndroidPostGenerateGradleProject.cs +++ b/Editor/Mono/BuildPipeline/Android/AndroidPostGenerateGradleProject.cs @@ -13,43 +13,4 @@ public interface IPostGenerateGradleAndroidProject : IOrderedCallback { void OnPostGenerateGradleAndroidProject(string path); } - - internal static class AndroidBuildPipelineInterfaces - { - private static List buildPostProjectGeneratedProcessors; - - internal static void InitializeBuildCallbacks() - { - buildPostProjectGeneratedProcessors = new List(); - - foreach (var type in TypeCache.GetTypesDerivedFrom()) - { - if (type.IsAbstract || type.IsInterface) - continue; - buildPostProjectGeneratedProcessors.Add(Activator.CreateInstance(type) as IPostGenerateGradleAndroidProject); - } - - buildPostProjectGeneratedProcessors.Sort(BuildPipelineInterfaces.CompareICallbackOrder); - } - - internal static void OnGeneratePlatformProjectPostprocess(string path, bool strict) - { - if (buildPostProjectGeneratedProcessors != null) - { - foreach (var pggapp in buildPostProjectGeneratedProcessors) - { - try - { - pggapp.OnPostGenerateGradleAndroidProject(path); - } - catch (Exception ex) - { - Debug.LogException(ex); - if (strict) - throw; - } - } - } - } - } } diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 4c490fac60..24af76cfc5 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -292,9 +292,10 @@ public static List GetLinkXmlFiles(UnityLinkerRunInformation runInformat if (runInformation.rcr != null) { + var buildFiles = runInformation.BuildReport.GetFiles(); linkXmlFiles.Add(WriteMethodsToPreserveBlackList(runInformation)); - linkXmlFiles.Add(WriteTypesInScenesBlacklist(runInformation)); - linkXmlFiles.Add(WriteSerializedTypesBlacklist(runInformation)); + linkXmlFiles.Add(WriteTypesInScenesBlacklist(runInformation, buildFiles)); + linkXmlFiles.Add(WriteSerializedTypesBlacklist(runInformation, buildFiles)); } linkXmlFiles.AddRange(ProcessBuildPipelineGenerateAdditionalLinkXmlFiles(runInformation)); @@ -323,7 +324,7 @@ static bool BuildFileMatchesAssembly(BuildFile file, string assemblyName) file.role == "ManagedEngineAPI"); } - private static string WriteTypesInScenesBlacklist(UnityLinkerRunInformation runInformation) + private static string WriteTypesInScenesBlacklist(UnityLinkerRunInformation runInformation, BuildFile[] buildFiles) { var items = runInformation.rcr.GetAllManagedTypesInScenes(); @@ -336,7 +337,7 @@ private static string WriteTypesInScenesBlacklist(UnityLinkerRunInformation runI // // Filter anything out where the assembly doesn't exist so that UnityLinker can be strict about preservations in link xml files var filename = assemblyTypePair.Key.ToNPath().FileNameWithoutExtension; - if (runInformation.BuildReport.files.All(file => !BuildFileMatchesAssembly(file, filename))) + if (buildFiles.All(file => !BuildFileMatchesAssembly(file, filename))) continue; sb.AppendLine($"\t"); @@ -353,7 +354,7 @@ private static string WriteTypesInScenesBlacklist(UnityLinkerRunInformation runI return path; } - private static string WriteSerializedTypesBlacklist(UnityLinkerRunInformation runInformation) + private static string WriteSerializedTypesBlacklist(UnityLinkerRunInformation runInformation, BuildFile[] buildFiles) { var items = runInformation.rcr.GetAllSerializedClassesAsString(); var oneOrMoreItemsWritten = false; @@ -362,7 +363,7 @@ private static string WriteSerializedTypesBlacklist(UnityLinkerRunInformation ru foreach (var assemblyTypePair in items.OrderBy(t => t.Key)) { // Filter anything out where the assembly doesn't exist so that UnityLinker can be strict about preservations in link xml files - if (runInformation.BuildReport.files.All(file => !BuildFileMatchesAssembly(file, assemblyTypePair.Key))) + if (buildFiles.All(file => !BuildFileMatchesAssembly(file, assemblyTypePair.Key))) continue; sb.AppendLine($"\t"); diff --git a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs index d8e8e20f61..b76309bf6e 100644 --- a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs +++ b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs @@ -407,6 +407,14 @@ private static bool InvokeCallbackInterfacesPair(List oneInterfaces, invocationTwo(callback); } } + catch (TargetInvocationException e) + { + // Note: Attribute based callbacks are called via reflection. + // Exceptions in those calls are wrapped in TargetInvocationException + Debug.LogException(e.InnerException); + if (exitOnFailure) + return false; + } catch (Exception e) { Debug.LogException(e); diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index e39f9172b4..e834c5bc91 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -729,13 +729,14 @@ private void ConvertPlayerDlltoCpp(Il2CppBuildPipelineData data) if (m_BuildForMonoRuntime) arguments.Add("--mono-runtime"); - if (EditorUserBuildSettings.il2CppCodeGeneration == Il2CppCodeGeneration.OptimizeSize) - arguments.Add("--generics-option=EnableFullSharing"); - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup); arguments.Add(string.Format("--dotnetprofile=\"{0}\"", IL2CPPUtils.ApiCompatibilityLevelToDotNetProfileArgument(apiCompatibilityLevel, m_PlatformProvider.target))); + var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup); + var il2cppCodeGeneration = PlayerSettings.GetIl2CppCodeGeneration(namedBuildTarget); + if (il2cppCodeGeneration == Il2CppCodeGeneration.OptimizeSize) + arguments.Add("--generics-option=EnableFullSharing"); var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder(); if (il2CppNativeCodeBuilder != null) diff --git a/Editor/Mono/BuildPlayerWindow.cs b/Editor/Mono/BuildPlayerWindow.cs index 20b3a852a4..fda2e95fef 100644 --- a/Editor/Mono/BuildPlayerWindow.cs +++ b/Editor/Mono/BuildPlayerWindow.cs @@ -65,7 +65,6 @@ public GUIContent GetDownloadErrorForTarget(BuildTarget target) // string and matching enum values for standalone subtarget dropdowm public GUIContent debugBuild = EditorGUIUtility.TrTextContent("Development Build"); - public GUIContent il2cppCodeGeneration = EditorGUIUtility.TrTextContent("IL2CPP Code Generation", "Determines whether IL2CPP should generate code optimized for runtime performance or build size/iteration."); public GUIContent autoconnectProfiler = EditorGUIUtility.TrTextContent("Autoconnect Profiler", "When the build is started, an open Profiler Window will automatically connect to the Player and start profiling. The \"Build And Run\" option will also automatically open the Profiler Window."); public GUIContent autoconnectProfilerDisabled = EditorGUIUtility.TrTextContent("Autoconnect Profiler", "Profiling is only enabled in a Development Player."); public GUIContent buildWithDeepProfiler = EditorGUIUtility.TrTextContent("Deep Profiling Support", "Build Player with Deep Profiling Support. This might affect Player performance."); @@ -130,12 +129,6 @@ public GUIContent GetDownloadErrorForTarget(BuildTarget target) EditorGUIUtility.TrTextContent("LZ4HC"), }; - public GUIContent[] il2cppCodeGenerationStrings = - { - EditorGUIUtility.TrTextContent("Faster runtime"), - EditorGUIUtility.TrTextContent("Faster (smaller) builds"), - }; - public static GUIStyle boldFoldout; static Styles() @@ -299,7 +292,7 @@ static void DrawOverrideLine() var rect = EditorGUILayout.s_LastRect; var prevMargin = EditorGUIUtility.leftMarginCoord; EditorGUIUtility.leftMarginCoord = 2; - EditorGUI.DrawOverrideBackground(rect); + EditorGUI.DrawOverrideBackgroundApplicable(rect); EditorGUIUtility.leftMarginCoord = prevMargin; } @@ -993,11 +986,6 @@ void ShowBuildTargetSettings() GUI.enabled = true; - if (PlayerSettings.GetScriptingBackend(namedBuildTarget) == ScriptingImplementation.IL2CPP) - { - EditorUserBuildSettings.il2CppCodeGeneration = (Il2CppCodeGeneration)EditorGUILayout.Popup(styles.il2cppCodeGeneration, (int)EditorUserBuildSettings.il2CppCodeGeneration, styles.il2cppCodeGenerationStrings); - } - if (postprocessor != null && postprocessor.SupportsLz4Compression()) { var cmpIdx = Array.IndexOf(styles.compressionTypes, EditorUserBuildSettings.GetCompressionType(namedBuildTarget.ToBuildTargetGroup())); diff --git a/Editor/Mono/BuildPlayerWindowBuildMethods.cs b/Editor/Mono/BuildPlayerWindowBuildMethods.cs index 5797199a87..594dbd4dfe 100644 --- a/Editor/Mono/BuildPlayerWindowBuildMethods.cs +++ b/Editor/Mono/BuildPlayerWindowBuildMethods.cs @@ -435,7 +435,15 @@ internal static bool IsBuildPathValid(string path) var tempPath = NormalizePath(basePath + "/Temp"); var libraryPath = NormalizePath(basePath + "/Library"); var userSettingsPath = NormalizePath(basePath + "/UserSettings"); - if (basePath.Contains(cleanedPath) || cleanedPath == assetsPath || cleanedPath == settingsPath || cleanedPath == tempPath || cleanedPath == libraryPath || cleanedPath == userSettingsPath) + var userDesktopPath = NormalizePath(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); + + if (basePath.Contains(cleanedPath) || + cleanedPath == assetsPath || + cleanedPath == settingsPath || + cleanedPath == tempPath || + cleanedPath == libraryPath || + cleanedPath == userSettingsPath || + cleanedPath == userDesktopPath) { Debug.LogError("Invalid build path: " + cleanedPath); return false; diff --git a/Editor/Mono/Clipboard/ClipboardParser.cs b/Editor/Mono/Clipboard/ClipboardParser.cs index 92ba1223d2..e3c9134e83 100644 --- a/Editor/Mono/Clipboard/ClipboardParser.cs +++ b/Editor/Mono/Clipboard/ClipboardParser.cs @@ -327,6 +327,18 @@ static string CustomPrefix() return typeof(T).FullName + "JSON:"; } + static object GetIntegerValue(in SerializedProperty p) + { + switch (p.type) + { + case "long": + case "ulong": + return p.longValue; + } + + return p.intValue; + } + // Given a serialized property, produce an object structure for JSON encoding of it. internal static Dictionary WriteGenericSerializedProperty(SerializedProperty p) { @@ -340,7 +352,7 @@ internal static Dictionary WriteGenericSerializedProperty(Serial case SerializedPropertyType.Integer: case SerializedPropertyType.LayerMask: case SerializedPropertyType.Character: - res["val"] = p.intValue; break; + res["val"] = GetIntegerValue(p); break; case SerializedPropertyType.Boolean: res["val"] = p.boolValue; break; case SerializedPropertyType.Float: res["val"] = p.floatValue; break; case SerializedPropertyType.String: res["val"] = p.stringValue; break; @@ -415,7 +427,11 @@ internal static void ParseGenericSerializedProperty(SerializedProperty prop, Dic case SerializedPropertyType.Integer: case SerializedPropertyType.LayerMask: case SerializedPropertyType.Character: - prop.intValue = Convert.ToInt32(oval); + if (string.Equals(prop.type, "long", StringComparison.Ordinal) || + string.Equals(prop.type, "ulong", StringComparison.Ordinal)) + prop.longValue = Convert.ToInt64(oval); + else + prop.intValue = Convert.ToInt32(oval); break; case SerializedPropertyType.Boolean: prop.boolValue = Convert.ToBoolean(oval); diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index cc6fc81db2..f533730608 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -433,6 +433,7 @@ void SetActiveEntry(LogEntry entry) if (entry != null) { m_ActiveText = entry.message; + entry.callstackTextStartUTF8 = entry.message.Length; m_CallstackTextStart = entry.callstackTextStartUTF16; // ping object referred by the log entry if (m_ActiveInstanceID != entry.instanceID) diff --git a/Editor/Mono/DragAndDrop.bindings.cs b/Editor/Mono/DragAndDrop.bindings.cs index 454c6ebfba..a4856d0aca 100644 --- a/Editor/Mono/DragAndDrop.bindings.cs +++ b/Editor/Mono/DragAndDrop.bindings.cs @@ -201,6 +201,7 @@ public static void PrepareStartDrag() s_GenericData = null; paths = null; objectReferences = new UnityEngine.Object[] {}; + visualMode = DragAndDropVisualMode.None; PrepareStartDrag_Internal(); } diff --git a/Editor/Mono/EditorApplication.bindings.cs b/Editor/Mono/EditorApplication.bindings.cs index e4dfb4975c..f84c9037ef 100644 --- a/Editor/Mono/EditorApplication.bindings.cs +++ b/Editor/Mono/EditorApplication.bindings.cs @@ -22,6 +22,12 @@ namespace UnityEditor [StaticAccessor("EditorApplicationBindings", StaticAccessorType.DoubleColon)] public sealed partial class EditorApplication { + internal static extern string kLastOpenedScene + { + [NativeMethod("GetLastOpenedScenePref")] + get; + } + // Load the level at /path/ in play mode. [Obsolete("Use EditorSceneManager.LoadSceneInPlayMode instead.")] public static void LoadLevelInPlayMode(string path) @@ -179,13 +185,20 @@ public static extern string applicationPath get; } - // Retuns true if resources are being built + // Returns true if resources are being built internal static extern bool isBuildingAnyResources { [FreeFunction("IsBuildingAnyResources")] get; } + // Returns true if the Package Manager is disabled + internal static extern bool isPackageManagerDisabled + { + [FreeFunction("IsPackageManagerDisabled")] + get; + } + internal static extern string userJavascriptPackagesPath { get; diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs index 653d45e101..9c02817ab5 100644 --- a/Editor/Mono/EditorApplication.cs +++ b/Editor/Mono/EditorApplication.cs @@ -13,6 +13,8 @@ using UnityEditor.Scripting; using UnityEngine.TestTools; using Unity.Profiling; +using UnityEditor.Profiling; +using UnityEditor.SceneManagement; using UnityEditor.VersionControl; using UnityEngine.Profiling; @@ -42,13 +44,12 @@ public enum PauseState internal class ApplicationTitleDescriptor { - public ApplicationTitleDescriptor(string projectName, string unityVersion, string activeSceneName, string licenseType, string targetName, bool codeCoverageEnabled) + public ApplicationTitleDescriptor(string projectName, string unityVersion, string activeSceneName, string targetName, bool codeCoverageEnabled) { title = ""; this.projectName = projectName; this.unityVersion = unityVersion; this.activeSceneName = activeSceneName; - this.licenseType = licenseType; this.targetName = targetName; this.codeCoverageEnabled = codeCoverageEnabled; } @@ -57,7 +58,6 @@ public ApplicationTitleDescriptor(string projectName, string unityVersion, strin public string projectName { get; private set; } public string unityVersion { get; private set; } public string activeSceneName { get; private set; } - public string licenseType { get; private set; } public string targetName { get; private set; } public bool codeCoverageEnabled { get; private set; } } @@ -314,10 +314,6 @@ internal static string GetDefaultMainWindowTitle(ApplicationTitleDescriptor desc } title += $" - Unity {desc.unityVersion}"; - if (!string.IsNullOrEmpty(desc.licenseType)) - { - title += $" {desc.licenseType}"; - } if (desc.codeCoverageEnabled) { @@ -348,7 +344,6 @@ internal static ApplicationTitleDescriptor GetApplicationTitleDescriptor() isTemporaryProject ? PlayerSettings.productName : Path.GetFileName(Path.GetDirectoryName(Application.dataPath)), InternalEditorUtility.GetUnityDisplayVersion(), activeSceneName, - GetLicenseType(), BuildPipeline.GetBuildTargetGroupDisplayName(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget)), Coverage.enabled ); @@ -503,5 +498,50 @@ internal static void TogglePlaying() isPlaying = !isPlaying; InternalEditorUtility.RepaintAllViews(); } + + [RequiredByNativeCode] + static void Internal_RestoreLastOpenedScenes() + { + using (new EditorPerformanceTracker("Application.RestoreLastOpenedScenes")) + { + // Unfortunately kLastOpenedScene would more appropriately be named kLastSpecifiedScene as it refers + // to the last scene file as specified by the user/as chosen using Double-Click on the scene file in + // the file browser. However this editor preference has been around for a while, the name stays. + // + // Try to open the last specified scene first + var lastOpenedScene = EditorPrefs.GetString(kLastOpenedScene); + + // Open requested scene if any + if (!string.IsNullOrEmpty(lastOpenedScene)) + { + if (EditorSceneManager.CanOpenScene()) + EditorSceneManager.OpenScene(lastOpenedScene, OpenSceneMode.Single); + else + InstantiateDefaultScene(); + + // Regardless of the operation outcome, reset last opened scene so that we don't + // force it next time around + EditorPrefs.SetString(kLastOpenedScene, ""); + } + else + { + // Open last opened scenes + if (!EditorSceneManager.LoadLastSceneManagerSetup()) + InstantiateDefaultScene(); + } + } + } + + static void InstantiateDefaultScene() + { + if (CommandService.Exists("Menu/File/InstantiateDefaultScene")) + { + CommandService.Execute("Menu/File/InstantiateDefaultScene"); + } + else + { + EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single); + } + } } } diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 26465fae02..02715ebfb3 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -109,9 +109,9 @@ private enum DragCandidateState internal const float kObjectFieldThumbnailHeight = 64; internal const float kObjectFieldMiniThumbnailHeight = 18f; internal const float kObjectFieldMiniThumbnailWidth = 32f; - internal static string kFloatFieldFormatString = "g7"; - internal static string kDoubleFieldFormatString = "g15"; - internal static string kIntFieldFormatString = "#######0"; + internal static string kFloatFieldFormatString = UINumericFieldsUtils.k_FloatFieldFormatString; + internal static string kDoubleFieldFormatString = UINumericFieldsUtils.k_DoubleFieldFormatString; + internal static string kIntFieldFormatString = UINumericFieldsUtils.k_IntFieldFormatString; internal static int ms_IndentLevel = 0; private const float kIndentPerLevel = 15; internal const int kControlVerticalSpacingLegacy = 2; @@ -163,6 +163,7 @@ private enum DragCandidateState internal static Color k_OverrideMarginColor = new Color(1f / 255f, 153f / 255f, 235f / 255f, 0.75f); internal static Color k_OverrideMarginColorSelected = new Color(239f / 255f, 239f / 255f, 239f / 239f, 1f); + internal static Color k_OverrideMarginColorNotApplicable = new Color(1f / 255f, 153f / 255f, 235f / 255f, 0.35f); private const int kInspTitlebarSpacing = 4; private static readonly GUIContent s_PropertyFieldTempContent = new GUIContent(); @@ -2240,9 +2241,9 @@ internal static long DoLongField(RecycledTextEditor editor, Rect position, Rect // - infinity/nan // - expressions // - expression evaluation functions - internal static readonly string s_AllowedCharactersForFloat = "inftynaeINFTYNAE0123456789.,-*/+%^()cosqrludxvRL=pP#"; + internal static readonly string s_AllowedCharactersForFloat = UINumericFieldsUtils.k_AllowedCharactersForFloat; - internal static readonly string s_AllowedCharactersForInt = "0123456789-*/+%^()cosintaqrtelfundxvRL,=pPI#"; + internal static readonly string s_AllowedCharactersForInt = UINumericFieldsUtils.k_AllowedCharactersForInt; static bool HasKeyboardFocus(int controlID) { @@ -2361,17 +2362,7 @@ internal static bool StringToDouble(string str, out double value) static void StringToDouble(string str, ref NumberFieldValue value) { - value.expression = null; - value.success = true; - string lowered = str.ToLower(); - if (lowered == "inf" || lowered == "infinity") - value.doubleVal = double.PositiveInfinity; - else if (lowered == "-inf" || lowered == "-infinity") - value.doubleVal = double.NegativeInfinity; - else if (lowered == "nan") - value.doubleVal = double.NaN; - else - value.success = ExpressionEvaluator.Evaluate(str, out value.doubleVal, out value.expression); + value.success = UINumericFieldsUtils.StringToDouble(str, out value.doubleVal, out value.expression); } internal static bool StringToLong(string str, out long value) @@ -2385,7 +2376,7 @@ internal static bool StringToLong(string str, out long value) static void StringToLong(string str, ref NumberFieldValue value) { value.expression = null; - value.success = ExpressionEvaluator.Evaluate(str, out value.longVal, out value.expression); + value.success = UINumericFieldsUtils.StringToLong(str, out value.longVal, out value.expression); } internal static int ArraySizeField(Rect position, GUIContent label, int value, GUIStyle style) @@ -2887,14 +2878,14 @@ internal static GenericMenu FillPropertyContextMenu(SerializedProperty property, PrefabUtility.HandleApplyRevertMenuItems( null, targetObject, - (menuItemContent, sourceObject) => + (menuItemContent, sourceObject, _) => { // Add apply menu item for this apply target. TargetChoiceHandler.PropertyAndSourcePathInfo info = new TargetChoiceHandler.PropertyAndSourcePathInfo(); info.properties = properties; info.assetPath = AssetDatabase.GetAssetPath(sourceObject); GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject); - if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || EditorUtility.IsPersistent(targetObject)) + if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || !PrefabUtility.CanPropertyBeAppliedToTarget(property, rootObject)) pm.AddDisabledItem(menuItemContent); else pm.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabPropertyOverride, info); @@ -5009,19 +5000,29 @@ internal static void MultiIntFieldInternal(Rect position, GUIContent[] subLabels } public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, GUIContent label) + { + MultiPropertyField(position, subLabels, valuesIterator, label, PropertyVisibility.OnlyVisible); + } + + public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, GUIContent label, PropertyVisibility visibility) { int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); position = MultiFieldPrefixLabel(position, id, label, subLabels.Length); position.height = kSingleLineHeight; - MultiPropertyField(position, subLabels, valuesIterator); + MultiPropertyField(position, subLabels, valuesIterator, visibility); } public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator) { - MultiPropertyFieldInternal(position, subLabels, valuesIterator, PropertyVisibility.OnlyVisible); + MultiPropertyField(position, subLabels, valuesIterator, PropertyVisibility.OnlyVisible); + } + + public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, PropertyVisibility visibility) + { + MultiPropertyFieldInternal(position, subLabels, valuesIterator, visibility); } - internal enum PropertyVisibility + public enum PropertyVisibility { All, OnlyVisible @@ -5698,7 +5699,7 @@ internal static void DoInspectorTitlebar(Rect position, int id, bool foldout, Ob if (ShouldDrawOverrideBackground(targetObjs, evt, comp)) { isAddedComponentAndEventIsRepaint = true; - DrawOverrideBackground(position, true); + DrawOverrideBackgroundApplicable(position, true); } int enabled = -1; @@ -5883,7 +5884,7 @@ internal static void RemovedComponentTitlebar(Rect position, GameObject instance baseStyle.Draw(position, GUIContent.none, false, false, false, false); if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None) - DrawOverrideBackground(position, true); + DrawOverrideBackgroundApplicable(position, true); EditorStyles.optionsButtonStyle.Draw(settingsRect, GUIContent.none, id, false, settingsRect.Contains(Event.current.mousePosition)); @@ -5910,7 +5911,7 @@ internal static void RemovedComponentTitlebar(Rect position, GameObject instance PrefabUtility.HandleApplyRevertMenuItems( "Removed Component", instanceGo, - (menuItemContent, sourceObject) => + (menuItemContent, sourceObject, _) => { TargetChoiceHandler.ObjectInstanceAndSourceInfo info = new TargetChoiceHandler.ObjectInstanceAndSourceInfo(); info.instanceObject = instanceGo; @@ -6536,7 +6537,7 @@ internal static GUIContent BeginPropertyInternal(Rect totalPosition, GUIContent bool wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont(); var so = property.serializedObject; - if (so.HasAnyInstantiatedPrefabs() && EditorGUIUtility.comparisonViewMode != EditorGUIUtility.ComparisonViewMode.Original) + if (so.HasAnyInstantiatedPrefabsWithValidAsset() && EditorGUIUtility.comparisonViewMode != EditorGUIUtility.ComparisonViewMode.Original) { PropertyGUIData parentData = s_PropertyStack.Count > 0 ? s_PropertyStack.Peek() : new PropertyGUIData(); bool linkedProperties = parentData.totalPosition == totalPosition; @@ -6549,7 +6550,11 @@ internal static GUIContent BeginPropertyInternal(Rect totalPosition, GUIContent { Rect highlightRect = totalPosition; highlightRect.xMin += EditorGUI.indent; - DrawOverrideBackground(highlightRect, false); + + if (!PrefabUtility.CanPropertyBeAppliedToSource(property)) + DrawOverrideBackgroundNonApplicable(highlightRect, false); + else + DrawOverrideBackgroundApplicable(highlightRect, false); } } @@ -6664,7 +6669,7 @@ public static void EndProperty() } } - internal static void DrawOverrideBackground(Rect position, bool fixupRectForHeadersAndBackgrounds = false) + internal static void DrawOverrideBackground(Rect position, Color color, bool fixupRectForHeadersAndBackgrounds = false) { if (fixupRectForHeadersAndBackgrounds) { @@ -6673,7 +6678,17 @@ internal static void DrawOverrideBackground(Rect position, bool fixupRectForHead position.yMax += 1; } - DrawMarginLineForRect(position, k_OverrideMarginColor); + DrawMarginLineForRect(position, color); + } + + internal static void DrawOverrideBackgroundApplicable(Rect position, bool fixupRectForHeadersAndBackgrounds = false) + { + DrawOverrideBackground(position, k_OverrideMarginColor, fixupRectForHeadersAndBackgrounds); + } + + internal static void DrawOverrideBackgroundNonApplicable(Rect position, bool fixupRectForHeadersAndBackgrounds = false) + { + DrawOverrideBackground(position, k_OverrideMarginColorNotApplicable, fixupRectForHeadersAndBackgrounds); } internal static void DrawMarginLineForRect(Rect position, Color color) @@ -8564,7 +8579,8 @@ public static float GetPropertyHeight(SerializedProperty property, [DefaultValue [ExcludeFromDocs] public static bool PropertyField(Rect position, SerializedProperty property) { - return PropertyField(position, property, false); + // Allow reorderable list to include children by default to keep similar behaviour to old arrays + return PropertyField(position, property, PropertyHandler.UseReorderabelListControl(property)); } public static bool PropertyField(Rect position, SerializedProperty property, [DefaultValue("false")] bool includeChildren) @@ -8575,7 +8591,8 @@ public static bool PropertyField(Rect position, SerializedProperty property, [De [ExcludeFromDocs] public static bool PropertyField(Rect position, SerializedProperty property, GUIContent label) { - return PropertyField(position, property, label, false); + // Allow reorderable list to include children by default to keep similar behaviour to old arrays + return PropertyField(position, property, label, PropertyHandler.UseReorderabelListControl(property)); } public static bool PropertyField(Rect position, SerializedProperty property, GUIContent label, [DefaultValue("false")] bool includeChildren) @@ -11021,7 +11038,7 @@ internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent overrideRect.y += margin; overrideRect.height -= margin * 2; EditorGUIUtility.leftMarginCoord = overrideRect.x + margin; - EditorGUI.DrawOverrideBackground(overrideRect); + EditorGUI.DrawOverrideBackgroundApplicable(overrideRect); EditorGUIUtility.leftMarginCoord = prevMargin; } } diff --git a/Editor/Mono/EditorHandles/FreeMove.cs b/Editor/Mono/EditorHandles/FreeMove.cs index 2427f1c3c0..2aff41d253 100644 --- a/Editor/Mono/EditorHandles/FreeMove.cs +++ b/Editor/Mono/EditorHandles/FreeMove.cs @@ -14,7 +14,13 @@ internal class FreeMove private static Vector2 s_StartMousePosition, s_CurrentMousePosition, s_CurrentMousePositionScreen; private static Vector3 s_StartPosition; + [Obsolete("Rotation parameter is obsolete.")] public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float size, Vector3 snap, Handles.CapFunction handleFunction) + { + return Do(id, position, size, snap, handleFunction); + } + + public static Vector3 Do(int id, Vector3 position, float size, Vector3 snap, Handles.CapFunction handleFunction) { Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); Matrix4x4 origMatrix = Handles.matrix; diff --git a/Editor/Mono/EditorHandles/PositionHandle.cs b/Editor/Mono/EditorHandles/PositionHandle.cs index e92f3f5d64..34268079b7 100644 --- a/Editor/Mono/EditorHandles/PositionHandle.cs +++ b/Editor/Mono/EditorHandles/PositionHandle.cs @@ -334,7 +334,7 @@ static Vector3 DoPositionHandle_Internal(PositionHandleIds ids, Vector3 position { color = ToActiveColorSpace(centerColor); GUI.SetNextControlName("FreeMoveAxis"); - position = FreeMoveHandle(ids.xyz, position, rotation, size * kFreeMoveHandleSizeFactor, GridSnapping.active ? Vector3.zero : EditorSnapSettings.move, RectangleHandleCap); + position = FreeMoveHandle(ids.xyz, position, size * kFreeMoveHandleSizeFactor, GridSnapping.active ? Vector3.zero : EditorSnapSettings.move, RectangleHandleCap); } if (GridSnapping.active) diff --git a/Editor/Mono/EditorSceneManager.bindings.cs b/Editor/Mono/EditorSceneManager.bindings.cs index 8e2685ba4d..e13a85b2de 100644 --- a/Editor/Mono/EditorSceneManager.bindings.cs +++ b/Editor/Mono/EditorSceneManager.bindings.cs @@ -76,6 +76,9 @@ public extern static SceneAsset playModeStartScene set; } + [FreeFunction("GetSceneTracker().CanOpenScene")] + internal static extern bool CanOpenScene(); + [NativeThrows] [StaticAccessor("EditorSceneManagerBindings", StaticAccessorType.DoubleColon)] [NativeMethod("OpenScene")] @@ -110,12 +113,12 @@ public static Scene NewPreviewScene() private extern static bool CreateSceneAssetInternal(string scenePath, bool createDefaultGameObjects); [StaticAccessor("EditorSceneManagerBindings", StaticAccessorType.DoubleColon)] - [NativeMethod("RemapAssetReferencesInternal")] - private extern static void RemapAssetReferencesInternal(UnityEngine.SceneManagement.Scene scene, string[] srcPaths, string[] dstPaths, int[] srcIds, int[] dstIds); + [NativeMethod("RemapAssetReferencesInSceneInternal")] + private extern static void RemapAssetReferencesInSceneInternal(UnityEngine.SceneManagement.Scene scene, string[] srcPaths, string[] dstPaths, int[] srcIds, int[] dstIds); internal static void RemapAssetReferencesInScene(UnityEngine.SceneManagement.Scene scene, Dictionary pathMap, Dictionary idMap = null) { - RemapAssetReferencesInternal(scene, + RemapAssetReferencesInSceneInternal(scene, pathMap.Keys.ToArray(), pathMap.Values.ToArray(), idMap == null ? new int[0] : idMap.Keys.ToArray(), idMap == null ? new int[0] : idMap.Values.ToArray() @@ -246,6 +249,9 @@ internal static void RemapAssetReferencesInScene(UnityEngine.SceneManagement.Sce [NativeMethod("LoadSceneManagerSetup")] internal extern static bool LoadSceneManagerSetup(string path); + [StaticAccessor("EditorSceneManagerBindings", StaticAccessorType.DoubleColon)] + internal static extern bool LoadLastSceneManagerSetup(); + [StaticAccessor("EditorSceneManagerBindings", StaticAccessorType.DoubleColon)] [NativeMethod("DetectCrossSceneReferences")] public extern static bool DetectCrossSceneReferences(Scene scene); diff --git a/Editor/Mono/EditorSettings.bindings.cs b/Editor/Mono/EditorSettings.bindings.cs index 9e2641c826..5689447634 100644 --- a/Editor/Mono/EditorSettings.bindings.cs +++ b/Editor/Mono/EditorSettings.bindings.cs @@ -55,12 +55,21 @@ public enum CacheServerMode Disabled = 2 } + public enum CacheServerValidationMode + { + Disabled = 0, + UploadOnly = 1, + Enabled = 2, + Required = 3 + } + [Flags] public enum EnterPlayModeOptions { - None = 0, + None = 0, DisableDomainReload = 1 << 0, - DisableSceneReload = 1 << 1 + DisableSceneReload = 1 << 1, + DisableSceneBackupUnlessDirty = 1 << 2 } [NativeHeader("Editor/Src/EditorSettings.h")] @@ -280,6 +289,9 @@ public static bool enableCookiesInLightmapper [StaticAccessor("GetEditorSettings()", StaticAccessorType.Dot)] public static extern bool cacheServerEnableTls { get; set; } + [StaticAccessor("GetEditorSettings()", StaticAccessorType.Dot)] + public static extern CacheServerValidationMode cacheServerValidationMode { get; set; } + public enum NamingScheme { SpaceParenthesis = 0, diff --git a/Editor/Mono/EditorUIService.cs b/Editor/Mono/EditorUIService.cs index 4861b37507..20ac27451b 100644 --- a/Editor/Mono/EditorUIService.cs +++ b/Editor/Mono/EditorUIService.cs @@ -61,5 +61,7 @@ internal interface IEditorUIService internal static class EditorUIService { public static IEditorUIService instance { get; set; } + + public static bool disableInspectorElementThrottling { get; set; } = false; } } diff --git a/Editor/Mono/EditorUserBuildSettings.bindings.cs b/Editor/Mono/EditorUserBuildSettings.bindings.cs index 8337b34f60..b52dd43bd7 100644 --- a/Editor/Mono/EditorUserBuildSettings.bindings.cs +++ b/Editor/Mono/EditorUserBuildSettings.bindings.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using Object = UnityEngine.Object; +using Debug = UnityEngine.Debug; using UnityEngine.Bindings; using System; using System.ComponentModel; @@ -682,7 +683,12 @@ public static string GetPlatformSettings(string platformName, string name) // Enables a development build. public static extern bool development { get; set; } - public static extern Build.Il2CppCodeGeneration il2CppCodeGeneration { get; set; } + [Obsolete("Use PlayerSettings.SetIl2CppCodeGeneration and PlayerSettings.GetIl2CppCodeGeneration instead.", true)] + public static Build.Il2CppCodeGeneration il2CppCodeGeneratione + { + get { return Build.Il2CppCodeGeneration.OptimizeSpeed; } + set { Debug.LogWarning("EditorUserBuildSettings.il2CppCodeGeneratione is obsolete. Please use PlayerSettings.SetIl2CppCodeGeneration and PlayerSettings.GetIl2CppCodeGeneration instead." ); } + } [Obsolete("Building with pre-built Engine option is no longer supported.", true)] public static bool webGLUsePreBuiltUnityEngine diff --git a/Editor/Mono/EditorUtility.cs b/Editor/Mono/EditorUtility.cs index 6228551d12..00b7f51972 100644 --- a/Editor/Mono/EditorUtility.cs +++ b/Editor/Mono/EditorUtility.cs @@ -375,10 +375,10 @@ public static Object CreateEmptyPrefab(string path) return PrefabUtility.CreateEmptyPrefab(path); } - [Obsolete("Use PrefabUtility.RevertPrefabInstance.", false)] + [Obsolete("This method does nothing. Use PrefabUtility.RevertPrefabInstance.", false)] public static bool ReconnectToLastPrefab(GameObject go) { - return PrefabUtility.ReconnectToLastPrefab(go); + return false; } [Obsolete("Use PrefabUtility.GetPrefabAssetType and PrefabUtility.GetPrefabInstanceStatus to get the full picture about Prefab types.", false)] @@ -492,7 +492,7 @@ internal static void DisplayObjectContextMenu(Rect position, Object[] context, i Component targetComponent = (Component)targetObject; // Do nothing if component is not on a prefab instance. - if (PrefabUtility.GetCorrespondingConnectedObjectFromSource(targetComponent.gameObject) == null) {} + if (PrefabUtility.GetCorrespondingConnectedObjectFromSource(targetComponent.gameObject) == null) { } // Handle added component. else if (PrefabUtility.GetCorrespondingObjectFromSource(targetObject) == null && targetComponent != null) { @@ -500,7 +500,7 @@ internal static void DisplayObjectContextMenu(Rect position, Object[] context, i PrefabUtility.HandleApplyRevertMenuItems( "Added Component", instanceGo, - (menuItemContent, sourceGo) => + (menuItemContent, sourceGo, _) => { TargetChoiceHandler.ObjectInstanceAndSourcePathInfo info = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo(); info.instanceObject = targetComponent; @@ -559,13 +559,15 @@ internal static void DisplayObjectContextMenu(Rect position, Object[] context, i PrefabUtility.HandleApplyRevertMenuItems( "Modified Component", targetObject, - (menuItemContent, sourceObject) => + (menuItemContent, sourceObject, instanceOrAssetObject) => { TargetChoiceHandler.ObjectInstanceAndSourcePathInfo info = new TargetChoiceHandler.ObjectInstanceAndSourcePathInfo(); info.instanceObject = targetObject; info.assetPath = AssetDatabase.GetAssetPath(sourceObject); GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject); - if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || EditorUtility.IsPersistent(targetObject)) + bool isPersistent = EditorUtility.IsPersistent(instanceOrAssetObject); + + if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || (!isPersistent && !PrefabUtility.HasApplicableObjectOverridesForTarget(instanceOrAssetObject, rootObject, false))) pm.AddDisabledItem(menuItemContent); else pm.AddItem(menuItemContent, false, TargetChoiceHandler.ApplyPrefabObjectOverride, info); diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 73032844ad..9ba3e9b413 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -37,7 +37,6 @@ public partial class EditorWindow : ScriptableObject // We use a 24-bit depth/stencil buffer by default to support the UIRenderer clipping feature [HideInInspector] int m_DepthBufferBits = 24; - [HideInInspector] int m_AntiAliasing = 1; diff --git a/Editor/Mono/GUI/AboutWindow.cs b/Editor/Mono/GUI/AboutWindow.cs index eea27e5f77..bc18751184 100644 --- a/Editor/Mono/GUI/AboutWindow.cs +++ b/Editor/Mono/GUI/AboutWindow.cs @@ -111,33 +111,27 @@ public void OnGUI() { ListenForSecretCodes(); - var licenseTypeString = ""; - if (InternalEditorUtility.HasFreeLicense()) - licenseTypeString = " Personal"; - if (InternalEditorUtility.HasEduLicense()) - licenseTypeString = " Edu"; string extensionVersion = FormatExtensionVersionString(); - m_ShowDetailedVersion |= evt.alt; + m_ShowDetailedVersion |= evt.alt; if (m_ShowDetailedVersion) { int t = InternalEditorUtility.GetUnityVersionDate(); DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0); string branch = InternalEditorUtility.GetUnityBuildBranch(); EditorGUILayout.SelectableLabel( - string.Format("{0}{1}{2}\nRevision: {3} {4}\nBuilt: {5:r}", - InternalEditorUtility.GetUnityDisplayVersionVerbose(), licenseTypeString, extensionVersion, + string.Format("{0}{1}\nRevision: {2} {3}\nBuilt: {4:r}", + InternalEditorUtility.GetUnityDisplayVersionVerbose(), extensionVersion, branch, InternalEditorUtility.GetUnityBuildHash(), dt.AddSeconds(t)), Styles.versionStyle, GUILayout.MaxWidth(mainLayoutWidth), GUILayout.Height(38f)); } else { - GUILayout.Label(string.Format("{0}{1}{2}", InternalEditorUtility.GetUnityDisplayVersion(), licenseTypeString, extensionVersion), Styles.versionStyle); + GUILayout.Label(string.Format("{0}{1}", InternalEditorUtility.GetUnityDisplayVersion(), extensionVersion), Styles.versionStyle); } if (evt.type == EventType.ValidateCommand) return; - } using (new GUILayout.HorizontalScope(Styles.creditsLayout)) diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs index 30835f93c8..4d5e450d43 100644 --- a/Editor/Mono/GUI/DockArea.cs +++ b/Editor/Mono/GUI/DockArea.cs @@ -797,6 +797,7 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle, G float xPos = 0f; switch (evt.GetTypeForControl(id)) { + case EventType.TouchDown: case EventType.MouseDown: // Handle double click if (EditorWindow.focusedWindow != null) @@ -836,7 +837,12 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle, G PopupGenericMenu(null, menuPos); } break; + case EventType.TouchMove: case EventType.MouseDrag: + + if (evt.pointerType == PointerType.Pen && !evt.penStatus.HasFlag(PenStatus.Contact)) + break; + if (GUIUtility.hotControl == id) { Vector2 delta = evt.mousePosition - s_StartDragPosition; @@ -936,6 +942,7 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle, G } } break; + case EventType.TouchUp: case EventType.MouseUp: if (GUIUtility.hotControl == id) { diff --git a/Editor/Mono/GUI/EditorCache.cs b/Editor/Mono/GUI/EditorCache.cs index e5c09fbd65..27548f8d8b 100644 --- a/Editor/Mono/GUI/EditorCache.cs +++ b/Editor/Mono/GUI/EditorCache.cs @@ -49,21 +49,27 @@ static public EditorWrapper Make(Object obj, EditorFeatures requirements) private bool Init(Object obj, EditorFeatures requirements) { - MethodInfo onSceneDragMi; - editor = Editor.CreateEditor(obj); if (editor == null) return false; - if ((int)(requirements & EditorFeatures.PreviewGUI) > 0 && !editor.HasPreviewGUI()) + if (requirements.HasFlag(EditorFeatures.PreviewGUI) && !editor.HasPreviewGUI()) return false; - System.Type t = editor.GetType(); + var onSceneDragMi = editor.GetType().GetMethod("OnSceneDrag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + var objs = new[] { obj }; + var rootEditorType = RootEditorUtils.FindRootEditor(objs); + if (rootEditorType != null && onSceneDragMi == null) + { + // Create normal editor: + editor = RootEditorUtils.CreateNonRootEditor(objs); + onSceneDragMi = editor.GetType().GetMethod("OnSceneDrag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + } - onSceneDragMi = t.GetMethod("OnSceneDrag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (onSceneDragMi != null) OnSceneDrag = (VoidDelegate)System.Delegate.CreateDelegate(typeof(VoidDelegate), editor, onSceneDragMi); - else if ((int)(requirements & EditorFeatures.OnSceneDrag) > 0) + else if (requirements.HasFlag(EditorFeatures.OnSceneDrag)) return false; else OnSceneDrag = DefaultOnSceneDrag; diff --git a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs b/Editor/Mono/GUI/PopupWindowWithoutFocus.cs index dfa5062a1b..5d129e8426 100644 --- a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs +++ b/Editor/Mono/GUI/PopupWindowWithoutFocus.cs @@ -63,8 +63,8 @@ protected override void OnEnable() protected override void OnDisable() { - base.OnDisable(); s_PopupWindowWithoutFocus = null; + base.OnDisable(); } // Invoked from C++ diff --git a/Editor/Mono/GUI/SearchField.cs b/Editor/Mono/GUI/SearchField.cs index 4ccef32253..7367438158 100644 --- a/Editor/Mono/GUI/SearchField.cs +++ b/Editor/Mono/GUI/SearchField.cs @@ -2,7 +2,6 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System.Runtime.Remoting.Messaging; using UnityEngine; namespace UnityEditor.IMGUI.Controls diff --git a/Editor/Mono/GUI/Toolbars/Core/EditorToolbar.cs b/Editor/Mono/GUI/Toolbars/Core/EditorToolbar.cs index 34571ec791..88b56addcc 100644 --- a/Editor/Mono/GUI/Toolbars/Core/EditorToolbar.cs +++ b/Editor/Mono/GUI/Toolbars/Core/EditorToolbar.cs @@ -4,167 +4,80 @@ using System; using System.Collections.Generic; +using System.Linq; using UnityEditor.Overlays; -using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace UnityEditor.Toolbars { - struct ToolbarElementDefinition - { - public string id { get; } - public Type elementType { get; } - public Type[] targetContexts { get; } - - public ToolbarElementDefinition(string id, Type elementType, Type[] targetContexts) - { - this.id = id; - this.elementType = elementType; - this.targetContexts = targetContexts; - } - } - sealed class EditorToolbar { - struct ToolbarElement - { - public string id { get; } - public VisualElement visual { get; } - - public ToolbarElement(string id, VisualElement visual) - { - this.id = id; - this.visual = visual; - } - } - public const string elementClassName = "unity-editor-toolbar-element"; public const string elementIconClassName = elementClassName + "__icon"; public const string elementLabelClassName = elementClassName + "__label"; - List m_AddedElementIds = new List(); - - readonly List m_LoadedElements = new List(); + string[] m_ToolbarElements; readonly EditorWindow m_Context; - VisualElement m_Root; - - public VisualElement root => m_Root; + VisualElement m_RootVisualElement; - public EditorToolbar(EditorWindow context, VisualElement root, params string[] idAddedByDefault) + public VisualElement rootVisualElement { - m_Context = context; - m_Root = root; - - foreach (var toAdd in idAddedByDefault) - { - AddElement(toAdd, false); - } - - //Load saved toolbar elements if it should be included - for (var i = 0; i < m_AddedElementIds.Count; ++i) + get { - var id = m_AddedElementIds[i]; - if (!LoadElement(id)) - m_AddedElementIds[i] = null; + if (m_RootVisualElement != null) + return m_RootVisualElement; + return m_RootVisualElement = CreateOverlay(m_ToolbarElements, m_Context); } - - //Clear all ids that failed to load - m_AddedElementIds.RemoveAll((id) => id == null); - - EditorToolbarUtility.LoadStyleSheets("EditorToolbar", root); } - public void AddElement(string id) + public EditorToolbar(IEnumerable toolbarElementIds, EditorWindow context = null) { - AddElement(id, true); + m_Context = context; + m_ToolbarElements = toolbarElementIds.ToArray(); } - public void AddElement(string id, VisualElement ve) + public static OverlayToolbar CreateOverlay(IEnumerable toolbarElementIds, EditorWindow context = null) { - if (ContainsElement(id)) - return; - - m_AddedElementIds.Add(id); + var root = new OverlayToolbar(); - ve.AddToClassList(elementClassName); - var element = new ToolbarElement(id, ve); - root.Add(ve); - m_LoadedElements.Add(element); - - if (ve is IAccessContainerWindow visualWithContext) - visualWithContext.containerWindow = m_Context; - } - - void AddElement(string id, bool load) - { - if (!EditorToolbarManager.instance.Exists(id)) + foreach (var id in toolbarElementIds) { - Debug.LogError($"Trying to add the id '{id}' to the toolbar {GetType().FullName}. " + - "No element with that Id was registered using the EditorToolbarElement attribute."); - return; + if (TryCreateElement(id, context, out var ve)) + root.Add(ve); } - if (ContainsElement(id)) - return; - - m_AddedElementIds.Add(id); - - if (load) - LoadElement(id); + return root; } - public bool RemoveElement(string id) + // Used by MainToolbar, as it doesn't use the same Overlay styling + internal void LoadToolbarElements(VisualElement root) { - if (GetElementFromId(id, out ToolbarElement element, out int index)) - { - root.Remove(element.visual); - m_LoadedElements.RemoveAt(index); - - return true; - } + if (root == null) + throw new ArgumentNullException(nameof(root)); - return false; - } - - public bool ContainsElement(string id) - { - return m_AddedElementIds.Contains(id); - } + EditorToolbarUtility.LoadStyleSheets("EditorToolbar", root); - bool LoadElement(string id) - { - if (EditorToolbarManager.instance.TryCreateElementFromId(m_Context, id, out VisualElement visual)) + foreach (var id in m_ToolbarElements) { - var element = new ToolbarElement(id, visual); - root.Add(visual); - m_LoadedElements.Add(element); - - if (visual is IAccessContainerWindow visualWithContext) - { - visualWithContext.containerWindow = m_Context; - } - return true; + if(TryCreateElement(id, m_Context, out var ve)) + root.Add(ve); } - - return false; } - bool GetElementFromId(string id, out ToolbarElement element, out int index) + static bool TryCreateElement(string id, EditorWindow ctx, out VisualElement ve) { - for (var i = 0; i < m_LoadedElements.Count; ++i) + if (EditorToolbarManager.instance.TryCreateElementFromId(ctx, id, out ve)) { - var ele = m_LoadedElements[i]; - if (ele.id == id) - { - element = ele; - index = i; - return true; - } + if (ve is IAccessContainerWindow visualWithContext) + visualWithContext.containerWindow = ctx; + ve.AddToClassList(elementClassName); + return true; } - element = default(ToolbarElement); - index = -1; + Debug.LogError($"Failed to load EditorToolbar ID '{id}' for window '{ctx}'. " + + "No element with that ID and target toolbar was registered using the EditorToolbarElement attribute."); + return false; } } diff --git a/Editor/Mono/GUI/Toolbars/Core/EditorToolbarManager.cs b/Editor/Mono/GUI/Toolbars/Core/EditorToolbarManager.cs index 5917de52a3..7cad17ee73 100644 --- a/Editor/Mono/GUI/Toolbars/Core/EditorToolbarManager.cs +++ b/Editor/Mono/GUI/Toolbars/Core/EditorToolbarManager.cs @@ -11,6 +11,20 @@ namespace UnityEditor.Toolbars { + readonly struct ToolbarElementDefinition + { + public string id { get; } + public Type elementType { get; } + public Type[] targetContexts { get; } + + public ToolbarElementDefinition(string id, Type elementType, Type[] targetContexts) + { + this.id = id; + this.elementType = elementType; + this.targetContexts = targetContexts; + } + } + sealed class EditorToolbarManager : ScriptableSingleton { readonly Dictionary m_IdToDefinition; diff --git a/Editor/Mono/GUI/Toolbars/Core/EditorToolbarUtility.cs b/Editor/Mono/GUI/Toolbars/Core/EditorToolbarUtility.cs index 0567854446..1295421de2 100644 --- a/Editor/Mono/GUI/Toolbars/Core/EditorToolbarUtility.cs +++ b/Editor/Mono/GUI/Toolbars/Core/EditorToolbarUtility.cs @@ -18,7 +18,6 @@ public static class EditorToolbarUtility internal const string middleStripElementClassName = stripElementClassName + "--middle"; internal const string rightStripElementClassName = stripElementClassName + "--right"; internal const string aloneStripElementClassName = stripElementClassName + "--alone"; - static bool IsRendered(VisualElement element) => element.style.display != DisplayStyle.None && element.visible; public static void SetupChildrenAsButtonStrip(VisualElement root) @@ -28,7 +27,6 @@ public static void SetupChildrenAsButtonStrip(VisualElement root) child.AddToClassList(stripElementClassName); ApplyButtonStripStylesToChildren(root); } - internal static void ApplyButtonStripStylesToChildren(VisualElement root) { int count = root.hierarchy.childCount; @@ -57,7 +55,6 @@ internal static void ApplyButtonStripStylesToChildren(VisualElement root) element.EnableInClassList(middleStripElementClassName, i != begin && i != end); } } - internal static void LoadStyleSheets(string name, VisualElement target) { var path = k_StyleSheetsPath + name; diff --git a/Editor/Mono/GUI/Tools/BuiltinTools.cs b/Editor/Mono/GUI/Tools/BuiltinTools.cs index 1f17f33e24..45c3e1c291 100644 --- a/Editor/Mono/GUI/Tools/BuiltinTools.cs +++ b/Editor/Mono/GUI/Tools/BuiltinTools.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using UnityEngine; using UnityEditor.EditorTools; using UnityEditor.SceneManagement; @@ -14,23 +15,23 @@ namespace UnityEditor { // This serves as the default tool setting implementation. [CustomEditor(typeof(EditorTool), true)] - class ManipulationToolCustomEditor : Editor, ICreateHorizontalToolbar, ICreateVerticalToolbar + class ManipulationToolCustomEditor : Editor, IAccessContainerWindow, ICreateToolbar { - VisualElement m_RootVisualElement; - EditorToolbar m_Toolbar; - - public VisualElement CreateHorizontalToolbarContent() => CreateInspectorGUI(); + public IEnumerable toolbarElements + { + get + { + // UIServiceEditor/EditorToolbar/ToolbarElements/BuiltinToolSettings.cs + yield return "Tool Settings/Pivot Mode"; + yield return "Tool Settings/Pivot Rotation"; + } + } - public VisualElement CreateVerticalToolbarContent() => CreateInspectorGUI(); + public EditorWindow containerWindow { get; set; } public override VisualElement CreateInspectorGUI() { - m_Toolbar = OverlayUtilities.CreateToolbar( - m_RootVisualElement = new VisualElement() { name = "toolbar-overlay" }, - null, - "Tool Settings/Pivot Mode", - "Tool Settings/Pivot Rotation"); - return m_RootVisualElement; + return new EditorToolbar(toolbarElements, containerWindow).rootVisualElement; } } diff --git a/Editor/Mono/GUI/Tools/EditorToolCache.cs b/Editor/Mono/GUI/Tools/EditorToolCache.cs index 060fd44bb5..f93de7524b 100644 --- a/Editor/Mono/GUI/Tools/EditorToolCache.cs +++ b/Editor/Mono/GUI/Tools/EditorToolCache.cs @@ -52,6 +52,14 @@ public void OnAfterDeserialize() [Serializable] class ComponentEditor { + internal enum EditorToolScope + { + NotInitialized, + ToolContext, + ComponentTool, + ManipulationToolOverride + }; + [SerializeField] bool m_LockedInspector; @@ -64,11 +72,13 @@ class ComponentEditor EditorTypeAssociation m_EditorTypeAssociation; public readonly ActiveEditorTracker tracker; public List additionalEditors; + public EditorToolScope m_EditorToolScope; public Editor inspector => m_Inspector; public Type editorType => m_EditorTypeAssociation.editor; public EditorTypeAssociation typeAssociation => m_EditorTypeAssociation; public bool lockedInspector => m_LockedInspector; + public EditorToolScope editorToolScope => m_EditorToolScope; public UnityObject editor => m_Editor; @@ -88,6 +98,7 @@ public ComponentEditor(EditorTypeAssociation typeAssociation, ActiveEditorTracke m_Inspector = inspector; m_LockedInspector = tracker.isLocked; m_EditorTypeAssociation = typeAssociation; + m_EditorToolScope = EditorToolScope.NotInitialized; } public UnityObject target => inspector != null ? inspector.target : null; @@ -125,6 +136,14 @@ public UnityObject InstantiateEditor() m_Editor.hideFlags = HideFlags.DontSave; + if(m_Editor is EditorToolContext) + m_EditorToolScope = EditorToolScope.ToolContext; + else if(m_Editor is EditorTool tool && + EditorToolUtility.GetEnumWithEditorTool(tool, EditorToolManager.activeToolContext) != Tool.Custom) + m_EditorToolScope = EditorToolScope.ManipulationToolOverride; + else + m_EditorToolScope = EditorToolScope.ComponentTool; + return m_Editor; } } @@ -228,6 +247,7 @@ internal IEnumerable GetEditorsForTargetType(Type target) void CollectEditorsForTracker(EditorToolContext ctx, ActiveEditorTracker tracker, List editors) { + var trackerEditors = tracker.activeEditors; for (int i = 0, c = trackerEditors.Length; i < c; i++) diff --git a/Editor/Mono/GUI/Tools/EditorToolContext.cs b/Editor/Mono/GUI/Tools/EditorToolContext.cs index 038fa6f665..ac0fd57160 100644 --- a/Editor/Mono/GUI/Tools/EditorToolContext.cs +++ b/Editor/Mono/GUI/Tools/EditorToolContext.cs @@ -3,12 +3,32 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Linq; using System.Collections.Generic; +using UnityEditor.Overlays; +using UnityEditor.Toolbars; using UnityEngine; +using UnityEngine.UIElements; using UnityObject = UnityEngine.Object; namespace UnityEditor.EditorTools { + // This serves as the default tool setting implementation. + [CustomEditor(typeof(EditorToolContext), true)] + class GameObjectToolContextCustomEditor : Editor, ICreateToolbar + { + string[] k_ToolbarIds = new string [0]; + + public IEnumerable toolbarElements => k_ToolbarIds; + + public EditorWindow containerWindow { get; set; } + + public override VisualElement CreateInspectorGUI() + { + return new EditorToolbar(toolbarElements, containerWindow).rootVisualElement; + } + } + public abstract class EditorToolContext : ScriptableObject, IEditor { [HideInInspector] @@ -80,5 +100,7 @@ protected virtual Type GetEditorToolType(Tool tool) "View, Custom, and None are not applicable."); } } + + public virtual IEnumerable GetAdditionalToolTypes() => Enumerable.Empty(); } } diff --git a/Editor/Mono/GUI/Tools/EditorToolManager.cs b/Editor/Mono/GUI/Tools/EditorToolManager.cs index 78aee03ecd..3e47adb2a6 100644 --- a/Editor/Mono/GUI/Tools/EditorToolManager.cs +++ b/Editor/Mono/GUI/Tools/EditorToolManager.cs @@ -45,6 +45,8 @@ sealed class EditorToolManager : ScriptableSingleton internal static int availableComponentContextCount => instance.m_ComponentContexts.Count; + internal static IEnumerable additionalContextToolTypesCache = Enumerable.Empty(); + [SerializeField] EditorToolContext m_ActiveToolContext; @@ -271,11 +273,15 @@ void OnEnable() ActiveEditorTracker.editorTrackerRebuilt += TrackerRebuilt; Selection.selectedObjectWasDestroyed += SelectedObjectWasDestroyed; AssemblyReloadEvents.beforeAssemblyReload += BeforeAssemblyReload; + ToolManager.activeContextChanged += ActiveContextChanged; if (activeTool != null) EditorApplication.delayCall += activeTool.OnActivated; - if (activeToolContext != null) + if(activeToolContext != null) + { EditorApplication.delayCall += activeToolContext.OnActivated; + ActiveContextChanged(); + } } void OnDisable() @@ -284,6 +290,7 @@ void OnDisable() ActiveEditorTracker.editorTrackerRebuilt -= TrackerRebuilt; Selection.selectedObjectWasDestroyed -= SelectedObjectWasDestroyed; AssemblyReloadEvents.beforeAssemblyReload -= BeforeAssemblyReload; + ToolManager.activeContextChanged -= ActiveContextChanged; } void BeforeAssemblyReload() @@ -295,6 +302,11 @@ void BeforeAssemblyReload() m_ActiveToolContext.OnWillBeDeactivated(); } + void ActiveContextChanged() + { + additionalContextToolTypesCache = activeToolContext.GetAdditionalToolTypes(); + } + // used by tests internal static void ForceTrackerRebuild() { @@ -466,6 +478,23 @@ internal static void OnToolGUI(EditorWindow window) { current.OnToolGUI(window); } + + var evt = Event.current; + if(evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Escape) + { + if(!Tools.viewToolActive + && !EditorToolUtility.IsManipulationTool(EditorToolUtility.GetEnumWithEditorTool(current, instance.m_ActiveToolContext)) + && additionalContextToolTypesCache.All(toolType => toolType != current.GetType())) + { + RestorePreviousPersistentTool(); + evt.Use(); + } + else + { + //if is in a Manipulation or additional tool leaves the current context to return to GameObject Context + ToolManager.SetActiveContext(); + } + } } static bool IsCustomEditorTool(EditorTool tool) @@ -577,8 +606,8 @@ internal static EditorTool GetComponentTool(Func predicat if (!searchLockedInspectors && customEditorTool.lockedInspector) continue; - if (predicate(customEditorTool)) - return customEditorTool.GetEditor(); + if (predicate(customEditorTool) && customEditorTool.editor is EditorTool tool && tool.IsAvailable()) + return tool; } return null; @@ -589,7 +618,13 @@ internal static EditorTool GetComponentTool(Func predicat // case you can use `GetComponentTools(x => x.inspector == editor)`. public static void GetComponentToolsForSharedTracker(List list) { - GetComponentTools(x => x.typeAssociation.targetContext == null, list, false); + var ctx = activeToolContext.GetType(); + + GetComponentTools(x => + { + var target_ctx = x.typeAssociation.targetContext; + return (target_ctx == null || target_ctx == ctx) && x.editorToolScope == ComponentEditor.EditorToolScope.ComponentTool; + }, list, false); } // Used by tests. @@ -610,8 +645,8 @@ internal static void GetComponentTools(Func predicate, if (!searchLockedInspectors && customEditorTool.lockedInspector) continue; - if (predicate(customEditorTool)) - list.Add(customEditorTool.GetEditor()); + if (predicate(customEditorTool) && customEditorTool.editor is EditorTool tool && tool.IsAvailable()) + list.Add(tool); } } diff --git a/Editor/Mono/GUI/Tools/EditorToolSettingsOverlay.cs b/Editor/Mono/GUI/Tools/EditorToolSettingsOverlay.cs index 9a02d9c293..784c4bd3bf 100644 --- a/Editor/Mono/GUI/Tools/EditorToolSettingsOverlay.cs +++ b/Editor/Mono/GUI/Tools/EditorToolSettingsOverlay.cs @@ -2,7 +2,11 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; +using System.Collections.Generic; +using System.Reflection; using UnityEditor.Overlays; +using UnityEditor.Toolbars; using UnityEngine; using UnityEngine.UIElements; using UnityObject = UnityEngine.Object; @@ -11,31 +15,27 @@ namespace UnityEditor.EditorTools { [Overlay(typeof(SceneView), "Tool Settings", true)] [Icon("Icons/Overlays/ToolSettings.png")] - sealed class EditorToolSettingsOverlay : Overlay, ICreateHorizontalToolbar, ICreateVerticalToolbar + sealed class EditorToolSettingsOverlay : Overlay, ICreateToolbar, ICreateHorizontalToolbar, ICreateVerticalToolbar { - Editor m_Editor; - VisualElement m_Content; - VisualElement content - { - get - { - if (m_Content == null) - m_Content = new VisualElement() { name = "Tool Settings Container" }; - return m_Content; - } - } + Editor m_ToolEditor, m_ContextEditor; protected internal override Layout supportedLayouts { get { var ret = Layout.Panel; - if (m_Editor == null) + + if (m_ToolEditor == null && m_ContextEditor == null) return ret; - if (m_Editor is ICreateHorizontalToolbar) + + if ((m_ToolEditor is ICreateHorizontalToolbar || m_ToolEditor is ICreateToolbar) + && (m_ContextEditor is ICreateHorizontalToolbar || m_ContextEditor is ICreateToolbar)) ret |= Layout.HorizontalToolbar; - if (m_Editor is ICreateVerticalToolbar) + + if ((m_ToolEditor is ICreateVerticalToolbar || m_ToolEditor is ICreateToolbar) + && (m_ContextEditor is ICreateVerticalToolbar || m_ContextEditor is ICreateToolbar)) ret |= Layout.VerticalToolbar; + return ret; } } @@ -43,13 +43,23 @@ protected internal override Layout supportedLayouts public EditorToolSettingsOverlay() { ToolManager.activeToolChanged += OnToolChanged; + ToolManager.activeContextChanged += OnToolChanged; CreateEditor(); } + public override void OnWillBeDestroyed() + { + UnityObject.DestroyImmediate(m_ToolEditor); + UnityObject.DestroyImmediate(m_ContextEditor); + } + void CreateEditor() { - UnityObject.DestroyImmediate(m_Editor); - m_Editor = Editor.CreateEditor(EditorToolManager.activeTool); + UnityObject.DestroyImmediate(m_ContextEditor); + UnityObject.DestroyImmediate(m_ToolEditor); + + m_ContextEditor = Editor.CreateEditor(EditorToolManager.activeToolContext); + m_ToolEditor = Editor.CreateEditor(EditorToolManager.activeTool); } void OnToolChanged() @@ -58,64 +68,100 @@ void OnToolChanged() RebuildContent(); } - public override VisualElement CreatePanelContent() + // As a rule, Overlays should be compatible with toolbars or not. This class is an exception, hence the + // possibility for ICreateToolbar implementations to return null. + + public OverlayToolbar CreateHorizontalToolbarContent() { - CreateEditorContent(); - return content; + var root = new OverlayToolbar(); + + if(m_ContextEditor is ICreateHorizontalToolbar ctx) + root.Add(ctx.CreateHorizontalToolbarContent()); + else if(m_ContextEditor is ICreateToolbar toolbar) + root.Add(EditorToolbar.CreateOverlay(toolbar.toolbarElements, containerWindow)); + + if(m_ToolEditor is ICreateHorizontalToolbar tool) + root.Add(tool.CreateHorizontalToolbarContent()); + else if(m_ToolEditor is ICreateToolbar toolbar) + root.Add(EditorToolbar.CreateOverlay(toolbar.toolbarElements, containerWindow)); + + return root; } - public VisualElement CreateHorizontalToolbarContent() + public OverlayToolbar CreateVerticalToolbarContent() { - CreateEditorContent(); - return content; + var root = new OverlayToolbar(); + + if(m_ContextEditor is ICreateVerticalToolbar ctx) + root.Add(ctx.CreateVerticalToolbarContent()); + else if(m_ContextEditor is ICreateToolbar toolbar) + root.Add(EditorToolbar.CreateOverlay(toolbar.toolbarElements, containerWindow)); + + if(m_ToolEditor is ICreateVerticalToolbar tool) + root.Add(tool.CreateVerticalToolbarContent()); + else if(m_ToolEditor is ICreateToolbar toolbar) + root.Add(EditorToolbar.CreateOverlay(toolbar.toolbarElements, containerWindow)); + + return root; } - public VisualElement CreateVerticalToolbarContent() + public IEnumerable toolbarElements { - CreateEditorContent(); - return content; + get + { + if (m_ContextEditor is ICreateToolbar ctx) + { + foreach (var id in ctx.toolbarElements) + yield return id; + } + + if (m_ToolEditor is ICreateToolbar tool) + { + foreach (var id in tool.toolbarElements) + yield return id; + } + } } - void CreateEditorContent() + VisualElement GetPanelContent(Editor editor) { - m_Content?.RemoveFromHierarchy(); - m_Content = null; + if (editor == null) + return null; + + var root = editor.CreateInspectorGUI(); - if(m_Editor == null) - return; + if (root != null) + return root; - switch (layout) + // If the Editor does not provide an OnInspectorGUI, try to fall back to a toolbar. + var inspector = editor.GetType().GetMethod("OnInspectorGUI", + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + if (inspector == null || inspector.DeclaringType != editor.GetType()) { - case Layout.HorizontalToolbar: - if (m_Editor is ICreateHorizontalToolbar horizontal) - { - var toolbar = horizontal.CreateHorizontalToolbarContent(); - - if (toolbar != null) - { - content.Add(toolbar); - break; - } - } - goto default; - - case Layout.VerticalToolbar: - if (m_Editor is ICreateVerticalToolbar vertical) - { - var toolbar = vertical.CreateVerticalToolbarContent(); - - if (toolbar != null) - { - content.Add(toolbar); - break; - } - } - goto default; - - default: - content.Add(m_Editor.CreateInspectorGUI() ?? new IMGUIContainer(m_Editor.OnInspectorGUI)); - break; + if (editor is ICreateToolbar toolbar) + return EditorToolbar.CreateOverlay(toolbar.toolbarElements, containerWindow); + + if (editor is ICreateHorizontalToolbar horizontal) + return horizontal.CreateHorizontalToolbarContent(); + + if (editor is ICreateVerticalToolbar vertical) + return vertical.CreateVerticalToolbarContent(); } + + return new IMGUIContainer(editor.OnInspectorGUI); + } + + public override VisualElement CreatePanelContent() + { + var context = GetPanelContent(m_ContextEditor); + var tool = GetPanelContent(m_ToolEditor); + var root = context is OverlayToolbar && tool is OverlayToolbar + ? new OverlayToolbar() + : new VisualElement(); + root.Add(context); + root.Add(tool); + return root; } } } diff --git a/Editor/Mono/GUI/Tools/EditorToolUtility.cs b/Editor/Mono/GUI/Tools/EditorToolUtility.cs index 50740ac431..d4bac72de5 100644 --- a/Editor/Mono/GUI/Tools/EditorToolUtility.cs +++ b/Editor/Mono/GUI/Tools/EditorToolUtility.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Text.RegularExpressions; using UnityEngine; using UObject = UnityEngine.Object; @@ -56,10 +55,20 @@ internal static string SanitizeToolPath(string path) internal static string GetToolMenuPath(Type tool) { - if (typeof(EditorTool).IsAssignableFrom(tool)) + if (typeof(EditorTool).IsAssignableFrom(tool) || typeof(EditorToolContext).IsAssignableFrom(tool)) { - var editorToolAttribute = tool.GetCustomAttributes(typeof(EditorToolAttribute), false).FirstOrDefault(); - if (editorToolAttribute is EditorToolAttribute attrib && !string.IsNullOrEmpty(attrib.displayName)) + var toolAttribute = tool.GetCustomAttributes(typeof(ToolAttribute), false).FirstOrDefault(); + if (toolAttribute is ToolAttribute attrib && !string.IsNullOrEmpty(attrib.displayName)) + { + string path = SanitizeToolPath(attrib.displayName); + if (!string.IsNullOrEmpty(path)) + return L10n.Tr(path); + } + } + else if (typeof(EditorToolContext).IsAssignableFrom(tool)) + { + var editorToolAttribute = tool.GetCustomAttributes(typeof(EditorToolContextAttribute), false).FirstOrDefault(); + if (editorToolAttribute is EditorToolContextAttribute attrib && !string.IsNullOrEmpty(attrib.displayName)) { string path = SanitizeToolPath(attrib.displayName); if (!string.IsNullOrEmpty(path)) @@ -84,7 +93,8 @@ internal static EditorToolAttribute GetEditorToolAttribute(Type type) internal static int GetNonBuiltinToolCount() { - return GetCustomEditorToolsForType(null).Count(); + var globalEditorTools = GetCustomEditorToolsForType(null).Where(t => EditorToolManager.additionalContextToolTypesCache.All(tc => tc != t.editor)); + return globalEditorTools.Count(); } internal static bool IsComponentEditor(Type type) @@ -181,6 +191,18 @@ internal static bool IsComponentTool(Type type) return s_ToolCache.GetTargetType(type) != null; } + internal static bool IsGlobalTool(EditorTool tool) + { + if(GetEnumWithEditorTool(tool) == Tool.Custom) + { + var type = tool.GetType(); + return !IsComponentTool(type) + && EditorToolManager.additionalContextToolTypesCache.All(t => t != type); + } + + return false; + } + internal static GUIContent GetToolbarIcon(T obj) where T : IEditor { if (obj == null) diff --git a/Editor/Mono/GUI/Tools/ToolManager.cs b/Editor/Mono/GUI/Tools/ToolManager.cs index 47c5138ba0..34abb68e45 100644 --- a/Editor/Mono/GUI/Tools/ToolManager.cs +++ b/Editor/Mono/GUI/Tools/ToolManager.cs @@ -136,27 +136,36 @@ public static bool IsActiveContext(EditorToolContext context) return EditorToolManager.activeToolContext == context; } - static IEnumerable allContextsExceptGameObject + internal static IEnumerable allContextsExceptGameObject { get { + foreach(var ctx in EditorToolManager.componentContexts) + yield return ctx.editorType; + foreach(var ctx in EditorToolUtility.availableGlobalToolContexts) if (ctx.editor != typeof(GameObjectToolContext)) yield return ctx.editor; - - foreach(var ctx in EditorToolManager.componentContexts) - yield return ctx.editorType; } } + internal static Type GetLastContextType() + { + var lastContext = EditorToolManager.lastCustomContext; + if (lastContext != null && lastContext != typeof(GameObjectToolContext)) + return lastContext; + + return allContextsExceptGameObject.FirstOrDefault(); + } + [Shortcut("Tools/Enter GameObject Mode", typeof(ToolShortcutContext))] - static void ExitToolContext() + internal static void ExitToolContext() { SetActiveContext(); } [Shortcut("Tools/Cycle Tool Modes", typeof(ToolShortcutContext))] - static void CycleToolContexts() + internal static void CycleToolContexts() { if (EditorToolUtility.toolContextsInProject < 2) return; diff --git a/Editor/Mono/GUIDebugger/StylePicker.cs b/Editor/Mono/GUIDebugger/StylePicker.cs index 45382d7875..d3b4edd289 100644 --- a/Editor/Mono/GUIDebugger/StylePicker.cs +++ b/Editor/Mono/GUIDebugger/StylePicker.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Runtime.Remoting.Messaging; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.UIElements; diff --git a/Editor/Mono/GlobalObjectId.bindings.cs b/Editor/Mono/GlobalObjectId.bindings.cs index d7b8a6f845..b28f13af92 100644 --- a/Editor/Mono/GlobalObjectId.bindings.cs +++ b/Editor/Mono/GlobalObjectId.bindings.cs @@ -64,18 +64,13 @@ public static bool TryParse(string stringValue, out GlobalObjectId id) { id = new GlobalObjectId(); string[] tokens = stringValue.Split('-'); - if (tokens.Length != 5 || tokens[0] != "GlobalObjectId_V1") + if (tokens.Length != 5 || !string.Equals(tokens[0], "GlobalObjectId_V1", StringComparison.Ordinal)) return false; - int identifierType; - GUID assetGUID; - ulong targetObject; - ulong targetPrefab; - - if (!int.TryParse(tokens[1], out identifierType) || - !GUID.TryParse(tokens[2], out assetGUID) || - !ulong.TryParse(tokens[3], out targetObject) || - !ulong.TryParse(tokens[4], out targetPrefab)) + if (!int.TryParse(tokens[1], out var identifierType) || + !GUID.TryParse(tokens[2], out var assetGUID) || + !ulong.TryParse(tokens[3], out var targetObject) || + !ulong.TryParse(tokens[4], out var targetPrefab)) return false; id.m_IdentifierType = identifierType; diff --git a/Editor/Mono/Graphics/StaticBatchingEditorHelper.cs b/Editor/Mono/Graphics/StaticBatchingEditorHelper.cs index 4579a2f091..196d36ede6 100644 --- a/Editor/Mono/Graphics/StaticBatchingEditorHelper.cs +++ b/Editor/Mono/Graphics/StaticBatchingEditorHelper.cs @@ -13,6 +13,6 @@ namespace UnityEditor internal struct StaticBatchingEditorHelper { [FreeFunction("StaticBatching::CombineAllStaticMeshesInSceneForStaticBatching")] - extern internal static void CombineAllStaticMeshesForScenePostProcessing(ulong sceneHash); + extern internal static void CombineAllStaticMeshesForScenePostProcessing(ulong sceneHash, UnityEngine.SceneManagement.Scene scene); } } diff --git a/Editor/Mono/HandleUtility.cs b/Editor/Mono/HandleUtility.cs index 86a8c3f542..0f8ad8420f 100644 --- a/Editor/Mono/HandleUtility.cs +++ b/Editor/Mono/HandleUtility.cs @@ -667,6 +667,7 @@ public static void AddDefaultControl(int controlId) static int s_PreviousNearestControl; static int s_NearestControl; static float s_NearestDistance; + static Camera s_PreviousCamera; internal const float kPickDistance = 5.0f; internal static float s_CustomPickDistance = kPickDistance; @@ -687,6 +688,12 @@ internal static void BeginHandles() Handles.color = Color.white; Handles.zTest = CompareFunction.Always; s_CustomPickDistance = kPickDistance; + + if (null != Camera.current) + { + s_PreviousCamera = Camera.current; + } + Handles.Internal_SetCurrentCamera(null); EditorGUI.s_DelayedTextEditor.BeginGUI(); } @@ -695,11 +702,19 @@ internal static void BeginHandles() internal static void EndHandles() { if (s_PreviousNearestControl != s_NearestControl - && s_NearestControl != 0) + && s_NearestControl != 0 + && Event.current.type != EventType.Layout) { s_PreviousNearestControl = s_NearestControl; Repaint(); } + + if (null != s_PreviousCamera) + { + Handles.Internal_SetCurrentCamera(s_PreviousCamera); + s_PreviousCamera = null; + } + // Give the delayed text editor a chance to notice that it lost focus. EditorGUI.s_DelayedTextEditor.EndGUI(Event.current.type); } diff --git a/Editor/Mono/Handles.cs b/Editor/Mono/Handles.cs index 6826d26023..51dbf11201 100644 --- a/Editor/Mono/Handles.cs +++ b/Editor/Mono/Handles.cs @@ -543,17 +543,30 @@ public static Vector3 Slider(int controlID, Vector3 position, Vector3 offset, Ve return UnityEditorInternal.Slider1D.Do(controlID, position, offset, direction, direction, size, capFunction, snap); } + [Obsolete("Rotation parameter is obsolete. (UnityUpgradable) -> !1")] public static Vector3 FreeMoveHandle(Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction) { int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive); return UnityEditorInternal.FreeMove.Do(id, position, rotation, size, snap, capFunction); } + [Obsolete("Rotation parameter is obsolete. (UnityUpgradable) -> !2")] public static Vector3 FreeMoveHandle(int controlID, Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction) { return UnityEditorInternal.FreeMove.Do(controlID, position, rotation, size, snap, capFunction); } + public static Vector3 FreeMoveHandle(Vector3 position, float size, Vector3 snap, CapFunction capFunction) + { + int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive); + return UnityEditorInternal.FreeMove.Do(id, position, size, snap, capFunction); + } + + public static Vector3 FreeMoveHandle(int controlID, Vector3 position, float size, Vector3 snap, CapFunction capFunction) + { + return UnityEditorInternal.FreeMove.Do(controlID, position, size, snap, capFunction); + } + // Make a single-float draggable handle. public static float ScaleValueHandle(float value, Vector3 position, Quaternion rotation, float size, CapFunction capFunction, float snap) { diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs index 55cb382c92..860a7b0db3 100644 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs @@ -59,7 +59,7 @@ internal virtual void DrawItem(AdvancedDropdownItem item, string name, Texture2D //we need to pretend we have an icon to calculate proper width in case if (content.image == null) content.image = Texture2D.whiteTexture; - var rect = GUILayoutUtility.GetRect(content, lineStyle, GUILayout.ExpandWidth(true)); + var rect = GetItemRect(content); content.image = imgTemp; if (!string.IsNullOrEmpty(content.tooltip) && rect.Contains(Event.current.mousePosition) && @@ -88,7 +88,8 @@ internal virtual void DrawItem(AdvancedDropdownItem item, string name, Texture2D rect.width -= iconSize.x + 1; } EditorGUI.BeginDisabled(!enabled); - lineStyle.Draw(rect, content, false, false, selected, selected); + + DrawItemContent(item, rect, content, false, false, selected, selected); content.image = imageTemp; if (drawArrow) { @@ -203,7 +204,7 @@ internal Vector2 CalculateContentSize(AdvancedDropdownDataSource dataSource) foreach (var child in dataSource.mainTree.children) { var content = child.content; - var a = lineStyle.CalcSize(content); + var a = CalcItemSize(content); a.x += iconSize.x + 1; if (maxWidth < a.x) @@ -217,7 +218,7 @@ internal Vector2 CalculateContentSize(AdvancedDropdownDataSource dataSource) } else { - maxHeight += lineStyle.CalcHeight(content, maxWidth); + maxHeight += CalcItemHeight(content, maxWidth); } } if (includeArrow) @@ -258,7 +259,7 @@ internal float GetSelectionHeight(AdvancedDropdownDataSource dataSource, Rect bu var content = child.content; if (state.GetSelectedIndex(dataSource.mainTree) == i) { - var diff = (lineStyle.CalcHeight(content, 0) - buttonRect.height) / 2f; + var diff = (CalcItemHeight(content, 0) - buttonRect.height) / 2f; return heigth + diff; } if (child.IsSeparator()) @@ -267,10 +268,30 @@ internal float GetSelectionHeight(AdvancedDropdownDataSource dataSource, Rect bu } else { - heigth += lineStyle.CalcHeight(content, 0); + heigth += CalcItemHeight(content, 0); } } return heigth; } + + internal virtual Rect GetItemRect(in GUIContent content) + { + return GUILayoutUtility.GetRect(content, lineStyle, GUILayout.ExpandWidth(true)); + } + + internal virtual float CalcItemHeight(GUIContent content, float width) + { + return lineStyle.CalcHeight(content, width); + } + + internal virtual Vector2 CalcItemSize(GUIContent content) + { + return lineStyle.CalcSize(content); + } + + internal virtual void DrawItemContent(AdvancedDropdownItem item, Rect rect, GUIContent content, bool isHover, bool isActive, bool on, bool hasKeyboardFocus) + { + lineStyle.Draw(rect, content, isHover, isActive, on, hasKeyboardFocus); + } } } diff --git a/Editor/Mono/Inspector/AvatarPreview.cs b/Editor/Mono/Inspector/AvatarPreview.cs index f8547d819c..3dffa63e2f 100644 --- a/Editor/Mono/Inspector/AvatarPreview.cs +++ b/Editor/Mono/Inspector/AvatarPreview.cs @@ -13,6 +13,7 @@ namespace UnityEditor { internal class AvatarPreview { + const string kDefaultAvatarPreviewOption = "DefaultAvatarPreviewOption"; const string kIkPref = "AvatarpreviewShowIK"; const string k2DPref = "Avatarpreview2D"; const string kReferencePref = "AvatarpreviewShowReference"; @@ -724,7 +725,7 @@ public void DoRenderPreview(Rect previewRect, GUIStyle background) SetPreviewCharacterEnabled(true, m_ShowReference); foreach (var previewable in m_Previewables) previewable.OnPreviewUpdate(); - previewUtility.Render(m_Option != PreviewPopupOptions.DefaultModel); + previewUtility.Render(option != PreviewPopupOptions.DefaultModel); SetPreviewCharacterEnabled(false, false); // Texture offset - negative in order to compensate the floor movement. @@ -877,7 +878,12 @@ public void AvatarTimeControlGUI(Rect rect) ); } - enum PreviewPopupOptions { Auto, DefaultModel, Other } + enum PreviewPopupOptions : int + { + Auto = 0, + DefaultModel = 1, + Other = 2 + } protected enum ViewTool { None, Pan, Zoom, Orbit } protected ViewTool m_ViewTool = ViewTool.None; @@ -1112,21 +1118,32 @@ public void DoAvatarPreview(Rect rect, GUIStyle background) EditorGUIUtility.AddCursorRect(previewRect, currentCursor); } - private PreviewPopupOptions m_Option; + private PreviewPopupOptions option + { + get => (PreviewPopupOptions) EditorPrefs.GetInt(kDefaultAvatarPreviewOption); + set => EditorPrefs.SetInt(kDefaultAvatarPreviewOption, (int)value); + } + void SetPreviewAvatarOption(object obj) { - m_Option = (PreviewPopupOptions)obj; - if (m_Option == PreviewPopupOptions.Auto) - { - SetPreview(null); - } - else if (m_Option == PreviewPopupOptions.DefaultModel) - { - SetPreview(GetHumanoidFallback()); - } - else if (m_Option == PreviewPopupOptions.Other) + var newSelectedOption = (PreviewPopupOptions)obj; + + if (option != newSelectedOption) { - ObjectSelectorOperation.Start(this); + option = newSelectedOption; + + switch (option) + { + case PreviewPopupOptions.Auto: + SetPreview(null); + break; + case PreviewPopupOptions.DefaultModel: + SetPreview(GetHumanoidFallback()); + break; + case PreviewPopupOptions.Other: + ObjectSelectorOperation.Start(this); + break; + } } } diff --git a/Editor/Mono/Inspector/EditorElementUpdater.cs b/Editor/Mono/Inspector/EditorElementUpdater.cs new file mode 100644 index 0000000000..10cbd88e3d --- /dev/null +++ b/Editor/Mono/Inspector/EditorElementUpdater.cs @@ -0,0 +1,133 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; +using System.Diagnostics; +using UnityEditorInternal; +using UnityEngine.UIElements; + +namespace UnityEditor +{ + /// + /// The handles calling in a time-sliced manner. + /// + class EditorElementUpdater + { + readonly PropertyEditor m_PropertyEditor; + readonly List m_EditorElements = new List(); + readonly Stopwatch m_UpdateTickTimer = new Stopwatch(); + + Panel Panel => m_PropertyEditor.rootVisualElement.panel as Panel; + + int m_Index; + + public int Position => m_Index; + public int Count => m_EditorElements.Count; + + public EditorElementUpdater(PropertyEditor propertyEditor) + { + m_PropertyEditor = propertyEditor; + m_Index = 0; + } + + /// + /// Adds the specified to the updater. + /// + /// + public void Add(IEditorElement element) + { + m_EditorElements.Add(element); + } + + /// + /// Clears the internal state and resets the enumerator. + /// + public void Clear() + { + m_EditorElements.Clear(); + m_Index = 0; + } + + /// + /// Invokes until the first elements are created. + /// + /// The number of elements to create. + public void CreateMinimumInspectorElementsWithoutLayout(int count) + { + for (; m_Index < count && m_Index < m_EditorElements.Count; m_Index++) + m_EditorElements[m_Index].CreateInspectorElement(); + } + + /// + /// Invokes for the specified number of elements. + /// + /// The number of elements to create. + public void CreateInspectorElementsWithoutLayout(int count) + { + for (var i = 0; m_Index < m_EditorElements.Count && i < count; i++, m_Index++) + m_EditorElements[m_Index].CreateInspectorElement(); + } + + /// + /// Invokes followed by a layout until the given is filled. + /// + /// The viewport to build elements for. + /// + public void CreateInspectorElementsForViewport(ScrollView viewport, VisualElement contentContainer) + { + if (m_Index >= m_EditorElements.Count) + return; + + var scroll = viewport.verticalScroller.value; + + while (m_Index < m_EditorElements.Count) + { + var element = m_EditorElements[m_Index++]; + + element.CreateInspectorElement(); + + // If this element contributes to the layout, re-compute it immediately to determine how much of the viewport is occupied. + if (null != element.editor && InternalEditorUtility.GetIsInspectorExpanded(element.editor.target)) + { + Panel?.UpdateWithoutRepaint(); + + if (contentContainer.ElementAt(m_Index - 1).layout.yMax - scroll > viewport.layout.height) + break; + } + } + + viewport.verticalScroller.value = scroll; + } + + /// + /// Invokes followed by a layout until the target has been reached. + /// + /// + /// The time value includes creation of the GUI, styling and layout. This does NOT include render time. + /// + /// The target number of milliseconds to spend on the update. + public void CreateInspectorElementsForMilliseconds(long targetMilliseconds) + { + if (m_Index >= m_EditorElements.Count) + return; + + m_UpdateTickTimer.Restart(); + + while (m_UpdateTickTimer.ElapsedMilliseconds < targetMilliseconds) + { + var element = m_EditorElements[m_Index++]; + + element.CreateInspectorElement(); + + // If this was the last element. We can early out and let the standard update loop tick the layout and repaint. + if (m_Index >= m_EditorElements.Count) + break; + + // If this element contributes to the layout, re-compute it immediately to determine how much of the viewport is occupied. + if (null != element.editor && InternalEditorUtility.GetIsInspectorExpanded(element.editor.target)) + Panel?.UpdateWithoutRepaint(); + } + } + } +} diff --git a/Editor/Mono/Inspector/EditorSettingsInspector.cs b/Editor/Mono/Inspector/EditorSettingsInspector.cs index 1f0c757a87..ea4006544c 100644 --- a/Editor/Mono/Inspector/EditorSettingsInspector.cs +++ b/Editor/Mono/Inspector/EditorSettingsInspector.cs @@ -42,6 +42,7 @@ class Content public static GUIContent cacheServerEnableAuthLabel = EditorGUIUtility.TrTextContent("Authentication (using Unity ID)", "Enable authentication for cache server using Unity ID. Also forces TLS/SSL encryption."); public static GUIContent cacheServerAuthUserLabel = EditorGUIUtility.TrTextContent("User"); public static GUIContent cacheServerAuthPasswordLabel = EditorGUIUtility.TrTextContent("Password"); + public static GUIContent cacheServerValidationLabel = EditorGUIUtility.TrTextContent("Content Validation"); public static readonly GUIContent cacheServerLearnMore = new GUIContent("Learn more...", "Go to cacheserver documentation."); public static GUIContent assetSerialization = EditorGUIUtility.TrTextContent("Asset Serialization"); @@ -70,8 +71,9 @@ class Content public static GUIContent lineEndingForNewScripts = EditorGUIUtility.TrTextContent("Line Endings For New Scripts"); public static GUIContent streamingSettings = EditorGUIUtility.TrTextContent("Streaming Settings"); - public static GUIContent enablePlayModeTextureStreaming = EditorGUIUtility.TrTextContent("Enable Texture Streaming In Play Mode", "Texture Streaming must be enabled in Quality Settings for mipmap streaming to function in Play Mode"); - public static GUIContent enableEditModeTextureStreaming = EditorGUIUtility.TrTextContent("Enable Texture Streaming In Edit Mode", "Texture Streaming must be enabled in Quality Settings for mipmap streaming to function in Edit Mode"); + public static GUIContent enablePlayModeTextureStreaming = EditorGUIUtility.TrTextContent("Enable Texture Streaming In Play Mode", "Texture Streaming must be enabled in Quality Settings for mipmap streaming to function in Play Mode. This reduces GPU memory by streaming mips in and out as needed."); + public static GUIContent enableEditModeTextureStreaming = EditorGUIUtility.TrTextContent("Enable Texture Streaming In Edit Mode", "Texture Streaming must be enabled in Quality Settings for mipmap streaming to function in Edit Mode. This reduces GPU memory by streaming mips in and out as needed."); + public static GUIContent enableEditorAsyncCPUTextureLoading = EditorGUIUtility.TrTextContent("Load texture data on demand", "While in Editor, load CPU side texture data for streaming textures from disk asynchronously on demand (will avoid some stalls and reduce CPU memory usage). Change requires Editor restart."); public static GUIContent shaderCompilation = EditorGUIUtility.TrTextContent("Shader Compilation"); public static GUIContent asyncShaderCompilation = EditorGUIUtility.TrTextContent("Asynchronous Shader Compilation", "Enables async shader compilation in Game and Scene view. Async compilation for custom editor tools can be achieved via script API and is not affected by this option."); @@ -86,6 +88,7 @@ class Content public static readonly GUIContent enterPlayModeOptionsEnabled = EditorGUIUtility.TrTextContent("Enter Play Mode Options", "Enables options when Entering Play Mode"); public static readonly GUIContent enterPlayModeOptionsEnableDomainReload = EditorGUIUtility.TrTextContent("Reload Domain", "Enables Domain Reload when Entering Play Mode. Domain reload reinitializes game completely making loading behavior very close to the Player"); public static readonly GUIContent enterPlayModeOptionsEnableSceneReload = EditorGUIUtility.TrTextContent("Reload Scene", "Enables Scene Reload when Entering Play Mode. Scene reload makes loading behavior and performance characteristics very close to the Player"); + public static readonly GUIContent enterPlayModeOptionsDisableSceneBackup = EditorGUIUtility.TrTextContent("Disable Scene Backup", "Conditionally skips writing a backup of the open scenes to disk. Only scenes that are modified in-memory need to be backed up, but making modifications from script may change the scene without setting the scene's dirty flag."); public static readonly GUIContent numberingScheme = EditorGUIUtility.TrTextContent("Numbering Scheme"); @@ -142,8 +145,8 @@ public PopupElement(string id, string content) new PopupElement("Disabled"), new PopupElement("Sprite Atlas V1 - Enabled For Builds"), new PopupElement("Sprite Atlas V1 - Always Enabled"), - new PopupElement("Sprite Atlas V2 (Experimental) - Enabled"), - new PopupElement("Sprite Atlas V2 (Experimental) - Enabled for Builds"), + new PopupElement("Sprite Atlas V2 - Enabled"), + new PopupElement("Sprite Atlas V2 - Enabled for Builds"), }; private static readonly int spritePackDeprecatedEnums = 2; @@ -190,6 +193,14 @@ public PopupElement(string id, string content) new PopupElement("Basic") }; + private GUIContent[] cacheServerValidationPopupList = + { + EditorGUIUtility.TrTextContent("Disabled", "Content hashes are not calculated for uploaded artifacts and are not validated for downloaded artifacts."), + EditorGUIUtility.TrTextContent("Upload Only", "Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes are not validated for downloaded artifacts." ), + EditorGUIUtility.TrTextContent("Enabled", "Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes, if provided by the Accelerator, are validated for downloaded artifacts."), + EditorGUIUtility.TrTextContent("Required", "Content hashes are calculated for uploaded artifacts and sent to the Accelerator. Content hashes are required and validated for downloaded artifacts."), + }; + private GUIContent[] bc7TextureCompressorOptions = { EditorGUIUtility.TrTextContent("Default", "Use default BC7 compressor (currently bc7e)"), @@ -227,6 +238,7 @@ public PopupElement(string id, string content) SerializedProperty m_EnableTextureStreamingInPlayMode; SerializedProperty m_EnableTextureStreamingInEditMode; + SerializedProperty m_EnableEditorAsyncCPUTextureLoading; SerializedProperty m_EnableRoslynAnalyzers; @@ -255,6 +267,7 @@ public PopupElement(string id, string content) SerializedProperty m_EnterPlayModeOptions; SerializedProperty m_ProjectGenerationIncludedExtensions; SerializedProperty m_ProjectGenerationRootNamespace; + SerializedProperty m_CacheServerValidationMode; bool m_IsGlobalSettings; @@ -273,6 +286,7 @@ public void OnEnable() m_EnableTextureStreamingInPlayMode = serializedObject.FindProperty("m_EnableTextureStreamingInPlayMode"); m_EnableTextureStreamingInEditMode = serializedObject.FindProperty("m_EnableTextureStreamingInEditMode"); + m_EnableEditorAsyncCPUTextureLoading = serializedObject.FindProperty("m_EnableEditorAsyncCPUTextureLoading"); m_EnableRoslynAnalyzers = serializedObject.FindProperty("m_EnableRoslynAnalyzers"); @@ -342,6 +356,9 @@ public void OnEnable() m_ProjectGenerationRootNamespace = serializedObject.FindProperty("m_ProjectGenerationRootNamespace"); Assert.IsNotNull(m_ProjectGenerationRootNamespace); + m_CacheServerValidationMode = serializedObject.FindProperty("m_CacheServerValidationMode"); + Assert.IsNotNull(m_ProjectGenerationRootNamespace); + m_CacheServerConnectionState = CacheServerConnectionState.Unknown; m_IsGlobalSettings = EditorSettings.GetEditorSettings() == target; @@ -546,12 +563,6 @@ public override void OnInspectorGUI() index = Mathf.Clamp(m_SpritePackerMode.intValue - spritePackDeprecatedEnums, 0, spritePackerPopupList.Length - 1); CreatePopupMenu(Content.mode.text, spritePackerPopupList, index, SetSpritePackerMode); - if (m_SpritePackerMode.intValue < (int)SpritePackerMode.SpriteAtlasV2) - { - var message = "Sprite Atlas V2 (Experimental) supports CacheServer with Importer workflow. Please take a backup of your project before switching to V2."; - EditorGUILayout.HelpBox(message, MessageType.Info, true); - } - DoProjectGenerationSettings(); var compressorsChanged = DoTextureCompressorSettings(); DoLineEndingsSettings(); @@ -835,6 +846,10 @@ private void DoCacheServerSettings() EditorSettings.cacheServerEnableTls = true; } } + + int validationIndex = Mathf.Clamp((int)EditorSettings.cacheServerValidationMode, 0, cacheServerValidationPopupList.Length - 1); + + EditorGUILayout.Popup(m_CacheServerValidationMode, cacheServerValidationPopupList, Content.cacheServerValidationLabel); } } } @@ -866,6 +881,7 @@ private void DoStreamingSettings() EditorGUILayout.PropertyField(m_EnableTextureStreamingInPlayMode, Content.enablePlayModeTextureStreaming); EditorGUILayout.PropertyField(m_EnableTextureStreamingInEditMode, Content.enableEditModeTextureStreaming); + EditorGUILayout.PropertyField(m_EnableEditorAsyncCPUTextureLoading, Content.enableEditorAsyncCPUTextureLoading); } EditorSettings.NamingScheme m_PrevGoNamingScheme; @@ -924,6 +940,7 @@ private void DoEnterPlayModeSettings() EnterPlayModeOptions options = (EnterPlayModeOptions)m_EnterPlayModeOptions.intValue; options = ToggleEnterPlayModeOptions(options, EnterPlayModeOptions.DisableDomainReload, Content.enterPlayModeOptionsEnableDomainReload); options = ToggleEnterPlayModeOptions(options, EnterPlayModeOptions.DisableSceneReload, Content.enterPlayModeOptionsEnableSceneReload); + options = ToggleEnterPlayModeOptions(options, EnterPlayModeOptions.DisableSceneBackupUnlessDirty, Content.enterPlayModeOptionsDisableSceneBackup); if (m_EnterPlayModeOptions.intValue != (int)options) { @@ -1095,6 +1112,11 @@ private void SetCacheServerAuthMode(object data) EditorUserSettings.SetConfigValue("cacheServerAuthMode", $"{(int)data}"); } + private void SetCacheServerValidationMode(object data) + { + EditorSettings.cacheServerValidationMode = (CacheServerValidationMode)data; + } + private void SetEtcTextureCompressorBehavior(object data) { int newValue = (int)data; diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index f8490c248c..2db1c3fcb8 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -172,7 +172,6 @@ public void Dispose() bool m_PlayModeObjects; bool m_IsAsset; bool m_ImmutableSelf; - bool m_IsDisconnected; bool m_IsMissing; bool m_IsPrefabInstanceAnyRoot; bool m_IsPrefabInstanceOutermostRoot; @@ -213,7 +212,6 @@ void CalculatePrefabStatus() m_PlayModeObjects = false; m_IsAsset = false; m_ImmutableSelf = false; - m_IsDisconnected = false; m_IsMissing = false; m_IsPrefabInstanceAnyRoot = true; m_IsPrefabInstanceOutermostRoot = true; @@ -265,8 +263,6 @@ void CalculatePrefabStatus() m_ImmutableSelf = true; // Conservative is true if any is true } } - if (PrefabUtility.IsDisconnectedFromPrefabAsset(go)) - m_IsDisconnected = true; if (PrefabUtility.IsPrefabAssetMissing(go)) m_IsMissing = true; } @@ -516,7 +512,7 @@ private void DoPrefabButtons() { EditorGUILayout.BeginHorizontal(GUILayout.Width(kIconSize + Styles.tagFieldWidth)); GUILayout.FlexibleSpace(); - if (m_IsDisconnected || m_IsMissing) + if (m_IsMissing) { GUI.contentColor = GUI.skin.GetStyle("CN StatusWarn").normal.textColor; DoPrefixLabel(prefixLabel, EditorStyles.whiteLabel); diff --git a/Editor/Mono/Inspector/GenericInspector.cs b/Editor/Mono/Inspector/GenericInspector.cs index 130f6a19cc..263dd5117e 100644 --- a/Editor/Mono/Inspector/GenericInspector.cs +++ b/Editor/Mono/Inspector/GenericInspector.cs @@ -117,7 +117,9 @@ internal override bool OnOptimizedInspectorGUI(Rect contentRect) var behaviour = target as MonoBehaviour; var property = m_SerializedObject.GetIterator(); - var isInspectorModeNormal = inspectorMode == InspectorMode.Normal; + bool isInspectorModeNormal = inspectorMode == InspectorMode.Normal; + bool isInPrefabInstance = PrefabUtility.GetPrefabInstanceHandle(behaviour) != null; + bool isMultiSelection = m_SerializedObject.targetObjectsCount > 1; using (new LocalizationGroup(behaviour)) { @@ -131,7 +133,7 @@ internal override bool OnOptimizedInspectorGUI(Rect contentRect) if (contentRect.Overlaps(visibleRect)) { EditorGUI.indentLevel = property.depth; - using (new EditorGUI.DisabledScope(isInspectorModeNormal && string.Equals("m_Script", property.propertyPath, System.StringComparison.Ordinal))) + using (new EditorGUI.DisabledScope((isInspectorModeNormal || isInPrefabInstance || isMultiSelection) && string.Equals("m_Script", property.propertyPath, System.StringComparison.Ordinal))) childrenAreExpanded &= handler.OnGUI(contentRect, property, GetPropertyLabel(property), PropertyHandler.UseReorderabelListControl(property), visibleRect); } diff --git a/Editor/Mono/Inspector/IEditorElement.cs b/Editor/Mono/Inspector/IEditorElement.cs index f854c33822..84d90afa49 100644 --- a/Editor/Mono/Inspector/IEditorElement.cs +++ b/Editor/Mono/Inspector/IEditorElement.cs @@ -15,6 +15,7 @@ internal interface IEditorElement void Reinit(int editorIndex); void ReinitCulled(int editorIndex); + void CreateInspectorElement(); void AddPrefabComponent(VisualElement comp); diff --git a/Editor/Mono/Inspector/InspectorWindowUtils.cs b/Editor/Mono/Inspector/InspectorWindowUtils.cs index ba8bb8bcac..375159071c 100644 --- a/Editor/Mono/Inspector/InspectorWindowUtils.cs +++ b/Editor/Mono/Inspector/InspectorWindowUtils.cs @@ -152,7 +152,7 @@ public static void DrawAddedComponentBackground(Rect position, Object[] targets, { // Ensure colored margin here for component body doesn't overlap colored margin from InspectorTitlebar, // and extends down to exactly touch the separator line between/after components. - EditorGUI.DrawOverrideBackground(new Rect(position.x, position.y + 3 + adjust, position.width, + EditorGUI.DrawOverrideBackgroundApplicable(new Rect(position.x, position.y + 3 + adjust, position.width, position.height - 2)); } } diff --git a/Editor/Mono/Inspector/LODGroupEditor.cs b/Editor/Mono/Inspector/LODGroupEditor.cs index 436e61f500..9ec02df3fd 100644 --- a/Editor/Mono/Inspector/LODGroupEditor.cs +++ b/Editor/Mono/Inspector/LODGroupEditor.cs @@ -24,6 +24,9 @@ internal class LODGroupEditor : Editor private bool m_IsPrefab; private bool m_IsPreset; + private int m_SelectedLODGroupCount; + private int m_MaxLODCountForMultiselection; + private SerializedProperty m_FadeMode; private SerializedProperty m_AnimateCrossFading; private SerializedProperty m_LastLODIsBillboard; @@ -90,6 +93,8 @@ void OnEnable() EditorApplication.update += Update; m_LODGroup = (LODGroup)target; + m_SelectedLODGroupCount = targets.Length; + m_MaxLODCountForMultiselection = GetMaxLODCountForMultiSelection(); // Calculate if the newly selected LOD group is a prefab... they require special handling m_IsPrefab = PrefabUtility.IsPartOfPrefabAsset(m_LODGroup.gameObject); @@ -215,14 +220,21 @@ public static bool IsSceneGUIEnabled() public void OnSceneGUI() { + if (!target) + return; + + if (m_SelectedLODGroupCount > 1) + return; + + LODGroup lodGroup = (LODGroup)target; Camera camera = SceneView.lastActiveSceneView.camera; - var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(m_LODGroup); + var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(lodGroup); if (Vector3.Dot(camera.transform.forward, (camera.transform.position - worldReferencePoint).normalized) > 0) return; - var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, -1); + var info = LODUtility.CalculateVisualizationData(camera, lodGroup, -1); float size = info.worldSpaceSize; // Draw cap around LOD to visualize it's size @@ -346,14 +358,12 @@ void DrawLODGroupFoldouts() if (camera == null) return; - var count = GetMaxLODCountForMultiSelection(); - - for (int i = 0; i < count; i++) + for (int i = 0; i < m_MaxLODCountForMultiselection; i++) { if (targets.Length == 1) DrawLODGroupFoldout(camera, i, ref m_LODGroupFoldoutHeaderValues[i]); else - DrawLODTransitionPropertyField(camera, i, count); + DrawLODTransitionPropertyField(camera, i, m_MaxLODCountForMultiselection); } } diff --git a/Editor/Mono/Inspector/LightEditor.cs b/Editor/Mono/Inspector/LightEditor.cs index fae85113c6..b7c228362b 100644 --- a/Editor/Mono/Inspector/LightEditor.cs +++ b/Editor/Mono/Inspector/LightEditor.cs @@ -74,15 +74,15 @@ private static class Styles public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent("Shape", "Specifies the shape of the Area light. Possible types are Rectangle and Disc."); public static readonly GUIContent Range = EditorGUIUtility.TrTextContent("Range", "Controls how far the light is emitted from the center of the object."); public static readonly GUIContent SpotAngle = EditorGUIUtility.TrTextContent("Spot Angle", "Controls the angle in degrees at the base of a Spot light's cone."); - public static readonly GUIContent InnerOuterSpotAngle = EditorGUIUtility.TrTextContent("Inner / Outer Spot Angle", "Controls the inner and outer angle in degrees, at the base of a Spot light's cone."); + public static readonly GUIContent InnerOuterSpotAngle = EditorGUIUtility.TrTextContent("Inner / Outer Spot Angle", "Controls the inner and outer angles in degrees, at the base of a Spot light's cone."); public static readonly GUIContent Color = EditorGUIUtility.TrTextContent("Color", "Controls the color being emitted by the light."); public static readonly GUIContent UseColorTemperature = EditorGUIUtility.TrTextContent("Use color temperature mode", "Choose between RGB and temperature mode for light's color."); public static readonly GUIContent ColorFilter = EditorGUIUtility.TrTextContent("Filter", "A colored gel can be put in front of the light source to tint the light."); public static readonly GUIContent ColorTemperature = EditorGUIUtility.TrTextContent("Temperature", "Also known as CCT (Correlated color temperature). The color temperature of the electromagnetic radiation emitted from an ideal black body is defined as its surface temperature in Kelvin. White is 6500K"); public static readonly GUIContent Intensity = EditorGUIUtility.TrTextContent("Intensity", "Controls the brightness of the light. Light color is multiplied by this value."); public static readonly GUIContent LightmappingMode = EditorGUIUtility.TrTextContent("Mode", "Specifies the light mode used to determine if and how a light will be baked. Possible modes are Baked, Mixed, and Realtime."); - public static readonly GUIContent LightBounceIntensityRealtimeGISupport = EditorGUIUtility.TrTextContent("Indirect Multiplier", "Controls the intensity of indirect light being contributed to the scene. A value of 0 will cause Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting. Has no effect when both Realtime and Baked Global Illumination are disabled."); - public static readonly GUIContent LightBounceIntensity = EditorGUIUtility.TrTextContent("Indirect Multiplier", "Controls the intensity of indirect light being contributed to the scene. A value of 0 will cause Baked and Mixed lights to no longer emit indirect lighting. Has no effect when Baked Global Illumination are disabled."); + public static readonly GUIContent LightBounceIntensityRealtimeGISupport = EditorGUIUtility.TrTextContent("Indirect Multiplier", "Determines the intensity of indirect light being contributed to the scene. Has no effect when both Realtime and Baked Global Illumination are disabled. If this value is 0, Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting."); + public static readonly GUIContent LightBounceIntensity = EditorGUIUtility.TrTextContent("Indirect Multiplier", "Determines the intensity of indirect light being contributed to to the scene. Has no effect when Baked Global Illumination is disabled. If this value is 0, Baked and Mixed lights no longer emit indirect lighting."); public static readonly GUIContent ShadowType = EditorGUIUtility.TrTextContent("Shadow Type", "Specifies whether Hard Shadows, Soft Shadows, or No Shadows will be cast by the light."); public static readonly GUIContent CastShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Specifies whether Soft Shadows or No Shadows will be cast by the light."); //realtime diff --git a/Editor/Mono/Inspector/LightProbeGroupInspector.cs b/Editor/Mono/Inspector/LightProbeGroupInspector.cs index 6a121f7168..4668ed30c7 100644 --- a/Editor/Mono/Inspector/LightProbeGroupInspector.cs +++ b/Editor/Mono/Inspector/LightProbeGroupInspector.cs @@ -518,10 +518,10 @@ private static class Styles { public static readonly GUIContent showWireframe = EditorGUIUtility.TrTextContent("Show Wireframe", "Show the tetrahedron wireframe visualizing the blending between probes."); public static readonly GUIContent selectedProbePosition = EditorGUIUtility.TrTextContent("Selected Probe Position", "The local position of this probe relative to the parent group."); - public static readonly GUIContent addProbe = EditorGUIUtility.TrTextContent("Add Probe"); - public static readonly GUIContent deleteSelected = EditorGUIUtility.TrTextContent("Delete Selected"); - public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent("Select All"); - public static readonly GUIContent duplicateSelected = EditorGUIUtility.TrTextContent("Duplicate Selected"); + public static readonly GUIContent addProbe = EditorGUIUtility.TrTextContent("Add Probe", "Add a Light Probe to the Light Probe Group."); + public static readonly GUIContent deleteSelected = EditorGUIUtility.TrTextContent("Delete Selected", "Delete the selected Light Probes from the Light Probe Group."); + public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent("Select All", "Select all Light Probes in the Light Probe Group."); + public static readonly GUIContent duplicateSelected = EditorGUIUtility.TrTextContent("Duplicate Selected", "Duplicate the selected Light Probes."); public static readonly GUIContent performDeringing = EditorGUIUtility.TrTextContent("Remove Ringing", "When enabled, removes visible overshooting often observed as ringing on objects affected by intense lighting at the expense of reduced contrast."); // Toolbar diff --git a/Editor/Mono/Inspector/LightingSettingsEditor.cs b/Editor/Mono/Inspector/LightingSettingsEditor.cs index ee619f702c..3cf49a5bf7 100644 --- a/Editor/Mono/Inspector/LightingSettingsEditor.cs +++ b/Editor/Mono/Inspector/LightingSettingsEditor.cs @@ -104,6 +104,7 @@ internal class SharedLightingSettingsEditor SerializedProperty m_ForceUpdates; SerializedProperty m_FilterMode; SerializedProperty m_TiledBaking; + SerializedProperty m_NumRaysToShootPerTexel; enum DenoiserTarget { @@ -353,6 +354,7 @@ public void UpdateSettings(SerializedObject lso) m_FilterMode = lso.FindProperty("m_FilterMode"); m_BounceScale = lso.FindProperty("m_BounceScale"); m_TiledBaking = lso.FindProperty("m_PVRTiledBaking"); + m_NumRaysToShootPerTexel = lso.FindProperty("m_NumRaysToShootPerTexel"); } } diff --git a/Editor/Mono/Inspector/MaskFieldDropdown.cs b/Editor/Mono/Inspector/MaskFieldDropdown.cs index 73bb54a9f6..46a3f9afc8 100644 --- a/Editor/Mono/Inspector/MaskFieldDropdown.cs +++ b/Editor/Mono/Inspector/MaskFieldDropdown.cs @@ -232,7 +232,7 @@ public override void OnOpen() if (size.x > m_windowSize) m_windowSize = size.x; } - m_windowSize = Mathf.Clamp(m_windowSize, 100, 386); + m_windowSize = Mathf.Clamp(m_windowSize, 100, Screen.currentResolution.width * 0.95f); Undo.undoRedoPerformed += OnUndoRedoPerformed; } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 7c26b0d46c..b24cff0f57 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -148,6 +148,9 @@ class SettingsContent public static readonly GUIContent graphicsJobsNonExperimental = EditorGUIUtility.TrTextContent("Graphics Jobs"); public static readonly GUIContent graphicsJobsExperimental = EditorGUIUtility.TrTextContent("Graphics Jobs (Experimental)"); public static readonly GUIContent graphicsJobsMode = EditorGUIUtility.TrTextContent("Graphics Jobs Mode"); + public static readonly GUIContent applicationIdentifierWarning = EditorGUIUtility.TrTextContent("Invalid characters have been removed from the Application Identifier."); + public static readonly GUIContent applicationIdentifierError = EditorGUIUtility.TrTextContent("The Application Identifier must follow the convention 'com.YourCompanyName.YourProductName' and must contain only alphanumeric and hyphen characters."); + public static readonly GUIContent packageNameError = EditorGUIUtility.TrTextContent("The Package Name must follow the convention 'com.YourCompanyName.YourProductName' and must contain only alphanumeric and underscore characters. Each segment must start with an alphabetical character."); public static readonly GUIContent applicationBuildNumber = EditorGUIUtility.TrTextContent("Build"); public static readonly GUIContent appleDeveloperTeamID = EditorGUIUtility.TrTextContent("iOS Developer Team ID", "Developers can retrieve their Team ID by visiting the Apple Developer site under Account > Membership."); public static readonly GUIContent useOnDemandResources = EditorGUIUtility.TrTextContent("Use on-demand resources*"); @@ -177,8 +180,7 @@ class SettingsContent public static readonly GUIContent require31 = EditorGUIUtility.TrTextContent("Require ES3.1"); public static readonly GUIContent requireAEP = EditorGUIUtility.TrTextContent("Require ES3.1+AEP"); public static readonly GUIContent require32 = EditorGUIUtility.TrTextContent("Require ES3.2"); - public static readonly GUIContent skinOnGPU = EditorGUIUtility.TrTextContent("GPU Skinning*", "Use DX11/ES3 GPU Skinning"); - public static readonly GUIContent skinOnGPUCompute = EditorGUIUtility.TrTextContent("Compute Skinning*", "Use Compute pipeline for Skinning"); + public static readonly GUIContent skinOnGPU = EditorGUIUtility.TrTextContent("GPU Compute Skinning*", "Calculate mesh skinning and blend shapes on the GPU via compute shaders"); public static readonly GUIContent scriptingDefineSymbols = EditorGUIUtility.TrTextContent("Scripting Define Symbols", "Preprocessor defines passed to the C# script compiler."); public static readonly GUIContent additionalCompilerArguments = EditorGUIUtility.TrTextContent("Additional Compiler Arguments", "Additional arguments passed to the C# script compiler."); public static readonly GUIContent scriptingDefineSymbolsApply = EditorGUIUtility.TrTextContent("Apply"); @@ -188,6 +190,8 @@ class SettingsContent public static readonly GUIContent scriptingBackend = EditorGUIUtility.TrTextContent("Scripting Backend"); public static readonly GUIContent managedStrippingLevel = EditorGUIUtility.TrTextContent("Managed Stripping Level", "If scripting backend is IL2CPP, managed stripping can't be disabled."); public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); + public static readonly GUIContent il2cppCodeGeneration = EditorGUIUtility.TrTextContent("IL2CPP Code Generation", "Determines whether IL2CPP should generate code optimized for runtime performance or build size/iteration."); + public static readonly GUIContent[] il2cppCodeGenerationNames = new GUIContent[] { EditorGUIUtility.TrTextContent("Faster runtime"), EditorGUIUtility.TrTextContent("Faster (smaller) builds") }; public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent("IL2CPP"); public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent("Default"); @@ -421,6 +425,7 @@ PlayerSettingsIconsEditor iconsEditor SerializedProperty m_APICompatibilityLevel; SerializedProperty m_DefaultAPICompatibilityLevel; SerializedProperty m_Il2CppCompilerConfiguration; + SerializedProperty m_Il2CppCodeGeneration; SerializedProperty m_ScriptingDefines; SerializedProperty m_AdditionalCompilerArguments; SerializedProperty m_StackTraceTypes; @@ -564,6 +569,7 @@ void OnEnable() m_APICompatibilityLevel = FindPropertyAssert("apiCompatibilityLevelPerPlatform"); m_DefaultAPICompatibilityLevel = FindPropertyAssert("apiCompatibilityLevel"); m_Il2CppCompilerConfiguration = FindPropertyAssert("il2cppCompilerConfiguration"); + m_Il2CppCodeGeneration = FindPropertyAssert("il2cppCodeGeneration"); m_ScriptingDefines = FindPropertyAssert("scriptingDefineSymbols"); m_StackTraceTypes = FindPropertyAssert("m_StackTraceTypes"); m_ManagedStrippingLevel = FindPropertyAssert("managedStrippingLevel"); @@ -1123,7 +1129,11 @@ static private string GraphicsDeviceTypeToString(BuildTarget target, GraphicsDev if (name.Contains("OpenGLES")) name += " (Deprecated)"; } - if (name == "Direct3D12") + else if (graphicsDeviceType == GraphicsDeviceType.OpenGLES2) + { + name += " (Deprecated)"; + } + else if (name == "Direct3D12") name = "Direct3D12 (Experimental)"; return name; } @@ -1834,13 +1844,8 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, ISettingEditorExte // GPU Skinning toggle (only show on relevant platforms) if (!BuildTargetDiscovery.PlatformHasFlag(platform.defaultTarget, TargetAttributes.GPUSkinningNotSupported)) { - GraphicsDeviceType[] gfxAPIs = PlayerSettings.GetGraphicsAPIs(platform.defaultTarget); - bool computeSkinningOnly = - gfxAPIs[0] != GraphicsDeviceType.XboxOneD3D12 && - gfxAPIs[0] != GraphicsDeviceType.Direct3D11 && - gfxAPIs[0] != GraphicsDeviceType.Direct3D12; EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_SkinOnGPU, computeSkinningOnly ? SettingsContent.skinOnGPUCompute : SettingsContent.skinOnGPU); + EditorGUILayout.PropertyField(m_SkinOnGPU, SettingsContent.skinOnGPU); if (EditorGUI.EndChangeCheck()) { ShaderUtil.RecreateSkinnedMeshResources(); @@ -2248,11 +2253,21 @@ internal void ShowPlatformIconsByKind(PlatformIconFieldGroup iconFieldGroup, boo m_IconsEditor.ShowPlatformIconsByKind(iconFieldGroup, foldByKind, foldBySubkind); } + internal static GUIContent GetApplicationIdentifierError(BuildTargetGroup targetGroup) + { + if (targetGroup == BuildTargetGroup.Android) + return SettingsContent.packageNameError; + + return SettingsContent.applicationIdentifierError; + } + internal static void ShowApplicationIdentifierUI(SerializedProperty prop, BuildTargetGroup targetGroup, bool overrideDefaultID, string defaultID, string label, string tooltip) { var oldIdentifier = ""; - string currentIdentifier = PlayerSettings.SanitizeApplicationIdentifier(defaultID, targetGroup); + var currentIdentifier = PlayerSettings.SanitizeApplicationIdentifier(defaultID, targetGroup); var buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(targetGroup); + var warningMessage = SettingsContent.applicationIdentifierWarning.text; + var errorMessage = GetApplicationIdentifierError(targetGroup).text; if (!prop.serializedObject.isEditingMultipleObjects) { @@ -2269,13 +2284,14 @@ internal static void ShowApplicationIdentifierUI(SerializedProperty prop, BuildT prop.SetMapValue(buildTargetGroup, currentIdentifier); } + EditorGUILayout.BeginVertical(); EditorGUI.BeginChangeCheck(); using (new EditorGUI.DisabledScope(!overrideDefaultID)) { var sanitizedIdentifier = PlayerSettings.SanitizeApplicationIdentifier(currentIdentifier, targetGroup); - if (overrideDefaultID && sanitizedIdentifier != currentIdentifier) - Debug.LogError("Invalid characters have been removed from the Applicaton Identifier"); + if (currentIdentifier != oldIdentifier && (sanitizedIdentifier != currentIdentifier || currentIdentifier != defaultID)) + Debug.LogError(warningMessage); currentIdentifier = sanitizedIdentifier; currentIdentifier = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(label, tooltip), currentIdentifier); } @@ -2283,11 +2299,18 @@ internal static void ShowApplicationIdentifierUI(SerializedProperty prop, BuildT if (EditorGUI.EndChangeCheck()) { var sanitizedIdentifier = PlayerSettings.SanitizeApplicationIdentifier(currentIdentifier, targetGroup); - if (overrideDefaultID && sanitizedIdentifier != currentIdentifier) - Debug.LogError("Invalid characters have been removed from the Applicaton Identifier"); + if (currentIdentifier != oldIdentifier && (sanitizedIdentifier != currentIdentifier || currentIdentifier != defaultID)) + Debug.LogError(warningMessage); currentIdentifier = sanitizedIdentifier; prop.SetMapValue(buildTargetGroup, currentIdentifier); } + + if (!PlayerSettings.IsApplicationIdentifierValid(currentIdentifier, targetGroup)) + EditorGUILayout.HelpBox(errorMessage, MessageType.Error); + else if (!overrideDefaultID && currentIdentifier != defaultID) + EditorGUILayout.HelpBox(warningMessage, MessageType.Warning); + + EditorGUILayout.EndVertical(); } } @@ -2327,6 +2350,13 @@ private Il2CppCompilerConfiguration GetCurrentIl2CppCompilerConfigurationForTarg else return Il2CppCompilerConfiguration.Release; } + private Il2CppCodeGeneration GetCurrentIl2CppCodeGenerationForTarget(NamedBuildTarget namedBuildTarget) + { + if (m_Il2CppCodeGeneration.TryGetMapEntry(namedBuildTarget.TargetName, out var entry)) + return (Il2CppCodeGeneration)entry.FindPropertyRelative("second").intValue; + else + return Il2CppCodeGeneration.OptimizeSpeed; + } private ManagedStrippingLevel GetCurrentManagedStrippingLevelForTarget(NamedBuildTarget namedBuildTarget, ScriptingImplementation backend) { @@ -2441,6 +2471,27 @@ private void OtherSectionConfigurationGUI(BuildPlatform platform, ISettingEditor } } + // Il2cpp Code Generation + using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects)) + { + using (var horizontal = new EditorGUILayout.HorizontalScope()) + { + using (var propertyScope = new EditorGUI.PropertyScope(horizontal.rect, GUIContent.none, m_Il2CppCodeGeneration)) + { + using (new EditorGUI.DisabledScope(currentBackend != ScriptingImplementation.IL2CPP)) + { + var currentCodeGeneration = GetCurrentIl2CppCodeGenerationForTarget(platform.namedBuildTarget); + + var codeGenerationValues = new [] { Il2CppCodeGeneration.OptimizeSpeed, Il2CppCodeGeneration.OptimizeSize }; + var newCodeGeneration = BuildEnumPopup(SettingsContent.il2cppCodeGeneration, currentCodeGeneration, codeGenerationValues, SettingsContent.il2cppCodeGenerationNames); + + if (currentCodeGeneration != newCodeGeneration) + m_Il2CppCodeGeneration.SetMapValue(platform.namedBuildTarget.TargetName, (int)newCodeGeneration); + } + } + } + } + // Il2cpp Compiler Configuration using (new EditorGUI.DisabledScope(m_SerializedObject.isEditingMultipleObjects)) { diff --git a/Editor/Mono/Inspector/PreviewRenderUtility.cs b/Editor/Mono/Inspector/PreviewRenderUtility.cs index c083a67613..260924c6ac 100644 --- a/Editor/Mono/Inspector/PreviewRenderUtility.cs +++ b/Editor/Mono/Inspector/PreviewRenderUtility.cs @@ -153,12 +153,12 @@ public PreviewRenderUtility() { if (m_Type != null) { - Debug.LogErrorFormat("{0} created a PreviewRenderUtility but didn't call its Cleanup() during OnDisable. This is leaking the Preview scene in the Editor and should be fixed.", m_Type); + Debug.LogErrorFormat("{0} created a PreviewRenderUtility but didn't call its Cleanup() during OnDisable (or its execution was interrupted). This is leaking the Preview scene in the Editor and should be fixed.", m_Type); } else { Debug.LogError("A PreviewRenderUtility was not clean up properly before assembly reloading which lead to leaking this scene in the Editor. " + - "This can be caused by not calling Cleanup() during the OnDisable of an Editor or an EditorWindow."); + "This can be caused by not calling Cleanup() (or its execution being interrupted) during the OnDisable of an Editor or an EditorWindow."); } } diff --git a/Editor/Mono/Inspector/PropertyEditor.cs b/Editor/Mono/Inspector/PropertyEditor.cs index c3528cd242..1573176c17 100644 --- a/Editor/Mono/Inspector/PropertyEditor.cs +++ b/Editor/Mono/Inspector/PropertyEditor.cs @@ -19,6 +19,7 @@ using Object = UnityEngine.Object; using AssetImporterEditor = UnityEditor.AssetImporters.AssetImporterEditor; using JetBrains.Annotations; +using Unity.Profiling; namespace UnityEditor { @@ -66,6 +67,16 @@ class PropertyEditor : EditorWindow, IPropertyView, IHasCustomMenu protected const long delayRepaintWhilePlayingAnimation = 150; // Delay between repaints in milliseconds while playing animation protected long m_LastUpdateWhilePlayingAnimation = 0; + /// + /// The number of inspector elements to create on the initial draw. + /// + const int k_CreateInspectorElementMinCount = 2; + + /// + /// The target number of milliseconds to spend on creating inspector elements per update. + /// + const int k_CreateInspectorElementTargetUpdateTime = 5; + [SerializeField] protected List m_ObjectsLockedBeforeSerialization = new List(); [SerializeField] protected List m_InstanceIDsLockedBeforeSerialization = new List(); [SerializeField] protected PreviewResizer m_PreviewResizer = new PreviewResizer(); @@ -116,6 +127,8 @@ class PropertyEditor : EditorWindow, IPropertyView, IHasCustomMenu internal static PropertyEditor HoveredPropertyEditor { get; private set; } internal static PropertyEditor FocusedPropertyEditor { get; private set; } + EditorElementUpdater m_EditorElementUpdater; + public InspectorMode inspectorMode { get { return m_InspectorMode; } @@ -276,6 +289,7 @@ internal PropertyEditor() { editorDragging = new EditorDragging(this); minSize = new Vector2(k_MinimumWindowWidth, minSize.y); + m_EditorElementUpdater = new EditorElementUpdater(this); } [UsedImplicitly] @@ -410,6 +424,8 @@ protected virtual void Update() wantsRepaint = true; } + m_EditorElementUpdater.CreateInspectorElementsForMilliseconds(k_CreateInspectorElementTargetUpdateTime); + if (wantsRepaint && m_lastRenderedTime + 0.033f < EditorApplication.timeSinceStartup) { m_lastRenderedTime = EditorApplication.timeSinceStartup; @@ -428,6 +444,7 @@ protected void SetMode(InspectorMode mode) RefreshTitle(); // Clear the editors Element so that a real rebuild is done editorsElement.Clear(); + m_EditorElementUpdater.Clear(); tracker.inspectorMode = mode; m_ResetKeyboardControl = true; SceneView.SetActiveEditorsDirty(true); @@ -519,6 +536,7 @@ private void SetUseUIEDefaultInspector() useUIElementsDefaultInspector = !useUIElementsDefaultInspector; // Clear the editors Element so that a real rebuild is done editorsElement.Clear(); + m_EditorElementUpdater.Clear(); RebuildContentsContainers(); } @@ -860,6 +878,8 @@ public IMGUIContainer CreateIMGUIContainer(Action onGUIHandler, string name = nu return result; } + static readonly ProfilerMarker k_CreateInspectorElements = new ProfilerMarker("PropertyEditor.CreateInspectorElements"); + protected virtual void BeginRebuildContentContainers() {} protected virtual void EndRebuildContentContainers() {} internal virtual void RebuildContentsContainers() @@ -943,6 +963,19 @@ internal virtual void RebuildContentsContainers() previewAndLabelElement.Add(previewAndLabelsContainer); } + k_CreateInspectorElements.Begin(); + // Only trigger the fixed count and viewport creation if this is the first build. Otherwise let the update method handle it. + if (m_EditorElementUpdater.Position == 0) + { + // Force create a certain number of inspector elements without invoking a layout pass. + // We always want a minimum number of elements to be added. + m_EditorElementUpdater.CreateInspectorElementsWithoutLayout(k_CreateInspectorElementMinCount); + + // Continue creating elements until the viewport is full. + m_EditorElementUpdater.CreateInspectorElementsForViewport(m_ScrollView, editorsElement); + } + k_CreateInspectorElements.End(); + rootVisualElement.MarkDirtyRepaint(); ScriptAttributeUtility.ClearGlobalCache(); @@ -1662,6 +1695,7 @@ private void DrawEditors(Editor[] editors) if (mapping == null) { editorsElement.Clear(); + m_EditorElementUpdater.Clear(); } if (editors.Length == 0) @@ -1678,11 +1712,10 @@ private void DrawEditors(Editor[] editors) if (m_RemovedComponents == null) ExtractPrefabComponents(); // needed after assembly reload (due to HashSet not being serializable) - bool checkForRemovedComponents = m_ComponentsInPrefabSource != null; int prefabComponentIndex = -1; int targetGameObjectIndex = -1; GameObject targetGameObject = null; - if (checkForRemovedComponents) + if (m_ComponentsInPrefabSource != null) { targetGameObjectIndex = editors[0] is PrefabImporterEditor ? 1 : 0; targetGameObject = (GameObject)editors[targetGameObjectIndex].target; @@ -1692,7 +1725,7 @@ private void DrawEditors(Editor[] editors) { editors[editorIndex].propertyViewer = this; VisualElement prefabsComponentElement = new VisualElement() { name = "PrefabComponentElement" }; - if (checkForRemovedComponents && editorIndex > targetGameObjectIndex) + if (m_ComponentsInPrefabSource != null && editorIndex > targetGameObjectIndex) { if (prefabComponentIndex == -1) prefabComponentIndex = 0; @@ -1735,6 +1768,9 @@ private void DrawEditors(Editor[] editors) culledEditorContainer = EditorUIService.instance.CreateCulledEditorElement(editorIndex, this, editorTitle); editorsElement.Add(culledEditorContainer as VisualElement); + + if (!EditorUIService.disableInspectorElementThrottling) + m_EditorElementUpdater.Add(culledEditorContainer); } continue; @@ -1747,6 +1783,9 @@ private void DrawEditors(Editor[] editors) $"{editor.GetType().Name}_{editorTarget.GetType().Name}_{editorTarget.GetInstanceID()}"; editorContainer = EditorUIService.instance.CreateEditorElement(editorIndex, this, editorTitle); editorsElement.Add(editorContainer as VisualElement); + + if (!EditorUIService.disableInspectorElementThrottling) + m_EditorElementUpdater.Add(editorContainer); } if (prefabsComponentElement.childCount > 0) @@ -1771,10 +1810,10 @@ private void DrawEditors(Editor[] editors) } // Make sure to display any remaining removed components that come after the last component on the GameObject. - if (checkForRemovedComponents) + if (m_ComponentsInPrefabSource != null) { VisualElement prefabsComponentElement = new VisualElement() { name = "RemainingPrefabComponentElement" }; - while (prefabComponentIndex < m_ComponentsInPrefabSource.Length) + while (prefabComponentIndex > -1 && prefabComponentIndex < m_ComponentsInPrefabSource.Length) { Component nextInSource = m_ComponentsInPrefabSource[prefabComponentIndex]; AddRemovedPrefabComponentElement(targetGameObject, nextInSource, prefabsComponentElement); diff --git a/Editor/Mono/Inspector/ReflectionProbeEditor.cs b/Editor/Mono/Inspector/ReflectionProbeEditor.cs index a0e1e5080a..a9eb5df846 100644 --- a/Editor/Mono/Inspector/ReflectionProbeEditor.cs +++ b/Editor/Mono/Inspector/ReflectionProbeEditor.cs @@ -92,24 +92,27 @@ static Styles() public static string[] bakeButtonsText = { "Bake All Reflection Probes" }; public static GUIContent bakeCustomButtonText = EditorGUIUtility.TrTextContent("Bake", "Bakes Reflection Probe's cubemap, overwriting the existing cubemap texture asset (if any)."); - public static GUIContent runtimeSettingsHeader = EditorGUIUtility.TrTextContent("Runtime Settings", "These settings are used by objects when they render with the cubemap of this probe"); + public static GUIContent runtimeSettingsHeader = EditorGUIUtility.TrTextContent("Runtime Settings", "These settings determine this Probe's priority, blending, intensity, and zone of effect and works in conjunction with the cubemap of this probe when it is rendered."); public static GUIContent backgroundColorText = EditorGUIUtility.TrTextContent("Background Color", "Camera clears the screen to this color before rendering."); - public static GUIContent clearFlagsText = EditorGUIUtility.TrTextContent("Clear Flags"); - public static GUIContent intensityText = EditorGUIUtility.TrTextContent("Intensity"); - public static GUIContent resolutionText = EditorGUIUtility.TrTextContent("Resolution"); - public static GUIContent captureCubemapHeader = EditorGUIUtility.TrTextContent("Cubemap Capture Settings"); - public static GUIContent boxProjectionText = EditorGUIUtility.TrTextContent("Box Projection", "Box projection causes reflections to appear to change based on the object's position within the probe's box, while still using a single probe as the source of the reflection. This works well for reflections on objects that are moving through enclosed spaces such as corridors and rooms. Setting box projection to False and the cubemap reflection will be treated as coming from infinitely far away. Note that this feature can be globally disabled from Graphics Settings -> Tier Settings"); + public static GUIContent clearFlagsText = EditorGUIUtility.TrTextContent("Clear Flags", "Specify how to fill empty areas of the cubemap."); + public static GUIContent intensityText = EditorGUIUtility.TrTextContent("Intensity", "The intensity modifier the Editor applies to this probe's texture in its shader."); + public static GUIContent resolutionText = EditorGUIUtility.TrTextContent("Resolution", "The resolution of the cubemap."); + public static GUIContent captureCubemapHeader = EditorGUIUtility.TrTextContent("Cubemap Capture Settings", "Settings that determine how to render this probe's cubemap."); + public static GUIContent boxProjectionText = EditorGUIUtility.TrTextContent("Box Projection", "When enabled, Unity assumes that the reflected light is originating from the inside of the probe's box, rather than from infinitely far away. This is useful for box-shaped indoor environments."); public static GUIContent blendDistanceText = EditorGUIUtility.TrTextContent("Blend Distance", "Area around the probe where it is blended with other probes. Only used in deferred probes."); public static GUIContent sizeText = EditorGUIUtility.TrTextContent("Box Size", "The size of the box in which the reflections will be applied to objects. The value is not affected by the Transform of the Game Object."); public static GUIContent centerText = EditorGUIUtility.TrTextContent("Box Offset", "The center of the box in which the reflections will be applied to objects. The value is relative to the position of the Game Object."); - public static GUIContent customCubemapText = EditorGUIUtility.TrTextContent("Cubemap"); - public static GUIContent importanceText = EditorGUIUtility.TrTextContent("Importance"); + public static GUIContent customCubemapText = EditorGUIUtility.TrTextContent("Cubemap", "Sets a custom cubemap for this probe."); + public static GUIContent importanceText = EditorGUIUtility.TrTextContent("Importance", "When reflection probes overlap, Unity uses Importance to determine which probe should take priority."); public static GUIContent renderDynamicObjects = EditorGUIUtility.TrTextContent("Dynamic Objects", "If enabled dynamic objects are also rendered into the cubemap"); public static GUIContent timeSlicing = EditorGUIUtility.TrTextContent("Time Slicing", "If enabled this probe will update over several frames, to help reduce the impact on the frame rate"); public static GUIContent refreshMode = EditorGUIUtility.TrTextContent("Refresh Mode", "Controls how this probe refreshes in the Player"); - public static GUIContent useOcclusionCulling = EditorGUIUtility.TrTextContent("Occlusion Culling"); + public static GUIContent useOcclusionCulling = EditorGUIUtility.TrTextContent("Occlusion Culling", "If this property is enabled, geometries which are blocked from the probe's line of sight are skipped during rendering."); + public static GUIContent hdrText = EditorGUIUtility.TrTextContent("HDR", "Enable High Dynamic Range rendering."); + public static GUIContent shadowDistanceText = EditorGUIUtility.TrTextContent("Shadow Distance", "Maximum distance at which Unity renders shadows associated with this probe."); + public static GUIContent cullingMaskText = EditorGUIUtility.TrTextContent("Culling Mask", "Allows objects on specified layers to be included or excluded in the reflection."); - public static GUIContent typeText = EditorGUIUtility.TrTextContent("Type", "'Baked Cubemap' uses the 'Auto Baking' mode from the Lighting window. If it is enabled, then baking is automatic otherwise manual bake is needed (use the bake button below). \n'Custom' can be used if a custom cubemap is wanted. \n'Realtime' can be used to dynamically re-render the cubemap during runtime (via scripting)."); + public static GUIContent typeText = EditorGUIUtility.TrTextContent("Type", "Specify the lighting setup for this probe: Baked, Custom, or Realtime."); public static GUIContent[] reflectionProbeMode = { EditorGUIUtility.TrTextContent("Baked"), EditorGUIUtility.TrTextContent("Custom"), EditorGUIUtility.TrTextContent("Realtime") }; public static int[] reflectionProbeModeValues = { (int)ReflectionProbeMode.Baked, (int)ReflectionProbeMode.Custom, (int)ReflectionProbeMode.Realtime }; @@ -123,9 +126,13 @@ static Styles() }; public static int[] clearFlagsValues = { 1, 2 }; // taken from Camera.h + private static GUIContent customPrivitiveBoundsHandleEditModeButton = new GUIContent( + EditorGUIUtility.IconContent("EditCollider").image, + EditorGUIUtility.TrTextContent("Adjust the probe's zone of effect. Holding Alt or Shift and click the control handle to pin the center or scale the volume uniformly.").text + ); public static GUIContent[] toolContents = { - PrimitiveBoundsHandle.editModeButton, + customPrivitiveBoundsHandleEditModeButton, EditorGUIUtility.TrIconContent("MoveTool", "Move the selected objects.") }; public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[] @@ -519,11 +526,11 @@ public override void OnInspectorGUI() GetResolutionArray(ref reflectionResolutionValuesArray, ref reflectionResolutionTextArray); EditorGUILayout.IntPopup(m_Resolution, reflectionResolutionTextArray, reflectionResolutionValuesArray, Styles.resolutionText, GUILayout.MinWidth(40)); - EditorGUILayout.PropertyField(m_HDR); - EditorGUILayout.PropertyField(m_ShadowDistance); + EditorGUILayout.PropertyField(m_HDR, Styles.hdrText); + EditorGUILayout.PropertyField(m_ShadowDistance, Styles.shadowDistanceText); EditorGUILayout.IntPopup(m_ClearFlags, Styles.clearFlags, Styles.clearFlagsValues, Styles.clearFlagsText); EditorGUILayout.PropertyField(m_BackgroundColor, Styles.backgroundColorText); - EditorGUILayout.PropertyField(m_CullingMask); + EditorGUILayout.PropertyField(m_CullingMask, Styles.cullingMaskText); EditorGUILayout.PropertyField(m_UseOcclusionCulling, Styles.useOcclusionCulling); EditorGUILayout.PropertiesField(EditorGUI.s_ClipingPlanesLabel, m_NearAndFarProperties, EditorGUI.s_NearAndFarLabels, EditorGUI.kNearFarLabelsWidth); diff --git a/Editor/Mono/Inspector/RenderTextureEditor.cs b/Editor/Mono/Inspector/RenderTextureEditor.cs index fa6d197948..68d9dd4a2b 100644 --- a/Editor/Mono/Inspector/RenderTextureEditor.cs +++ b/Editor/Mono/Inspector/RenderTextureEditor.cs @@ -156,7 +156,7 @@ protected void OnRenderTextureGUI(GUIElements guiElements) EditorGUILayout.PropertyField(m_DepthStencilFormat, styles.depthStencilFormat); } - if (isDepthStencilFormatIncompatible && depthStencilFormat != compatibleDepthStencilFormat) + if (depthStencilFormat != compatibleDepthStencilFormat) { string text = string.Format("Format {0} is not supported on this platform. ", depthStencilFormat.ToString()); if (compatibleDepthStencilFormat != GraphicsFormat.None) diff --git a/Editor/Mono/Inspector/ReorderableListWrapper.cs b/Editor/Mono/Inspector/ReorderableListWrapper.cs index a0d3941800..b0c7608afa 100644 --- a/Editor/Mono/Inspector/ReorderableListWrapper.cs +++ b/Editor/Mono/Inspector/ReorderableListWrapper.cs @@ -102,9 +102,9 @@ internal void ClearCache() m_ReorderableList.ClearCache(); } - public float GetHeight(bool includeChildren) + public float GetHeight() { - return m_HeaderHeight + (includeChildren && Property.isExpanded && m_ReorderableList != null ? Constants.kHeaderPadding + m_ReorderableList.GetHeight() : 0.0f); + return m_HeaderHeight + (Property.isExpanded && m_ReorderableList != null ? Constants.kHeaderPadding + m_ReorderableList.GetHeight() : 0.0f); } public void Draw(GUIContent label, Rect r, Rect visibleArea, string tooltip, bool includeChildren) @@ -158,8 +158,6 @@ public void Draw(GUIContent label, Rect r, Rect visibleArea, string tooltip, boo m_ReorderableList.ClearCacheRecursive(); } - if (!includeChildren) return; - DrawChildren(r, headerRect, sizeRect, visibleArea, prevType); } diff --git a/Editor/Mono/Inspector/RootEditor.cs b/Editor/Mono/Inspector/RootEditor.cs index 5a4af33eb5..af4ebca087 100644 --- a/Editor/Mono/Inspector/RootEditor.cs +++ b/Editor/Mono/Inspector/RootEditor.cs @@ -37,6 +37,7 @@ internal class RootEditorDesc public bool supportsAddComponent; } + private static bool s_SuppressRootEditor = false; private static readonly List kSRootEditor = new List(); static RootEditorUtils() @@ -44,6 +45,19 @@ static RootEditorUtils() Rebuild(); } + internal static Editor CreateNonRootEditor(UnityEngine.Object[] objects) + { + try + { + s_SuppressRootEditor = true; + return Editor.CreateEditor(objects); + } + finally + { + s_SuppressRootEditor = false; + } + } + internal static bool SupportsAddComponent(Editor[] editors) { if (editors.Length != 1) @@ -61,6 +75,8 @@ internal static bool SupportsAddComponent(Editor[] editors) internal static Type FindRootEditor(UnityEngine.Object[] objects) { + if (s_SuppressRootEditor) + return null; foreach (var desc in kSRootEditor) { var rootEditorType = desc.needsRootEditor(objects); diff --git a/Editor/Mono/Inspector/SortingGroupEditor.cs b/Editor/Mono/Inspector/SortingGroupEditor.cs index 2f08dfd8c8..ef7332e05b 100644 --- a/Editor/Mono/Inspector/SortingGroupEditor.cs +++ b/Editor/Mono/Inspector/SortingGroupEditor.cs @@ -12,20 +12,30 @@ namespace UnityEditor [CanEditMultipleObjects] internal class SortingGroupEditor : Editor { + private static class Styles + { + public static GUIContent m_SortAtRootStyle = EditorGUIUtility.TrTextContent("Sort At Root" + , "Ignores all parent Sorting Groups and sorts at the root level against other Sorting Groups and Renderers"); + } + + private SerializedProperty m_SortingOrder; private SerializedProperty m_SortingLayerID; + private SerializedProperty m_SortAtRoot; public virtual void OnEnable() { alwaysAllowExpansion = true; m_SortingOrder = serializedObject.FindProperty("m_SortingOrder"); m_SortingLayerID = serializedObject.FindProperty("m_SortingLayerID"); + m_SortAtRoot = serializedObject.FindProperty("m_SortAtRoot"); } public override void OnInspectorGUI() { serializedObject.Update(); SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID); + EditorGUILayout.PropertyField(m_SortAtRoot, Styles.m_SortAtRootStyle); serializedObject.ApplyModifiedProperties(); } } diff --git a/Editor/Mono/Inspector/SpriteFrameInspector.cs b/Editor/Mono/Inspector/SpriteFrameInspector.cs index 097f31f453..92d63aa511 100644 --- a/Editor/Mono/Inspector/SpriteFrameInspector.cs +++ b/Editor/Mono/Inspector/SpriteFrameInspector.cs @@ -20,7 +20,7 @@ private static class Styles public static readonly GUIContent nameLabel = EditorGUIUtility.TrTextContent("Name", "The name for the Sprite."); public static readonly GUIContent spriteAlignmentLabel = EditorGUIUtility.TrTextContent("Pivot", "The value is normalized to the Sprite's size where (0, 0) is the lower left and (1, 1) is the upper right. May be used for syncing animation frames of different sizes."); public static readonly GUIContent spriteAlignmentText = EditorGUIUtility.TrTextContent("X:{0:0.##}, Y:{1:0.##}"); - public static readonly GUIContent borderLabel = EditorGUIUtility.TrTextContent("Border", "Border values for the Sprite set in Sprite Editor window. May be useful for 9-Slicing Sprites."); + public static readonly GUIContent borderLabel = EditorGUIUtility.TrTextContent("Border", "Border values for the Sprite set in Sprite Editor window. May be useful for 9-Slicing Sprites. The values are in pixels units."); public static readonly GUIContent borderText = EditorGUIUtility.TrTextContent("L:{0:0.##} B:{1:0.##} R:{2:0.##} T:{3:0.##}"); public static readonly GUIContent multiValueText = EditorGUIUtility.TrTextContent("-"); } @@ -37,7 +37,7 @@ void OnEnable() { m_Name = serializedObject.FindProperty("m_Name"); m_Pivot = serializedObject.FindProperty("m_Pivot"); - m_BorderValue = GetSpriteBorderValue(sprite); + m_BorderValue = sprite.border; CheckBorderHasSameValue(); m_SpriteNameContent = new GUIContent(sprite.name); @@ -45,14 +45,6 @@ void OnEnable() m_SpriteBorderContent = new GUIContent(UnityString.Format(Styles.borderText.text, m_BorderValue.x, m_BorderValue.y, m_BorderValue.z, m_BorderValue.w)); } - Vector4 GetSpriteBorderValue(Sprite sprite) - { - return new Vector4(sprite.border.x / sprite.rect.width, - sprite.border.y / sprite.rect.height, - sprite.border.z / sprite.rect.width, - sprite.border.w / sprite.rect.height); - } - void CheckBorderHasSameValue() { foreach (var obj in serializedObject.targetObjects) @@ -62,7 +54,7 @@ void CheckBorderHasSameValue() if (obj is Sprite) { var spr = (Sprite)obj; - var borderValue = GetSpriteBorderValue(spr); + var borderValue = spr.border; if (borderValue != m_BorderValue) { m_BorderHasSameValue = false; diff --git a/Editor/Mono/InternalEditorUtility.bindings.cs b/Editor/Mono/InternalEditorUtility.bindings.cs index 2b3fcb51d7..c52fcafe82 100644 --- a/Editor/Mono/InternalEditorUtility.bindings.cs +++ b/Editor/Mono/InternalEditorUtility.bindings.cs @@ -12,6 +12,8 @@ using System.Globalization; using Unity.CodeEditor; using TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; namespace UnityEditorInternal { @@ -35,6 +37,31 @@ public enum DllType WinMDNET40 = 6 } + [RequiredByNativeCode] + internal class LoadFileAndForgetOperationHelper + { + // When the load operation completes this is invoked to hold the result so that it doesn't + // get garbage collected + [RequiredByNativeCode] + public static void SetObjectResult(LoadFileAndForgetOperation op, UnityEngine.Object result) + { + op.m_ObjectReference = result; + } + } + + [StructLayout(LayoutKind.Sequential)] + [RequiredByNativeCode] + public class LoadFileAndForgetOperation : AsyncOperation + { + internal UnityEngine.Object m_ObjectReference; + + public extern UnityEngine.Object Result + { + [NativeMethod("GetRequestedObject")] + get; + } + } + [NativeHeader("Editor/Src/InternalEditorUtility.bindings.h")] [NativeHeader("Editor/Mono/MonoEditorUtility.h")] @@ -57,6 +84,7 @@ public enum DllType [NativeHeader("Editor/Src/Gizmos/GizmoUtil.h")] [NativeHeader("Editor/Src/HierarchyState.h")] [NativeHeader("Editor/Src/InspectorExpandedState.h")] + [NativeHeader("Editor/Src/LoadFileAndForgetOperation.h")] [NativeHeader("Runtime/Interfaces/ILicensing.h")] [NativeHeader("Editor/Src/RemoteInput/RemoteInput.h")] [NativeHeader("Editor/Src/ShaderMenu.h")] @@ -173,9 +201,6 @@ public static CanAppendBuild BuildCanBeAppended(BuildTarget target, string locat return (CanAppendBuild)BuildPipeline.BuildCanBeAppended(target, location); } - [FreeFunction("InternalEditorUtilityBindings::RegisterExtensionDll")] - extern internal static void RegisterExtensionDll(string dllLocation, string guid); - [FreeFunction] extern internal static void RegisterPlatformModuleAssembly(string dllName, string dllLocation); @@ -244,6 +269,9 @@ public static void SaveToSerializedFileAndForget(Object[] obj, string path, bool [FreeFunction("InternalEditorUtilityBindings::LoadSerializedFileAndForget")] extern public static Object[] LoadSerializedFileAndForget(string path); + [FreeFunction("LoadFileAndForgetOperation::LoadSerializedFileAndForgetAsync")] + extern public static LoadFileAndForgetOperation LoadSerializedFileAndForgetAsync(string path, long localIdentifierInFile, ulong offsetInFile=0, long fileSize=-1); + [FreeFunction("InternalEditorUtilityBindings::ProjectWindowDrag")] extern public static DragAndDropVisualMode ProjectWindowDrag(HierarchyProperty property, bool perform); @@ -866,6 +894,9 @@ internal static PrecompiledAssembly[] GetUnityAssemblies(bool buildingForEditor, [FreeFunction("GetPrecompiledAssembliesManaged")] extern internal static PrecompiledAssembly[] GetPrecompiledAssemblies(bool buildingForEditor, BuildTargetGroup buildTargetGroup, BuildTarget target, string[] extraScriptingDefines = null); + [FreeFunction("GetPrecompiledAssemblyPathsManaged")] + extern internal static string[] GetPrecompiledAssemblyPaths(); + [Obsolete("The Module Manager is deprecated", error: true)] [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] public static void ShowPackageManagerWindow() { throw new NotSupportedException("The Module Manager is deprecated"); } diff --git a/Editor/Mono/LogEntries.bindings.cs b/Editor/Mono/LogEntries.bindings.cs index aeb4dc499b..a583996b8e 100644 --- a/Editor/Mono/LogEntries.bindings.cs +++ b/Editor/Mono/LogEntries.bindings.cs @@ -23,6 +23,7 @@ internal partial class LogEntry public int instanceID; public int identifier; public int globalLineIndex; + public int callstackTextStartUTF8; public int callstackTextStartUTF16; internal static extern void RemoveLogEntriesByMode(int mode); } diff --git a/Editor/Mono/Macros/MethodEvaluator.cs b/Editor/Mono/Macros/MethodEvaluator.cs index 0bcdc7ad0d..d299c3bca2 100644 --- a/Editor/Mono/Macros/MethodEvaluator.cs +++ b/Editor/Mono/Macros/MethodEvaluator.cs @@ -81,6 +81,33 @@ public static object Eval(string assemblyFile, string typeName, } } + private static Type TypeOrTypeName(object o) + { + switch (o) + { + case Type t: + return t; + case string s: + return Type.GetType(s); + default: + throw new FormatException($"Expected {o} to be a string or a Type. It is a {o.GetType()}"); + } + } + + private static Type[] TypesOrTypeNames(object o) + { + + switch (o) + { + case Type[] t: + return t; + case string[] s: + return s.Select(Type.GetType).ToArray(); + default: + throw new FormatException($"Expected {o} to be a string[] or a Type[]. It is a {o.GetType()}"); + } + } + public static object ExecuteExternalCode(string parcel) { using (var stream = new MemoryStream(Convert.FromBase64String(parcel))) @@ -89,38 +116,75 @@ public static object ExecuteExternalCode(string parcel) if (header != "com.unity3d.automation") throw new Exception("Invalid parcel for external code execution."); var assemblyPath = (string)s_Formatter.Deserialize(stream); - var resolver = new AssemblyResolver(Path.GetDirectoryName(assemblyPath)); - - AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve; - AppDomain.CurrentDomain.TypeResolve += resolver.TypeResolve; - - var assembly = Assembly.LoadFrom(assemblyPath); + AssemblyResolver resolver = null; + Assembly assembly = null; + if (assemblyPath != "netstandard") { + resolver = new AssemblyResolver(Path.GetDirectoryName(assemblyPath)); + + AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve; + AppDomain.CurrentDomain.TypeResolve += resolver.TypeResolve; + assembly = Assembly.LoadFrom(assemblyPath); + } try { - var type = (Type)s_Formatter.Deserialize(stream); + var type = TypeOrTypeName(s_Formatter.Deserialize(stream)); var methodName = (string)s_Formatter.Deserialize(stream); const BindingFlags methodVisibility = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; - var methodParametersTypes = (Type[])s_Formatter.Deserialize(stream); + var methodParametersTypes = TypesOrTypeNames(s_Formatter.Deserialize(stream)); var method = type.GetMethod(methodName, methodVisibility, null, methodParametersTypes, null); if (method == null) throw new Exception(string.Format( "Could not find method {0}.{1} in assembly {2} located in {3}.", - type.FullName, methodName, assembly.GetName().Name, assemblyPath)); + type.FullName, methodName, type.Assembly.GetName().Name, assemblyPath)); var arguments = (object[])s_Formatter.Deserialize(stream); + TransformArgumentsBack(methodParametersTypes, arguments); var returnValue = ExecuteCode(type, method, arguments); return returnValue; } finally { - AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve; + if (resolver != null) + { + AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve; + } + } + } + } + + private static void TransformArgumentsBack(Type[] argTypes, object[] args) + { + for(int i = 0; i new StreamingAssetsFile { File = e.src.ToString(), RelativePath = e.dst.ToString() }) .ToArray(), UseNewInputSystem = IsNewInputSystemEnabled(), - ManagedAssemblies = args.report.files + ManagedAssemblies = args.report.GetFiles() .Where(file => file.role == "ManagedLibrary" || file.role == "DependentManagedLibrary" || file.role == "ManagedEngineAPI") .Select(file => file.path.ToNPath()) .GroupBy(file => file.FileName) @@ -365,11 +366,16 @@ protected virtual IEnumerable GetDataForBuildProgramFor(BuildPostProcess yield return Il2CppConfigFor(args); } + protected virtual RunnableProgram BeeBackendProgram(BuildPostProcessArgs args) + { + return null; + } + void SetupBeeDriver(BuildPostProcessArgs args) { RunnableProgram buildProgram = MakePlayerBuildProgram(args); progressAPI = new PlayerBuildProgressAPI($"Building {args.productName}"); - Driver = UnityBeeDriver.Make(buildProgram, DagName(args), DagDirectory.ToString(), false, "", progressAPI); + Driver = UnityBeeDriver.Make(buildProgram, DagName(args), DagDirectory.ToString(), false, "", progressAPI, BeeBackendProgram(args)); foreach (var o in GetDataForBuildProgramFor(args)) { diff --git a/Editor/Mono/Modules/ModuleManager.cs b/Editor/Mono/Modules/ModuleManager.cs index 7e59608bed..eff6836d2e 100644 --- a/Editor/Mono/Modules/ModuleManager.cs +++ b/Editor/Mono/Modules/ModuleManager.cs @@ -31,8 +31,6 @@ internal static class ModuleManager [NonSerialized] static IPlatformSupportModule s_ActivePlatformModule; - private const string k_IsCacheBuildKey = "ModuleManagerIsExtensionsRegistered"; - internal static bool EnableLogging { get @@ -45,7 +43,6 @@ internal static Dictionary platformSupportModule { get { - InitializeModuleManager(); if (s_PlatformModules == null) RegisterPlatformSupportModules(); return s_PlatformModules; @@ -127,19 +124,6 @@ internal static void RegisterAdditionalUnityExtensions() } } - [NonSerialized] - static ProfilerMarker s_InitializeModuleManagerMarker = new ProfilerMarker("ModuleManager.InitializeModuleManager"); - - // entry point from native - [RequiredByNativeCode] - internal static void InitializeModuleManager() - { - using (s_InitializeModuleManagerMarker.Auto()) - { - RegisterPackageManager(); - } - } - // entry point from native // Note that in order for this function to work properly, it must be called between two domain // reloads. The first domain reload is needed because RegisterPlatformSupportModules() @@ -155,7 +139,6 @@ internal static void InitializePlatformSupportModules() return; } - InitializeModuleManager(); foreach (var module in platformSupportModules.Values) { foreach (var library in module.NativeLibraries) @@ -194,22 +177,6 @@ internal static void ShutdownModuleManager() s_PlatformModules = null; } - private static void RegisterPackageManager() - { - try - { - if (!SessionState.GetBool(k_IsCacheBuildKey, false)) - { - SessionState.SetBool(k_IsCacheBuildKey, true); - LoadLegacyExtensionsFromIvyFiles(); - } - } - catch (Exception ex) - { - Console.WriteLine("Error initializing extension manager. {0}", ex); - } - } - class IvyPackageFileData { public string filename; @@ -233,116 +200,6 @@ public static IvyPackageFileData CreateFromRegexMatch(Match match) } } - static void LoadLegacyExtensionsFromIvyFiles() - { - //We can't use the cached native type scanner here since this is called to early for that to be built up. - - HashSet ivyFiles; - try - { - ivyFiles = new HashSet(); - - string unityExtensionsFolder = FileUtil.CombinePaths(Directory.GetParent(EditorApplication.applicationPath).ToString(), "Data", "UnityExtensions"); - string playbackEngineFolders = FileUtil.CombinePaths(Directory.GetParent(EditorApplication.applicationPath).ToString(), "PlaybackEngines"); - - foreach (var searchPath in new[] - { - FileUtil.NiceWinPath(EditorApplication.applicationContentsPath), - FileUtil.NiceWinPath(unityExtensionsFolder), - FileUtil.NiceWinPath(playbackEngineFolders) - }) - { - if (!Directory.Exists(searchPath)) - continue; - - ivyFiles.UnionWith(Directory.GetFiles(searchPath, "ivy.xml", SearchOption.AllDirectories)); - } - } - catch (Exception ex) - { - Console.WriteLine("Error scanning for extension ivy.xml files: {0}", ex); - return; - } - - if (ivyFiles.Count == 0) - return; - - var packages = new Dictionary>(); - - var artifactRegex = new Regex(@"[^""]*)""|type=""(?[^""]*)""|ext=""(?[^""]*)""|e:guid=""(?[^""]*)""))+\s*/>", - RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture); - - foreach (var ivyFile in ivyFiles) - { - try - { - var ivyFileContent = File.ReadAllText(ivyFile); - var artifacts = artifactRegex.Matches(ivyFileContent).Cast() - .Select(IvyPackageFileData.CreateFromRegexMatch).ToList(); - if (artifacts.Count > 0) - { - var packageDir = Path.GetDirectoryName(ivyFile); - packages.Add(packageDir, artifacts); - } - } - catch (Exception ex) - { - Console.WriteLine("Error reading extensions from ivy.xml file at {0}: {1}", ivyFile, ex); - } - } - - try - { - foreach (var packageInfo in packages) - { - var files = packageInfo.Value; - foreach (var packageInfoFile in files) - { - string fullPath = Paths.NormalizePath(Path.Combine(packageInfo.Key, packageInfoFile.filename)); - - if (!File.Exists(fullPath)) - Debug.LogWarningFormat( - "Missing assembly \t{0} listed in ivy file {1}. Extension support may be incomplete.", fullPath, - packageInfo.Key); - - if (!packageInfoFile.IsDll) - continue; - - if (!string.IsNullOrEmpty(packageInfoFile.guid)) - { - InternalEditorUtility.RegisterExtensionDll(fullPath.Replace('\\', '/'), - packageInfoFile.guid); - } - else - { - InternalEditorUtility.RegisterPrecompiledAssembly(fullPath, fullPath); - } - } - } - } - catch (Exception ex) - { - Console.WriteLine("Error scanning for extensions. {0}", ex); - } - } - - static bool TryParseBuildTarget(string targetString, out BuildTargetGroup buildTargetGroup, out BuildTarget target) - { - buildTargetGroup = BuildTargetGroup.Standalone; - target = BuildTarget.StandaloneWindows; - try - { - target = (BuildTarget)Enum.Parse(typeof(BuildTarget), targetString); - buildTargetGroup = BuildPipeline.GetBuildTargetGroup(target); - return true; - } - catch - { - Debug.LogWarning(string.Format("Couldn't find build target for {0}", targetString)); - } - return false; - } - private static void RegisterPlatformSupportModules() { var allTypesWithInterface = TypeCache.GetTypesDerivedFrom(); diff --git a/Editor/Mono/ObjectListLocalGroup.cs b/Editor/Mono/ObjectListLocalGroup.cs index 19abbfff7f..c28d3d2cfb 100644 --- a/Editor/Mono/ObjectListLocalGroup.cs +++ b/Editor/Mono/ObjectListLocalGroup.cs @@ -1231,7 +1231,7 @@ private bool ShouldGetAssetPreview(int instanceId) string path = AssetDatabase.GetAssetPath(instanceId); if (m_AssetExtensionsPreviewIgnoreList.Contains(System.IO.Path.GetExtension(path).ToLowerInvariant())) return false; - Type assetDataType = AssetDatabase.GetMainAssetTypeAtPath(path); + Type assetDataType = InternalEditorUtility.GetTypeWithoutLoadingObject(instanceId); if (m_AssetPreviewIgnoreList.Contains(assetDataType)) return false; return true; diff --git a/Editor/Mono/Overlays/ICreateToolbar.cs b/Editor/Mono/Overlays/ICreateToolbar.cs index b29df9e8c4..073e6afeb0 100644 --- a/Editor/Mono/Overlays/ICreateToolbar.cs +++ b/Editor/Mono/Overlays/ICreateToolbar.cs @@ -2,17 +2,22 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using UnityEngine.UIElements; +using System.Collections.Generic; namespace UnityEditor.Overlays { - interface ICreateHorizontalToolbar + public interface ICreateHorizontalToolbar { - VisualElement CreateHorizontalToolbarContent(); + OverlayToolbar CreateHorizontalToolbarContent(); } - interface ICreateVerticalToolbar + public interface ICreateVerticalToolbar { - VisualElement CreateVerticalToolbarContent(); + OverlayToolbar CreateVerticalToolbarContent(); + } + + public interface ICreateToolbar + { + public IEnumerable toolbarElements { get; } } } diff --git a/Editor/Mono/Overlays/Overlay.cs b/Editor/Mono/Overlays/Overlay.cs index 00ef36e0e6..929fba01fc 100644 --- a/Editor/Mono/Overlays/Overlay.cs +++ b/Editor/Mono/Overlays/Overlay.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using UnityEditor.Toolbars; using UnityEngine; using UnityEngine.UIElements; @@ -39,6 +40,7 @@ public abstract partial class Overlay // Persistent State Data string m_Id, m_RootVisualElementName, m_DisplayName; Layout m_Layout = Layout.Panel; + Layout m_ActiveLayout = Layout.Panel; bool m_Collapsed; internal bool dontSaveInLayout {get; set;} internal bool m_HasMenuEntry = true; @@ -124,6 +126,9 @@ internal set } } + // layout is the preferred layout, active layout is what this overlay is actually using + internal Layout activeLayout => m_ActiveLayout; + public bool collapsed { get => collapsedContent.parent == contentRoot; @@ -162,6 +167,10 @@ internal OverlayContainer container set => m_Container = value; } + internal DockZone dockZone => floating ? DockZone.Floating : OverlayCanvas.GetDockZone(container); + + internal DockPosition dockPosition => container?.GetDockPosition(this) ?? DockPosition.Bottom; + internal static VisualTreeAsset treeAsset { get @@ -201,6 +210,8 @@ protected internal virtual Layout supportedLayouts get { var supported = Layout.Panel; + if (this is ICreateToolbar) + supported |= Layout.HorizontalToolbar | Layout.VerticalToolbar; if (this is ICreateHorizontalToolbar) supported |= Layout.HorizontalToolbar; if (this is ICreateVerticalToolbar) @@ -292,7 +303,7 @@ internal void RebuildContent() // We need to invoke a callback if the collapsed state changes (either from user request or invalid layout) bool wasCollapsed = collapsedContent.parent == contentRoot; var prevLayout = layout; - var activeLayout = GetBestLayoutForState(); + m_ActiveLayout = GetBestLayoutForState(); // Clear any existing contents. m_CurrentContent?.RemoveFromHierarchy(); @@ -305,7 +316,7 @@ internal void RebuildContent() // An Overlay can collapsed by request, or by necessity. If collapsed due to invalid layout/container match, // the collapsed property is not modified. The next time a content rebuild is requested we'll try again to // create the contents with the st ored state. - bool isCollapsed = m_Collapsed || activeLayout == 0; + bool isCollapsed = m_Collapsed || m_ActiveLayout == 0; if (isCollapsed) { @@ -314,13 +325,13 @@ internal void RebuildContent() } else { - m_CurrentContent = CreateContent(activeLayout); + m_CurrentContent = CreateContent(m_ActiveLayout); contentRoot.Add(m_CurrentContent); } m_ContentsChanged = true; - activeLayout = activeLayout == 0 ? container.preferredLayout : activeLayout; + m_ActiveLayout = m_ActiveLayout == 0 ? container.preferredLayout : m_ActiveLayout; // Update styling if (floating) @@ -335,9 +346,9 @@ internal void RebuildContent() rootVisualElement.RemoveFromClassList(k_Floating); } - rootVisualElement.EnableInClassList(k_ToolbarVerticalLayout, activeLayout == Layout.VerticalToolbar); - rootVisualElement.EnableInClassList(k_ToolbarHorizontalLayout, activeLayout == Layout.HorizontalToolbar); - rootVisualElement.EnableInClassList(k_PanelLayout, activeLayout == Layout.Panel); + rootVisualElement.EnableInClassList(k_ToolbarVerticalLayout, m_ActiveLayout == Layout.VerticalToolbar); + rootVisualElement.EnableInClassList(k_ToolbarHorizontalLayout, m_ActiveLayout == Layout.HorizontalToolbar); + rootVisualElement.EnableInClassList(k_PanelLayout, m_ActiveLayout == Layout.Panel); rootVisualElement.EnableInClassList(k_Collapsed, isCollapsed); rootVisualElement.EnableInClassList(k_Expanded, !isCollapsed); @@ -352,8 +363,8 @@ internal void RebuildContent() if(wasCollapsed != isCollapsed) collapsedChanged?.Invoke(isCollapsed); - if (prevLayout != activeLayout) - layoutChanged?.Invoke(activeLayout); + if (prevLayout != m_ActiveLayout) + layoutChanged?.Invoke(m_ActiveLayout); } // CreateContent always returns a new VisualElement tree with the Overlay contents. It does not modify the @@ -362,13 +373,13 @@ internal void RebuildContent() // supports it. The only reason that content would not be created with the requested layout is if the Overlay // does not implement the correct ICreate{Horizontal, Vertical}Toolbar interface. // To rebuild content taking into account the parent container, use RebuildContent(). - VisualElement CreateContent(Layout requestedLayout) + public VisualElement CreateContent(Layout requestedLayout) { var previousContent = m_ContentRoot; try { - VisualElement content; + VisualElement content = null; switch (requestedLayout) { @@ -389,8 +400,13 @@ VisualElement CreateContent(Layout requestedLayout) break; default: - Debug.LogError($"Overlay {GetType()} attempting to set unsupported layout: {requestedLayout}"); - goto case Layout.Panel; + if (!(this is ICreateToolbar toolbar)) + { + Debug.LogError($"Overlay {GetType()} attempting to set unsupported layout: {requestedLayout}"); + goto case Layout.Panel; + } + content = new EditorToolbar(toolbar.toolbarElements, canvas.containerWindow).rootVisualElement; + break; } if (content != null) diff --git a/Editor/Mono/Overlays/OverlayAttribute.cs b/Editor/Mono/Overlays/OverlayAttribute.cs index 31e14fe8f6..69768cbfea 100644 --- a/Editor/Mono/Overlays/OverlayAttribute.cs +++ b/Editor/Mono/Overlays/OverlayAttribute.cs @@ -9,35 +9,100 @@ namespace UnityEditor.Overlays [AttributeUsage(AttributeTargets.Class)] public sealed class OverlayAttribute : Attribute { - readonly Type m_EditorWindowType; - readonly string m_Id; - readonly string m_UssName; - readonly bool m_DefaultDisplay; - readonly string m_DisplayName; - - public Type editorWindowType => m_EditorWindowType; - public string id => m_Id; - public string displayName => m_DisplayName; - public string ussName => m_UssName; - public bool defaultDisplay => m_DefaultDisplay; + Type m_EditorWindowType; + string m_Id; + string m_UssName; + bool m_DefaultDisplay; + string m_DisplayName; + DockZone m_DefaultDockZone; + DockPosition m_DefaultDockPosition; + int m_DefaultDockIndex; + Layout m_DefaultLayout; - public OverlayAttribute(Type editorWindowType, string id, string displayName, string ussName, bool defaultDisplay = false) + public Type editorWindowType + { + get => m_EditorWindowType; + set => m_EditorWindowType = value; + } + + public string id + { + get => m_Id; + set => m_Id = value; + } + + public string displayName + { + get => m_DisplayName; + set => m_DisplayName = value; + } + + public string ussName + { + get => m_UssName; + set => m_UssName = value; + } + + public bool defaultDisplay + { + get => m_DefaultDisplay; + set => m_DefaultDisplay = value; + } + + public DockZone defaultDockZone { - m_EditorWindowType = editorWindowType; - m_DefaultDisplay = defaultDisplay; - m_Id = id; - m_DisplayName = displayName; - m_UssName = ussName; + get => m_DefaultDockZone; + set => m_DefaultDockZone = value; + } + + public DockPosition defaultDockPosition + { + get => m_DefaultDockPosition; + set => m_DefaultDockPosition = value; + } + + public int defaultDockIndex + { + get => m_DefaultDockIndex; + set => m_DefaultDockIndex = value; + } + + public Layout defaultLayout + { + get => m_DefaultLayout; + set => m_DefaultLayout = value; + } + + public OverlayAttribute() + { + m_EditorWindowType = null; + m_DefaultDisplay = false; + m_Id = null; + m_DisplayName = null; + m_UssName = null; + m_DefaultDockZone = DockZone.RightColumn; + m_DefaultDockPosition = DockPosition.Bottom; + m_DefaultDockIndex = int.MaxValue; + m_DefaultLayout = Layout.Panel; if (string.IsNullOrEmpty(m_UssName)) m_UssName = m_Id; } - public OverlayAttribute(Type editorWindowType, string id, string displayName, bool defaultLayout = false) - : this(editorWindowType, id, displayName, displayName, defaultLayout) + public OverlayAttribute(Type editorWindowType, string id, string displayName, string ussName, bool defaultDisplay = false) + { + this.editorWindowType = editorWindowType; + this.displayName = displayName; + this.id = id; + this.defaultDisplay = defaultDisplay; + this.ussName = ussName; + } + + public OverlayAttribute(Type editorWindowType, string id, string displayName, bool defaultDisplay = false) + : this(editorWindowType, id, displayName, displayName, defaultDisplay) { } - public OverlayAttribute(Type editorWindowType, string displayName, bool defaultLayout = false) - : this(editorWindowType, displayName, displayName, displayName, defaultLayout) + public OverlayAttribute(Type editorWindowType, string displayName, bool defaultDisplay = false) + : this(editorWindowType, displayName, displayName, displayName, defaultDisplay) { } } diff --git a/Editor/Mono/Overlays/OverlayCanvas.cs b/Editor/Mono/Overlays/OverlayCanvas.cs index aba2262e52..35a588c83e 100644 --- a/Editor/Mono/Overlays/OverlayCanvas.cs +++ b/Editor/Mono/Overlays/OverlayCanvas.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Reflection; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.UIElements; @@ -112,7 +114,7 @@ public override int GetHashCode() //Dock position within container //for a horizontal container, Top is left, Bottom is right - enum DockPosition + public enum DockPosition { Top, Bottom @@ -126,6 +128,18 @@ enum SnapCorner BottomRight, } + // public API to set a default docking zone. default is RightColumnBottom + public enum DockZone + { + LeftToolbar = 0, + RightToolbar = 1, + TopToolbar = 2, + BottomToolbar = 3, + LeftColumn = 4, + RightColumn = 5, + Floating = 6 + } + [Serializable] public sealed class OverlayCanvas : ISerializationCallbackReceiver { @@ -135,6 +149,7 @@ public sealed class OverlayCanvas : ISerializationCallbackReceiver internal const string k_StyleCommon = "StyleSheets/Overlays/OverlayCommon.uss"; internal const string k_StyleLight = "StyleSheets/Overlays/OverlayLight.uss"; internal const string k_StyleDark = "StyleSheets/Overlays/OverlayDark.uss"; + const int k_ContainerCount = 6; const string k_FloatingContainer = "overlay-container--floating"; const string k_ToolbarZone = "overlay-toolbar-zone"; @@ -146,17 +161,47 @@ public sealed class OverlayCanvas : ISerializationCallbackReceiver static VisualTreeAsset s_TreeAsset; static VisualTreeAsset s_DropZoneTreeAsset; - static readonly SaveData k_DefaultSaveData = new SaveData() - { - floating = false, - collapsed = false, - containerId = null, - displayed = false, - dockPosition = DockPosition.Bottom, - index = int.MaxValue, - layout = Layout.Panel + static SaveData defaultSaveData => new SaveData() + { + floating = false, + collapsed = false, + containerId = null, + displayed = false, + dockPosition = DockPosition.Bottom, + index = int.MaxValue, + layout = Layout.Panel + }; + + // order must match OverlayDockArea + static readonly string[] k_DockZoneContainerIDs = new string[7] + { + "overlay-toolbar__left", + "overlay-toolbar__right", + "overlay-toolbar__top", + "overlay-toolbar__bottom", + "overlay-container--left", + "overlay-container--right", + k_DefaultContainer }; + internal static DockZone GetDockZone(OverlayContainer container) + { + for(int i = 0, c = k_DockZoneContainerIDs.Length; i < c; i++) + if (k_DockZoneContainerIDs[i] == container.name) + return (DockZone)i; + return DockZone.Floating; + } + + // used by tests + [EditorBrowsable(EditorBrowsableState.Never)] + internal OverlayContainer GetDockZoneContainer(DockZone zone) + { + foreach(var container in containers) + if (container.name == k_DockZoneContainerIDs[(int)zone]) + return container; + return null; + } + OverlayMenu m_Menu; internal string lastAppliedPresetName => m_LastAppliedPresetName; List m_Overlays = new List(); @@ -181,7 +226,7 @@ public sealed class OverlayCanvas : ISerializationCallbackReceiver OverlayContainer defaultContainer { get; set; } OverlayContainer defaultToolbarContainer { get; set; } - List containers { get; set; } + List containers; List toolbarZones { get; set; } readonly Dictionary m_OverlaysByVE = new Dictionary(); @@ -257,8 +302,8 @@ VisualElement CreateRoot() ve.name = ussClassName; ve.style.flexGrow = 1; - containers = ve.Query().ToList(); + foreach (var container in containers) { container.RegisterCallback(OnMouseEnterOverlayContainer); @@ -539,6 +584,16 @@ internal void ApplySaveData(SaveData[] saveData) RestoreOverlays(); } + internal void Move(Overlay overlay, DockZone zone, DockPosition position = DockPosition.Bottom) + { + var container = GetDockZoneContainer(zone); + if(position == DockPosition.Bottom) + container.AddToBottom(overlay); + else + container.AddToTop(overlay); + overlay.RebuildContent(); + } + public void Add(Overlay overlay, bool show = true) { if(m_Overlays.Contains(overlay)) @@ -610,7 +665,25 @@ void AddOverlay(Overlay overlay) SaveData FindSaveData(Overlay overlay) { - return m_SaveData.FirstOrDefault(x => x.id == overlay.id) ?? k_DefaultSaveData; + var data = m_SaveData.FirstOrDefault(x => x.id == overlay.id); + + if (data == null) + { + data = defaultSaveData; + + var attrib = overlay.GetType().GetCustomAttribute(); + + if (attrib != null) + { + data.containerId = k_DockZoneContainerIDs[(int)attrib.defaultDockZone]; + data.index = attrib.defaultDockIndex; + data.dockPosition = attrib.defaultDockPosition; + data.floating = attrib.defaultDockZone == DockZone.Floating; + data.layout = attrib.defaultLayout; + } + } + + return data; } void RestoreOverlay(Overlay overlay, SaveData data = null) diff --git a/Editor/Mono/Overlays/OverlayContainer.cs b/Editor/Mono/Overlays/OverlayContainer.cs index cb00ca6889..5e197727a9 100644 --- a/Editor/Mono/Overlays/OverlayContainer.cs +++ b/Editor/Mono/Overlays/OverlayContainer.cs @@ -396,5 +396,12 @@ internal int FindIndex(Overlay overlay) return top; return bottomOverlays.IndexOf(overlay); } + + internal DockPosition GetDockPosition(Overlay overlay) + { + if (topOverlays.Contains(overlay)) + return DockPosition.Top; + return DockPosition.Bottom; + } } } diff --git a/Editor/Mono/Overlays/OverlayToolbar.cs b/Editor/Mono/Overlays/OverlayToolbar.cs new file mode 100644 index 0000000000..6e38035b1f --- /dev/null +++ b/Editor/Mono/Overlays/OverlayToolbar.cs @@ -0,0 +1,24 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + + +using UnityEditor.Toolbars; +using UnityEngine.UIElements; + +namespace UnityEditor.Overlays +{ + public class OverlayToolbar : VisualElement + { + public OverlayToolbar() + { + EditorToolbarUtility.LoadStyleSheets("EditorToolbar", this); + AddToClassList("unity-toolbar-overlay"); + } + + public void SetupChildrenAsButtonStrip() + { + EditorToolbarUtility.SetupChildrenAsButtonStrip(this); + } + } +} diff --git a/Editor/Mono/Overlays/OverlayUtilities.cs b/Editor/Mono/Overlays/OverlayUtilities.cs index 249f752ca5..6ad80b3f8f 100644 --- a/Editor/Mono/Overlays/OverlayUtilities.cs +++ b/Editor/Mono/Overlays/OverlayUtilities.cs @@ -38,40 +38,30 @@ static OverlayEditorWindowAssociation[] overlays .ToArray(); int len = ovrls.Length; - var overlays = new List(len); + var overlayWindows = new List(len); for (int i = 0; i < len; i++) { var overlayAttribute = (OverlayAttribute)ovrls[i].GetCustomAttributes(typeof(OverlayAttribute), false).FirstOrDefault(); - if (!ValidateOverlayWindowType(ovrls[i], overlayAttribute.editorWindowType)) + // Overlays that are implemented as instances don't need to define a target editor window. + if (overlayAttribute?.editorWindowType == null) continue; - overlays.Add(new OverlayEditorWindowAssociation + overlayWindows.Add(new OverlayEditorWindowAssociation { overlay = ovrls[i], editorWindowType = overlayAttribute.editorWindowType }); } - s_Overlays = overlays.ToArray(); + s_Overlays = overlayWindows.ToArray(); } return s_Overlays; } } - internal static bool ValidateOverlayWindowType(Type overlayType, Type windowType) - { - if (windowType == null) - { - Debug.LogErrorFormat(nullWindowTypeErrorMsg, overlayType.FullName); - return false; - } - - return true; - } - internal static List GetOverlaysForType(Type type) { List res; @@ -162,16 +152,6 @@ internal static string GetSignificantLettersForIcon(string s) return words[0].Substring(0, 1) + words[1].Substring(0, 1); } - // Context is usually the containing EditorWindow - public static EditorToolbar CreateToolbar(this VisualElement rootVisualElement, EditorWindow context = null, params string[] elementIDs) - { - rootVisualElement.AddToClassList("unity-toolbar-overlay"); - var toolbar = new EditorToolbar(context, rootVisualElement); - foreach (var id in elementIDs) - toolbar.AddElement(id); - return toolbar; - } - internal static bool EnsureValidId(IEnumerable existing, Overlay overlay) { var id = string.IsNullOrEmpty(overlay.id) ? $"{overlay.GetType()}" : overlay.id; diff --git a/Editor/Mono/Overlays/ToolbarOverlay.cs b/Editor/Mono/Overlays/ToolbarOverlay.cs index 217e9ba31c..54d631d81b 100644 --- a/Editor/Mono/Overlays/ToolbarOverlay.cs +++ b/Editor/Mono/Overlays/ToolbarOverlay.cs @@ -2,33 +2,32 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; +using System.Collections.Generic; using UnityEditor.Toolbars; using UnityEngine.UIElements; namespace UnityEditor.Overlays { - public abstract class ToolbarOverlay : Overlay, ICreateHorizontalToolbar, ICreateVerticalToolbar + public abstract class ToolbarOverlay : Overlay, ICreateToolbar { - EditorToolbar m_Toolbar; readonly string[] m_ToolbarElementIds; - - public VisualElement CreateHorizontalToolbarContent() => CreateToolbarContent(); - - public VisualElement CreateVerticalToolbarContent() => CreateToolbarContent(); - - public override VisualElement CreatePanelContent() => CreateToolbarContent(); + public IEnumerable toolbarElements => m_ToolbarElementIds; protected ToolbarOverlay(params string[] toolbarElementIds) { - m_ToolbarElementIds = toolbarElementIds ?? System.Array.Empty(); + m_ToolbarElementIds = toolbarElementIds ?? Array.Empty(); } - VisualElement CreateToolbarContent() + [Obsolete("Use Overlay.CreateContent(Layout.Horizontal)")] + public VisualElement CreateHorizontalToolbarContent() => CreatePanelContent(); + + [Obsolete("Use Overlay.CreateContent(Layout.Vertical)")] + public VisualElement CreateVerticalToolbarContent() => CreatePanelContent(); + + public override VisualElement CreatePanelContent() { - rootVisualElement.AddToClassList("unity-toolbar-overlay"); - var toolbarRoot = new VisualElement { name = "toolbar-overlay" }; - m_Toolbar = new EditorToolbar(canvas.containerWindow, toolbarRoot, m_ToolbarElementIds); - return toolbarRoot; + return new EditorToolbar(toolbarElements, containerWindow).rootVisualElement; } } } diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index 64365e71e7..22af9efea7 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -1007,6 +1007,9 @@ public static ScriptingImplementation GetDefaultScriptingBackend(NamedBuildTarge return GetDefaultScriptingBackendForGroup(buildTarget.ToBuildTargetGroup()); } + [StaticAccessor("GetPlayerSettings().GetEditorOnly()")] + internal static extern bool IsApplicationIdentifierValid(string name, BuildTargetGroup targetGroup); + [StaticAccessor("GetPlayerSettings().GetEditorOnly()")] internal static extern string SanitizeApplicationIdentifier(string name, BuildTargetGroup targetGroup); @@ -1097,6 +1100,19 @@ public static void SetManagedStrippingLevel(NamedBuildTarget buildTarget, Manage public static void SetApiCompatibilityLevel(NamedBuildTarget buildTarget, ApiCompatibilityLevel value) => SetApiCompatibilityLevelInternal(buildTarget.TargetName, value); + [NativeThrows] + [StaticAccessor("GetPlayerSettings().GetEditorOnly()")] + [NativeMethod("GetIl2CppCodeGeneration")] + private static extern Il2CppCodeGeneration GetIl2CppCodeGenerationInternal(string buildTargetName); + public static Il2CppCodeGeneration GetIl2CppCodeGeneration(NamedBuildTarget buildTarget) => GetIl2CppCodeGenerationInternal(buildTarget.TargetName); + + [NativeThrows] + [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()")] + [NativeMethod("SetIl2CppCodeGeneration")] + private static extern void SetIl2CppCodeGenerationInternal(string buildTargetName, Il2CppCodeGeneration value); + public static void SetIl2CppCodeGeneration(NamedBuildTarget buildTarget, Il2CppCodeGeneration value) => + SetIl2CppCodeGenerationInternal(buildTarget.TargetName, value); + [NativeThrows] [NativeMethod("SetMobileMTRendering")] private static extern void SetMobileMTRenderingInternal(string buildTargetName, bool enable); diff --git a/Editor/Mono/PostprocessScene.cs b/Editor/Mono/PostprocessScene.cs index 6495e0114a..3dce297f8d 100644 --- a/Editor/Mono/PostprocessScene.cs +++ b/Editor/Mono/PostprocessScene.cs @@ -19,7 +19,7 @@ public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, Build.Report using (StaticBatchingUtility.s_CombineMarker.Auto()) { ulong sceneHash = Hash128.Compute(AssetDatabase.AssetPathToGUID(scene.path)).u64_0; - StaticBatchingEditorHelper.CombineAllStaticMeshesForScenePostProcessing(sceneHash); + StaticBatchingEditorHelper.CombineAllStaticMeshesForScenePostProcessing(sceneHash, scene); } } } diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs index c9477e6583..6002c869bf 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs @@ -69,11 +69,13 @@ internal void HandleApplyMenuItems(GenericMenu menu, GenericMenu.MenuFunction2 a PrefabUtility.HandleApplyMenuItems( null, obj, - (menuItemContent, sourceObject) => + (menuItemContent, sourceObject, instanceOrAssetObject) => { string prefabAssetPath = AssetDatabase.GetAssetPath(sourceObject); GameObject rootObject = PrefabUtility.GetRootGameObject(sourceObject); - if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject)) + bool isPersistent = EditorUtility.IsPersistent(instanceOrAssetObject); + + if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootObject) || (!isPersistent && !PrefabUtility.HasApplicableObjectOverridesForTarget(instanceOrAssetObject, sourceObject, false))) menu.AddDisabledItem(menuItemContent); else menu.AddItem(menuItemContent, false, applyAction, prefabAssetPath); diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs index 6b69366361..fe513a4419 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs @@ -95,7 +95,9 @@ static PrefabOverrides GetPrefabOverrides(GameObject prefabInstance, bool includ return mods; } - public bool hasModifications { get; set; } + public bool hasModifications { get; private set; } + + public bool hasApplicableModifications { get; private set; } public bool IsValidTargetPrefabInstance() { @@ -182,8 +184,11 @@ void BuildPrefabOverridesPerObject(out Dictionary instance } } - internal void ComparisonPopupClosed(Object instanceObject) + internal void ComparisonPopupClosed(Object instanceObject, bool ownerNeedsRefresh) { + if(ownerNeedsRefresh) + ReloadOverridesDisplay(); + if (instanceObject != null && instanceObject is GameObject) SyncTreeViewItemNameForGameObject((GameObject)instanceObject); } @@ -217,9 +222,29 @@ protected override TreeViewItem BuildRoot() var hiddenRoot = new TreeViewItem { id = 0, depth = -1, displayName = "Hidden Root" }; var idSequence = new IdSequence(); + + hasApplicableModifications = false; hasModifications = AddTreeViewItemRecursive(hiddenRoot, m_PrefabInstanceRoot, instanceIDToPrefabOverridesMap, idSequence); if (!hasModifications) hiddenRoot.AddChild(new TreeViewItem { id = 1, depth = 0, displayName = "No Overrides" }); + else + { + bool CanAnyPropertiesBeApplied() + { + if (m_AllModifications.addedComponents.Count != 0 || m_AllModifications.removedComponents.Count != 0 || m_AllModifications.addedGameObjects.Count != 0) + return true; + + foreach (var objectOverride in m_AllModifications.objectOverrides) + { + if (PrefabUtility.HasApplicableObjectOverrides(objectOverride.instanceObject, false)) + return true; + } + + return false; + } + + hasApplicableModifications = CanAnyPropertiesBeApplied(); + } if (m_Debug) AddDebugItems(hiddenRoot, idSequence); @@ -555,6 +580,7 @@ class ComparisonViewPopup : PopupWindowContent Vector2 m_PreviewSize = new Vector2(600f, 0); Vector2 m_Scroll; bool m_RenderOverlayAfterResizeChange; + bool m_OwnerNeedsRefresh; static class Styles { @@ -617,7 +643,7 @@ public ComparisonViewPopup(Object source, Object instance, PrefabOverride modifi public override void OnClose() { Undo.postprocessModifications -= RecheckOverrideStatus; - m_Owner.ComparisonPopupClosed(m_Instance); + m_Owner.ComparisonPopupClosed(m_Instance, m_OwnerNeedsRefresh); base.OnClose(); if (m_SourceEditor != null) @@ -803,11 +829,8 @@ void Apply(object prefabAssetPathObject) void UpdateAndClose() { - if (editorWindow != null) - { - editorWindow.Close(); - m_Owner.ReloadOverridesDisplay(); - } + m_OwnerNeedsRefresh = true; + editorWindow?.Close(); } float DrawEditor(Rect rect, Editor editor, bool disabled, EditorGUIUtility.ComparisonViewMode comparisonViewMode) @@ -832,6 +855,7 @@ float DrawEditor(Rect rect, Editor editor, bool disabled, EditorGUIUtility.Compa } else { + EditorGUI.BeginChangeCheck(); if (editor.target is GameObject) { editor.DrawHeader(); @@ -845,6 +869,9 @@ float DrawEditor(Rect rect, Editor editor, bool disabled, EditorGUIUtility.Compa EditorGUILayout.Space(); EditorGUILayout.EndVertical(); } + + if (EditorGUI.EndChangeCheck()) + m_OwnerNeedsRefresh = true; } } } diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs index 1249b3d783..560493719b 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs @@ -32,8 +32,6 @@ public static List GetObjectOverrides(GameObject prefabInstance, // that are not part of that source prefab objects component list (these must be added) TransformVisitor transformVisitor = new TransformVisitor(); var modifiedObjects = new List(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstance)) - return modifiedObjects; Func checkMethod; if (includeDefaultOverrides) @@ -89,9 +87,6 @@ public static List GetAddedComponents(GameObject prefabInstance) // From root of instance traverse all child go and detect any components that are not part of that source prefab objects component list (these must be added) TransformVisitor transformVisitor = new TransformVisitor(); var addedComponents = new List(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstance)) - return addedComponents; - transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, CheckForAddedComponents, addedComponents); return addedComponents; } @@ -142,8 +137,6 @@ public static List GetRemovedComponents(GameObject prefabInsta // From root of asset traverse all children and detect any Components that are not present on the instance object (these must be deleted) var removedComponents = new List(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstance)) - return removedComponents; TransformVisitor transformVisitor = new TransformVisitor(); transformVisitor.VisitPrefabInstanceTransforms(prefabInstanceRoot.transform, CheckForRemovedComponents, removedComponents); return removedComponents; @@ -154,8 +147,6 @@ public static List GetRemovedComponentsForSingleGameObject(Gam ThrowExceptionIfNullOrNotPartOfPrefabInstance(prefabInstance); var removedComponents = new List(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstance)) - return removedComponents; CheckForRemovedComponents(prefabInstance.transform, removedComponents); return removedComponents; } @@ -226,8 +217,6 @@ public static List GetAddedGameObjects(GameObject prefabInstanc // From root instance traverse all children and detect any GameObjects that are not a prefab gameobject (these must be added) TransformVisitor transformVisitor = new TransformVisitor(); var addedGameObjects = new List(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstance)) - return addedGameObjects; transformVisitor.VisitAndConditionallyEnterChildren( prefabInstanceRoot.transform, diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs index 940bc164f9..fdd4bbcd02 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs @@ -37,14 +37,13 @@ internal class PrefabOverridesWindow : PopupWindowContent float m_ButtonWidth; bool m_AnyOverrides; - bool m_Disconnected; + bool m_HasApplicableOverrides; bool m_InvalidComponentOnInstance; bool m_ModelPrefab; bool m_Immutable; bool m_InvalidComponentOnAsset; bool m_HasManagedReferencesWithMissingTypesOnAsset; - static class Styles { public static GUIContent revertAllContent = EditorGUIUtility.TrTextContent("Revert All", "Revert all overrides."); @@ -56,6 +55,8 @@ static class Styles public static GUIContent instanceLabel = EditorGUIUtility.TrTextContent("Overrides to"); public static GUIContent contextLabel = EditorGUIUtility.TrTextContent("in"); + public static string nonApplicableTooltip = L10n.Tr("There are no overrides that can be applied to Prefab source '{0}'."); + public static GUIContent infoMultiple = EditorGUIUtility.TrTextContent("Multiple Prefabs selected. Cannot show overrides."); public static GUIContent infoMultipleNoApply = EditorGUIUtility.TrTextContent("Multiple Prefabs selected. Cannot show overrides.\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details."); @@ -63,7 +64,6 @@ static class Styles public static GUIContent infoModel = EditorGUIUtility.TrTextContent("Click on individual items to review and revert.\nApplying to a Model Prefab is not possible."); public static GUIContent infoDefault = EditorGUIUtility.TrTextContent("Click on individual items to review, revert and apply."); public static GUIContent infoNoApply = EditorGUIUtility.TrTextContent("Click on individual items to review and revert."); - public static GUIContent warningDisconnected = EditorGUIUtility.TrTextContent("Disconnected. Cannot show overrides."); // Messages related to reasons for inability to apply. public static GUIContent warningInvalidAsset = EditorGUIUtility.TrTextContent("The Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and remove or recover the script."); @@ -131,13 +131,7 @@ internal void RefreshStatus(bool reloadTreeView = true) m_TreeView.CullNonExistingItemsFromSelection(); } - if (m_SelectedGameObjects.Length == 1) - UpdateTextSingle(PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObjects[0])); - else - UpdateTextMultiple(); - m_AnyOverrides = false; - m_Disconnected = false; m_InvalidComponentOnInstance = false; m_ModelPrefab = false; m_Immutable = false; @@ -147,6 +141,11 @@ internal void RefreshStatus(bool reloadTreeView = true) for (int i = 0; i < m_SelectedGameObjects.Length; i++) UpdateStatusChecks(m_SelectedGameObjects[i]); + if (m_SelectedGameObjects.Length == 1) + UpdateTextSingle(PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObjects[0])); + else + UpdateTextMultiple(); + // There are a few cases where the Tree View reports no overrides even though // PrefabUtility.HasPrefabInstanceAnyOverrides says there are; for example if // a component has been removed on an instance, but also removed on the Asset. @@ -163,8 +162,6 @@ void UpdateStatusChecks(GameObject prefabInstanceRoot) if (PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false)) m_AnyOverrides = true; - if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstanceRoot)) - m_Disconnected = true; if (PrefabUtility.HasInvalidComponent(prefabInstanceRoot)) m_InvalidComponentOnInstance = true; @@ -179,11 +176,13 @@ void UpdateStatusChecks(GameObject prefabInstanceRoot) if (PrefabUtility.HasManagedReferencesWithMissingTypes(prefabAssetRoot)) m_HasManagedReferencesWithMissingTypesOnAsset = true; + + m_HasApplicableOverrides = m_TreeView == null || m_TreeView.hasApplicableModifications; } bool IsShowingActionButton() { - return m_AnyOverrides || m_Disconnected; + return m_AnyOverrides; } bool HasMultiSelection() @@ -200,7 +199,7 @@ bool IsShowingApplyWarning() { return !HasMultiSelection() && - (m_AnyOverrides || m_Disconnected) && + m_AnyOverrides && !m_ModelPrefab && (m_InvalidComponentOnInstance || m_InvalidComponentOnAsset || m_HasManagedReferencesWithMissingTypesOnAsset || m_Immutable); } @@ -284,11 +283,7 @@ public override void OnGUI(Rect rect) } else { - if (m_Disconnected) - { - EditorGUILayout.HelpBox(Styles.warningDisconnected.text, MessageType.Warning); - } - else if (m_AnyOverrides) + if (m_AnyOverrides) { Rect treeViewRect = GUILayoutUtility.GetRect(100, 10000, 0, 10000); m_TreeView.OnGUI(treeViewRect); @@ -361,7 +356,7 @@ public override void OnGUI(Rect rect) } } - using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance || !m_HasApplicableOverrides)) { if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(m_ButtonWidth))) { @@ -512,7 +507,7 @@ void UpdateText(Texture assetIcon, string assetName) m_RevertSelectedContent = Styles.revertSelectedContent; m_ButtonWidth = k_ButtonWidth; - var applyAllContent = Styles.applyAllContent; + var applyAllContent = new GUIContent(Styles.applyAllContent); var applySelectedContent = Styles.applySelectedContent; if (stage is PrefabStage && PrefabUtility.IsPartOfVariantPrefab(AssetDatabase.LoadAssetAtPath(stage.assetPath))) { @@ -521,8 +516,10 @@ void UpdateText(Texture assetIcon, string assetName) applySelectedContent = Styles.applySelectedToBaseContent; } - m_ApplyAllContent.text = applyAllContent.text; - m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, assetName); + if (!m_HasApplicableOverrides) + applyAllContent.tooltip = Styles.nonApplicableTooltip; + + m_ApplyAllContent = new GUIContent(applyAllContent.text, string.Format(applyAllContent.tooltip, assetName)); m_ApplySelectedContent.text = applySelectedContent.text; m_ApplySelectedContent.tooltip = string.Format(applySelectedContent.tooltip, assetName); } diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 1cf514e3d5..193b07321f 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -67,6 +67,13 @@ public sealed partial class PrefabUtility [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static void SetPropertyModifications(Object targetPrefab, PropertyModification[] modifications); + [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] + [NativeThrows] + extern internal static bool HasApplicableObjectOverridesForTarget([NotNull] Object targetPrefab, [NotNull] Object applyTarget, bool includeDefaultOverrides); + + [NativeMethod("PrefabUtilityBindings::FindNearestInstanceOfAsset", IsFreeFunction = true)] + extern internal static GameObject FindNearestInstanceOfAsset(Object componentOrGameObjectInstance, Object prefab); + [FreeFunction] extern public static bool HasPrefabInstanceAnyOverrides(GameObject instanceRoot, bool includeDefaultOverrides); @@ -93,11 +100,6 @@ public sealed partial class PrefabUtility [NativeThrows] extern private static GameObject[] FindAllInstancesOfPrefab_internal([NotNull("NullExceptionObject")] GameObject prefabRoot, int sceneHandle); - // Disconnects the prefab instance from its parent prefab. - [Obsolete("The concept of disconnecting Prefab instances has been deprecated.")] - [FreeFunction] - extern public static void DisconnectPrefabInstance(Object targetObject); - [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] extern public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject instanceRoot, PrefabUnpackMode unpackMode); @@ -127,11 +129,6 @@ public sealed partial class PrefabUtility [Obsolete("FindValidUploadPrefabInstanceRoot is deprecated, please use GetOutermostPrefabInstanceRoot instead.")] extern public static GameObject FindValidUploadPrefabInstanceRoot([NotNull("NullExceptionObject")] GameObject target); - // Connects the game object to the prefab that it was last connected to. - [FreeFunction] - [Obsolete("Use RevertPrefabInstance.")] - extern public static bool ReconnectToLastPrefab([NotNull("NullExceptionObject")] GameObject go); - // Resets the properties of the component or game object to the parent prefab state [Obsolete("Use RevertObjectOverride.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] @@ -290,7 +287,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, // Returns true if the object is an instance of a prefab, // regardless of whether the instance is a regular prefab, a variant or model. - // Also returns true if disconnected, and if the asset is missing. + // Also returns if the asset is missing. // Is also true for prefab instances inside persistent prefab assets - // use IsPartOfNonAssetPrefabInstance to exclude those. [FreeFunction] @@ -298,7 +295,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, // Returns true if the object is an instance of a prefab, // regardless of whether the instance is a regular prefab, a variant or model. - // Also returns true if disconnected, and if the asset is missing. + // Also returns true if the asset is missing. // Is false for prefab instances inside persistent prefab assets - // use IsPartOfPrefabInstance to include those. // Note that prefab instances in prefab mode are not assets/persistent since technically, @@ -329,9 +326,6 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, [FreeFunction] extern public static bool IsPartOfImmutablePrefab([NotNull] Object componentOrGameObject); - [FreeFunction] - extern public static bool IsDisconnectedFromPrefabAsset([NotNull] Object componentOrGameObject); - [FreeFunction] extern public static bool IsPrefabAssetMissing([NotNull] Object instanceComponentOrGameObject); diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index fd127be698..68a8c80013 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -30,6 +30,7 @@ public enum PrefabInstanceStatus { NotAPrefab = 0, Connected = 1, + [Obsolete("PrefabInstanceStatus.Disconnected has been deprecated and is not used. Prefabs can not be in a disconnected state.")] Disconnected = 2, MissingAsset = 3 } @@ -58,8 +59,10 @@ public enum PrefabType // The object was an instance of a prefab, but the original prefab could not be found. MissingPrefabInstance = 5, // The object is an instance of a user created prefab, but the connection is broken. + [Obsolete("PrefabType.DisconnectedPrefabInstance has been deprecated and is not used. Prefabs can not be in a disconnected state.")] DisconnectedPrefabInstance = 6, // The object is an instance of an imported 3D model, but the connection is broken. + [Obsolete("PrefabType.DisconnectedModelPrefabInstance has been deprecated and is not used. Prefabs can not be in a disconnected state.")] DisconnectedModelPrefabInstance = 7, } @@ -76,6 +79,8 @@ public enum ReplacePrefabOptions ReplaceNameBased = 2, } + internal delegate void AddApplyMenuItemDelegate(GUIContent menuItem, Object sourceObject, Object instanceOrAssetObject); + public sealed partial class PrefabUtility { internal static class GameObjectStyles @@ -247,7 +252,7 @@ private static void RegisterNewObjects(GameObject newHierarchy, HashSet hie var comp = (Component)danglingObject; if (comp.gameObject != currentGO) { - addedTypes = new HashSet() { typeof(Transform) }; + addedTypes = new HashSet(); currentGO = comp.gameObject; } } @@ -256,7 +261,9 @@ private static void RegisterNewObjects(GameObject newHierarchy, HashSet hie var requiredComponentsExist = true; foreach (RequireComponent req in reqs) { - if ((req.m_Type0 != null && !addedTypes.Contains(req.m_Type0)) || (req.m_Type1 != null && !addedTypes.Contains(req.m_Type1)) || (req.m_Type2 != null && !addedTypes.Contains(req.m_Type2))) + bool addedTypesContainsRequired = (req.m_Type0 != null && addedTypes.Contains(req.m_Type0)) || (req.m_Type1 != null && addedTypes.Contains(req.m_Type1)) || (req.m_Type2 != null && addedTypes.Contains(req.m_Type2)); + bool gameObjectHasRequired = (req.m_Type0 != null && currentGO.GetComponent(req.m_Type0)) || (req.m_Type1 != null && currentGO.GetComponent(req.m_Type1)) || (req.m_Type2 != null && currentGO.GetComponent(req.m_Type2)); + if (!addedTypesContainsRequired && !gameObjectHasRequired) { requiredComponentsExist = false; break; @@ -344,8 +351,6 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode { ThrowExceptionIfNotValidPrefabInstanceObject(instanceRoot, false); - bool isDisconnected = PrefabUtility.IsDisconnectedFromPrefabAsset(instanceRoot); - GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); var actionName = "Revert Prefab Instance"; @@ -363,10 +368,6 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode if (action == InteractionMode.UserAction) { RegisterNewObjects(prefabInstanceRoot, hierarchy, actionName); - if (isDisconnected) - { - Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(prefabInstanceRoot), actionName); - } } } @@ -379,7 +380,6 @@ public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode using (new AtomicUndoScope()) { GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); - var isDisconnected = GetPrefabInstanceHandle(prefabInstanceRoot) == null; var actionName = "Apply instance to prefab"; Object correspondingSourceObject = GetCorrespondingObjectFromSource(prefabInstanceRoot); @@ -399,12 +399,6 @@ public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode if (action == InteractionMode.UserAction) { RegisterNewObjects(correspondingSourceObject as GameObject, prefabHierarchy, actionName); // handles created objects - if (isDisconnected) - { - var prefabInstanceHandle = GetPrefabInstanceHandle(prefabInstanceRoot); - Assert.IsNotNull(prefabInstanceHandle); - Undo.RegisterCreatedObjectUndo(prefabInstanceHandle, actionName); - } } } @@ -418,14 +412,14 @@ public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode ); } - private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedProperty property, string assetPath) + private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedProperty property, Object prefabSourceObject) { var referencedObject = property.objectReferenceValue; if (referencedObject == null) { return; } - referencedObject = GetCorrespondingObjectFromSourceAtPath(referencedObject, assetPath); + referencedObject = GetCorrespondingObjectFromSourceInAsset(referencedObject, prefabSourceObject); if (referencedObject != null) { property.objectReferenceValue = referencedObject; @@ -554,7 +548,7 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper if (!property.hasVisibleChildren) { if (property.prefabOverride) - ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, true, allowApplyDefaultOverride, serializedObjects, changedObjects, action); + ApplySingleProperty(property, prefabSourceSerializedObject, prefabSourceObject, isObjectOnRootInAsset, true, allowApplyDefaultOverride, serializedObjects, changedObjects, action); } else { @@ -580,7 +574,7 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper // NOTE: all property modifications are leafs except in the context of managed references. // Managed references can be overriden (and have visible children). if (property.prefabOverride && (property.propertyType == SerializedPropertyType.ManagedReference || !property.hasVisibleChildren)) - ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, false, allowApplyDefaultOverride, serializedObjects, changedObjects, action); + ApplySingleProperty(property, prefabSourceSerializedObject, prefabSourceObject, isObjectOnRootInAsset, false, allowApplyDefaultOverride, serializedObjects, changedObjects, action); } } @@ -720,7 +714,7 @@ static SerializedProperty GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInI static void ApplySingleProperty( SerializedProperty instanceProperty, SerializedObject prefabSourceSerializedObject, - string assetPath, + Object applyTarget, bool isObjectOnRootInAsset, bool singlePropertyOnly, bool allowApplyDefaultOverride, @@ -776,8 +770,9 @@ static void ApplySingleProperty( // Abort if property has reference to object in scene. if (sourceProperty.propertyType == SerializedPropertyType.ObjectReference) { - MapObjectReferencePropertyToSourceIfApplicable(sourceProperty, assetPath); - if (sourceProperty.objectReferenceValue != null && !EditorUtility.IsPersistent(sourceProperty.objectReferenceValue)) + if (PrefabUtility.CanPropertyBeAppliedToTarget(instanceProperty, applyTarget)) + MapObjectReferencePropertyToSourceIfApplicable(sourceProperty, applyTarget); + else { // The property is a reference to a non-persistent object (scene object which could not be mapped to the asset. // It can not be applied. @@ -1353,7 +1348,7 @@ public static List GetAddedGameObjects(GameObject prefabInstanc internal static void HandleApplyRevertMenuItems( string thingThatChanged, Object instanceObject, - Action addApplyMenuItemAction, + AddApplyMenuItemDelegate addApplyMenuItemAction, Action addRevertMenuItemAction, bool isAllDefaultOverridesComparedToOriginalSource = false, int targetCount = 1) @@ -1367,7 +1362,7 @@ internal static void HandleApplyRevertMenuItems( internal static void HandleApplyMenuItems( string thingThatChanged, Object instanceOrAssetObject, - Action addApplyMenuItemAction, + AddApplyMenuItemDelegate addApplyMenuItemAction, bool isAllDefaultOverridesComparedToOriginalSource = false, bool includeSelfAsTarget = false) { @@ -1391,7 +1386,7 @@ internal static void HandleApplyMenuItems( if (i == applyTargets.Count - 1) translatedText = L10n.Tr("Apply to Prefab '{0}'"); GUIContent applyContent = new GUIContent(thingThatChanged + String.Format(translatedText, sourceRoot.name)); - addApplyMenuItemAction(applyContent, source); + addApplyMenuItemAction(applyContent, source, instanceOrAssetObject); } } @@ -1459,6 +1454,23 @@ public static string GetPrefabAssetPathOfNearestInstanceRoot(Object instanceComp return AssetDatabase.GetAssetPath(GetOriginalSourceOrVariantRoot(instanceComponentOrGameObject)); } + [Obsolete("The concept of disconnecting Prefab instances has been deprecated. This method always returns False.")] + public static bool IsDisconnectedFromPrefabAsset(Object componentOrGameObject) + { + return false; + } + + [Obsolete("The concept of disconnecting Prefab instances has been deprecated. This method does nothing.")] + public static void DisconnectPrefabInstance(Object targetObject) + { + } + + [Obsolete("This method does nothing. Use PrefabUtility.RevertPrefabInstance.", false)] + public static bool ReconnectToLastPrefab(GameObject go) + { + return false; + } + public static Texture2D GetIconForGameObject(GameObject gameObject) { if (IsAnyPrefabInstanceRoot(gameObject)) @@ -1683,21 +1695,9 @@ internal static void ApplyPrefabInstance(GameObject instance) if (!IsPartOfNonAssetPrefabInstance(instance)) throw new ArgumentException("Provided GameObject is not a Prefab instance"); - if (IsDisconnectedFromPrefabAsset(instance)) - { - // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab - // to re-connect existing disconnected prefabs. - var validRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(instance); - var ok = validRoot == instance; - if (!ok && PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance) != PrefabUtility.GetCorrespondingObjectFromSource(instance)) - throw new ArgumentException("Can't save Prefab from an object that originates from a nested Prefab"); - } - else - { - var root = GetOutermostPrefabInstanceRoot(instance); - if (root != instance) - throw new ArgumentException("GameObject to save Prefab from must be a Prefab root"); - } + var root = GetOutermostPrefabInstanceRoot(instance); + if (root != instance) + throw new ArgumentException("GameObject to save Prefab from must be a Prefab root"); var assetObject = GetCorrespondingObjectFromSource(instance); string path = AssetDatabase.GetAssetPath(assetObject); @@ -1793,11 +1793,9 @@ public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, Repla } // Returns the corresponding object from its immediate source from a connected Prefab, - // or null if it can't be found, or the Prefab instance is disconnected. + // or null if it can't be found internal static TObject GetCorrespondingConnectedObjectFromSource(TObject componentOrGameObject) where TObject : Object { - if (IsDisconnectedFromPrefabAsset(GetGameObject(componentOrGameObject))) - return null; return (TObject)GetCorrespondingObjectFromSource_internal(componentOrGameObject); } @@ -1863,20 +1861,6 @@ public static PrefabType GetPrefabType(Object target) return PrefabType.Prefab; } - if (IsDisconnectedFromPrefabAsset(target)) - { - var corresponding = GetCorrespondingObjectFromSource(target); - var prefabObject = GetPrefabObject(corresponding); - // Object was at some point connected to a prefab, but now it is not attached to one anymore and the prefab no longer exists - if (prefabObject == null) - return PrefabType.None; - - if (isModel) - return PrefabType.DisconnectedModelPrefabInstance; - - return PrefabType.DisconnectedPrefabInstance; - } - if (IsPrefabAssetMissing(target)) return PrefabType.MissingPrefabInstance; @@ -1906,9 +1890,6 @@ public static bool IsAddedGameObjectOverride(GameObject gameObject) if (parent == null) return false; - if (IsDisconnectedFromPrefabAsset(parent)) - return false; - // Can't be added to a prefab instance if the parent is not part of a prefab instance. GameObject parentAsset = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(parent.gameObject); if (parentAsset == null) @@ -2088,9 +2069,6 @@ public static PrefabInstanceStatus GetPrefabInstanceStatus(Object componentOrGam if (!PrefabUtility.IsPartOfNonAssetPrefabInstance(componentOrGameObject)) return PrefabInstanceStatus.NotAPrefab; - if (PrefabUtility.IsDisconnectedFromPrefabAsset(componentOrGameObject)) - return PrefabInstanceStatus.Disconnected; - if (PrefabUtility.IsPrefabAssetMissing(componentOrGameObject)) return PrefabInstanceStatus.MissingAsset; @@ -2146,6 +2124,56 @@ public static void UnloadPrefabContents(GameObject contentsRoot) EditorSceneManager.ClosePreviewScene(scene); } + internal static bool CanPropertyBeAppliedToSource(SerializedProperty property) + { + if (property.hasMultipleDifferentValues) + return false; + + if (property.propertyType != SerializedPropertyType.ObjectReference + || property.objectReferenceValue == null + || EditorUtility.IsPersistent(property.objectReferenceValue)) + return true; + + Object referenceSource = GetCorrespondingObjectFromSource(property.objectReferenceValue); + if (referenceSource == null) + return false; //Points to object not in prefab + + Object applyTarget = GetCorrespondingObjectFromSource(property.m_SerializedObject.targetObject); + if (applyTarget == null) + return false; //Added components/gameobjects. Can never be applied to + + var target = PrefabUtility.GetPrefabInstanceHandle(property.objectReferenceValue); + var source = PrefabUtility.GetPrefabInstanceHandle(property.serializedObject.targetObject); + return target == source; + } + + internal static bool CanPropertyBeAppliedToTarget(SerializedProperty property, Object applyTarget) + { + if (property.hasMultipleDifferentValues || applyTarget == null) + return false; + + if (property.propertyType != SerializedPropertyType.ObjectReference + || property.objectReferenceValue == null + || EditorUtility.IsPersistent(property.objectReferenceValue)) + return true; + + var referenceRootInScene = FindNearestInstanceOfAsset(property.objectReferenceValue, applyTarget); + if (referenceRootInScene == null) + return false; + + var targetReference = FindNearestInstanceOfAsset(property.serializedObject.targetObject, applyTarget); + if (targetReference == null) + return false; + + return referenceRootInScene == targetReference; + } + + internal static bool HasApplicableObjectOverrides(Object componentOrGameObjectInInstance, bool includeDefaultOverrides) + { + var applyTarget = GetCorrespondingObjectFromSource(componentOrGameObjectInInstance); + return HasApplicableObjectOverridesForTarget(componentOrGameObjectInInstance, applyTarget, includeDefaultOverrides); + } + // Since an override can be applied to multiple different apply targets, what is not a default override // compared to e.g. the outermost apply target may still be a default override compared to e.g. the innermost. // For example, if you have child Prefab B inside Prefab A in the scene and try want to apply the position of B, diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index c4a54259fd..27c10dacdf 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -1262,7 +1262,7 @@ void CreateGameObjectContextClick(GenericMenu menu, int contextClickedItemID) PrefabUtility.HandleApplyRevertMenuItems( (selectedGOs.Length > 1) ? "Added GameObjects" : "Added GameObject", parentTransform.gameObject, - (menuItemContent, sourceGo) => + (menuItemContent, sourceGo, _) => { GameObject rootGo = PrefabUtility.GetRootGameObject(sourceGo); if (!PrefabUtility.IsPartOfPrefabThatCanBeAppliedTo(rootGo) || EditorUtility.IsPersistent(parentTransform) || !PrefabUtility.HasSameParent(selectedGOs)) diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index ffcaaeb14f..5d82705e25 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -1751,8 +1751,7 @@ internal override void OnPostSceneViewRender(SceneView sceneView) Texture2D DeterminePrefabFileIconFromInstanceRootGameObject() { bool partOfInstance = PrefabUtility.IsPartOfNonAssetPrefabInstance(prefabContentsRoot); - bool disconnected = PrefabUtility.GetPrefabInstanceStatus(prefabContentsRoot) == PrefabInstanceStatus.Disconnected; - if (partOfInstance && !disconnected) + if (partOfInstance) return Icons.prefabVariantIcon; return Icons.prefabIcon; } diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 214dd8b96f..4f4f142f2c 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -153,6 +153,18 @@ private set internal static SavedBool s_PreferenceEnableFilteringWhileSearching = new SavedBool("SceneView.enableFilteringWhileSearching", true); internal static SavedBool s_PreferenceEnableFilteringWhileLodGroupEditing = new SavedBool("SceneView.enableFilteringWhileLodGroupEditing", true); + internal static SavedFloat s_DrawModeExposure = new SavedFloat("SceneView.drawModeExposure", 0.0f); + + [RequiredByNativeCode] + internal static float GetDrawModeExposure() + { + return SceneView.s_DrawModeExposure; + } + + internal bool showExposureSettings => + (this.cameraMode.drawMode == DrawCameraMode.BakedEmissive || this.cameraMode.drawMode == DrawCameraMode.BakedLightmap || + this.cameraMode.drawMode == DrawCameraMode.RealtimeEmissive || this.cameraMode.drawMode == DrawCameraMode.RealtimeIndirect || this.cameraMode.drawMode == DrawCameraMode.LitClustering); + internal static Transform GetDefaultParentObjectIfSet() { Transform parentObject = null; @@ -602,19 +614,6 @@ public bool validateTrueMetals } } - [SerializeField] - float m_ExposureSliderValue = 0.0f; - - internal float bakedLightmapExposure - { - get => m_ExposureSliderValue; - set => m_ExposureSliderValue = value; - } - - internal bool showExposureSettings => - (this.cameraMode.drawMode == DrawCameraMode.BakedEmissive || this.cameraMode.drawMode == DrawCameraMode.BakedLightmap || - this.cameraMode.drawMode == DrawCameraMode.RealtimeEmissive || this.cameraMode.drawMode == DrawCameraMode.RealtimeIndirect || this.cameraMode.drawMode == DrawCameraMode.LitClustering); - [SerializeField] SceneViewState m_SceneViewState; @@ -1378,7 +1377,11 @@ internal void Awake() m_LastSceneViewOrtho = false; m_Rotation.value = Quaternion.identity; m_Ortho.value = true; - m_2DMode = true; + if(!m_2DMode) + { + m_2DMode = true; + modeChanged2D?.Invoke(m_2DMode); + } // Enforcing Rect tool as the default in 2D mode. if (Tools.current == Tool.Move) @@ -2304,6 +2307,8 @@ void DoOnGUI() HandleClickAndDragToFocus(); + BeginWindows(); + if (evt.type == EventType.Layout) m_ShowSceneViewWindows = (lastActiveSceneView == this); @@ -2442,7 +2447,7 @@ void DoOnGUI() Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.Off); // Handle Dragging of stuff over scene view - HandleDragging(); + HandleDragging(evt); if (evt.type == EventType.Repaint) { @@ -2464,6 +2469,8 @@ void DoOnGUI() GUI.EndGroup(); GUI.color = origColor; + EndWindows(); + HandleMouseCursor(); s_CurrentDrawingSceneView = null; @@ -3256,10 +3263,8 @@ internal static bool CanDoDrag(ICollection objects) return true; } - void HandleDragging() + internal void HandleDragging(Event evt) { - Event evt = Event.current; - Object[] dragAndDropObjects = DragAndDrop.objectReferences; switch (evt.type) @@ -3275,35 +3280,42 @@ void HandleDragging() if (!CanDoDrag(dragAndDropObjects)) { DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; - break; + return; } bool isPerform = evt.type == EventType.DragPerform; - var defaultParentObject = GetDefaultParentObjectIfSet(); - var parent = defaultParentObject != null ? defaultParentObject : customParentForDraggedObjects; - var go = HandleUtility.PickGameObject(Event.current.mousePosition, true); + GameObject pickedObject = null; + Transform parentTransform = null; + bool dropHandled = false; // Allow user defined Custom Drop Handler if (DragAndDrop.HasHandler(DragAndDropWindowTarget.sceneView)) { - DragAndDrop.visualMode = DragAndDrop.Drop(DragAndDropWindowTarget.sceneView, go, pivot, Event.current.mousePosition, parent, isPerform); + PickObject(ref pickedObject, ref parentTransform); + DragAndDrop.visualMode = DragAndDrop.Drop(DragAndDropWindowTarget.sceneView, pickedObject, pivot, Event.current.mousePosition, parentTransform, isPerform); + dropHandled = DragAndDrop.visualMode != DragAndDropVisualMode.None; } // Allow editor Wrapper Drop Handler var allObjectsHandled = false; - if (DragAndDrop.visualMode == DragAndDropVisualMode.None) + if (!dropHandled) { allObjectsHandled = CallEditorDragFunctions(dragAndDropObjects); } + if (evt.type == EventType.Used || allObjectsHandled) + return; + // C++ legacy Drop Handler - if (!IsDropAccepted(allObjectsHandled)) + if (!dropHandled) { - DragAndDrop.visualMode = InternalEditorUtility.SceneViewDrag(go, pivot, Event.current.mousePosition, parent, isPerform); + if (pickedObject == null || parentTransform == null) + PickObject(ref pickedObject, ref parentTransform); + DragAndDrop.visualMode = InternalEditorUtility.SceneViewDrag(pickedObject, pivot, Event.current.mousePosition, parentTransform, isPerform); } evt.Use(); - if (IsDropAccepted(allObjectsHandled)) + if (isPerform && DragAndDrop.visualMode != DragAndDropVisualMode.None && DragAndDrop.visualMode != DragAndDropVisualMode.Rejected) { DragAndDrop.AcceptDrag(); // Bail out as state can be messed up by now. @@ -3317,9 +3329,11 @@ void HandleDragging() } } - bool IsDropAccepted(bool allObjectsHandledInExternalHandlers) + void PickObject(ref GameObject dropUpon, ref Transform parentTransform) { - return allObjectsHandledInExternalHandlers || DragAndDrop.visualMode != DragAndDropVisualMode.None || DragAndDrop.visualMode != DragAndDropVisualMode.Rejected; + var defaultParentObject = GetDefaultParentObjectIfSet(); + parentTransform = defaultParentObject != null ? defaultParentObject : customParentForDraggedObjects; + dropUpon = HandleUtility.PickGameObject(Event.current.mousePosition, true); } void CommandsGUI() @@ -3682,9 +3696,7 @@ void CallOnSceneGUI() // Ironically, only allow multi object access inside OnSceneGUI if editor does NOT support multi-object editing. // since there's no harm in going through the serializedObject there if there's always only one target. Editor.m_AllowMultiObjectAccess = !canEditMultipleObjects; - BeginWindows(); onSceneGui(editor); - EndWindows(); Editor.m_AllowMultiObjectAccess = true; if (EditorGUI.EndChangeCheck()) editor.serializedObject.SetIsDifferentCacheDirty(); @@ -3700,8 +3712,8 @@ void CallOnSceneGUI() GUIUtility.ExitGUI(); } } - } + EditorToolManager.InvokeOnSceneGUICustomEditorTools(); if (duringSceneGui != null) diff --git a/Editor/Mono/SceneView/SceneViewToolbars.cs b/Editor/Mono/SceneView/SceneViewToolbars.cs index 3c6451a992..4ab2f6a3c9 100644 --- a/Editor/Mono/SceneView/SceneViewToolbars.cs +++ b/Editor/Mono/SceneView/SceneViewToolbars.cs @@ -2,12 +2,18 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using UnityEditor.Overlays; +using UnityEditor.Toolbars; using UnityEngine; using UnityEngine.UIElements; namespace UnityEditor { + // See also + // - UIServiceEditor/SceneView/SceneViewToolbarElements.cs + // - UIServiceEditor/EditorToolbar/ToolbarElements/BuiltinTools.cs + [Overlay(typeof(SceneView), k_Id, "Tools", true)] [Icon("Icons/Overlays/ToolsToggle.png")] class TransformToolsOverlayToolBar : ToolbarOverlay @@ -40,20 +46,20 @@ class SearchToolBar : Overlay, ICreateHorizontalToolbar { const string k_Id = "unity-search-toolbar"; - public override VisualElement CreatePanelContent() + public OverlayToolbar CreateHorizontalToolbarContent() { - return new IMGUIContainer { onGUIHandler = OnGUI }; + return EditorToolbar.CreateOverlay(toolbarElements, containerWindow); } - void OnGUI() + public override VisualElement CreatePanelContent() { - EditorGUILayout.BeginHorizontal(); - if (containerWindow is SceneView sceneView) - sceneView.ToolbarSearchFieldGUI(); - EditorGUILayout.EndHorizontal(); + return CreatePanelContent(); } - public VisualElement CreateHorizontalToolbarContent() => CreatePanelContent(); + public IEnumerable toolbarElements + { + get { yield return "SceneView/Search"; } + } } [Overlay(typeof(SceneView), k_Id, "Grid and Snap", true)] diff --git a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs index f983328861..8c8964fb4e 100644 --- a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs +++ b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs @@ -185,6 +185,9 @@ internal bool OnGUI(Rect position, SerializedProperty property, GUIContent label } else { + if (!includeChildren) + return EditorGUI.DefaultPropertyField(position, property, label); + if (UseReorderabelListControl(property)) { ReorderableListWrapper reorderableList; @@ -209,9 +212,6 @@ internal bool OnGUI(Rect position, SerializedProperty property, GUIContent label return !includeChildren && property.isExpanded; } - if (!includeChildren) - return EditorGUI.DefaultPropertyField(position, property, label); - // Remember state Vector2 oldIconSize = EditorGUIUtility.GetIconSize(); bool wasEnabled = GUI.enabled; @@ -280,22 +280,6 @@ public float GetHeight(SerializedProperty property, GUIContent label, bool inclu foreach (DecoratorDrawer drawer in m_DecoratorDrawers) height += drawer.GetHeight(); - if (UseReorderabelListControl(property)) - { - ReorderableListWrapper reorderableList; - string key = ReorderableListWrapper.GetPropertyIdentifier(property); - - // If collection doesn't have a ReorderableList assigned to it, create one and assign it - if (!s_reorderableLists.TryGetValue(key, out reorderableList)) - { - reorderableList = new ReorderableListWrapper(property, label, true); - s_reorderableLists[key] = reorderableList; - } - - reorderableList.Property = property; - height += s_reorderableLists[key].GetHeight(includeChildren); - return height; - } if (propertyDrawer != null) { @@ -310,6 +294,22 @@ public float GetHeight(SerializedProperty property, GUIContent label, bool inclu { height += EditorGUI.GetSinglePropertyHeight(property, label); } + else if (UseReorderabelListControl(property)) + { + ReorderableListWrapper reorderableList; + string key = ReorderableListWrapper.GetPropertyIdentifier(property); + + // If collection doesn't have a ReorderableList assigned to it, create one and assign it + if (!s_reorderableLists.TryGetValue(key, out reorderableList)) + { + reorderableList = new ReorderableListWrapper(property, label, true); + s_reorderableLists[key] = reorderableList; + } + + reorderableList.Property = property; + height += s_reorderableLists[key].GetHeight(); + return height; + } else { property = property.Copy(); @@ -430,7 +430,9 @@ internal static bool IsArrayReorderable(SerializedProperty property) { const BindingFlags fieldFilter = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - if (property == null) return false; + if (property == null || property.serializedObject == null || !property.serializedObject.targetObject) + return false; + if (property.IsReorderable()) return true; FieldInfo listInfo = null; diff --git a/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs b/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs index 09b8f8cdc2..167b2f6010 100644 --- a/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs +++ b/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs @@ -29,28 +29,15 @@ internal class APIUpdaterAssemblyHelper internal static int Run(string arguments, string workingDir, out string stdOut, out string stdErr) { - var monodistribution = MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"); - - var monoexe = Path.Combine(monodistribution, "bin/mono"); - if (Application.platform == RuntimePlatform.WindowsEditor) + var assemblyUpdaterProcess = new NetCoreProgram(AssemblyUpdaterPath(), arguments, psi => { - monoexe = Application.platform == RuntimePlatform.WindowsEditor - ? CommandLineFormatter.EscapeCharsWindows(monoexe + ".exe") - : CommandLineFormatter.EscapeCharsQuote(monoexe + ".exe"); - } + psi.CreateNoWindow = true; + psi.RedirectStandardError = true; + psi.RedirectStandardOutput = true; + psi.WorkingDirectory = workingDir; + psi.UseShellExecute = false; + }); - var startInfo = new ProcessStartInfo - { - Arguments = AssemblyUpdaterPath() + " " + arguments, - CreateNoWindow = true, - FileName = monoexe, - RedirectStandardError = true, - RedirectStandardOutput = true, - WorkingDirectory = workingDir, - UseShellExecute = false - }; - - var assemblyUpdaterProcess = new Program(startInfo); assemblyUpdaterProcess.LogProcessStartInfo(); assemblyUpdaterProcess.Start(); @@ -110,7 +97,9 @@ private static string ResolveAssemblyPath(string assemblyPath) private static string AssemblySearchPathArgument(IEnumerable configurationSourceDirectories = null) { - var searchPath = Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "Managed").Escape(Path.PathSeparator) + Path.PathSeparator + var searchPath = NetStandardFinder.GetReferenceDirectory().Escape(Path.PathSeparator) + Path.PathSeparator + + NetStandardFinder.GetNetStandardCompatShimsDirectory().Escape(Path.PathSeparator) + Path.PathSeparator + + NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory().Escape(Path.PathSeparator) + Path.PathSeparator + "+" + Application.dataPath.Escape(Path.PathSeparator); if (configurationSourceDirectories != null) diff --git a/Editor/Mono/Scripting/APIUpdater/AssemblyDependencyGraph.cs b/Editor/Mono/Scripting/APIUpdater/AssemblyDependencyGraph.cs index 008334ff5a..98719a31dc 100644 --- a/Editor/Mono/Scripting/APIUpdater/AssemblyDependencyGraph.cs +++ b/Editor/Mono/Scripting/APIUpdater/AssemblyDependencyGraph.cs @@ -259,7 +259,9 @@ public void SaveTo(Stream stream) stream.Write(hash, 0, hash.Length); // and reserve space of the "payload" hash. var formatter = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 formatter.Serialize(stream, this); +#pragma warning restore SYSLIB0011 var endOfStream = stream.Position; @@ -301,7 +303,9 @@ public static AssemblyDependencyGraph LoadFrom(Stream stream) stream.Position = startOfSerializedData; var serializer = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 return (AssemblyDependencyGraph)serializer.Deserialize(stream); +#pragma warning restore SYSLIB0011 } internal DependencyEntry FindAssembly(string dependent) diff --git a/Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriver.cs b/Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriver.cs index eae314fc69..4eb596a26d 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriver.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnityBeeDriver.cs @@ -4,7 +4,11 @@ using System; using System.Collections.Generic; +using System.Globalization; +using System.IO; using System.Linq; +using System.Security.Cryptography; +using System.Text; using Bee.BeeDriver; using BeeBuildProgramCommon.Data; using NiceIO; @@ -16,6 +20,32 @@ namespace UnityEditor.Scripting.ScriptCompilation { static class UnityBeeDriver { + internal static readonly string BeeBackendExecutable = new NPath($"{EditorApplication.applicationContentsPath}/bee_backend{BeeScriptCompilation.ExecutableExtension}").ToString(); + [Serializable] + internal class BeeBackendInfo + { + public string UnityVersion; + public string BeeBackendHash; + } + internal static string BeeBackendHash + { + get + { + // Using SessionState, that way we won't need to rehash on domain reload. + var hash = SessionState.GetString(nameof(BeeBackendHash), string.Empty); + if (!string.IsNullOrEmpty(hash)) + return hash; + using var hasher = new SHA256Managed(); + using var stream = File.OpenRead(BeeBackendExecutable); + var bytes = hasher.ComputeHash(stream); + var sb = new StringBuilder(); + foreach (var b in bytes) + sb.Append(b.ToString("x2", CultureInfo.InvariantCulture)); + hash = sb.ToString(); + SessionState.SetString(nameof(BeeBackendHash), hash); + return hash; + } + } public static BeeBuildProgramCommon.Data.PackageInfo[] GetPackageInfos(string projectDirectory) { return PackageManager.PackageInfo.GetAllRegisteredPackages().Select(p => @@ -32,13 +62,60 @@ public static BeeBuildProgramCommon.Data.PackageInfo[] GetPackageInfos(string pr }).ToArray(); } + private static void RecreateDagDirectoryIfNeeded(NPath dagDirectory) + { + var beeBackendInfoPath = dagDirectory.Combine("bee_backend.info"); + var currentInfo = new BeeBackendInfo() + { + BeeBackendHash = BeeBackendHash, + UnityVersion = Application.unityVersion + }; + + var diskInfo = new BeeBackendInfo(); + + // Clear dag directory if it was produced with a different bee_backend, to avoid problem where bee_backend sometimes looses track of files. + if (dagDirectory.Exists()) + { + if (beeBackendInfoPath.Exists()) + { + var contents = beeBackendInfoPath.ReadAllText(); + EditorJsonUtility.FromJsonOverwrite(contents, diskInfo); + + // Note: We're clearing dag directory only when bee backend hash has changed, it's fine for Unity version to be different. + // Unity version is used here for informational purposes, so we can clearly see from which Unity version the user was upgrading + if (string.IsNullOrEmpty(diskInfo.BeeBackendHash) || + !diskInfo.BeeBackendHash.Equals(currentInfo.BeeBackendHash)) + { + Console.WriteLine($"Clearing Bee directory '{dagDirectory}', since bee backend hash ('{beeBackendInfoPath}') is different, previous hash was {diskInfo.BeeBackendHash} (Unity version: {diskInfo.UnityVersion}), current hash is {currentInfo.BeeBackendHash} (Unity version: {currentInfo.UnityVersion})."); + dagDirectory.Delete(); + } + } + else + { + Console.WriteLine($"Clearing Bee directory '{dagDirectory}', since bee backend information ('{beeBackendInfoPath}') is missing."); + dagDirectory.Delete(); + } + } + + dagDirectory.CreateDirectory(); + + // Update info, if at least of one the fields is different + if (string.IsNullOrEmpty(diskInfo.BeeBackendHash) || + string.IsNullOrEmpty(diskInfo.UnityVersion) || + !diskInfo.BeeBackendHash.Equals(currentInfo.BeeBackendHash) || + !diskInfo.UnityVersion.Equals(currentInfo.UnityVersion)) + { + beeBackendInfoPath.WriteAllText(EditorJsonUtility.ToJson(currentInfo, true)); + } + } + public static BeeDriver Make(RunnableProgram buildProgram, EditorCompilation editorCompilation, string dagName, string dagDirectory = null, bool useScriptUpdater = true) { return Make(buildProgram, dagName, dagDirectory, useScriptUpdater, editorCompilation.projectDirectory); } public static BeeDriver Make(RunnableProgram buildProgram, string dagName, - string dagDirectory, bool useScriptUpdater, string projectDirectory, ProgressAPI progressAPI = null) + string dagDirectory, bool useScriptUpdater, string projectDirectory, ProgressAPI progressAPI = null, RunnableProgram beeBackendProgram = null) { var sourceFileUpdaters = useScriptUpdater ? new[] {new UnityScriptUpdater(projectDirectory)} @@ -47,9 +124,10 @@ public static BeeDriver Make(RunnableProgram buildProgram, string dagName, var processSourceFileUpdatersResult = new UnitySourceFileUpdatersResultHandler(); NPath dagDir = dagDirectory ?? "Library/Bee"; - dagDir.CreateDirectory(); + + RecreateDagDirectoryIfNeeded(dagDir); NPath profilerOutputFile = UnityBeeDriverProfilerSession.GetTraceEventsOutputForNewBeeDriver() ?? $"{dagDir}/fullprofile.json"; - var result = new BeeDriver(buildProgram, UnityBeeBackendProgram(), projectDirectory, dagName, dagDir.ToString(), sourceFileUpdaters, processSourceFileUpdatersResult, progressAPI ?? new UnityProgressAPI("Script Compilation"), profilerOutputFile: profilerOutputFile.ToString()); + var result = new BeeDriver(buildProgram, beeBackendProgram ?? UnityBeeBackendProgram(), projectDirectory, dagName, dagDir.ToString(), sourceFileUpdaters, processSourceFileUpdatersResult, progressAPI ?? new UnityProgressAPI("Script Compilation"), profilerOutputFile: profilerOutputFile.ToString()); result.DataForBuildProgram.Add(new ConfigurationData { @@ -68,10 +146,13 @@ public static BeeDriver Make(RunnableProgram buildProgram, string dagName, return result; } - private static RunnableProgram UnityBeeBackendProgram() + internal static RunnableProgram UnityBeeBackendProgram() { - var executable = new NPath($"{EditorApplication.applicationContentsPath}/bee_backend{BeeScriptCompilation.ExecutableExtension}").ToString(); - return new SystemProcessRunnableProgram(executable, alwaysEnvironmentVariables: new Dictionary() {{ "BEE_CACHE_BEHAVIOUR", "_"}}, stdOutMode: StdOutMode.LogStdOutOnFinish | StdOutMode.LogStartArgumentsAndExitcode); + return new SystemProcessRunnableProgram(BeeBackendExecutable, alwaysEnvironmentVariables: new Dictionary() + { + { "BEE_CACHE_BEHAVIOUR", "_"}, + { "CHROMETRACE_TIMEOFFSET","unixepoch"} + }, stdOutMode: StdOutMode.LogStdOutOnFinish | StdOutMode.LogStartArgumentsAndExitcode); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 2fa66b51f5..cff92f9917 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -1200,7 +1200,9 @@ public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions opti Debug.RemoveLogEntriesByIdentifier(logIdentifier); foreach (var message in compilerMessages) { - Debug.LogCompilerMessage(message.message, message.file, message.line, message.column, activeBeeBuild.settings.BuildingForEditor, message.type == CompilerMessageType.Error, logIdentifier); + // Ensure that we don't emit info messages (user cannot do anything with these and they are generated by DiagnosticSuppressors) + if (message.type != CompilerMessageType.Information) + Debug.LogCompilerMessage(message.message, message.file, message.line, message.column, activeBeeBuild.settings.BuildingForEditor, message.type == CompilerMessageType.Error, logIdentifier); } } diff --git a/Editor/Mono/SerializedObject.bindings.cs b/Editor/Mono/SerializedObject.bindings.cs index 86eddc143a..c3e90eaa34 100644 --- a/Editor/Mono/SerializedObject.bindings.cs +++ b/Editor/Mono/SerializedObject.bindings.cs @@ -211,8 +211,8 @@ public extern bool forceChildVisibility set; } - [NativeMethod("HasAnyInstantiatedPrefabs")] - internal extern bool HasAnyInstantiatedPrefabs(); + [NativeMethod("HasAnyInstantiatedPrefabsWithValidAsset")] + internal extern bool HasAnyInstantiatedPrefabsWithValidAsset(); internal static bool VersionEquals(SerializedObject x, SerializedObject y) { diff --git a/Editor/Mono/SerializedProperty.bindings.cs b/Editor/Mono/SerializedProperty.bindings.cs index e95dc7fadd..5edc0d8e2a 100644 --- a/Editor/Mono/SerializedProperty.bindings.cs +++ b/Editor/Mono/SerializedProperty.bindings.cs @@ -19,7 +19,7 @@ namespace UnityEditor // Type of a [[SerializedProperty]]. public enum SerializedPropertyType { - //*undocumented + // Struct, array or class that is serialized by value. Generic = -1, // Integer property. Integer = 0, @@ -270,31 +270,159 @@ internal void SetToValueOfTarget(UnityObject target) Debug.LogError(target.name + " does not have the property " + propertyPath); return; } - switch (propertyType) - { - case SerializedPropertyType.Integer: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Boolean: boolValue = targetProperty.boolValue; break; - case SerializedPropertyType.Float: floatValue = targetProperty.floatValue; break; - case SerializedPropertyType.String: stringValue = targetProperty.stringValue; break; - case SerializedPropertyType.Color: colorValue = targetProperty.colorValue; break; - case SerializedPropertyType.ObjectReference: objectReferenceValue = targetProperty.objectReferenceValue; break; - case SerializedPropertyType.LayerMask: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Enum: enumValueIndex = targetProperty.enumValueIndex >= 0 ? targetProperty.enumValueIndex : 0; - intValue = targetProperty.intValue >= 0 ? targetProperty.intValue : intValue; break; - case SerializedPropertyType.Vector2: vector2Value = targetProperty.vector2Value; break; - case SerializedPropertyType.Vector3: vector3Value = targetProperty.vector3Value; break; - case SerializedPropertyType.Vector4: vector4Value = targetProperty.vector4Value; break; - case SerializedPropertyType.Vector2Int: vector2IntValue = targetProperty.vector2IntValue; break; - case SerializedPropertyType.Vector3Int: vector3IntValue = targetProperty.vector3IntValue; break; - case SerializedPropertyType.Rect: rectValue = targetProperty.rectValue; break; - case SerializedPropertyType.RectInt: rectIntValue = targetProperty.rectIntValue; break; - case SerializedPropertyType.ArraySize: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Character: intValue = targetProperty.intValue; break; - case SerializedPropertyType.AnimationCurve: animationCurveValue = targetProperty.animationCurveValue; break; - case SerializedPropertyType.Bounds: boundsValue = targetProperty.boundsValue; break; - case SerializedPropertyType.BoundsInt: boundsIntValue = targetProperty.boundsIntValue; break; - case SerializedPropertyType.Gradient: gradientValue = targetProperty.gradientValue; break; - case SerializedPropertyType.ExposedReference: exposedReferenceValue = targetProperty.exposedReferenceValue; break; + + try + { + boxedValue = targetProperty.boxedValue; + } + catch (NotSupportedException ex) + { + // Previous implementation silently did nothing for unsupported types, now moving towards more strict error handling with this warning + Debug.LogWarning(ex.Message); + } + } + + public System.Object boxedValue + { + get + { + switch (propertyType) + { + case SerializedPropertyType.Generic: return structValue; + case SerializedPropertyType.Enum: goto case SerializedPropertyType.Integer; + case SerializedPropertyType.Integer: + { + switch (numericType) + { + case SerializedPropertyNumericType.UInt64: + return ulongValue; + case SerializedPropertyNumericType.Int64: + return longValue; + case SerializedPropertyNumericType.UInt32: + return uintValue; + case SerializedPropertyNumericType.UInt16: + return (System.UInt16)uintValue; + case SerializedPropertyNumericType.Int16: + return (System.Int16)intValue; + case SerializedPropertyNumericType.UInt8: + return (System.Byte)uintValue; + case SerializedPropertyNumericType.Int8: + return (System.SByte)intValue; + default: + return intValue; + } + } + case SerializedPropertyType.Boolean: return boolValue; + case SerializedPropertyType.Float: + { + if (numericType == SerializedPropertyNumericType.Double) + return doubleValue; + else + return floatValue; + } + + case SerializedPropertyType.String: return stringValue; + case SerializedPropertyType.Color: return colorValue; + case SerializedPropertyType.ObjectReference: return objectReferenceValue; + case SerializedPropertyType.LayerMask: return (LayerMask)intValue; + case SerializedPropertyType.Vector2: return vector2Value; + case SerializedPropertyType.Vector3: return vector3Value; + case SerializedPropertyType.Vector4: return vector4Value; + case SerializedPropertyType.Rect: return rectValue; + case SerializedPropertyType.ArraySize: return intValue; + case SerializedPropertyType.Character: return (System.UInt16)uintValue; + case SerializedPropertyType.AnimationCurve: return animationCurveValue; + case SerializedPropertyType.Bounds: return boundsValue; + case SerializedPropertyType.Gradient: return gradientValue; + case SerializedPropertyType.Quaternion: return quaternionValue; + case SerializedPropertyType.ExposedReference: return exposedReferenceValue; + case SerializedPropertyType.FixedBufferSize: return intValue; + case SerializedPropertyType.Vector2Int: return vector2IntValue; + case SerializedPropertyType.Vector3Int: return vector3IntValue; + case SerializedPropertyType.RectInt: return rectIntValue; + case SerializedPropertyType.BoundsInt: return boundsIntValue; + case SerializedPropertyType.ManagedReference: return managedReferenceValue; + case SerializedPropertyType.Hash128: return hash128Value; + + default: + throw new NotSupportedException(string.Format("The boxedValue property is not supported on \"{0}\" because it has an unsupported propertyType {1}.", propertyPath, propertyType)); + } + } + + set + { + try + { + // Note: typecast from System.Object enforces strict match between the boxed type and cast type. + // The Convert API is used for cases where multiple types can safely and commonly be converted to the underlying SerializedProperty type. + switch (propertyType) + { + case SerializedPropertyType.Generic: structValue = value; break; + case SerializedPropertyType.Enum: goto case SerializedPropertyType.Integer; + case SerializedPropertyType.ArraySize: goto case SerializedPropertyType.Integer; + case SerializedPropertyType.Integer: + { + //Convert so that simple mismatches like sbyte to int are accepted + if (numericType == SerializedPropertyNumericType.UInt64) + { + ulongValue = Convert.ToUInt64(value); + } + else + { + // all smaller numeric datatypes fit into the range of long and are cast back to the correct type internally + longValue = Convert.ToInt64(value); + } + break; + } + case SerializedPropertyType.Boolean: boolValue = (bool)value; break; + case SerializedPropertyType.Float: + { + if (numericType == SerializedPropertyNumericType.Double) + doubleValue = Convert.ToDouble(value); + else + floatValue = Convert.ToSingle(value); + break; + } + case SerializedPropertyType.String: stringValue = (string)value; break; + case SerializedPropertyType.Color: colorValue = (Color)value; break; + case SerializedPropertyType.ObjectReference: objectReferenceValue = (UnityEngine.Object)value; break; + case SerializedPropertyType.LayerMask: + { + try + { + intValue = ((LayerMask)value).value; + } + catch (InvalidCastException) + { + intValue = Convert.ToInt32(value); + } + break; + } + case SerializedPropertyType.Vector2: vector2Value = (Vector2)value; break; + case SerializedPropertyType.Vector3: vector3Value = (Vector3)value; break; + case SerializedPropertyType.Vector4: vector4Value = (Vector4)value; break; + case SerializedPropertyType.Rect: rectValue = (Rect)value; break; + case SerializedPropertyType.Character: uintValue = Convert.ToUInt16(value); break; + case SerializedPropertyType.AnimationCurve: animationCurveValue = (AnimationCurve)value; break; + case SerializedPropertyType.Bounds: boundsValue = (Bounds)value; break; + case SerializedPropertyType.Gradient: gradientValue = (Gradient)value; break; + case SerializedPropertyType.Quaternion: quaternionValue = (Quaternion)value; break; + case SerializedPropertyType.ExposedReference: exposedReferenceValue = (UnityEngine.Object)value; break; + case SerializedPropertyType.Vector2Int: vector2IntValue = (Vector2Int)value; break; + case SerializedPropertyType.Vector3Int: vector3IntValue = (Vector3Int)value; break; + case SerializedPropertyType.RectInt: rectIntValue = (RectInt)value; break; + case SerializedPropertyType.BoundsInt: boundsIntValue = (BoundsInt)value; break; + case SerializedPropertyType.ManagedReference: managedReferenceValue = value; break; + case SerializedPropertyType.Hash128: hash128Value = (Hash128)value; break; + + default: // FixedBufferSize is read-only + throw new NotSupportedException(string.Format("Set on boxedValue property is not supported on \"{0}\" because it has an unsupported propertyType {1}.", propertyPath, propertyType)); + } + } + catch (InvalidCastException) + { + throw new InvalidCastException(string.Format("The value passed to boxedValue on \"{0}\" cannot be cast to expected propertyType {1}.", propertyPath, propertyType)); + } } } @@ -1156,6 +1284,51 @@ public string managedReferenceFieldTypename [NativeName("SetManagedReferenceValue")] private extern void SetManagedReferenceValueInternal(object value); + [NativeName("SetStructValue")] + [NativeThrows] + internal extern void SetStructValueInternal(object value); + + [NativeName("GetStructValue")] + [NativeThrows] + internal extern object GetStructValueInternal(string assemblyName, string nameSpace, string className); + + // exposed for public access via boxedValue + internal object structValue + { + get + { + if (isArray) + throw new System.InvalidOperationException($"'{propertyPath}' is an array so it cannot be read with boxedValue."); + + // Unlike managed references, the precise type for a struct or by-value class field is easier to determine in C# + // rather than at the native level, so we pass that info in. + UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out Type type); + + var nameSpace = type.Namespace; + string typeName = type.FullName.Replace("+", "/"); + + if (!string.IsNullOrEmpty(nameSpace)) + typeName = typeName.Substring(nameSpace.Length + 1); + + return GetStructValueInternal(type.Assembly.GetName().Name, nameSpace, typeName); + } + + set + { + if (isArray) + throw new System.InvalidOperationException($"'{propertyPath}' is an array so it cannot be set with boxedValue."); + + // Retrieve the C# type info this property + UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out Type propertyType); + + if (propertyType.FullName != value.GetType().FullName) + throw new System.InvalidOperationException( + $"The input to boxedValue has type '{value.GetType().FullName.Replace("+","/")}', which does not match the expected type '{propertyType.FullName.Replace("+","/")}'."); + + SetStructValueInternal(value); + } + } + [NativeName("LookupInstanceById")] private extern object LookupInstanceByIdInternal(RefId refId); diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index 9edb028a72..48b5f29145 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -482,9 +482,34 @@ private void HandleSearchFiltering() [MenuItem("Edit/Project Settings...", false, 259, false)] internal static void OpenProjectSettings() { + SendTopMenuProjectSettingsEvent(); Show(SettingsScope.Project); } + static void SendTopMenuProjectSettingsEvent() + { + EditorAnalytics.SendEventEditorGameService(new EditorGameServiceEvent + { + action = "Project Settings", + assembly_info = "", + component = "Top Menu", + package = "Unity Editor", + package_ver = "" + }); + } + + + [Serializable] + internal struct EditorGameServiceEvent + { + public string action; + public string assembly_info; + public string component; + public string package; + public string package_ver; + } + + internal static SettingsWindow OpenUserPreferences() { return Show(SettingsScope.User); diff --git a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs b/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs index 282ac955ef..50ff94f9d3 100644 --- a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs +++ b/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs @@ -193,6 +193,7 @@ internal class ShaderStrippingEditor : Editor SerializedProperty m_FogKeepExp; SerializedProperty m_FogKeepExp2; SerializedProperty m_InstancingStripping; + SerializedProperty m_BrgStripping; public void OnEnable() { @@ -208,6 +209,7 @@ public void OnEnable() m_FogKeepExp = serializedObject.FindProperty("m_FogKeepExp"); m_FogKeepExp2 = serializedObject.FindProperty("m_FogKeepExp2"); m_InstancingStripping = serializedObject.FindProperty("m_InstancingStripping"); + m_BrgStripping = serializedObject.FindProperty("m_BrgStripping"); } public override void OnInspectorGUI() @@ -261,6 +263,7 @@ public override void OnInspectorGUI() } EditorGUILayout.PropertyField(m_InstancingStripping, Styles.instancingVariants); + EditorGUILayout.PropertyField(m_BrgStripping, Styles.brgVariants); serializedObject.ApplyModifiedProperties(); @@ -293,6 +296,7 @@ internal partial class Styles public static readonly GUIContent fogFromScene = EditorGUIUtility.TrTextContent("Import From Current Scene", "Calculate fog modes used by the current scene."); public static readonly GUIContent instancingVariants = EditorGUIUtility.TrTextContent("Instancing Variants"); + public static readonly GUIContent brgVariants = EditorGUIUtility.TrTextContent("BatchRendererGroup Variants"); public static readonly GUIContent shaderPreloadSave = EditorGUIUtility.TrTextContent("Save to asset...", "Save currently tracked shaders into a Shader Variant Manifest asset."); public static readonly GUIContent shaderPreloadClear = EditorGUIUtility.TrTextContent("Clear", "Clear currently tracked shader variant information."); diff --git a/Editor/Mono/UnityConnect/CloudProjectSettings.cs b/Editor/Mono/UnityConnect/CloudProjectSettings.cs index 73a41fbc44..5d98a54f7e 100644 --- a/Editor/Mono/UnityConnect/CloudProjectSettings.cs +++ b/Editor/Mono/UnityConnect/CloudProjectSettings.cs @@ -9,6 +9,10 @@ namespace UnityEditor { public class CloudProjectSettings { + /// + /// The user ID is derived from the user name without the domain (removing all characters starting with '@'), + /// formatted in lowercase with no symbols. + /// public static string userId { get @@ -17,6 +21,9 @@ public static string userId } } + /// + /// The user name is the email used for the user's Unity account. + /// public static string userName { get @@ -38,6 +45,17 @@ public static void RefreshAccessToken(Action refresh) UnityConnect.instance.RefreshAccessToken(refresh); } + /// + /// This method shows the Unity login popup. + /// + public static void ShowLogin() + { + UnityConnect.instance.ShowLogin(); + } + + /// + /// The Project ID, or GUID. + /// public static string projectId { get @@ -46,6 +64,9 @@ public static string projectId } } + /// + /// The name of the project. + /// public static string projectName { get @@ -54,6 +75,9 @@ public static string projectName } } + /// + /// The Organization ID, formatted in lowercase with no symbols. + /// public static string organizationId { get @@ -62,6 +86,9 @@ public static string organizationId } } + /// + /// The Organization name used on the dashboard. + /// public static string organizationName { get @@ -69,5 +96,38 @@ public static string organizationName return UnityConnect.instance.GetOrganizationName(); } } + + /// + /// The key of the organization used on the dashboard + /// + public static string organizationKey + { + get + { + return UnityConnect.instance.GetOrganizationForeignKey(); + } + } + + /// + /// The current COPPA compliance state. + /// + public static CoppaCompliance coppaCompliance + { + get + { + return UnityConnect.instance.projectInfo.COPPA; + } + } + + /// + /// Returns true if the project has been bound. + /// + public static bool projectBound + { + get + { + return UnityConnect.instance.projectInfo.projectBound; + } + } } } diff --git a/Editor/Mono/UnityConnect/CloudProjectSettingsEventManager.cs b/Editor/Mono/UnityConnect/CloudProjectSettingsEventManager.cs new file mode 100644 index 0000000000..c557d22cb2 --- /dev/null +++ b/Editor/Mono/UnityConnect/CloudProjectSettingsEventManager.cs @@ -0,0 +1,63 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor.Connect; +using UnityEngine; + +namespace UnityEditor +{ + /// + /// Manages the events related to the project state + /// + public class CloudProjectSettingsEventManager + { + /// + /// The instance of the Cloud Project Settings event manager. + /// + public static CloudProjectSettingsEventManager instance { get; } = new CloudProjectSettingsEventManager(); + + /// + /// The event fired when the state of the project changes. + /// + public event Action projectStateChanged; + + /// + /// The event fired when the state of the project is refreshed. + /// + public event Action projectRefreshed; + + CloudProjectSettingsEventManager() + { + RegisterToUnityConnectEvents(); + } + + ~CloudProjectSettingsEventManager() + { + UnregisterToUnityConnectEvents(); + } + + void RegisterToUnityConnectEvents() + { + UnityConnect.instance.ProjectStateChanged += OnProjectStateChanged; + UnityConnect.instance.ProjectRefreshed += OnProjectRefreshed; + } + + void UnregisterToUnityConnectEvents() + { + UnityConnect.instance.ProjectStateChanged -= OnProjectStateChanged; + UnityConnect.instance.ProjectRefreshed -= OnProjectRefreshed; + } + + void OnProjectStateChanged(ProjectInfo projectInfo) + { + projectStateChanged?.Invoke(); + } + + void OnProjectRefreshed(ProjectInfo projectInfo) + { + projectRefreshed?.Invoke(); + } + } +} diff --git a/Editor/Mono/UnityConnect/CoppaCompliance.cs b/Editor/Mono/UnityConnect/CoppaCompliance.cs new file mode 100644 index 0000000000..8694030151 --- /dev/null +++ b/Editor/Mono/UnityConnect/CoppaCompliance.cs @@ -0,0 +1,37 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEditor.Connect; + +namespace UnityEditor +{ + /// + /// The enumerated states of the project's COPPA compliance setting, where 1 indicates compliance. + /// + public enum CoppaCompliance + { + /// + /// The project has not yet defined the COPPA state. + /// + CoppaUndefined = COPPACompliance.COPPAUndefined, + + /// + /// The project will adhere to COPPA regulations because it targets an audience under a certain age. + /// + CoppaCompliant = COPPACompliance.COPPACompliant, + + /// + /// The project will not adhere to COPPA regulations because it does not target an audience under a specific age. + /// + CoppaNotCompliant = COPPACompliance.COPPANotCompliant, + } + + static class CoppaComplianceExtensions + { + internal static COPPACompliance ToCOPPACompliance(this CoppaCompliance coppaCompliance) + { + return (COPPACompliance)coppaCompliance; + } + } +} diff --git a/Editor/Mono/UnityConnect/UnityConnect.bindings.cs b/Editor/Mono/UnityConnect/UnityConnect.bindings.cs index f887d18e5e..514f537452 100644 --- a/Editor/Mono/UnityConnect/UnityConnect.bindings.cs +++ b/Editor/Mono/UnityConnect/UnityConnect.bindings.cs @@ -30,7 +30,6 @@ internal enum CloudConfigUrl CloudAssetStoreUrl = 13 } - //*undocumented* internal enum COPPACompliance { COPPAUndefined = 0, @@ -38,6 +37,14 @@ internal enum COPPACompliance COPPANotCompliant = 2 } + static class COPPAComplianceExtensions + { + internal static CoppaCompliance ToCoppaCompliance(this COPPACompliance coppaCompliance) + { + return (CoppaCompliance)coppaCompliance; + } + } + #pragma warning disable 649 //*undocumented* [NativeType(CodegenOptions.Custom, "MonoUnityProjectInfo")] @@ -52,13 +59,13 @@ internal struct ProjectInfo public string organizationId { get { return m_OrganizationID; } } public string organizationName { get { return m_OrganizationName; } } public string organizationForeignKey { get { return m_OrganizationForeignKey; } } - public COPPACompliance COPPA + public CoppaCompliance COPPA { get { - if (m_COPPA == 1) return COPPACompliance.COPPACompliant; - if (m_COPPA == 2) return COPPACompliance.COPPANotCompliant; - return COPPACompliance.COPPAUndefined; + if (m_COPPA == 1) return COPPACompliance.COPPACompliant.ToCoppaCompliance(); + if (m_COPPA == 2) return COPPACompliance.COPPANotCompliant.ToCoppaCompliance(); + return COPPACompliance.COPPAUndefined.ToCoppaCompliance(); } } public bool coppaLock { get { return m_COPPALock != 0; } } diff --git a/Editor/Mono/Unsupported.bindings.cs b/Editor/Mono/Unsupported.bindings.cs index a435f97a8d..7519ee8740 100644 --- a/Editor/Mono/Unsupported.bindings.cs +++ b/Editor/Mono/Unsupported.bindings.cs @@ -116,17 +116,12 @@ public static bool SetOverrideLightingSettings(Scene scene) internal static extern bool SetOverrideLightingSettingsInternal(int sceneHandle); + [NativeThrows] public static extern void RestoreOverrideLightingSettings(); [FreeFunction("GetRenderSettings().SetUseFogNoDirty")] public static extern void SetRenderSettingsUseFogNoDirty(bool fog); - [FreeFunction("GetRenderSettings().SetSceneViewDebugModeExposureNoDirty")] - public static extern void SetSceneViewDebugModeExposureNoDirty(float exposure); - - [FreeFunction("GetRenderSettings().GetSceneViewDebugModeExposure")] - public static extern float GetSceneViewDebugModeExposure(); - [FreeFunction("GetQualitySettings().SetShadowDistanceTemporarily")] public static extern void SetQualitySettingsShadowDistanceTemporarily(float distance); diff --git a/Editor/Mono/Utils/AssemblyReferenceChecker.cs b/Editor/Mono/Utils/AssemblyReferenceChecker.cs index 6e0e9199b4..71dc18be54 100644 --- a/Editor/Mono/Utils/AssemblyReferenceChecker.cs +++ b/Editor/Mono/Utils/AssemblyReferenceChecker.cs @@ -9,6 +9,7 @@ using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; +using UnityEditor.Utils; namespace UnityEditor { @@ -20,7 +21,7 @@ internal class AssemblyReferenceChecker private readonly HashSet _definedMethods = new HashSet(); private HashSet _assemblyDefinitions = new HashSet(); private readonly HashSet _assemblyFileNames = new HashSet(); - + private readonly INetStandardPathProvider _netStandardPathProvider; private DateTime _startTime = DateTime.MinValue; private float _progressValue = 0.0f; @@ -28,10 +29,26 @@ internal class AssemblyReferenceChecker public bool HasMouseEvent { get; private set; } - public AssemblyReferenceChecker() + public AssemblyReferenceChecker() : this(new DefaultStandardPathProvider()) { } + internal AssemblyReferenceChecker(INetStandardPathProvider netStandardPathProvider) { HasMouseEvent = false; _updateProgressAction = DisplayProgress; + _netStandardPathProvider = netStandardPathProvider; + } + + internal interface INetStandardPathProvider + { + IEnumerable GetNetStandardReferenceAndCompatShimDirs(); + } + internal class DefaultStandardPathProvider : INetStandardPathProvider + { + public IEnumerable GetNetStandardReferenceAndCompatShimDirs() + { + yield return NetStandardFinder.GetReferenceDirectory(); + yield return NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory(); + yield return NetStandardFinder.GetNetStandardCompatShimsDirectory(); + } } public static AssemblyReferenceChecker AssemblyReferenceCheckerWithUpdateProgressAction(Action action) @@ -40,6 +57,12 @@ public static AssemblyReferenceChecker AssemblyReferenceCheckerWithUpdateProgres checker._updateProgressAction = action; return checker; } + internal static AssemblyReferenceChecker AssemblyReferenceCheckerWithUpdateProgressAction(Action action, INetStandardPathProvider netStandardPathProvider) + { + var checker = new AssemblyReferenceChecker(netStandardPathProvider); + checker._updateProgressAction = action; + return checker; + } // Follows actually referenced libraries only private void CollectReferencesFromRootsRecursive(string dir, IEnumerable roots, bool ignoreSystemDlls) @@ -308,7 +331,7 @@ public static bool GetScriptsHaveMouseEvents(string path) return checker.HasMouseEvent; } - private static DefaultAssemblyResolver AssemblyResolverFor(string path) + private DefaultAssemblyResolver AssemblyResolverFor(string path) { var resolver = new DefaultAssemblyResolver(); if (File.Exists(path) || Directory.Exists(path)) @@ -318,6 +341,11 @@ private static DefaultAssemblyResolver AssemblyResolverFor(string path) path = Path.GetDirectoryName(path); resolver.AddSearchDirectory(Path.GetFullPath(path)); } + // add .net standard ref and compat shims dirs + foreach(var dir in _netStandardPathProvider.GetNetStandardReferenceAndCompatShimDirs()) + { + resolver.AddSearchDirectory(dir); + } return resolver; } diff --git a/Editor/Mono/Utils/MathUtils.cs b/Editor/Mono/Utils/MathUtils.cs index a15e92e725..a05bc6a537 100644 --- a/Editor/Mono/Utils/MathUtils.cs +++ b/Editor/Mono/Utils/MathUtils.cs @@ -10,93 +10,54 @@ namespace UnityEditor { public class MathUtils { - // We cannot round to more decimals than 15 according to docs for System.Math.Round. - private const int kMaxDecimals = 15; - internal static float ClampToFloat(double value) { - if (double.IsPositiveInfinity(value)) - return float.PositiveInfinity; - - if (double.IsNegativeInfinity(value)) - return float.NegativeInfinity; - - if (value < float.MinValue) - return float.MinValue; - - if (value > float.MaxValue) - return float.MaxValue; - - return (float)value; + return Mathf.ClampToFloat(value); } internal static int ClampToInt(long value) { - if (value < int.MinValue) - return int.MinValue; - - if (value > int.MaxValue) - return int.MaxValue; - - return (int)value; + return Mathf.ClampToInt(value); } internal static float RoundToMultipleOf(float value, float roundingValue) { - if (roundingValue == 0) - return value; - return Mathf.Round(value / roundingValue) * roundingValue; + return Mathf.RoundToMultipleOf(value, roundingValue); } internal static float GetClosestPowerOfTen(float positiveNumber) { - if (positiveNumber <= 0) - return 1; - return Mathf.Pow(10, Mathf.RoundToInt(Mathf.Log10(positiveNumber))); + return Mathf.GetClosestPowerOfTen(positiveNumber); } internal static int GetNumberOfDecimalsForMinimumDifference(float minDifference) { - return Mathf.Clamp(-Mathf.FloorToInt(Mathf.Log10(Mathf.Abs(minDifference))), 0, kMaxDecimals); + return Mathf.GetNumberOfDecimalsForMinimumDifference(minDifference); } internal static int GetNumberOfDecimalsForMinimumDifference(double minDifference) { - return (int)System.Math.Max(0.0, -System.Math.Floor(System.Math.Log10(System.Math.Abs(minDifference)))); + return Mathf.GetNumberOfDecimalsForMinimumDifference(minDifference); } internal static float RoundBasedOnMinimumDifference(float valueToRound, float minDifference) { - if (minDifference == 0) - return DiscardLeastSignificantDecimal(valueToRound); - return (float)System.Math.Round(valueToRound, GetNumberOfDecimalsForMinimumDifference(minDifference), System.MidpointRounding.AwayFromZero); + return Mathf.RoundBasedOnMinimumDifference(valueToRound, minDifference); } internal static double RoundBasedOnMinimumDifference(double valueToRound, double minDifference) { - if (minDifference == 0) - return DiscardLeastSignificantDecimal(valueToRound); - return System.Math.Round(valueToRound, GetNumberOfDecimalsForMinimumDifference(minDifference), System.MidpointRounding.AwayFromZero); + return Mathf.RoundBasedOnMinimumDifference(valueToRound, minDifference); } internal static float DiscardLeastSignificantDecimal(float v) { - int decimals = Mathf.Clamp((int)(5 - Mathf.Log10(Mathf.Abs(v))), 0, kMaxDecimals); - return (float)System.Math.Round(v, decimals, System.MidpointRounding.AwayFromZero); + return Mathf.DiscardLeastSignificantDecimal(v); } internal static double DiscardLeastSignificantDecimal(double v) { - int decimals = System.Math.Max(0, (int)(5 - System.Math.Log10(System.Math.Abs(v)))); - try - { - return System.Math.Round(v, decimals); - } - catch (System.ArgumentOutOfRangeException) - { - // This can happen for very small numbers. - return 0; - } + return Mathf.DiscardLeastSignificantDecimal(v); } public static float GetQuatLength(Quaternion q) diff --git a/Editor/Mono/Utils/NetCoreProgram.cs b/Editor/Mono/Utils/NetCoreProgram.cs index 7891412c7e..370e2c6e5a 100644 --- a/Editor/Mono/Utils/NetCoreProgram.cs +++ b/Editor/Mono/Utils/NetCoreProgram.cs @@ -24,13 +24,10 @@ public NetCoreProgram(string executable, string arguments, Action() == null) + { + // Create and initialize the EnumField. + var uiField = new EnumField(fieldLabel); + uiField.Init(defaultEnumValue); - uiField.RegisterValueChangedCallback(OnAttributeValueChange); - fieldElement = uiField; + uiField.RegisterValueChangedCallback(OnAttributeValueChange); + fieldElement = uiField; + } + else + { + // Create and initialize the EnumField. + var uiField = new EnumFlagsField(fieldLabel); + uiField.Init(defaultEnumValue); + + uiField.RegisterValueChangedCallback(OnAttributeValueChange); + fieldElement = uiField; + } } else { @@ -311,7 +323,7 @@ BuilderStyleRow CreateAttributeRow(UxmlAttributeDescription attribute) // Setup field binding path. fieldElement.bindingPath = attribute.name; fieldElement.tooltip = attribute.name; - + // Context menu. fieldElement.AddManipulator(new ContextualMenuManipulator(BuildAttributeFieldContextualMenu)); @@ -343,6 +355,10 @@ object GetCustomValueAbstract(string attributeName) // Use old API only if version is >= 2019_4 and <= 2020_3 return scrollView.verticalScrollerVisibility != ScrollerVisibility.Hidden; } + else if (attributeName == "touch-scroll-type") + { + return scrollView.touchScrollBehavior; + } } else if (currentVisualElement is ListView listView) { @@ -374,8 +390,20 @@ void RefreshAttributeField(BindableElement fieldElement) if (veValueAbstract == null) { - if (currentVisualElement is EnumField && attribute.name == "value") - fieldElement.SetEnabled(false); + if (currentVisualElement is EnumField defaultEnumField && + attribute.name == "value") + { + if (defaultEnumField.type == null) + { + fieldElement.SetEnabled(false); + } + else + { + ((EnumField)fieldElement).PopulateDataFromType(defaultEnumField.type); + fieldElement.SetEnabled(true); + } + } + return; } @@ -458,13 +486,12 @@ fieldElement is TextField textField && } else if (attributeType.IsGenericType && attributeType.GetGenericArguments()[0].IsEnum && - fieldElement is EnumField) + fieldElement is BaseField) { var propInfo = attributeType.GetProperty("defaultValue"); - var enumValue = propInfo.GetValue(attribute, null) as Enum; + var defaultEnumValue = propInfo.GetValue(attribute, null) as Enum; - // Create and initialize the EnumField. - var uiField = fieldElement as EnumField; + var uiField = fieldElement as BaseField; string enumAttributeValueStr; if (m_Selection.selectionType == BuilderSelectionType.ElementInTemplateInstance) @@ -491,8 +518,23 @@ fieldElement is TextField textField && // Set the value from the UXML attribute. if (!string.IsNullOrEmpty(enumAttributeValueStr)) { - var parsedValue = Enum.Parse(enumValue.GetType(), enumAttributeValueStr, true) as Enum; - uiField.SetValueWithoutNotify(parsedValue); + try + { + var parsedValue = Enum.Parse(defaultEnumValue.GetType(), enumAttributeValueStr, true) as Enum; + uiField.SetValueWithoutNotify(parsedValue); + } + catch (ArgumentException exception) + { + Debug.LogException(exception); + // use default if anything went wrong + uiField.SetValueWithoutNotify(defaultEnumValue); + } + catch (OverflowException exception) + { + Debug.LogException(exception); + // use default if anything went wrong + uiField.SetValueWithoutNotify(defaultEnumValue); + } } } else if (fieldElement is TextField) @@ -623,13 +665,13 @@ void ResetAttributeFieldToDefault(BindableElement fieldElement) } else if (attributeType.IsGenericType && attributeType.GetGenericArguments()[0].IsEnum && - fieldElement is EnumField) + fieldElement is BaseField) { var propInfo = attributeType.GetProperty("defaultValue"); - var enumValue = propInfo.GetValue(attribute, null) as Enum; + var defaultEnumValue = propInfo.GetValue(attribute, null) as Enum; - var uiField = fieldElement as EnumField; - uiField.SetValueWithoutNotify(enumValue); + var uiField = fieldElement as BaseField; + uiField.SetValueWithoutNotify(defaultEnumValue); } else if (fieldElement is TextField) { @@ -924,7 +966,7 @@ void OnAttributeValueChange(ChangeEvent evt) void OnAttributeValueChange(ChangeEvent evt) { - var field = evt.target as EnumField; + var field = evt.target as BaseField; PostAttributeValueChange(field, evt.newValue.ToString()); } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryContent.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryContent.cs index 287c03b491..c92ad84e13 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryContent.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryContent.cs @@ -265,6 +265,8 @@ static List GenerateControlsItemsTree() new BuilderLibraryTreeItem("Integer", nameof(IntegerField), typeof(IntegerField), () => new IntegerField("Int Field") { value = 42 }), new BuilderLibraryTreeItem("Float", nameof(FloatField), typeof(FloatField), () => new FloatField("Float Field") { value = 42.2f }), new BuilderLibraryTreeItem("Long", nameof(LongField), typeof(LongField), () => new LongField("Long Field") { value = 42 }), + new BuilderLibraryTreeItem("Double", nameof(DoubleField), typeof(DoubleField), () => new DoubleField("Double Field") { value = 42.2 }), + new BuilderLibraryTreeItem("Hash128", nameof(Hash128Field), typeof(Hash128Field), () => new Hash128Field("Hash128 Field") { value = Hash128.Compute("42") }), new BuilderLibraryTreeItem("Progress Bar", nameof(ProgressBar), typeof(ProgressBar), () => new ProgressBar() { title = "my-progress", value = 22 }), @@ -277,8 +279,7 @@ static List GenerateControlsItemsTree() new BuilderLibraryTreeItem("Vector3 (Int)", nameof(Vector3IntField), typeof(Vector3IntField), () => new Vector3IntField("Vector3Int")), new BuilderLibraryTreeItem("Rect (Int)", nameof(RectIntField), typeof(RectIntField), () => new RectIntField("RectInt")), new BuilderLibraryTreeItem("Bounds (Int)", nameof(BoundsIntField), typeof(BoundsIntField), () => new BoundsIntField("BoundsInt")), - new BuilderLibraryTreeItem("Object Field", nameof(ObjectField), typeof(ObjectField), () => new ObjectField("Object Field") { value = new Texture2D(10, 10) { name = "new_texture" } }), - }) { isEditorOnly = true, isHeader = true }; + }) { isHeader = true }; var valueFields = new BuilderLibraryTreeItem("Value Fields", null, null, null, null, new List> { @@ -326,6 +327,7 @@ static List GenerateControlsItemsTree() var inspectors = new BuilderLibraryTreeItem("Inspectors", null, null, null, null, new List> { + new BuilderLibraryTreeItem("Object Field", nameof(ObjectField), typeof(ObjectField), () => new ObjectField("Object Field") { value = new Texture2D(10, 10) { name = "new_texture" } }), new BuilderLibraryTreeItem("PropertyField", nameof(PropertyField), typeof(PropertyField), () => new PropertyField()) }) { isEditorOnly = true, isHeader = true }; diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryTreeView.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryTreeView.cs index 11114666d7..cfb86d2c24 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryTreeView.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Library/BuilderLibraryTreeView.cs @@ -79,7 +79,7 @@ void OnContextualMenuPopulateEvent(ContextualMenuPopulateEvent evt) evt.menu.AppendAction( "Open with IDE", - action => { AssetDatabase.OpenAsset(libraryItem.sourceAsset); }, + action => { AssetDatabase.OpenAsset(libraryItem.sourceAsset, BuilderConstants.OpenInIDELineNumber); }, action => DropdownMenuAction.Status.Normal); } } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Utilities/BuilderConstants.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Utilities/BuilderConstants.cs index f2e1eca899..8f0f7f05d8 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Utilities/BuilderConstants.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Builder/Utilities/BuilderConstants.cs @@ -38,6 +38,7 @@ internal static class BuilderConstants public static readonly float PickSelectionRepeatRectSize = 2f; public static readonly float PickSelectionRepeatRectHalfSize = PickSelectionRepeatRectSize / 2; public static readonly double PickSelectionRepeatMinTimeDelay = 0.5; + public static readonly int OpenInIDELineNumber = int.MinValue; // Paths public const string UIBuilderPackageRootPath = "UIBuilderPackageResources"; diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/DimensionStyleField.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/DimensionStyleField.cs index 44aa40cfb8..699df8f70a 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/DimensionStyleField.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/DimensionStyleField.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using UnityEditor; using UnityEditor.UIElements; @@ -51,7 +52,7 @@ public float length set { innerValue = value; - SetValueWithoutNotify(innerValue.ToString()); + SetValueWithoutNotify(innerValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); } } @@ -144,7 +145,7 @@ protected override List GenerateAdditionalOptions(string binding) protected bool TryParseValue(string val, out float value) { var num = new string(val.Where((c) => Char.IsDigit(c) || c == '.' || c == '-').ToArray()); - return float.TryParse(num, out value); + return float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out value); } protected override bool SetInnerValueFromValue(string val) @@ -191,7 +192,15 @@ protected override string ComposeValue() if (styleKeywords.Contains(option)) return option; - return innerValue.ToString() + option; + return innerValue.ToString(CultureInfo.InvariantCulture.NumberFormat) + option; + } + + protected override string GetTextFromValue() + { + if (styleKeywords.Contains(option)) + return option; + + return innerValue.ToString(CultureInfo.InvariantCulture.NumberFormat); } protected override void RefreshChildFields() @@ -211,8 +220,7 @@ void OnDraggerFieldUpdate(ChangeEvent evt) if (isKeyword) option = defaultUnit; - value = (evt.newValue * m_DragStep).ToString(); - + value = (evt.newValue * m_DragStep).ToString(CultureInfo.InvariantCulture.NumberFormat); evt.StopImmediatePropagation(); evt.PreventDefault(); } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/NumericStyleField.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/NumericStyleField.cs index 763ff0945a..d6020b7cca 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/NumericStyleField.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/NumericStyleField.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using UnityEngine.UIElements; @@ -18,7 +19,7 @@ public float number { innerValue = value; option = s_NoOptionString; - SetValueWithoutNotify(innerValue.ToString()); + SetValueWithoutNotify(innerValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); } } @@ -41,7 +42,7 @@ protected override bool SetInnerValueFromValue(string val) var num = new string(val.Where((c) => Char.IsDigit(c) || c == '.' || c == '-').ToArray()); float number; - var result = float.TryParse(num, out number); + var result = float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out number); if (!result) return false; @@ -60,5 +61,13 @@ protected override bool SetOptionFromValue(string val) option = s_NoOptionString; return true; } + + protected override string GetTextFromValue() + { + if (styleKeywords.Contains(option)) + return option; + + return innerValue.ToString(CultureInfo.InvariantCulture.NumberFormat); + } } } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/ScaleStyleField.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/ScaleStyleField.cs index 86935d1e96..7d747b1ce7 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/ScaleStyleField.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/ScaleStyleField.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using JetBrains.Annotations; using UnityEngine.UIElements; using UnityEditor; @@ -119,8 +120,8 @@ public override void SetValueWithoutNotify(BuilderScale newValue) void RefreshSubFields() { - m_ScaleXField.SetValueWithoutNotify(value.value.x.ToString()); - m_ScaleYField.SetValueWithoutNotify(value.value.y.ToString()); + m_ScaleXField.SetValueWithoutNotify(value.value.x.ToString(CultureInfo.InvariantCulture.NumberFormat)); + m_ScaleYField.SetValueWithoutNotify(value.value.y.ToString(CultureInfo.InvariantCulture.NumberFormat)); } void UpdateScaleField() diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleField.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleField.cs index 38384807ab..3fcd3a7a9f 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleField.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleField.cs @@ -146,7 +146,7 @@ protected virtual void RefreshChildFields() m_OptionsPopup.SetValueWithoutNotify(GetOptionFromValue()); } - protected string GetTextFromValue() + protected virtual string GetTextFromValue() { if (styleKeywords.Contains(option)) return option; diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleVariableUtilities.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleVariableUtilities.cs index 3e56593b54..b49d62cdbf 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleVariableUtilities.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/StyleVariableUtilities.cs @@ -60,64 +60,38 @@ static public Dictionary editorVariableDescriptions } } - private static List s_AllVariables = new List(); - public static IEnumerable GetAllAvailableVariables(VisualElement currentVisualElement, StyleValueType[] compatibleTypes, bool editorExtensionMode) { - s_AllVariables.Clear(); - HashSet names = new HashSet(); + return currentVisualElement.variableContext.variables + .Where(variable => + { + if (variable.name == BuilderConstants.SelectedStyleRulePropertyName) + return false; - // Traverse the element's parent hierarchy - var current = currentVisualElement; + if (!editorExtensionMode && variable.sheet.IsUnityEditorStyleSheet()) + return false; - while (current != null) - { - var customStyles = current.computedStyle.customProperties; + var valueHandle = variable.handles[0]; + var valueType = valueHandle.valueType; + if (valueType == StyleValueType.Enum) + { + var colorName = variable.sheet.ReadAsString(valueHandle); + if (StyleSheetColor.TryGetColor(colorName.ToLower(), out var color)) + valueType = StyleValueType.Color; + } - if (customStyles != null) + return (compatibleTypes == null || compatibleTypes.Contains(valueType)) && !variable.name.StartsWith("--unity-theme"); + }) + .Distinct() + .Select(variable => { - foreach (var varPair in customStyles) + string descr = null; + if (variable.sheet.IsUnityEditorStyleSheet()) { - var varName = varPair.Key; - - if (varName == BuilderConstants.SelectedStyleRulePropertyName) - continue; - var propValue = varPair.Value; - - if (!editorExtensionMode && propValue.sheet.IsUnityEditorStyleSheet()) - continue; - - var valueType = propValue.handle.valueType; - - // If the value of the style property is a color name (red, black, ...) then threat it as a color and not an enum - if (propValue.handle.valueType == StyleValueType.Enum) - { - var colorName = propValue.sheet.ReadAsString(propValue.handle); - if (StyleSheetColor.TryGetColor(colorName.ToLower(), out var color)) - valueType = StyleValueType.Color; - } - - if ((compatibleTypes == null || compatibleTypes.Contains(valueType)) && !varName.StartsWith("--unity-theme") && !names.Contains(varName)) - { - names.Add(varName); - string descr = null; - if (propValue.sheet.IsUnityEditorStyleSheet()) - { - editorVariableDescriptions.TryGetValue(varName, out descr); - } - s_AllVariables.Add(new VariableInfo() - { - name = varName, - value = propValue, - description = descr - }); - } + editorVariableDescriptions.TryGetValue(variable.name, out descr); } - } - current = current.parent; - } - - return s_AllVariables; + return new VariableInfo(variable, descr); + }); } public static VariableEditingHandler GetOrCreateVarHandler(BindableElement field) @@ -145,88 +119,28 @@ static public VariableEditingHandler GetVarHandler(BindableElement field) public static VariableInfo FindVariable(VisualElement currentVisualElement, string variableName, bool editorExtensionMode) { - // Traverse the element's parent hierarchy - var current = currentVisualElement; + var variables = currentVisualElement.variableContext.variables; - while (current != null) + for (int i = variables.Count - 1; i >= 0; --i) { - var customStyles = current.computedStyle.customProperties; - if (customStyles != null) - { - foreach (var varPair in customStyles) - { - var varName = varPair.Key; - var propValue = varPair.Value; - - if (!editorExtensionMode && propValue.sheet.isDefaultStyleSheet) - continue; - if (varName == variableName) - { - string descr = null; - if (propValue.sheet.isDefaultStyleSheet) - { - editorVariableDescriptions.TryGetValue(varName, out descr); - } - return new VariableInfo() - { - name = varName, - value = propValue, - description = descr - }; - } - } - } - current = current.parent; - } - return null; - } + var variable = variables[i]; - public static bool FindVariableOrigin(VisualElement currentVisualElement, string variableName, out StyleSheet outStyleSheet, out StyleComplexSelector outSelector) - { - outSelector = null; - outStyleSheet = null; - - if (string.IsNullOrEmpty(variableName)) - return false; + if (!editorExtensionMode && variable.sheet.isDefaultStyleSheet) + continue; - // Traverse the element's parent hierarchy to find best matching selector that define the variable - var extractor = new MatchedRulesExtractor(); - var current = currentVisualElement; - - while (current != null) - { - extractor.selectedElementRules.Clear(); - extractor.selectedElementStylesheets.Clear(); - extractor.FindMatchingRules(current); - - var matchedRules = extractor.selectedElementRules; - - for (var i = matchedRules.Count - 1; i >= 0; --i) + if (variables[i].name == variableName) { - var matchRecord = matchedRules.ElementAt(i).matchRecord; - var ruleProperty = matchRecord.sheet.FindProperty(matchRecord.complexSelector.rule, variableName); - - if (ruleProperty != null) + string descr = null; + if (variable.sheet.isDefaultStyleSheet) { - outSelector = matchRecord.complexSelector; - outStyleSheet = matchRecord.sheet; - break; + editorVariableDescriptions.TryGetValue(variableName, out descr); } - } - - if (outSelector != null) - break; - - current = current.parent; - } - // If the current visual element is a fake element created for the selector being edited and that the selector found is a fake selector then return the effective selector associated to the fake visual element - if (outSelector != null && current == currentVisualElement && StyleSheetToUss.ToUssSelector(outSelector).Contains(BuilderConstants.StyleSelectorElementName)) - { - outSelector = currentVisualElement.GetStyleComplexSelector(); + return new VariableInfo(variable, descr); + } } - return outSelector != null; + return default; } } } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableCompleter.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableCompleter.cs index 73afca3dc1..f5aabf5dc6 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableCompleter.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableCompleter.cs @@ -60,7 +60,7 @@ public VariableCompleter(VariableEditingHandler handler) onSelectionChange += data => { m_DetailsView.SetInfo(data); - if (data != null) + if (data.IsValid()) { m_DetailsView.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableEditingHandler.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableEditingHandler.cs index 0cd5131553..0867e701a9 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableEditingHandler.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableEditingHandler.cs @@ -327,14 +327,14 @@ static void ShowPopup(VariableEditingHandler handler) string varName = GetBoundVariableName(handler); - VariableInfo varInfo = null; + VariableInfo varInfo = default; if (!string.IsNullOrEmpty(varName)) { varInfo = StyleVariableUtilities.FindVariable(handler.m_Inspector.currentVisualElement, varName, handler.inspector.document.fileSettings.editorExtensionMode); - if (varInfo == null) - varInfo = new VariableInfo { name = varName }; + if (!varInfo.IsValid()) + varInfo = new VariableInfo(varName); } if (handler.variableInfoTooltip == null) diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfo.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfo.cs index 7ff4198ea0..d66d8e4ce4 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfo.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfo.cs @@ -1,12 +1,40 @@ -using UnityEngine.UIElements.StyleSheets; +using UnityEngine.UIElements; namespace Unity.UI.Builder { - class VariableInfo + struct VariableInfo { - public string name { get; set; } - public StylePropertyValue value { get; set; } - public bool isEditorVar => value.sheet ? value.sheet.IsUnityEditorStyleSheet() : false; + public VariableInfo(StyleVariable styleVariable, string description = null) + { + this.styleVariable = styleVariable; + this.description = description; + this.m_Name = null; + } + + public VariableInfo(string variableName) + { + this.styleVariable = default; + this.description = null; + this.m_Name = variableName; + } + + string m_Name; + + public StyleVariable styleVariable { get; set; } + public StyleSheet sheet => styleVariable.sheet; + public string name + { + get + { + if (styleVariable.sheet) + return styleVariable.name; + return m_Name; + } + } + + public bool isEditorVar => styleVariable.sheet && styleVariable.sheet.IsUnityEditorStyleSheet(); public string description { get; set; } + + public bool IsValid() => sheet || !string.IsNullOrEmpty(m_Name); } } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfoView.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfoView.cs index 5a459e7bbb..f29f0486cc 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfoView.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleField/VariableInfoView.cs @@ -100,63 +100,63 @@ public void SetInfo(VariableInfo info) { ClearUI(); - if (info != null) + if (!info.IsValid()) + return; + + if (info.sheet) { - if (info.value.sheet) - { - var varStyleSheetOrigin = info.value.sheet; - var fullPath = AssetDatabase.GetAssetPath(varStyleSheetOrigin); - string displayPath = null; + var varStyleSheetOrigin = info.sheet; + var fullPath = AssetDatabase.GetAssetPath(varStyleSheetOrigin); + string displayPath = null; - if (string.IsNullOrEmpty(fullPath)) - { + if (string.IsNullOrEmpty(fullPath)) + { + displayPath = varStyleSheetOrigin.name; + } + else + { + if (fullPath == "Library/unity editor resources") displayPath = varStyleSheetOrigin.name; - } else - { - if (fullPath == "Library/unity editor resources") - displayPath = varStyleSheetOrigin.name; - else - displayPath = Path.GetFileName(fullPath); - } - var valueText = StyleSheetToUss.ValueHandleToUssString(info.value.sheet, new UssExportOptions(), "", info.value.handle); - - variableValue = valueText; - sourceStyleSheet = displayPath; + displayPath = Path.GetFileName(fullPath); } + var valueText = StyleSheetToUss.ValueHandleToUssString(info.sheet, new UssExportOptions(), "", info.styleVariable.handles[0]); + + variableValue = valueText; + sourceStyleSheet = displayPath; + } - variableName = info.name; - description = info.description; + variableName = info.name; + description = info.description; - if (info.value.handle.valueType == StyleValueType.Color) + if (info.styleVariable.handles[0].valueType == StyleValueType.Color) + { + m_Preview.style.backgroundColor = info.sheet.ReadColor(info.styleVariable.handles[0]); + m_Preview.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); + } + else if (info.styleVariable.handles[0].valueType == StyleValueType.Enum) + { + var colorName = info.sheet.ReadAsString(info.styleVariable.handles[0]); + if (StyleSheetColor.TryGetColor(colorName.ToLower(), out var color)) { - m_Preview.style.backgroundColor = info.value.sheet.ReadColor(info.value.handle); + m_Preview.style.backgroundColor = color; m_Preview.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); } - else if (info.value.handle.valueType == StyleValueType.Enum) - { - var colorName = info.value.sheet.ReadAsString(info.value.handle); - if (StyleSheetColor.TryGetColor(colorName.ToLower(), out var color)) - { - m_Preview.style.backgroundColor = color; - m_Preview.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); - } - } - else if (info.value.handle.valueType == StyleValueType.ResourcePath || info.value.handle.valueType == StyleValueType.AssetReference) + } + else if (info.styleVariable.handles[0].valueType == StyleValueType.ResourcePath || info.styleVariable.handles[0].valueType == StyleValueType.AssetReference) + { + var source = new ImageSource(); + var dpiScaling = 1.0f; + if (StylePropertyReader.TryGetImageSourceFromValue(new StylePropertyValue{ sheet = info.sheet, handle = info.styleVariable.handles[0]}, dpiScaling, out source) == false) { - var source = new ImageSource(); - var dpiScaling = 1.0f; - if (StylePropertyReader.TryGetImageSourceFromValue(info.value, dpiScaling, out source) == false) - { - // Load a stand-in picture to make it easier to identify which image element is missing its picture - source.texture = Panel.LoadResource("d_console.warnicon", typeof(Texture2D), dpiScaling) as Texture2D; - } - - m_Thumbnail.image = source.texture; - m_Thumbnail.vectorImage = source.vectorImage; - m_Preview.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); - m_ValueAndPreviewContainer.AddToClassList(s_PreviewThumbnailUssClassName); + // Load a stand-in picture to make it easier to identify which image element is missing its picture + source.texture = Panel.LoadResource("d_console.warnicon", typeof(Texture2D), dpiScaling) as Texture2D; } + + m_Thumbnail.image = source.texture; + m_Thumbnail.vectorImage = source.vectorImage; + m_Preview.RemoveFromClassList(BuilderConstants.HiddenStyleClassName); + m_ValueAndPreviewContainer.AddToClassList(s_PreviewThumbnailUssClassName); } } } diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleSheetExtensions/StyleSheetToUss.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleSheetExtensions/StyleSheetToUss.cs index a08f3017b6..76f82b10c8 100644 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleSheetExtensions/StyleSheetToUss.cs +++ b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/StyleSheetExtensions/StyleSheetToUss.cs @@ -130,7 +130,7 @@ public static string ValueHandleToUssString(StyleSheet sheet, UssExportOptions o private static string GetPathValueFromAssetRef(UnityEngine.Object assetRef) { var assetPath = URIHelpers.MakeAssetUri(assetRef); - return assetRef == null ? "none" : $"url('{assetPath}')";; + return assetRef == null ? "none" : $"url('{assetPath}')"; } public static void ValueHandlesToUssString(StringBuilder sb, StyleSheet sheet, UssExportOptions options, string propertyName, StyleValueHandle[] values, ref int valueIndex, int valueCount = -1) diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitView.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitView.cs deleted file mode 100644 index 265208756e..0000000000 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitView.cs +++ /dev/null @@ -1,459 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Unity.UI.Builder -{ - /// - /// A SplitView that contains two resizable panes. One pane is fixed-size while the other pane has flex-grow style set to 1 to take all remaining space. The border between he panes is draggable to resize both panes. Both horizontal and vertical modes are supported. Requires _exactly_ two child elements to operate. - /// - internal class TwoPaneSplitView : VisualElement - { - static readonly string s_UssPath = BuilderConstants.UtilitiesPath + "/TwoPaneSplitView/TwoPaneSplitView.uss"; - - static readonly string s_UssClassName = "unity-two-pane-split-view"; - static readonly string s_ContentContainerClassName = "unity-two-pane-split-view__content-container"; - static readonly string s_HandleDragLineClassName = "unity-two-pane-split-view__dragline"; - static readonly string s_HandleDragLineVerticalClassName = s_HandleDragLineClassName + "--vertical"; - static readonly string s_HandleDragLineHorizontalClassName = s_HandleDragLineClassName + "--horizontal"; - static readonly string s_HandleDragLineAnchorClassName = "unity-two-pane-split-view__dragline-anchor"; - static readonly string s_HandleDragLineAnchorVerticalClassName = s_HandleDragLineAnchorClassName + "--vertical"; - static readonly string s_HandleDragLineAnchorHorizontalClassName = s_HandleDragLineAnchorClassName + "--horizontal"; - static readonly string s_VerticalClassName = "unity-two-pane-split-view--vertical"; - static readonly string s_HorizontalClassName = "unity-two-pane-split-view--horizontal"; - - /// - /// Instantiates a using the data read from a UXML file. - /// - public new class UxmlFactory : UxmlFactory {} - - /// - /// Defines for the . - /// - public new class UxmlTraits : VisualElement.UxmlTraits - { - UxmlIntAttributeDescription m_FixedPaneIndex = new UxmlIntAttributeDescription { name = "fixed-pane-index", defaultValue = 0 }; - UxmlIntAttributeDescription m_FixedPaneInitialDimension = new UxmlIntAttributeDescription { name = "fixed-pane-initial-dimension", defaultValue = 100 }; - UxmlEnumAttributeDescription m_Orientation = new UxmlEnumAttributeDescription { name = "orientation", defaultValue = TwoPaneSplitViewOrientation.Horizontal }; - - public override IEnumerable uxmlChildElementsDescription - { - get { yield break; } - } - - public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) - { - base.Init(ve, bag, cc); - var fixedPaneIndex = m_FixedPaneIndex.GetValueFromBag(bag, cc); - var fixedPaneInitialSize = m_FixedPaneInitialDimension.GetValueFromBag(bag, cc); - var orientation = m_Orientation.GetValueFromBag(bag, cc); - - ((TwoPaneSplitView)ve).Init(fixedPaneIndex, fixedPaneInitialSize, orientation); - } - } - - VisualElement m_LeftPane; - VisualElement m_RightPane; - - VisualElement m_FixedPane; - VisualElement m_FlexedPane; - - [SerializeField] float m_FixedPaneDimension = -1; - - /// - /// The child element that is set as the fixed size pane. - /// - public VisualElement fixedPane => m_FixedPane; - /// - /// The child element that is set as the flexable size pane. - /// - public VisualElement flexedPane => m_FlexedPane; - - VisualElement m_DragLine; - VisualElement m_DragLineAnchor; - - bool m_CollapseMode; - - VisualElement m_Content; - - TwoPaneSplitViewOrientation m_Orientation; - int m_FixedPaneIndex; - float m_FixedPaneInitialDimension; - - /// - /// 0 for setting first child as the fixed pane, 1 for the second child element. - /// - public int fixedPaneIndex - { - get => m_FixedPaneIndex; - set - { - if (value == m_FixedPaneIndex) - return; - - Init(value, m_FixedPaneInitialDimension, m_Orientation); - } - } - - /// - /// The initial width or height for the fixed pane. - /// - public float fixedPaneInitialDimension - { - get => m_FixedPaneInitialDimension; - set - { - if (value == m_FixedPaneInitialDimension) - return; - - Init(m_FixedPaneIndex, value, m_Orientation); - } - } - - /// - /// Orientation of the split view. - /// - public TwoPaneSplitViewOrientation orientation - { - get => m_Orientation; - set - { - if (value == m_Orientation) - return; - - Init(m_FixedPaneIndex, m_FixedPaneInitialDimension, value); - } - } - - internal float fixedPaneDimension - { - get => string.IsNullOrEmpty(viewDataKey) - ? m_FixedPaneInitialDimension - : m_FixedPaneDimension; - - set - { - if (value == m_FixedPaneDimension) - return; - m_FixedPaneDimension = value; - SaveViewData(); - } - } - - TwoPaneSplitViewResizer m_Resizer; - - public TwoPaneSplitView() - { - AddToClassList(s_UssClassName); - - styleSheets.Add(BuilderPackageUtilities.LoadAssetAtPath(s_UssPath)); - - m_Content = new VisualElement(); - m_Content.name = "unity-content-container"; - m_Content.AddToClassList(s_ContentContainerClassName); - hierarchy.Add(m_Content); - - // Create drag anchor line. - m_DragLineAnchor = new VisualElement(); - m_DragLineAnchor.name = "unity-dragline-anchor"; - m_DragLineAnchor.AddToClassList(s_HandleDragLineAnchorClassName); - hierarchy.Add(m_DragLineAnchor); - - // Create drag - m_DragLine = new VisualElement(); - m_DragLine.name = "unity-dragline"; - m_DragLine.AddToClassList(s_HandleDragLineClassName); - m_DragLineAnchor.Add(m_DragLine); - } - - /// - /// Parameterized constructor. - /// - /// 0 for setting first child as the fixed pane, 1 for the second child element. - /// Set an inital width or height for the fixed pane. - /// Orientation of the split view. - public TwoPaneSplitView( - int fixedPaneIndex, - float fixedPaneStartDimension, - TwoPaneSplitViewOrientation orientation) : this() - { - Init(fixedPaneIndex, fixedPaneStartDimension, orientation); - } - - /// - /// Collapse one of the panes of the split view. This will hide the resizer and make the other child take up all available space. - /// - /// Index of child to collapse. - public void CollapseChild(int index) - { - if (m_LeftPane == null) - return; - - m_DragLine.style.display = DisplayStyle.None; - m_DragLineAnchor.style.display = DisplayStyle.None; - if (index == 0) - { - m_RightPane.style.width = StyleKeyword.Initial; - m_RightPane.style.height = StyleKeyword.Initial; - m_RightPane.style.flexGrow = 1; - m_LeftPane.style.display = DisplayStyle.None; - } - else - { - m_LeftPane.style.width = StyleKeyword.Initial; - m_LeftPane.style.height = StyleKeyword.Initial; - m_LeftPane.style.flexGrow = 1; - m_RightPane.style.display = DisplayStyle.None; - } - - m_CollapseMode = true; - } - - /// - /// Un-collapse the split view. This will restore the split view to the state it was before the previous collapse. - /// - public void UnCollapse() - { - if (m_LeftPane == null) - return; - - m_LeftPane.style.display = DisplayStyle.Flex; - m_RightPane.style.display = DisplayStyle.Flex; - - m_DragLine.style.display = DisplayStyle.Flex; - m_DragLineAnchor.style.display = DisplayStyle.Flex; - - m_LeftPane.style.flexGrow = 0; - m_RightPane.style.flexGrow = 0; - m_CollapseMode = false; - - Init(m_FixedPaneIndex, m_FixedPaneInitialDimension, m_Orientation); - } - - internal void Init(int fixedPaneIndex, float fixedPaneInitialDimension, TwoPaneSplitViewOrientation orientation) - { - m_Orientation = orientation; - m_FixedPaneIndex = fixedPaneIndex; - m_FixedPaneInitialDimension = fixedPaneInitialDimension; - - m_Content.RemoveFromClassList(s_HorizontalClassName); - m_Content.RemoveFromClassList(s_VerticalClassName); - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - m_Content.AddToClassList(s_HorizontalClassName); - else - m_Content.AddToClassList(s_VerticalClassName); - - // Create drag anchor line. - m_DragLineAnchor.RemoveFromClassList(s_HandleDragLineAnchorHorizontalClassName); - m_DragLineAnchor.RemoveFromClassList(s_HandleDragLineAnchorVerticalClassName); - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - m_DragLineAnchor.AddToClassList(s_HandleDragLineAnchorHorizontalClassName); - else - m_DragLineAnchor.AddToClassList(s_HandleDragLineAnchorVerticalClassName); - - // Create drag - m_DragLine.RemoveFromClassList(s_HandleDragLineHorizontalClassName); - m_DragLine.RemoveFromClassList(s_HandleDragLineVerticalClassName); - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - m_DragLine.AddToClassList(s_HandleDragLineHorizontalClassName); - else - m_DragLine.AddToClassList(s_HandleDragLineVerticalClassName); - - if (m_Resizer != null) - { - m_DragLineAnchor.RemoveManipulator(m_Resizer); - m_Resizer = null; - } - - if (m_Content.childCount != 2) - RegisterCallback(OnPostDisplaySetup); - else - PostDisplaySetup(); - } - - void OnPostDisplaySetup(GeometryChangedEvent evt) - { - if (m_Content.childCount != 2) - { - Debug.LogError("TwoPaneSplitView needs exactly 2 chilren."); - return; - } - - PostDisplaySetup(); - - UnregisterCallback(OnPostDisplaySetup); - } - - void PostDisplaySetup() - { - if (m_Content.childCount != 2) - { - Debug.LogError("TwoPaneSplitView needs exactly 2 children."); - return; - } - - if (fixedPaneDimension < 0) - fixedPaneDimension = m_FixedPaneInitialDimension; - - var dimension = fixedPaneDimension; - - m_LeftPane = m_Content[0]; - if (m_FixedPaneIndex == 0) - m_FixedPane = m_LeftPane; - else - m_FlexedPane = m_LeftPane; - - m_RightPane = m_Content[1]; - if (m_FixedPaneIndex == 1) - m_FixedPane = m_RightPane; - else - m_FlexedPane = m_RightPane; - - m_FixedPane.style.flexBasis = StyleKeyword.Null; - m_FixedPane.style.flexShrink = StyleKeyword.Null; - m_FixedPane.style.flexGrow = StyleKeyword.Null; - m_FlexedPane.style.flexGrow = StyleKeyword.Null; - m_FlexedPane.style.flexShrink = StyleKeyword.Null; - m_FlexedPane.style.flexBasis = StyleKeyword.Null; - - m_FixedPane.style.width = StyleKeyword.Null; - m_FixedPane.style.height = StyleKeyword.Null; - m_FlexedPane.style.width = StyleKeyword.Null; - m_FlexedPane.style.height = StyleKeyword.Null; - - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - { - m_FixedPane.style.width = dimension; - m_FixedPane.style.height = StyleKeyword.Null; - } - else - { - m_FixedPane.style.width = StyleKeyword.Null; - m_FixedPane.style.height = dimension; - } - - m_FixedPane.style.flexShrink = 0; - m_FixedPane.style.flexGrow = 0; - m_FlexedPane.style.flexGrow = 1; - m_FlexedPane.style.flexShrink = 0; - m_FlexedPane.style.flexBasis = 0; - - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - { - if (m_FixedPaneIndex == 0) - m_DragLineAnchor.style.left = dimension; - else - m_DragLineAnchor.style.left = this.resolvedStyle.width - dimension; - } - else - { - if (m_FixedPaneIndex == 0) - m_DragLineAnchor.style.top = dimension; - else - m_DragLineAnchor.style.top = this.resolvedStyle.height - dimension; - } - - int direction = 1; - if (m_FixedPaneIndex == 0) - direction = 1; - else - direction = -1; - - m_Resizer = new TwoPaneSplitViewResizer(this, direction, m_Orientation); - - m_DragLineAnchor.AddManipulator(m_Resizer); - - RegisterCallback(OnSizeChange); - } - - void OnSizeChange(GeometryChangedEvent evt) - { - OnSizeChange(); - } - - void OnSizeChange() - { - if (m_CollapseMode) - return; - - var maxLength = resolvedStyle.width; - var fixedPaneLength = m_FixedPane.resolvedStyle.width; - var fixedPaneMinLength = m_FixedPane.resolvedStyle.minWidth.value; - var flexedPaneMinLength = m_FlexedPane.resolvedStyle.minWidth.value; - - if (m_Orientation == TwoPaneSplitViewOrientation.Vertical) - { - maxLength = resolvedStyle.height; - fixedPaneLength = m_FixedPane.resolvedStyle.height; - fixedPaneMinLength = m_FixedPane.resolvedStyle.minHeight.value; - flexedPaneMinLength = m_FlexedPane.resolvedStyle.minHeight.value; - } - - // Big enough to account for current fixed pane size and flexed pane minimun size, so we let the layout - // dictates where the dragger should be. - if (maxLength >= fixedPaneLength + flexedPaneMinLength) - { - SetDragLineOffset(m_FixedPaneIndex == 0 ? fixedPaneLength : maxLength - fixedPaneLength); - } - // Big enough to account for fixed and flexed pane minimum sizes, so we resize the fixed pane and adjust - // where the dragger should be. - else if (maxLength >= fixedPaneMinLength + flexedPaneMinLength) - { - var newDimension = maxLength - flexedPaneMinLength; - SetFixedPaneDimension(newDimension); - SetDragLineOffset(m_FixedPaneIndex == 0 ? newDimension : flexedPaneMinLength); - } - // Not big enough for fixed and flexed pane minimum sizes - else - { - SetFixedPaneDimension(fixedPaneMinLength); - SetDragLineOffset(m_FixedPaneIndex == 0 ? fixedPaneMinLength : flexedPaneMinLength); - } - } - - public override VisualElement contentContainer - { - get { return m_Content; } - } - - internal override void OnViewDataReady() - { - base.OnViewDataReady(); - var key = GetFullHierarchicalViewDataKey(); - - OverwriteFromViewData(this, key); - PostDisplaySetup(); - } - - void SetDragLineOffset(float offset) - { - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - m_DragLineAnchor.style.left = offset; - else - m_DragLineAnchor.style.top = offset; - } - - void SetFixedPaneDimension(float dimension) - { - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - m_FixedPane.style.width = dimension; - else - m_FixedPane.style.height = dimension; - } - } - - /// - /// Determines the orientation of the two resizable panes. - /// - internal enum TwoPaneSplitViewOrientation - { - /// - /// Split view panes layout is left/right with vertical resizable split. - /// - Horizontal, - /// - /// Split view panes layout is top/bottom with horizontal resizable split. - /// - Vertical - } -} diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewResizer.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewResizer.cs deleted file mode 100644 index 08fca98594..0000000000 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewResizer.cs +++ /dev/null @@ -1,144 +0,0 @@ -using UnityEngine; -using UnityEngine.UIElements; - -namespace Unity.UI.Builder -{ - internal class TwoPaneSplitViewResizer : MouseManipulator - { - Vector2 m_Start; - protected bool m_Active; - TwoPaneSplitView m_SplitView; - - int m_Direction; - TwoPaneSplitViewOrientation m_Orientation; - - VisualElement fixedPane => m_SplitView.fixedPane; - VisualElement flexedPane => m_SplitView.flexedPane; - - float fixedPaneMinDimension - { - get - { - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - return fixedPane.resolvedStyle.minWidth.value; - else - return fixedPane.resolvedStyle.minHeight.value; - } - } - - float flexedPaneMinDimension - { - get - { - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - return flexedPane.resolvedStyle.minWidth.value; - else - return flexedPane.resolvedStyle.minHeight.value; - } - } - - public TwoPaneSplitViewResizer(TwoPaneSplitView splitView, int dir, TwoPaneSplitViewOrientation orientation) - { - m_Orientation = orientation; - m_SplitView = splitView; - m_Direction = dir; - activators.Add(new ManipulatorActivationFilter { button = MouseButton.LeftMouse }); - m_Active = false; - } - - protected override void RegisterCallbacksOnTarget() - { - target.RegisterCallback(OnMouseDown); - target.RegisterCallback(OnMouseMove); - target.RegisterCallback(OnMouseUp); - } - - protected override void UnregisterCallbacksFromTarget() - { - target.UnregisterCallback(OnMouseDown); - target.UnregisterCallback(OnMouseMove); - target.UnregisterCallback(OnMouseUp); - } - - public void ApplyDelta(float delta) - { - float oldDimension = m_Orientation == TwoPaneSplitViewOrientation.Horizontal - ? fixedPane.resolvedStyle.width - : fixedPane.resolvedStyle.height; - float newDimension = oldDimension + delta; - - if (newDimension < oldDimension && newDimension < fixedPaneMinDimension) - newDimension = fixedPaneMinDimension; - - float maxDimension = m_Orientation == TwoPaneSplitViewOrientation.Horizontal - ? m_SplitView.resolvedStyle.width - : m_SplitView.resolvedStyle.height; - maxDimension -= flexedPaneMinDimension; - if (newDimension > oldDimension && newDimension > maxDimension) - newDimension = maxDimension; - - if (m_Orientation == TwoPaneSplitViewOrientation.Horizontal) - { - fixedPane.style.width = newDimension; - if (m_SplitView.fixedPaneIndex == 0) - target.style.left = newDimension; - else - target.style.left = m_SplitView.resolvedStyle.width - newDimension; - } - else - { - fixedPane.style.height = newDimension; - if (m_SplitView.fixedPaneIndex == 0) - target.style.top = newDimension; - else - target.style.top = m_SplitView.resolvedStyle.height - newDimension; - } - m_SplitView.fixedPaneDimension = newDimension; - } - - protected void OnMouseDown(MouseDownEvent e) - { - if (m_Active) - { - e.StopImmediatePropagation(); - return; - } - - if (CanStartManipulation(e)) - { - m_Start = e.localMousePosition; - - m_Active = true; - target.CaptureMouse(); - e.StopPropagation(); - } - } - - protected void OnMouseMove(MouseMoveEvent e) - { - if (!m_Active || !target.HasMouseCapture()) - return; - - Vector2 diff = e.localMousePosition - m_Start; - float mouseDiff = diff.x; - if (m_Orientation == TwoPaneSplitViewOrientation.Vertical) - mouseDiff = diff.y; - - float delta = m_Direction * mouseDiff; - - ApplyDelta(delta); - - e.StopPropagation(); - } - - protected void OnMouseUp(MouseUpEvent e) - { - if (!m_Active || !target.HasMouseCapture() || !CanStopManipulation(e)) - return; - - m_Active = false; - target.ReleaseMouse(); - e.StopPropagation(); - } - } -} diff --git a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewTestWindow.cs b/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewTestWindow.cs deleted file mode 100644 index b93890bd10..0000000000 --- a/External/MirroredPackageSources/com.unity.ui.builder/Editor/Utilities/TwoPaneSplitView/TwoPaneSplitViewTestWindow.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UnityEditor; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Unity.UI.Builder -{ - class TwoPaneSplitViewTestWindow : EditorWindow - { - //[MenuItem("Tests/UI Builder/TwoPaneSplitViewTest")] - static void ShowWindow() - { - var window = GetWindow(); - window.titleContent = new GUIContent("TwoPaneSplitViewTest"); - window.Show(); - } - - void OnEnable() - { - var root = rootVisualElement; - - root.styleSheets.Add(BuilderPackageUtilities.LoadAssetAtPath(BuilderConstants.UtilitiesPath + "/TwoPaneSplitView/TwoPaneSplitViewTestWindow.uss")); - - var xmlAsset = BuilderPackageUtilities.LoadAssetAtPath(BuilderConstants.UtilitiesPath + "/TwoPaneSplitView/TwoPaneSplitViewTestWindow.uxml"); - xmlAsset.CloneTree(root); - } - } -} diff --git a/External/NetStandardExtensions/System.CodeDom.dll b/External/NetStandardExtensions/System.CodeDom.dll new file mode 100644 index 0000000000000000000000000000000000000000..873495d3bd375f90477f0e323833feec565b8b4a GIT binary patch literal 183176 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�wldcF^%DA3N(cy1UB?c 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⪼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 A+W-In diff --git a/External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Rocks.dll b/External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Rocks.dll deleted file mode 100644 index 2f2e799a070814927052b860eed266652c73654c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 diff --git a/External/Unity.Cecil/builds/lib/net35/Unity.Cecil.dll b/External/Unity.Cecil/builds/lib/net35/Unity.Cecil.dll deleted file mode 100644 index 144e736c1ecf73e930a45ca3713df58fb816fcde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350720 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%0A=i8q1`=`x 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 d^-$LO7r3qMsn*vvya#QwY!6UG+<1 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

P4)RN^{HEVfRVzavZCIQ@vP~JaK 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 Ivk`&+0{9AJ-~a#s diff --git a/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Mdb.dll b/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Mdb.dll new file mode 100644 index 0000000000000000000000000000000000000000..af484b039fe91597b31f7ca4d877de2ea155b8d3 GIT binary patch literal 44544 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 J^?%a?{|kltXQu!F literal 0 HcmV?d00001 diff --git a/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Pdb.dll b/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Pdb.dll new file mode 100644 index 0000000000000000000000000000000000000000..649716c10a56ddafa1889b4befc3f29f737305e4 GIT binary patch literal 88064 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

A&I3mEk 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 Qd7%1fQ~Z>^b76sh18fq+q5uE@ literal 0 HcmV?d00001 diff --git a/ModuleOverrides/com.unity.ui/Core/ClickDetector.cs b/ModuleOverrides/com.unity.ui/Core/ClickDetector.cs index 1fec219430..c231d880b8 100644 --- a/ModuleOverrides/com.unity.ui/Core/ClickDetector.cs +++ b/ModuleOverrides/com.unity.ui/Core/ClickDetector.cs @@ -87,7 +87,7 @@ void SendClickEvent(EventBase evt) // Filter out event where button is released outside the window. var element = evt.target as VisualElement; - if (element != null && element.worldBound.Contains(pe.position)) + if (element != null && ContainsPointer(element, pe.position)) { if (clickStatus.m_Target != null && clickStatus.m_ClickCount > 0) { @@ -166,5 +166,15 @@ public void ProcessEvent(EventBase evt) SendClickEvent(evt); } } + + private static bool ContainsPointer(VisualElement element, Vector2 position) + { + if (!element.worldBound.Contains(position) || element.panel == null) + return false; + + // We need to use Pick(position) because PointerUpEvent sometimes calls ClearCachedElementUnderPointer + var elementUnderPointer = element.panel.Pick(position); + return element == elementUnderPointer || element.Contains(elementUnderPointer); + } } } diff --git a/ModuleOverrides/com.unity.ui/Core/Clickable.cs b/ModuleOverrides/com.unity.ui/Core/Clickable.cs index 8cdff160fb..d845632898 100644 --- a/ModuleOverrides/com.unity.ui/Core/Clickable.cs +++ b/ModuleOverrides/com.unity.ui/Core/Clickable.cs @@ -36,6 +36,8 @@ public class Clickable : PointerManipulator /// public Vector2 lastMousePosition { get; private set; } + private int m_ActivePointerId = -1; // The pointer that set the active state to true, if any + private bool m_AcceptClicksIfDisabled; internal bool acceptClicksIfDisabled @@ -94,7 +96,7 @@ private void OnTimer(TimerState timerState) { if ((clicked != null || clickedWithEventInfo != null) && IsRepeatable()) { - if (target.ContainsPoint(lastMousePosition)) + if (ContainsPointer(m_ActivePointerId)) { Invoke(null); target.pseudoStates |= PseudoStates.Active; @@ -266,6 +268,12 @@ void OnPointerCaptureOut(PointerCaptureOutEvent evt) } } + bool ContainsPointer(int pointerId) + { + var elementUnderPointer = target.elementPanel.GetTopElementUnderPointer(pointerId); + return target == elementUnderPointer || target.Contains(elementUnderPointer); + } + static bool IsNotMouseEvent(int pointerId) { return pointerId != PointerId.mousePointerId; @@ -293,6 +301,7 @@ internal void SimulateSingleClick(EventBase evt, int delayMs = 100) protected virtual void ProcessDownEvent(EventBase evt, Vector2 localPosition, int pointerId) { active = true; + m_ActivePointerId = pointerId; target.CapturePointer(pointerId); if (!(evt is IPointerEvent)) target.panel.ProcessPointerCapture(pointerId); @@ -301,7 +310,7 @@ protected virtual void ProcessDownEvent(EventBase evt, Vector2 localPosition, in if (IsRepeatable()) { // Repeatable button clicks are performed on the MouseDown and at timer events - if (target.ContainsPoint(localPosition)) + if (ContainsPointer(pointerId)) { Invoke(evt); } @@ -328,7 +337,7 @@ protected virtual void ProcessMoveEvent(EventBase evt, Vector2 localPosition) { lastMousePosition = localPosition; - if (target.ContainsPoint(localPosition)) + if (ContainsPointer(m_ActivePointerId)) { target.pseudoStates |= PseudoStates.Active; } @@ -346,6 +355,7 @@ protected virtual void ProcessMoveEvent(EventBase evt, Vector2 localPosition) protected virtual void ProcessUpEvent(EventBase evt, Vector2 localPosition, int pointerId) { active = false; + m_ActivePointerId = -1; target.ReleasePointer(pointerId); if (!(evt is IPointerEvent)) target.panel.ProcessPointerCapture(pointerId); @@ -360,7 +370,7 @@ protected virtual void ProcessUpEvent(EventBase evt, Vector2 localPosition, int else { // Non repeatable button clicks are performed on the MouseUp - if (target.ContainsPoint(localPosition)) + if (ContainsPointer(pointerId)) { Invoke(evt); } @@ -375,6 +385,7 @@ protected virtual void ProcessUpEvent(EventBase evt, Vector2 localPosition, int protected virtual void ProcessCancelEvent(EventBase evt, int pointerId) { active = false; + m_ActivePointerId = -1; target.ReleasePointer(pointerId); if (!(evt is IPointerEvent)) target.panel.ProcessPointerCapture(pointerId); diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/BaseCompositeField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/BaseCompositeField.cs similarity index 89% rename from ModuleOverrides/com.unity.ui/Editor/Controls/BaseCompositeField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/BaseCompositeField.cs index 4ee69dac5b..7993eb86df 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/BaseCompositeField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/BaseCompositeField.cs @@ -4,17 +4,27 @@ using System; using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { + internal delegate void RegisterSerializedPropertyBindCallback( + BaseCompositeField compositeField, TField field) + where TField : TextValueField, new(); + ///

/// This is the base class for the composite fields. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public abstract class BaseCompositeField : BaseField where TField : TextValueField, new() { + /// + /// Test. + /// + /// . + /// . + internal static RegisterSerializedPropertyBindCallback s_SerializedPropertyBindCallback; internal struct FieldDescription { public delegate void WriteDelegate(ref TValueType val, TFieldValue fieldValue); @@ -51,6 +61,18 @@ private VisualElement GetSpacer() int m_PropertyIndex; + internal int propertyIndex + { + get => m_PropertyIndex; + set => m_PropertyIndex = value; + } + + internal bool forceUpdateDisplay + { + get => m_ForceUpdateDisplay; + set => m_ForceUpdateDisplay = value; + } + /// /// USS class name of elements of this type. /// @@ -146,7 +168,7 @@ protected BaseCompositeField(string label, int fieldsByLine) field.label = desc.name; - field.RegisterCallback(OnSerializedPropertyBind); + s_SerializedPropertyBindCallback?.Invoke(this, field); field.onValidateValue += newValue => { @@ -213,27 +235,6 @@ protected BaseCompositeField(string label, int fieldsByLine) UpdateDisplay(); } - void OnSerializedPropertyBind(SerializedPropertyBindEvent e) - { - if (!(GetProperty(serializedPropertyCopyName) is SerializedProperty property)) return; - var propertyCopy = property.Copy(); - - var k = 0; - while (k <= m_PropertyIndex) - { - propertyCopy.Next(k == 0); - k++; - } - - var field = (TField)e.target; - field.SetProperty(serializedPropertyCopyName, propertyCopy); - field.showMixedValue = propertyCopy.hasMultipleDifferentValues; - - m_ForceUpdateDisplay = true; - - m_PropertyIndex++; - } - private void UpdateDisplay() { if (m_Fields.Count != 0) diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/BasePopupField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/BasePopupField.cs index 495f7cce94..8b28dca6a2 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/BasePopupField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/BasePopupField.cs @@ -16,7 +16,7 @@ namespace UnityEngine.UIElements /// /// Used for the BaseField /// Used for the choices list - [MovedFrom(true, "UnityEditor.UIElements", "UnityEditor.UIElementsModule")] + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public abstract class BasePopupField : BaseField { internal List m_Choices; diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/BoundsField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/BoundsField.cs similarity index 97% rename from ModuleOverrides/com.unity.ui/Editor/Controls/BoundsField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/BoundsField.cs index 5e2b764a44..b1d4ff0007 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/BoundsField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/BoundsField.cs @@ -4,13 +4,14 @@ using System; using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// A editor field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class BoundsField : BaseField { /// diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/BoundsIntField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/BoundsIntField.cs similarity index 96% rename from ModuleOverrides/com.unity.ui/Editor/Controls/BoundsIntField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/BoundsIntField.cs index a6e88c6303..004677111b 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/BoundsIntField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/BoundsIntField.cs @@ -5,13 +5,14 @@ using System; using System.Collections.Generic; using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class BoundsIntField : BaseField { /// diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/CompoundFields.cs b/ModuleOverrides/com.unity.ui/Core/Controls/CompoundFields.cs similarity index 96% rename from ModuleOverrides/com.unity.ui/Editor/Controls/CompoundFields.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/CompoundFields.cs index eca73fb2b7..231f562fa2 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/CompoundFields.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/CompoundFields.cs @@ -4,14 +4,14 @@ using System; using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class RectField : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -89,8 +89,9 @@ public RectField(string label) } /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class RectIntField : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -168,8 +169,9 @@ public RectIntField(string label) } /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Vector2Field : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -242,8 +244,9 @@ public Vector2Field(string label) } /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Vector3Field : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -319,8 +322,9 @@ public Vector3Field(string label) /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Vector4Field : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -397,8 +401,9 @@ public Vector4Field(string label) /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Vector2IntField : BaseCompositeField { internal override FieldDescription[] DescribeFields() @@ -471,8 +476,9 @@ public Vector2IntField(string label) } /// - /// A editor field. + /// A field. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Vector3IntField : BaseCompositeField { internal override FieldDescription[] DescribeFields() diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/DoubleField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/DoubleField.cs similarity index 90% rename from ModuleOverrides/com.unity.ui/Editor/Controls/DoubleField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/DoubleField.cs index 9d82c986bf..9b6ad5258d 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/DoubleField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/DoubleField.cs @@ -4,14 +4,14 @@ using System; using System.Globalization; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Makes a text field for entering doubles. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class DoubleField : TextValueField { // This property to alleviate the fact we have to cast all the time @@ -44,7 +44,7 @@ protected override string ValueToString(double v) protected override double StringToValue(string str) { double v; - EditorGUI.StringToDouble(str, out v); + UINumericFieldsUtils.StringToDouble(str, out v); return v; } @@ -105,13 +105,10 @@ class DoubleInput : TextValueInput internal DoubleInput() { - formatString = EditorGUI.kDoubleFieldFormatString; + formatString = UINumericFieldsUtils.k_DoubleFieldFormatString; } - protected override string allowedCharacters - { - get { return EditorGUI.s_AllowedCharactersForFloat; } - } + protected override string allowedCharacters => UINumericFieldsUtils.k_AllowedCharactersForFloat; public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, double startValue) { @@ -119,7 +116,7 @@ public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, doub float acceleration = NumericFieldDraggerUtility.Acceleration(speed == DeltaSpeed.Fast, speed == DeltaSpeed.Slow); double v = StringToValue(text); v += NumericFieldDraggerUtility.NiceDelta(delta, acceleration) * sensitivity; - v = MathUtils.RoundBasedOnMinimumDifference(v, sensitivity); + v = Mathf.RoundBasedOnMinimumDifference(v, sensitivity); if (parentDoubleField.isDelayed) { text = ValueToString(v); @@ -138,7 +135,7 @@ protected override string ValueToString(double v) protected override double StringToValue(string str) { double v; - EditorGUI.StringToDouble(str, out v); + UINumericFieldsUtils.StringToDouble(str, out v); return v; } } diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/EnumField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/EnumField.cs index b6c1df7299..97ac6d8748 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/EnumField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/EnumField.cs @@ -14,25 +14,25 @@ static class EnumFieldHelpers internal static readonly UxmlStringAttributeDescription value = new UxmlStringAttributeDescription { name = "value" }; internal static readonly UxmlBoolAttributeDescription includeObsoleteValues = new UxmlBoolAttributeDescription() { name = "include-obsolete-values", defaultValue = false }; - internal static bool ExtractValue(IUxmlAttributes bag, CreationContext cc, out Enum resEnumValue, out bool resIncludeObsoleteValues) + internal static bool ExtractValue(IUxmlAttributes bag, CreationContext cc, out Type resEnumType, out Enum resEnumValue, out bool resIncludeObsoleteValues) { resIncludeObsoleteValues = false; resEnumValue = null; - var systemType = type.GetValueFromBag(bag, cc); - if (systemType == null) + resEnumType = type.GetValueFromBag(bag, cc); + if (resEnumType == null) { return false; } string specifiedValue = null; - if (value.TryGetValueFromBag(bag, cc, ref specifiedValue) && !Enum.IsDefined(systemType, specifiedValue)) + if (value.TryGetValueFromBag(bag, cc, ref specifiedValue) && !Enum.IsDefined(resEnumType, specifiedValue)) { - Debug.LogErrorFormat("EnumField: Could not parse value of '{0}', because it isn't defined in the {1} enum.", specifiedValue, systemType.FullName); + Debug.LogErrorFormat("EnumField: Could not parse value of '{0}', because it isn't defined in the {1} enum.", specifiedValue, resEnumType.FullName); return false; } - resEnumValue = specifiedValue != null ? (Enum)Enum.Parse(systemType, specifiedValue) : (Enum)Enum.ToObject(systemType, 0); + resEnumValue = specifiedValue != null ? (Enum)Enum.Parse(resEnumType, specifiedValue) : (Enum)Enum.ToObject(resEnumType, 0); resIncludeObsoleteValues = includeObsoleteValues.GetValueFromBag(bag, cc); return true; @@ -42,7 +42,7 @@ internal static bool ExtractValue(IUxmlAttributes bag, CreationContext cc, out E /// /// Makes a dropdown for switching between enum values. /// - [MovedFrom(true, "UnityEditor.UIElements", "UnityEditor.UIElementsModule")] + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class EnumField : BaseField { /// @@ -71,17 +71,19 @@ public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext { base.Init(ve, bag, cc); - Enum resEnumValue; - bool resIncludeObsoleteValues; - if (EnumFieldHelpers.ExtractValue(bag, cc, out resEnumValue, out resIncludeObsoleteValues)) + if (EnumFieldHelpers.ExtractValue(bag, cc, out var resEnumType, out var resEnumValue, out var resIncludeObsoleteValues)) { EnumField enumField = (EnumField)ve; enumField.Init(resEnumValue, resIncludeObsoleteValues); } - else + // If we didn't have a valid value, try to set the type. + else if (null != resEnumType) { EnumField enumField = (EnumField)ve; - enumField.m_EnumType = null; + + enumField.m_EnumType = resEnumType; + if (enumField.m_EnumType != null) + enumField.PopulateDataFromType(enumField.m_EnumType); enumField.value = null; } } @@ -201,13 +203,18 @@ public void Init(Enum defaultValue, bool includeObsoleteValues) throw new ArgumentNullException(nameof(defaultValue)); } - m_EnumType = defaultValue.GetType(); - m_EnumData = EnumDataUtility.GetCachedEnumData(m_EnumType, !includeObsoleteValues); m_IncludeObsoleteValues = includeObsoleteValues; + PopulateDataFromType(defaultValue.GetType()); SetValueWithoutNotify(defaultValue); } + internal void PopulateDataFromType(Type enumType) + { + m_EnumType = enumType; + m_EnumData = EnumDataUtility.GetCachedEnumData(m_EnumType, !includeObsoleteValues); + } + public override void SetValueWithoutNotify(Enum newValue) { if (rawValue != newValue) @@ -223,6 +230,10 @@ public override void SetValueWithoutNotify(Enum newValue) { m_TextElement.text = m_EnumData.displayNames[idx]; } + else + { + m_TextElement.text = string.Empty; + } } } diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/FloatField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/FloatField.cs similarity index 86% rename from ModuleOverrides/com.unity.ui/Editor/Controls/FloatField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/FloatField.cs index 6f439080e2..066a688019 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/FloatField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/FloatField.cs @@ -3,14 +3,14 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System.Globalization; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Makes a text field for entering a float. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class FloatField : TextValueField { // This property to alleviate the fact we have to cast all the time @@ -43,8 +43,8 @@ protected override string ValueToString(float v) protected override float StringToValue(string str) { double v; - EditorGUI.StringToDouble(str, out v); - return MathUtils.ClampToFloat(v); + UINumericFieldsUtils.StringToDouble(str, out v); + return Mathf.ClampToFloat(v); } /// @@ -104,10 +104,10 @@ class FloatInput : TextValueInput internal FloatInput() { - formatString = EditorGUI.kFloatFieldFormatString; + formatString = UINumericFieldsUtils.k_FloatFieldFormatString; } - protected override string allowedCharacters => EditorGUI.s_AllowedCharactersForFloat; + protected override string allowedCharacters => UINumericFieldsUtils.k_AllowedCharactersForFloat; public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, float startValue) { @@ -115,14 +115,14 @@ public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, floa float acceleration = NumericFieldDraggerUtility.Acceleration(speed == DeltaSpeed.Fast, speed == DeltaSpeed.Slow); double v = StringToValue(text); v += NumericFieldDraggerUtility.NiceDelta(delta, acceleration) * sensitivity; - v = MathUtils.RoundBasedOnMinimumDifference(v, sensitivity); + v = Mathf.RoundBasedOnMinimumDifference(v, sensitivity); if (parentFloatField.isDelayed) { - text = ValueToString(MathUtils.ClampToFloat(v)); + text = ValueToString(Mathf.ClampToFloat(v)); } else { - parentFloatField.value = MathUtils.ClampToFloat(v); + parentFloatField.value = Mathf.ClampToFloat(v); } } @@ -134,8 +134,8 @@ protected override string ValueToString(float v) protected override float StringToValue(string str) { double v; - EditorGUI.StringToDouble(str, out v); - return MathUtils.ClampToFloat(v); + UINumericFieldsUtils.StringToDouble(str, out v); + return Mathf.ClampToFloat(v); } } } diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/GenericDropdownMenu.cs b/ModuleOverrides/com.unity.ui/Core/Controls/GenericDropdownMenu.cs index 729d5a6df3..f87fc9f987 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/GenericDropdownMenu.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/GenericDropdownMenu.cs @@ -67,6 +67,9 @@ class MenuItem Rect m_DesiredRect; KeyboardNavigationManipulator m_NavigationManipulator; + // Used for tests + internal VisualElement menuContainer => m_MenuContainer; + /// /// Returns the content container for the . Allows users to create their own /// dropdown menu if they don't want to use the default implementation. diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/Hash128Field.cs b/ModuleOverrides/com.unity.ui/Core/Controls/Hash128Field.cs similarity index 96% rename from ModuleOverrides/com.unity.ui/Editor/Controls/Hash128Field.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/Hash128Field.cs index 45e961ccb7..72f9636b9d 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/Hash128Field.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/Hash128Field.cs @@ -3,15 +3,14 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.Globalization; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Makes a field for editing an . /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class Hash128Field : TextInputBaseField { // This property to alleviate the fact we have to cast all the time @@ -109,7 +108,7 @@ internal override bool AcceptCharacter(char c) return base.AcceptCharacter(c) && c != 0 && allowedCharacters.IndexOf(c) != -1; } - public string formatString => EditorGUI.kIntFieldFormatString; + public string formatString => UINumericFieldsUtils.k_IntFieldFormatString; protected string ValueToString(Hash128 value) { diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/IntegerField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/IntegerField.cs similarity index 87% rename from ModuleOverrides/com.unity.ui/Editor/Controls/IntegerField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/IntegerField.cs index 7a16c2ac96..45af21aa62 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/IntegerField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/IntegerField.cs @@ -4,14 +4,14 @@ using System; using System.Globalization; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Makes a text field for entering an integer. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class IntegerField : TextValueField { // This property to alleviate the fact we have to cast all the time @@ -44,8 +44,8 @@ protected override string ValueToString(int v) protected override int StringToValue(string str) { long v; - EditorGUI.StringToLong(str, out v); - return MathUtils.ClampToInt(v); + UINumericFieldsUtils.StringToLong(str, out v); + return Mathf.ClampToInt(v); } /// @@ -106,10 +106,10 @@ class IntegerInput : TextValueInput internal IntegerInput() { - formatString = EditorGUI.kIntFieldFormatString; + formatString = UINumericFieldsUtils.k_IntFieldFormatString; } - protected override string allowedCharacters => EditorGUI.s_AllowedCharactersForInt; + protected override string allowedCharacters => UINumericFieldsUtils.k_AllowedCharactersForInt; public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, int startValue) { @@ -119,11 +119,11 @@ public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, int v += (long)Math.Round(NumericFieldDraggerUtility.NiceDelta(delta, acceleration) * sensitivity); if (parentIntegerField.isDelayed) { - text = ValueToString(MathUtils.ClampToInt(v)); + text = ValueToString(Mathf.ClampToInt(v)); } else { - parentIntegerField.value = MathUtils.ClampToInt(v); + parentIntegerField.value = Mathf.ClampToInt(v); } } @@ -135,8 +135,8 @@ protected override string ValueToString(int v) protected override int StringToValue(string str) { long v; - EditorGUI.StringToLong(str, out v); - return MathUtils.ClampToInt(v); + UINumericFieldsUtils.StringToLong(str, out v); + return Mathf.ClampToInt(v); } } } diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/LongField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/LongField.cs similarity index 92% rename from ModuleOverrides/com.unity.ui/Editor/Controls/LongField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/LongField.cs index 7d2a1af829..898c5202a8 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/LongField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/LongField.cs @@ -4,14 +4,14 @@ using System; using System.Globalization; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Makes a text field for entering long integers. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class LongField : TextValueField { // This property to alleviate the fact we have to cast all the time @@ -44,7 +44,7 @@ protected override string ValueToString(long v) protected override long StringToValue(string str) { long v; - EditorGUI.StringToLong(str, out v); + UINumericFieldsUtils.StringToLong(str, out v); return v; } @@ -106,12 +106,12 @@ class LongInput : TextValueInput internal LongInput() { - formatString = EditorGUI.kIntFieldFormatString; + formatString = UINumericFieldsUtils.k_IntFieldFormatString; } protected override string allowedCharacters { - get { return EditorGUI.s_AllowedCharactersForInt; } + get { return UINumericFieldsUtils.k_AllowedCharactersForInt; } } public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, long startValue) @@ -138,7 +138,7 @@ protected override string ValueToString(long v) protected override long StringToValue(string str) { long v; - EditorGUI.StringToLong(str, out v); + UINumericFieldsUtils.StringToLong(str, out v); return v; } } diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/MinMaxSlider.cs b/ModuleOverrides/com.unity.ui/Core/Controls/MinMaxSlider.cs index d5b5573467..ef1598c31c 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/MinMaxSlider.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/MinMaxSlider.cs @@ -3,7 +3,6 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.Collections.Generic; namespace UnityEngine.UIElements { @@ -38,10 +37,11 @@ public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext base.Init(ve, bag, cc); var slider = ((MinMaxSlider)ve); - slider.minValue = m_MinValue.GetValueFromBag(bag, cc); - slider.maxValue = m_MaxValue.GetValueFromBag(bag, cc); slider.lowLimit = m_LowLimit.GetValueFromBag(bag, cc); slider.highLimit = m_HighLimit.GetValueFromBag(bag, cc); + + var value = new Vector2(m_MinValue.GetValueFromBag(bag, cc), m_MaxValue.GetValueFromBag(bag, cc)); + slider.value = value; } } private enum DragState @@ -232,10 +232,16 @@ public MinMaxSlider(float minValue, float maxValue, float minLimit, float maxLim public MinMaxSlider(string label, float minValue = 0, float maxValue = kDefaultHighValue, float minLimit = float.MinValue, float maxLimit = float.MaxValue) : base(label, null) { + m_MinLimit = float.MinValue; + m_MaxLimit = float.MaxValue; + lowLimit = minLimit; highLimit = maxLimit; - this.minValue = minValue; - this.maxValue = maxValue; + + // Can't set to value here, because it could be overriden in a derived type. + var clampedValue = ClampValues(new Vector2(minValue, maxValue)); + this.minValue = clampedValue.x; + this.maxValue = clampedValue.y; AddToClassList(ussClassName); labelElement.AddToClassList(labelUssClassName); visualInput.AddToClassList(inputUssClassName); diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/PopupField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/PopupField.cs index fff134ec7d..c4a6007e73 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/PopupField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/PopupField.cs @@ -11,7 +11,7 @@ namespace UnityEngine.UIElements /// /// Generic popup selection field. /// - [MovedFrom(true, "UnityEditor.UIElements", "UnityEditor.UIElementsModule")] + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class PopupField : BasePopupField { /// @@ -69,7 +69,8 @@ public override void SetValueWithoutNotify(T newValue) base.SetValueWithoutNotify(newValue); } - private int m_Index = -1; + internal const int kPopupFieldDefaultIndex = -1; + private int m_Index = kPopupFieldDefaultIndex; /// /// The currently selected index in the popup menu. /// diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/ProgressBar.cs b/ModuleOverrides/com.unity.ui/Core/Controls/ProgressBar.cs index 80128c0f84..9a069ffa81 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/ProgressBar.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/ProgressBar.cs @@ -219,7 +219,7 @@ float CalculateProgressWidth(float width) /// /// A control that displays the progress between a lower and upper bound value. /// - [MovedFrom(true, "UnityEditor.UIElements", "UnityEditor.UIElementsModule")] + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class ProgressBar : AbstractProgressBar { /// diff --git a/ModuleOverrides/com.unity.ui/Core/Controls/ScrollView.cs b/ModuleOverrides/com.unity.ui/Core/Controls/ScrollView.cs index 458395df6b..8208389f6f 100644 --- a/ModuleOverrides/com.unity.ui/Core/Controls/ScrollView.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/ScrollView.cs @@ -1229,22 +1229,27 @@ bool ReleaseScrolling(int pointerId, IEventHandler target) if (touchScrollBehavior == TouchScrollBehavior.Elastic || hasInertia) { - ComputeInitialSpringBackVelocity(); - - if (m_PostPointerUpAnimation == null) - { - m_PostPointerUpAnimation = schedule.Execute(PostPointerUpAnimation).Every(30); - } - else - { - m_PostPointerUpAnimation.Resume(); - } + ExecuteElasticSpringAnimation(); } contentContainer.ReleasePointer(pointerId); return true; } + void ExecuteElasticSpringAnimation() + { + ComputeInitialSpringBackVelocity(); + + if (m_PostPointerUpAnimation == null) + { + m_PostPointerUpAnimation = schedule.Execute(PostPointerUpAnimation).Every(30); + } + else + { + m_PostPointerUpAnimation.Resume(); + } + } + void AdjustScrollers() { float horizontalFactor = contentContainer.boundingBox.width > UIRUtility.k_Epsilon ? contentViewport.layout.width / contentContainer.boundingBox.width : 1f; @@ -1345,7 +1350,22 @@ void OnScrollWheel(WheelEvent evt) } if (updateContentViewTransform) + { + // Update elastic behavior + if (touchScrollBehavior == TouchScrollBehavior.Elastic) + { + m_LowBounds = new Vector2( + Mathf.Min(horizontalScroller.lowValue, horizontalScroller.highValue), + Mathf.Min(verticalScroller.lowValue, verticalScroller.highValue)); + m_HighBounds = new Vector2( + Mathf.Max(horizontalScroller.lowValue, horizontalScroller.highValue), + Mathf.Max(verticalScroller.lowValue, verticalScroller.highValue)); + + ExecuteElasticSpringAnimation(); + } + UpdateContentViewTransform(); + } } void OnRootCustomStyleResolved(CustomStyleResolvedEvent evt) diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/TextValueField.cs b/ModuleOverrides/com.unity.ui/Core/Controls/TextValueField.cs similarity index 96% rename from ModuleOverrides/com.unity.ui/Editor/Controls/TextValueField.cs rename to ModuleOverrides/com.unity.ui/Core/Controls/TextValueField.cs index ab3cd1256a..c90118e975 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/TextValueField.cs +++ b/ModuleOverrides/com.unity.ui/Core/Controls/TextValueField.cs @@ -3,14 +3,14 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Speed at which the value changes for a given input device delta. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public enum DeltaSpeed { /// @@ -30,6 +30,7 @@ public enum DeltaSpeed /// /// Base interface for UIElements text value fields. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public interface IValueField { /// @@ -57,6 +58,7 @@ public interface IValueField /// /// Base class for text fields. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public abstract class TextValueField : TextInputBaseField, IValueField { // This property to alleviate the fact we have to cast all the time @@ -337,6 +339,7 @@ protected override void ExecuteDefaultAction(EventBase evt) /// /// Specifies the 's . /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class TextValueFieldTraits : BaseFieldTraits where TValueUxmlAttributeType : TypedUxmlAttributeDescription, new() { diff --git a/ModuleOverrides/com.unity.ui/Core/Cursor.cs b/ModuleOverrides/com.unity.ui/Core/Cursor.cs index 8758cdd0bf..575f674945 100644 --- a/ModuleOverrides/com.unity.ui/Core/Cursor.cs +++ b/ModuleOverrides/com.unity.ui/Core/Cursor.cs @@ -45,6 +45,14 @@ public override int GetHashCode() return hashCode; } + internal static IEnumerable allowedAssetTypes + { + get + { + yield return typeof(Texture2D); + } + } + /// public static bool operator==(Cursor style1, Cursor style2) { diff --git a/ModuleOverrides/com.unity.ui/Core/DefaultEventSystem.cs b/ModuleOverrides/com.unity.ui/Core/DefaultEventSystem.cs index c7d72db086..9af6e2999b 100644 --- a/ModuleOverrides/com.unity.ui/Core/DefaultEventSystem.cs +++ b/ModuleOverrides/com.unity.ui/Core/DefaultEventSystem.cs @@ -66,6 +66,7 @@ private bool ShouldIgnoreEventsOnAppNotFocused() private readonly float m_RepeatDelay = 0.5f; private bool m_SendingTouchEvents; + private bool m_SendingPenEvent; private Event m_Event = new Event(); private BaseRuntimePanel m_FocusedPanel; @@ -95,8 +96,11 @@ public void Update(UpdateMode updateMode = UpdateMode.Always) if (!isAppFocused && ShouldIgnoreEventsOnAppNotFocused() && updateMode == UpdateMode.IgnoreIfAppNotFocused) return; + m_SendingPenEvent = ProcessPenEvents(); + // touch needs to take precedence because of the mouse emulation layer - m_SendingTouchEvents = ProcessTouchEvents(); + if (!m_SendingPenEvent) + m_SendingTouchEvents = ProcessTouchEvents(); SendIMGUIEvents(); @@ -114,12 +118,15 @@ void SendIMGUIEvents() { SendFocusBasedEvent(self => UIElementsRuntimeUtility.CreateEvent(self.m_Event), this); } - else if (!m_SendingTouchEvents && input.mousePresent) + else if (!m_SendingTouchEvents && !m_SendingPenEvent && input.mousePresent) { + var pointerType = m_Event.pointerType == UnityEngine.PointerType.Mouse + ? PointerId.mousePointerId + : PointerId.penPointerIdBase; var screenPosition = GetLocalScreenPosition(m_Event, out var targetDisplay); if (m_Event.type == EventType.ScrollWheel) { - SendPositionBasedEvent(screenPosition, m_Event.delta, PointerId.mousePointerId, targetDisplay, (panelPosition, panelDelta, self) => + SendPositionBasedEvent(screenPosition, m_Event.delta, pointerType, targetDisplay, (panelPosition, panelDelta, self) => { self.m_Event.mousePosition = panelPosition; return UIElementsRuntimeUtility.CreateEvent(self.m_Event); @@ -127,7 +134,7 @@ void SendIMGUIEvents() } else { - SendPositionBasedEvent(screenPosition, m_Event.delta, PointerId.mousePointerId, targetDisplay, (panelPosition, panelDelta, self) => + SendPositionBasedEvent(screenPosition, m_Event.delta, pointerType, targetDisplay, (panelPosition, panelDelta, self) => { self.m_Event.mousePosition = panelPosition; self.m_Event.delta = panelDelta; @@ -326,6 +333,20 @@ private static EventBase MakeTouchEvent(Touch touch, EventModifiers modifiers) } } + private static EventBase MakePenEvent(PenData pen, EventModifiers modifiers) + { + switch (pen.contactType) + { + case PenEventType.PenDown: + return PointerDownEvent.GetPooled(pen, modifiers); + case PenEventType.PenUp: + return PointerUpEvent.GetPooled(pen, modifiers); + case PenEventType.NoContact: + default: + return null; + } + } + private bool ProcessTouchEvents() { for (int i = 0; i < input.touchCount; ++i) @@ -350,6 +371,22 @@ private bool ProcessTouchEvents() return input.touchCount > 0; } + private bool ProcessPenEvents() + { + PenData p = input.GetLastPenContactEvent(); + if (p.contactType == PenEventType.NoContact) + return false; + + SendPositionBasedEvent(p.position, p.deltaPos, PointerId.penPointerIdBase, null, (panelPosition, panelDelta, _pen) => + { + _pen.position = panelPosition; + _pen.deltaPos = panelDelta; + return MakePenEvent(_pen, EventModifiers.None); + }, p); + input.ClearLastPenContactEvent(); + return true; + } + private Vector2 GetRawMoveVector() { @@ -437,6 +474,11 @@ internal interface IInput { bool GetButtonDown(string button); float GetAxisRaw(string axis); + void ResetPenEvents(); + void ClearLastPenContactEvent(); + int penEventCount { get; } + PenData GetPenEvent(int index); + PenData GetLastPenContactEvent(); int touchCount { get; } Touch GetTouch(int index); bool mousePresent { get; } @@ -446,6 +488,11 @@ private class Input : IInput { public bool GetButtonDown(string button) => UnityEngine.Input.GetButtonDown(button); public float GetAxisRaw(string axis) => UnityEngine.Input.GetAxis(axis); + public void ResetPenEvents() => UnityEngine.Input.ResetPenEvents(); + public void ClearLastPenContactEvent() => UnityEngine.Input.ClearLastPenContactEvent(); + public int penEventCount => UnityEngine.Input.penEventCount; + public PenData GetPenEvent(int index) => UnityEngine.Input.GetPenEvent(index); + public PenData GetLastPenContactEvent() => UnityEngine.Input.GetLastPenContactEvent(); public int touchCount => UnityEngine.Input.touchCount; public Touch GetTouch(int index) => UnityEngine.Input.GetTouch(index); public bool mousePresent => UnityEngine.Input.mousePresent; @@ -457,6 +504,11 @@ private class NoInput : IInput public float GetAxisRaw(string axis) => 0f; public int touchCount => 0; public Touch GetTouch(int index) => default; + public void ResetPenEvents() { } + public void ClearLastPenContactEvent() { } + public int penEventCount => 0; + public PenData GetPenEvent(int index) => default; + public PenData GetLastPenContactEvent() => default; public bool mousePresent => false; } } diff --git a/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs b/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs index 255611d9ad..02dee2fc35 100644 --- a/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs +++ b/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs @@ -348,8 +348,11 @@ void ProcessEvent(EventBase evt, IPanel panel) { foreach (var element in evt.path.targetElements) { - evt.target = element; - EventDispatchUtilities.ExecuteDefaultAction(evt, panel); + if (element.panel == panel) + { + evt.target = element; + EventDispatchUtilities.ExecuteDefaultAction(evt); + } } // Reset target to leaf target @@ -362,7 +365,7 @@ void ProcessEvent(EventBase evt, IPanel panel) { evt.target = panel.visualTree; } - EventDispatchUtilities.ExecuteDefaultAction(evt, panel); + EventDispatchUtilities.ExecuteDefaultAction(evt); } m_DebuggerEventDispatchingStrategy.PostDispatch(evt, panel); diff --git a/ModuleOverrides/com.unity.ui/Core/Events/CaptureEvents.cs b/ModuleOverrides/com.unity.ui/Core/Events/CaptureEvents.cs index a66fcb6047..99bf4cb869 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/CaptureEvents.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/CaptureEvents.cs @@ -13,11 +13,16 @@ public interface IPointerCaptureEvent { } + internal interface IPointerCaptureEventInternal + { + int pointerId { get; } + } + /// /// Base class for pointer capture events and mouse capture events. /// [EventCategory(EventCategory.Pointer)] - public abstract class PointerCaptureEventBase : EventBase, IPointerCaptureEvent where T : PointerCaptureEventBase, new() + public abstract class PointerCaptureEventBase : EventBase, IPointerCaptureEvent, IPointerCaptureEventInternal where T : PointerCaptureEventBase, new() { /// /// For PointerCaptureEvent and MouseCaptureEvent, returns the VisualElement that loses the pointer capture, if any. For PointerCaptureOutEvent and MouseCaptureOutEvent, returns the VisualElement that captures the pointer. diff --git a/ModuleOverrides/com.unity.ui/Core/Events/CommandEventDispatchingStrategy.cs b/ModuleOverrides/com.unity.ui/Core/Events/CommandEventDispatchingStrategy.cs index 44bdc3530d..6ec62cf131 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/CommandEventDispatchingStrategy.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/CommandEventDispatchingStrategy.cs @@ -36,7 +36,7 @@ public void DispatchEvent(EventBase evt, IPanel panel) } else { - evt.target = panel.focusController.GetLeafFocusedElement(); + evt.target = leafFocusElement; EventDispatchUtilities.PropagateEvent(evt); if (!evt.isPropagationStopped && evt.propagateToIMGUI) { diff --git a/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs b/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs index 405b21ed51..616ef435aa 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs @@ -13,9 +13,9 @@ public bool CanDispatchEvent(EventBase evt) public void DispatchEvent(EventBase evt, IPanel panel) { - if (evt.target != null) + if (evt.target is VisualElement ve && ve.panel == panel) { - evt.propagateToIMGUI = evt.target is IMGUIContainer; + evt.propagateToIMGUI = ve.isIMGUIContainer; EventDispatchUtilities.PropagateEvent(evt); } else diff --git a/ModuleOverrides/com.unity.ui/Core/Events/EventBase.cs b/ModuleOverrides/com.unity.ui/Core/Events/EventBase.cs index daa7000c98..907208c2c8 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/EventBase.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/EventBase.cs @@ -33,6 +33,7 @@ internal enum EventPropagation TricklesDown = 2, Cancellable = 4, SkipDisabledElements = 8, + IgnoreCompositeRoots = 16, } [Flags] @@ -163,6 +164,22 @@ internal bool skipDisabledElements } } + internal bool ignoreCompositeRoots + { + get { return (propagation & EventPropagation.IgnoreCompositeRoots) != 0; } + set + { + if (value) + { + propagation |= EventPropagation.IgnoreCompositeRoots; + } + else + { + propagation &= ~EventPropagation.IgnoreCompositeRoots; + } + } + } + // Original target. May be different than 'target' when propagating event and 'target.isCompositeRoot' is true. internal IEventHandler leafTarget { get; private set; } diff --git a/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs b/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs index 9434370c10..144d0e3d83 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs @@ -342,13 +342,15 @@ public void InvokeCallbacks(EventBase evt, PropagationPhase propagationPhase) } m_IsInvoking++; + var currentTarget = (VisualElement) evt.currentTarget; + var panel = currentTarget.panel; for (var i = 0; i < m_Callbacks.Count; i++) { - if (evt.isImmediatePropagationStopped) + if (evt.isImmediatePropagationStopped || currentTarget.panel != panel) break; - if (evt.skipDisabledElements && evt.currentTarget is VisualElement ve && !ve.enabledInHierarchy && + if (evt.skipDisabledElements && !currentTarget.enabledInHierarchy && m_Callbacks[i].invokePolicy != InvokePolicy.IncludeDisabled) { continue; diff --git a/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs b/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs index 4d324504b0..965644001e 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs @@ -99,10 +99,13 @@ public static void PropagateEvent(EventBase evt) private static void HandleEventAcrossPropagationPath(EventBase evt) { // Build and store propagation path - var path = PropagationPaths.Build((VisualElement)evt.leafTarget, evt); + var leafTarget = (VisualElement) evt.leafTarget; + var path = PropagationPaths.Build(leafTarget, evt); evt.path = path; EventDebugger.LogPropagationPaths(evt, path); + var panel = leafTarget.panel; + // Phase 1: TrickleDown phase // Propagate event from root to target.parent if (evt.tricklesDown) @@ -114,12 +117,13 @@ private static void HandleEventAcrossPropagationPath(EventBase evt) if (evt.isPropagationStopped) break; - if (evt.Skip(path.trickleDownPath[i])) + var element = path.trickleDownPath[i]; + if (evt.Skip(element) || element.panel != panel) { continue; } - evt.currentTarget = path.trickleDownPath[i]; + evt.currentTarget = element; evt.currentTarget.HandleEvent(evt); } } @@ -131,7 +135,7 @@ private static void HandleEventAcrossPropagationPath(EventBase evt) evt.propagationPhase = PropagationPhase.AtTarget; foreach (var element in path.targetElements) { - if (evt.Skip(element)) + if (evt.Skip(element) || element.panel != panel) { continue; } @@ -145,7 +149,7 @@ private static void HandleEventAcrossPropagationPath(EventBase evt) evt.propagationPhase = PropagationPhase.DefaultActionAtTarget; foreach (var element in path.targetElements) { - if (evt.Skip(element)) + if (evt.Skip(element) || element.panel != panel) { continue; } @@ -166,7 +170,7 @@ private static void HandleEventAcrossPropagationPath(EventBase evt) foreach (var element in path.bubbleUpPath) { - if (evt.Skip(element)) + if (evt.Skip(element) || element.panel != panel) { continue; } @@ -223,7 +227,7 @@ internal static void PropagateToIMGUIContainer(VisualElement root, EventBase evt } } - public static void ExecuteDefaultAction(EventBase evt, IPanel panel) + public static void ExecuteDefaultAction(EventBase evt) { if (evt.target is VisualElement ve && ve.HasDefaultAction(evt.eventCategory)) { diff --git a/ModuleOverrides/com.unity.ui/Core/Events/MouseEventDispatchingStrategy.cs b/ModuleOverrides/com.unity.ui/Core/Events/MouseEventDispatchingStrategy.cs index 29f51a9c62..cbc80f369e 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/MouseEventDispatchingStrategy.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/MouseEventDispatchingStrategy.cs @@ -33,10 +33,11 @@ static bool SendEventToTarget(EventBase evt, BaseVisualElementPanel panel) static bool SendEventToRegularTarget(EventBase evt, BaseVisualElementPanel panel) { - if (evt.target == null) + if (!(evt.target is VisualElement ve)) return false; - EventDispatchUtilities.PropagateEvent(evt); + if (ve.panel == panel) + EventDispatchUtilities.PropagateEvent(evt); return IsDone(evt); } diff --git a/ModuleOverrides/com.unity.ui/Core/Events/MouseEvents.cs b/ModuleOverrides/com.unity.ui/Core/Events/MouseEvents.cs index 0f76b23c57..4b4b4b5ba5 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/MouseEvents.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/MouseEvents.cs @@ -722,7 +722,7 @@ protected override void Init() void LocalInit() { - propagation = EventPropagation.TricklesDown | EventPropagation.Cancellable; + propagation = EventPropagation.TricklesDown | EventPropagation.Cancellable | EventPropagation.IgnoreCompositeRoots; } /// @@ -756,7 +756,7 @@ protected override void Init() void LocalInit() { - propagation = EventPropagation.TricklesDown | EventPropagation.Cancellable; + propagation = EventPropagation.TricklesDown | EventPropagation.Cancellable | EventPropagation.IgnoreCompositeRoots; } /// diff --git a/ModuleOverrides/com.unity.ui/Core/Events/PointerEventDispatchingStrategy.cs b/ModuleOverrides/com.unity.ui/Core/Events/PointerEventDispatchingStrategy.cs index 913fa25e30..02b0ba835e 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/PointerEventDispatchingStrategy.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/PointerEventDispatchingStrategy.cs @@ -14,13 +14,13 @@ public bool CanDispatchEvent(EventBase evt) public virtual void DispatchEvent(EventBase evt, IPanel panel) { SetBestTargetForEvent(evt, panel); - SendEventToTarget(evt); + SendEventToTarget(evt, panel); evt.stopDispatch = true; } - static void SendEventToTarget(EventBase evt) + static void SendEventToTarget(EventBase evt, IPanel panel) { - if (evt.target != null) + if (evt.target is VisualElement ve && ve.panel == panel) { EventDispatchUtilities.PropagateEvent(evt); } diff --git a/ModuleOverrides/com.unity.ui/Core/Events/PointerEvents.cs b/ModuleOverrides/com.unity.ui/Core/Events/PointerEvents.cs index 7bc8d92e77..cb050693db 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/PointerEvents.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/PointerEvents.cs @@ -35,8 +35,10 @@ internal static string GetPointerType(int pointerId) { if (pointerId == PointerId.mousePointerId) return mouse; - - return touch; + else if (pointerId == PointerId.penPointerIdBase) + return pen; + else + return touch; } // A direct manipulation device is a device where the user directly manipulates elements @@ -143,8 +145,8 @@ public interface IPointerEvent /// /// /// Pressing a mouse button sets a bit. Releasing the button clears the bit. The left mouse button sets/clears Bit 0. - /// The right mouse button sets/clears Bit 1. The middle mouse button sets/clears Bit 2. Additional buttons set/clear - /// other bits. + /// The right mouse button and pen barrel button set/clear Bit 1. The middle mouse button sets/clears Bit 2. + /// The pen eraser sets/clears Bit 5. Additional buttons set/clear other bits. /// int pressedButtons { get; } @@ -199,6 +201,15 @@ public interface IPointerEvent /// float twist { get; } /// + /// Specifies the angle of the pen relative to the X and Y axis respectively, in radians. + /// + Vector2 tilt { get; } + /// + /// Specifies the state of the pen. For example, whether the pen is in contact with the screen or tablet, whether the pen is inverted, and whether buttons are pressed. + /// On macOS, penStatus will not reflect changes to button mappings. + /// + PenStatus penStatus { get; } + /// /// Gets an estimate of the radius of a touch. /// /// @@ -276,6 +287,14 @@ internal interface IPointerEventInternal public abstract class PointerEventBase : EventBase, IPointerEvent, IPointerEventInternal where T : PointerEventBase, new() { + private bool m_AltitudeNeedsConversion = true; + private bool m_AzimuthNeedsConversion = true; + private float m_AltitudeAngle = 0f; + private float m_AzimuthAngle = 0f; + + private bool m_TiltNeeded = true; + private Vector2 m_Tilt = new Vector2(0, 0); + /// /// Gets the identifier of the pointer that sent the event. /// @@ -352,19 +371,82 @@ public abstract class PointerEventBase : EventBase, IPointerEvent, IPointe /// /// A value of 0 indicates that the stylus is parallel to the surface. A value of pi/2 indicates that it is perpendicular to the surface. /// - public float altitudeAngle { get; protected set; } + public float altitudeAngle + { + // only calculate angle when requested + get + { + if (m_AltitudeNeedsConversion) + { + m_AltitudeAngle = TiltToAltitude(tilt); + m_AltitudeNeedsConversion = false; + } + return m_AltitudeAngle; + } + protected set + { + m_AltitudeNeedsConversion = true; + m_AltitudeAngle = value; + } + } /// /// Gets the angle of the stylus relative to the x-axis, in radians. /// /// /// A value of 0 indicates that the stylus is pointed along the x-axis of the device. /// - public float azimuthAngle { get; protected set; } + public float azimuthAngle + { + // only calculate angle when requested + get + { + if (m_AzimuthNeedsConversion) + { + m_AzimuthAngle = TiltToAzimuth(tilt); + m_AzimuthNeedsConversion = false; + } + return m_AzimuthAngle; + } + protected set + { + m_AzimuthNeedsConversion = true; + m_AzimuthAngle = value; + } + } /// /// Gets the rotation of the stylus around its axis, in radians. /// public float twist { get; protected set; } /// + /// Specifies the angle of the pen relative to the X and Y axis respectively, in radians. + /// + public Vector2 tilt + { + // only calculate tilt when requested and not natively provided + get + { + // windows does not provide altitude or azimuth for touch events, so there's nothing to convert + if (!(Application.platform == RuntimePlatform.WindowsEditor || + Application.platform == RuntimePlatform.WindowsPlayer) && this.pointerType == PointerType.touch && m_TiltNeeded) + { + m_Tilt = AzimuthAndAlitutudeToTilt(m_AltitudeAngle, m_AzimuthAngle); + m_TiltNeeded = false; + } + return m_Tilt; + } + + protected set + { + m_TiltNeeded = true; + m_Tilt = value; + } + } + /// + /// Specifies the state of the pen. For example, whether the pen is in contact with the screen or tablet, whether the pen is inverted, and whether buttons are pressed. + /// On macOS, penStatus will not reflect changes to button mappings. + /// + public PenStatus penStatus { get; protected set; } + /// /// Gets an estimate of the radius of a touch. /// /// @@ -476,7 +558,9 @@ void LocalInit() altitudeAngle = 0; azimuthAngle = 0; - twist = 0; + tilt = new Vector2(0f, 0f); + twist = 0.0f; + penStatus = PenStatus.None; radius = Vector2.zero; radiusVariance = Vector2.zero; @@ -523,6 +607,65 @@ private static bool IsMouse(Event systemEvent) || t == EventType.MouseLeaveWindow; } + private static bool IsTouch(Event systemEvent) + { + EventType t = systemEvent.rawType; + return t == EventType.TouchMove + || t == EventType.TouchDown + || t == EventType.TouchUp + || t == EventType.TouchStationary + || t == EventType.TouchEnter + || t == EventType.TouchLeave; + } + + /// + /// Converts touch or stylus tilt to azimuth angle. + /// + /// Angle relative to the X and Y axis, in radians. abs(tilt.y) must be < pi/2 + /// Azimuth angle as determined by tilt along x and y axese. + private static float TiltToAzimuth(Vector2 tilt) + { + float azimuth = 0f; + if (tilt.x != 0) + { + azimuth = Mathf.PI / 2 - Mathf.Atan2(-Mathf.Cos(tilt.x) * Mathf.Sin(tilt.y), Mathf.Cos(tilt.y) * Mathf.Sin(tilt.x)); + if (azimuth < 0) // fix range to [0, 2*pi) + azimuth += 2 * Mathf.PI; + // follow UIKit conventions where azimuth is 0 when the cap end of the stylus points along the positive x axis of the device's screen + if (azimuth >= (Mathf.PI / 2)) + azimuth -= Mathf.PI / 2; + else + azimuth += (3 * Mathf.PI / 2); + } + + return azimuth; + } + + /// + /// Converts touch or stylus azimuth and altitude to tilt + /// + /// Angle relative to the X and Y axis, in radians. abs(tilt.y) must be < pi/2 + /// Azimuth angle as determined by tilt along x and y axese. + private static Vector2 AzimuthAndAlitutudeToTilt(float altitude, float azimuth) + { + Vector2 t = new Vector2(0, 0); + + t.x = Mathf.Atan(Mathf.Cos(azimuth) * Mathf.Cos(altitude) / Mathf.Sin(azimuth)); + t.y = Mathf.Atan(Mathf.Cos(azimuth) * Mathf.Sin(altitude) / Mathf.Sin(azimuth)); + + return t; + } + + /// + /// Converts touch or stylus tilt to altitude angle. + /// + /// Angle relative to the X and Y axis, in radians. abs(tilt.y) must be < pi/2 + /// Altitude angle as determined by tilt along x and y axese. + private static float TiltToAltitude(Vector2 tilt) + { + return Mathf.PI / 2 - Mathf.Acos(Mathf.Cos(tilt.x) * Mathf.Cos(tilt.y)); + } + /// /// Gets an event from the event pool and initializes it with the given values. Use this function instead of creating new events. /// Events obtained using this method need to be released back to the pool. You can use `Dispose()` to release them. @@ -533,7 +676,7 @@ public static T GetPooled(Event systemEvent) { T e = GetPooled(); - if (!(IsMouse(systemEvent) || systemEvent.rawType == EventType.DragUpdated)) + if (!(IsMouse(systemEvent) || IsTouch(systemEvent) || systemEvent.rawType == EventType.DragUpdated)) { Debug.Assert(false, "Unexpected event type: " + systemEvent.rawType + " (" + systemEvent.type + ")"); } @@ -551,30 +694,40 @@ public static T GetPooled(Event systemEvent) case UnityEngine.PointerType.Pen: e.pointerType = PointerType.pen; e.pointerId = PointerId.penPointerIdBase; + // system events are not fired for pen buttons, so in order to keep buttonsate up to date we need to check the status of these buttons for all pen events + if (systemEvent.penStatus == PenStatus.Barrel) + PointerDeviceState.PressButton(e.pointerId, (int) PenButton.PenBarrel); + else + PointerDeviceState.ReleaseButton(e.pointerId, (int) PenButton.PenBarrel); + if (systemEvent.penStatus == PenStatus.Eraser) + PointerDeviceState.PressButton(e.pointerId, (int) PenButton.PenEraser); + else + PointerDeviceState.ReleaseButton(e.pointerId, (int) PenButton.PenEraser); break; } e.isPrimary = true; - e.altitudeAngle = 0; - e.azimuthAngle = 0; - e.twist = 0; + // calculate these on demand + e.altitudeAngle = 0f; + e.azimuthAngle = 0f; + e.radius = Vector2.zero; e.radiusVariance = Vector2.zero; e.imguiEvent = systemEvent; - if (systemEvent.rawType == EventType.MouseDown) + if (systemEvent.rawType == EventType.MouseDown || systemEvent.rawType == EventType.TouchDown) { - PointerDeviceState.PressButton(PointerId.mousePointerId, systemEvent.button); + PointerDeviceState.PressButton(e.pointerId, systemEvent.button); e.button = systemEvent.button; } - else if (systemEvent.rawType == EventType.MouseUp) + else if (systemEvent.rawType == EventType.MouseUp || systemEvent.rawType == EventType.TouchUp) { - PointerDeviceState.ReleaseButton(PointerId.mousePointerId, systemEvent.button); + PointerDeviceState.ReleaseButton(e.pointerId, systemEvent.button); e.button = systemEvent.button; } - else if (systemEvent.rawType == EventType.MouseMove) + else if (systemEvent.rawType == EventType.MouseMove || systemEvent.rawType == EventType.TouchMove) { e.button = -1; } @@ -585,6 +738,9 @@ public static T GetPooled(Event systemEvent) e.deltaPosition = systemEvent.delta; e.clickCount = systemEvent.clickCount; e.modifiers = systemEvent.modifiers; + e.tilt = systemEvent.tilt; + e.penStatus = systemEvent.penStatus; + e.twist = systemEvent.twist; switch (systemEvent.pointerType) { @@ -592,6 +748,8 @@ public static T GetPooled(Event systemEvent) e.pressure = e.pressedButtons == 0 ? 0f : 0.5f; break; case UnityEngine.PointerType.Touch: + e.pressure = systemEvent.pressure; + break; case UnityEngine.PointerType.Pen: e.pressure = systemEvent.pressure; break; @@ -658,7 +816,9 @@ public static T GetPooled(Touch touch, EventModifiers modifiers = EventModifiers e.altitudeAngle = touch.altitudeAngle; e.azimuthAngle = touch.azimuthAngle; - e.twist = 0; + e.twist = 0.0f; + e.tilt = new Vector2(0f, 0f); + e.penStatus = PenStatus.None; e.radius = new Vector2(touch.radius, touch.radius); e.radiusVariance = new Vector2(touch.radiusVariance, touch.radiusVariance); @@ -669,6 +829,68 @@ public static T GetPooled(Touch touch, EventModifiers modifiers = EventModifiers return e; } + /// + /// Gets a pointer event from the event pool and initializes it with the given values. Use this function instead of creating new events. + /// Events obtained using this method need to be released back to the pool. You can use `Dispose()` to release them. + /// + /// A structure from the InputManager containing pen event information. + /// The modifier keys held down during the event. + /// An initialized event. + public static T GetPooled(PenData pen, EventModifiers modifiers = EventModifiers.None) + { + T e = GetPooled(); + + e.pointerId = PointerId.penPointerIdBase; + e.pointerType = PointerType.pen; + + e.isPrimary = true; + + if (pen.contactType == PenEventType.PenDown) + { + PointerDeviceState.PressButton(e.pointerId, 0); + e.button = 0; + } + else if (pen.contactType == PenEventType.PenUp) + { + PointerDeviceState.ReleaseButton(e.pointerId, 0); + e.button = 0; + } + else + { + e.button = -1; + } + + // system events are not fired for pen buttons, so in order to keep buttonsate up to date we need to check the status of these buttons for all pen events + if (pen.penStatus == PenStatus.Barrel) + PointerDeviceState.PressButton(e.pointerId, (int) PenButton.PenBarrel); + else + PointerDeviceState.ReleaseButton(e.pointerId, (int) PenButton.PenBarrel); + if (pen.penStatus == PenStatus.Eraser) + PointerDeviceState.PressButton(e.pointerId, (int) PenButton.PenEraser); + else + PointerDeviceState.ReleaseButton(e.pointerId, (int) PenButton.PenEraser); + + e.pressedButtons = PointerDeviceState.GetPressedButtons(e.pointerId); + e.position = pen.position; + e.localPosition = pen.position; + e.deltaPosition = pen.deltaPos; + e.clickCount = 0; + e.pressure = pen.pressure; + e.tangentialPressure = 0; + + e.twist = pen.twist; + e.tilt = pen.tilt; + e.penStatus = pen.penStatus; + e.radius = Vector2.zero; + e.radiusVariance = Vector2.zero; + + e.modifiers = modifiers; + + ((IPointerEventInternal)e).triggeredByOS = true; + + return e; + } + internal static T GetPooled(IPointerEvent triggerEvent, Vector2 position, int pointerId) { if (triggerEvent != null) @@ -711,6 +933,8 @@ public static T GetPooled(IPointerEvent triggerEvent) e.altitudeAngle = triggerEvent.altitudeAngle; e.azimuthAngle = triggerEvent.azimuthAngle; e.twist = triggerEvent.twist; + e.tilt = triggerEvent.tilt; + e.penStatus = triggerEvent.penStatus; e.radius = triggerEvent.radius; e.radiusVariance = triggerEvent.radiusVariance; @@ -1162,7 +1386,7 @@ protected override void Init() void LocalInit() { - propagation = EventPropagation.TricklesDown; + propagation = EventPropagation.TricklesDown | EventPropagation.IgnoreCompositeRoots; } /// @@ -1196,7 +1420,7 @@ protected override void Init() void LocalInit() { - propagation = EventPropagation.TricklesDown; + propagation = EventPropagation.TricklesDown | EventPropagation.IgnoreCompositeRoots; } /// diff --git a/ModuleOverrides/com.unity.ui/Core/Events/PropagationPaths.cs b/ModuleOverrides/com.unity.ui/Core/Events/PropagationPaths.cs index f398358643..bde1fa2273 100644 --- a/ModuleOverrides/com.unity.ui/Core/Events/PropagationPaths.cs +++ b/ModuleOverrides/com.unity.ui/Core/Events/PropagationPaths.cs @@ -64,7 +64,7 @@ public static PropagationPaths Build(VisualElement elem, EventBase evt) // 2. It would require dirtying the parent categories when we set isCompositeRoot, so more overhead for (var ve = elem.nextParentWithEventCallback; ve != null; ve = ve.nextParentWithEventCallback) { - if (ve.isCompositeRoot) + if (ve.isCompositeRoot && !evt.ignoreCompositeRoots) { // Callback for elem must be called at the Target phase. Skip if no callback. if (ve.HasEventCallbacksOrDefaultActions(eventCategory)) diff --git a/ModuleOverrides/com.unity.ui/Editor/FieldMouseDragger.cs b/ModuleOverrides/com.unity.ui/Core/FieldMouseDragger.cs similarity index 75% rename from ModuleOverrides/com.unity.ui/Editor/FieldMouseDragger.cs rename to ModuleOverrides/com.unity.ui/Core/FieldMouseDragger.cs index b15eb42398..69d423be21 100644 --- a/ModuleOverrides/com.unity.ui/Editor/FieldMouseDragger.cs +++ b/ModuleOverrides/com.unity.ui/Core/FieldMouseDragger.cs @@ -2,14 +2,14 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using UnityEngine; -using UnityEngine.UIElements; +using UnityEngine.Scripting.APIUpdating; -namespace UnityEditor.UIElements +namespace UnityEngine.UIElements { /// /// Provides the base class for field mouse draggers. /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public abstract class BaseFieldMouseDragger { /// @@ -33,9 +33,10 @@ public void SetDragZone(VisualElement dragElement) /// Provides dragging on a visual element to change a value field. /// /// - /// To create a field mouse dragger use + /// To create a field mouse dragger use /// and then set the drag zone using /// + [MovedFrom(true, UpgradeConstants.EditorNamespace, UpgradeConstants.EditorAssembly)] public class FieldMouseDragger : BaseFieldMouseDragger { /// @@ -69,13 +70,7 @@ public sealed override void SetDragZone(VisualElement dragElement, Rect hotZone) if (m_DragElement != null) { m_DragElement.UnregisterCallback(UpdateValueOnPointerDown); - m_DragElement.UnregisterCallback(UpdateValueOnPointerMove); m_DragElement.UnregisterCallback(UpdateValueOnPointerUp); - - m_DragElement.UnregisterCallback(UpdateValueOnMouseDown); - m_DragElement.UnregisterCallback(UpdateValueOnMouseMove); - m_DragElement.UnregisterCallback(UpdateValueOnMouseUp); - m_DragElement.UnregisterCallback(UpdateValueOnKeyDown); } @@ -86,13 +81,8 @@ public sealed override void SetDragZone(VisualElement dragElement, Rect hotZone) { dragging = false; m_DragElement.RegisterCallback(UpdateValueOnPointerDown); - m_DragElement.RegisterCallback(UpdateValueOnPointerMove); m_DragElement.RegisterCallback(UpdateValueOnPointerUp); m_DragElement.RegisterCallback(UpdateValueOnKeyDown); - - m_DragElement.RegisterCallback(UpdateValueOnMouseDown); - m_DragElement.RegisterCallback(UpdateValueOnMouseMove); - m_DragElement.RegisterCallback(UpdateValueOnMouseUp); } } @@ -106,53 +96,39 @@ private void UpdateValueOnPointerDown(PointerDownEvent evt) { if (CanStartDrag(evt.button, evt.localPosition)) { - if (evt.pointerId != PointerId.mousePointerId) + // We want to allow dragging when using a mouse in any context and when in an Editor context with any pointer type. + if (evt.pointerType == PointerType.mouse) { - evt.PreventDefault(); - m_DragElement.CapturePointer(evt.pointerId); + m_DragElement.CaptureMouse(); ProcessDownEvent(evt); } - else + else if (m_DragElement.panel.contextType == ContextType.Editor) { - evt.StopImmediatePropagation(); + evt.PreventDefault(); + m_DragElement.CapturePointer(evt.pointerId); + ProcessDownEvent(evt); } } } - private void UpdateValueOnMouseDown(MouseDownEvent evt) - { - if (CanStartDrag(evt.button, evt.mousePosition)) - { - m_DragElement.CaptureMouse(); - ProcessDownEvent(evt); - } - } - private void ProcessDownEvent(EventBase evt) { // Make sure no other elements can capture the mouse! evt.StopPropagation(); dragging = true; + m_DragElement.RegisterCallback(UpdateValueOnPointerMove); startValue = m_DrivenField.value; m_DrivenField.StartDragging(); - EditorGUIUtility.SetWantsMouseJumping(1); + (m_DragElement.panel as BaseVisualElementPanel)?.uiElementsBridge?.SetWantsMouseJumping(1); } private void UpdateValueOnPointerMove(PointerMoveEvent evt) { - if (evt.pointerId == PointerId.mousePointerId) - return; - ProcessMoveEvent(evt.shiftKey, evt.altKey, evt.deltaPosition); } - private void UpdateValueOnMouseMove(MouseMoveEvent evt) - { - ProcessMoveEvent(evt.shiftKey, evt.altKey, evt.mouseDelta); - } - private void ProcessMoveEvent(bool shiftKey, bool altKey, Vector2 deltaPosition) { if (dragging) @@ -164,27 +140,20 @@ private void ProcessMoveEvent(bool shiftKey, bool altKey, Vector2 deltaPosition) private void UpdateValueOnPointerUp(PointerUpEvent evt) { - if (evt.pointerId == PointerId.mousePointerId) - return; - ProcessUpEvent(evt, evt.pointerId); } - private void UpdateValueOnMouseUp(MouseUpEvent evt) - { - ProcessUpEvent(evt, PointerId.mousePointerId); - } - private void ProcessUpEvent(EventBase evt, int pointerId) { if (dragging) { dragging = false; + m_DragElement.UnregisterCallback(UpdateValueOnPointerMove); m_DragElement.ReleasePointer(pointerId); if (evt is IMouseEvent) m_DragElement.panel.ProcessPointerCapture(PointerId.mousePointerId); - EditorGUIUtility.SetWantsMouseJumping(0); + (m_DragElement.panel as BaseVisualElementPanel)?.uiElementsBridge?.SetWantsMouseJumping(0); m_DrivenField.StopDragging(); } } @@ -198,7 +167,7 @@ private void UpdateValueOnKeyDown(KeyDownEvent evt) m_DrivenField.StopDragging(); IPanel panel = (evt.target as VisualElement)?.panel; panel.ReleasePointer(PointerId.mousePointerId); - EditorGUIUtility.SetWantsMouseJumping(0); + (panel as BaseVisualElementPanel)?.uiElementsBridge?.SetWantsMouseJumping(0); } } } diff --git a/ModuleOverrides/com.unity.ui/Core/Panel.cs b/ModuleOverrides/com.unity.ui/Core/Panel.cs index 2d457de320..b891d5d48d 100644 --- a/ModuleOverrides/com.unity.ui/Core/Panel.cs +++ b/ModuleOverrides/com.unity.ui/Core/Panel.cs @@ -244,10 +244,26 @@ abstract class BaseVisualElementPanel : IPanel, IGroupBox internal event Action panelDisposed; + private UIElementsBridge m_UIElementsBridge; + + internal UIElementsBridge uiElementsBridge + { + get + { + if (m_UIElementsBridge != null) + return m_UIElementsBridge; + + throw new Exception("Panel has no UIElementsBridge."); + } + + set => m_UIElementsBridge = value; + } + protected BaseVisualElementPanel() { yogaConfig = new YogaConfig(); yogaConfig.UseWebDefaults = YogaConfig.Default.UseWebDefaults; + m_UIElementsBridge = new RuntimeUIElementsBridge(); } public void Dispose() @@ -931,6 +947,15 @@ void UpdateForRepaint() m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.Repaint); } + internal void UpdateWithoutRepaint() + { + m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.ViewData); + m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.Bindings); + m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.Animation); + m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.Styles); + m_VisualTreeUpdater.UpdateVisualTreePhase(VisualTreeUpdatePhase.Layout); + } + public override void DirtyStyleSheets() { m_VisualTreeUpdater.DirtyStyleSheets(); diff --git a/ModuleOverrides/com.unity.ui/Core/PenButton.cs b/ModuleOverrides/com.unity.ui/Core/PenButton.cs new file mode 100644 index 0000000000..f4bd7f83d3 --- /dev/null +++ b/ModuleOverrides/com.unity.ui/Core/PenButton.cs @@ -0,0 +1,25 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +namespace UnityEngine.UIElements +{ + /// + /// Describes a PenButton. Based on W3 conventions: https://www.w3.org/TR/pointerevents2/#the-buttons-property. + /// + public enum PenButton + { + /// + /// The Pen is in Contact. + /// + PenContact = 0, + /// + /// The Pen Barrel Button. + /// + PenBarrel = 1, + /// + /// The Pen Eraser. + /// + PenEraser = 5 + } +} diff --git a/ModuleOverrides/com.unity.ui/Core/Style/Background.cs b/ModuleOverrides/com.unity.ui/Core/Style/Background.cs index 573e548ff2..0babfc857d 100644 --- a/ModuleOverrides/com.unity.ui/Core/Style/Background.cs +++ b/ModuleOverrides/com.unity.ui/Core/Style/Background.cs @@ -157,6 +157,17 @@ internal static Background FromObject(object obj) return default; } + internal static IEnumerable allowedAssetTypes + { + get + { + yield return typeof(Texture2D); + yield return typeof(RenderTexture); + yield return typeof(Sprite); + yield return typeof(VectorImage); + } + } + /// public static bool operator==(Background lhs, Background rhs) { diff --git a/ModuleOverrides/com.unity.ui/Core/Style/CustomStyle.cs b/ModuleOverrides/com.unity.ui/Core/Style/CustomStyle.cs index 4db7fba462..0ec5b04116 100644 --- a/ModuleOverrides/com.unity.ui/Core/Style/CustomStyle.cs +++ b/ModuleOverrides/com.unity.ui/Core/Style/CustomStyle.cs @@ -69,42 +69,52 @@ public override int GetHashCode() public interface ICustomStyle { /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out float value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out int value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out bool value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out Color value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out Texture2D value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out Sprite value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out VectorImage value); /// - /// Gets the value associated with the specified . + /// Gets the value associated with the specified . + /// + /// True if the property is found, false if not. + bool TryGetValue(CustomStyleProperty property, out Object value); + /// + /// Gets the value associated with the specified . + /// + /// True if the property is found, false if not. + bool TryGetValue(CustomStyleProperty property, out T value) where T : Object; + /// + /// Gets the value associated with the specified . /// /// True if the property is found, false if not. bool TryGetValue(CustomStyleProperty property, out string value); diff --git a/ModuleOverrides/com.unity.ui/Core/Style/FontDefinition.cs b/ModuleOverrides/com.unity.ui/Core/Style/FontDefinition.cs index d822d41862..46dfa534a8 100644 --- a/ModuleOverrides/com.unity.ui/Core/Style/FontDefinition.cs +++ b/ModuleOverrides/com.unity.ui/Core/Style/FontDefinition.cs @@ -77,6 +77,15 @@ internal static FontDefinition FromObject(object obj) return default; } + internal static IEnumerable allowedAssetTypes + { + get + { + yield return typeof(Font); + yield return typeof(FontAsset); + } + } + internal bool IsEmpty() { return m_Font == null && m_FontAsset == null; diff --git a/ModuleOverrides/com.unity.ui/Core/Style/Generated/StylePropertyUtil.cs b/ModuleOverrides/com.unity.ui/Core/Style/Generated/StylePropertyUtil.cs index abfc27361b..ece4ea694e 100644 --- a/ModuleOverrides/com.unity.ui/Core/Style/Generated/StylePropertyUtil.cs +++ b/ModuleOverrides/com.unity.ui/Core/Style/Generated/StylePropertyUtil.cs @@ -756,5 +756,24 @@ public static bool IsMatchingShorthand(StylePropertyId shorthand, StylePropertyI return false; } } + + public static IEnumerable GetAllowedAssetTypesForProperty(StylePropertyId id) + { + switch (id) + { + case StylePropertyId.BackgroundImage: + return Background.allowedAssetTypes; + case StylePropertyId.Cursor: + return Cursor.allowedAssetTypes; + case StylePropertyId.UnityFont: + return new[]{typeof(Font)}; + case StylePropertyId.UnityFontDefinition: + return FontDefinition.allowedAssetTypes; + case StylePropertyId.Custom: + return new[]{typeof(UnityEngine.Object)}; + default: + return System.Linq.Enumerable.Empty(); + } + } } } diff --git a/ModuleOverrides/com.unity.ui/Core/StyleSheets/StyleVariable.cs b/ModuleOverrides/com.unity.ui/Core/StyleSheets/StyleVariable.cs index 48aa74be75..d5956166ba 100644 --- a/ModuleOverrides/com.unity.ui/Core/StyleSheets/StyleVariable.cs +++ b/ModuleOverrides/com.unity.ui/Core/StyleSheets/StyleVariable.cs @@ -41,6 +41,8 @@ internal class StyleVariableContext private List m_Variables; private List m_SortedHash; + public List variables => m_Variables; + public void Add(StyleVariable sv) { // Avoid duplicates. Otherwise the variable context explodes as hierarchy gets deeper. diff --git a/ModuleOverrides/com.unity.ui/Core/UIElementsBridge.cs b/ModuleOverrides/com.unity.ui/Core/UIElementsBridge.cs new file mode 100644 index 0000000000..eb7683bb0b --- /dev/null +++ b/ModuleOverrides/com.unity.ui/Core/UIElementsBridge.cs @@ -0,0 +1,18 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +namespace UnityEngine.UIElements +{ + internal abstract class UIElementsBridge + { + public abstract void SetWantsMouseJumping(int value); + } + + internal class RuntimeUIElementsBridge : UIElementsBridge + { + public override void SetWantsMouseJumping(int value) + { + } + } +} diff --git a/ModuleOverrides/com.unity.ui/Core/UIElementsUtility.cs b/ModuleOverrides/com.unity.ui/Core/UIElementsUtility.cs index a29c71798f..954761acc7 100644 --- a/ModuleOverrides/com.unity.ui/Core/UIElementsUtility.cs +++ b/ModuleOverrides/com.unity.ui/Core/UIElementsUtility.cs @@ -368,10 +368,12 @@ internal static EventBase CreateEvent(Event systemEvent, EventType eventType) switch (eventType) { case EventType.MouseMove: + case EventType.TouchMove: return PointerMoveEvent.GetPooled(systemEvent); case EventType.MouseDrag: return PointerMoveEvent.GetPooled(systemEvent); case EventType.MouseDown: + case EventType.TouchDown: // If some buttons are already down, we generate PointerMove/MouseDown events. // Otherwise we generate PointerDown/MouseDown events. // See W3C pointer events recommendation: https://www.w3.org/TR/pointerevents2 @@ -385,6 +387,7 @@ internal static EventBase CreateEvent(Event systemEvent, EventType eventType) return PointerDownEvent.GetPooled(systemEvent); } case EventType.MouseUp: + case EventType.TouchUp: // If more buttons are still down, we generate PointerMove/MouseUp events. // Otherwise we generate PointerUp/MouseUp events. // See W3C pointer events recommendation: https://www.w3.org/TR/pointerevents2 diff --git a/ModuleOverrides/com.unity.ui/Core/UXML/UxmlAttributeDescription.cs b/ModuleOverrides/com.unity.ui/Core/UXML/UxmlAttributeDescription.cs index 3fe0bc7fa5..54f334d9c7 100644 --- a/ModuleOverrides/com.unity.ui/Core/UXML/UxmlAttributeDescription.cs +++ b/ModuleOverrides/com.unity.ui/Core/UXML/UxmlAttributeDescription.cs @@ -87,7 +87,7 @@ public IEnumerable obsoleteNames internal bool TryGetValueFromBagAsString(IUxmlAttributes bag, CreationContext cc, out string value) { - // Regardless of whether the attribute is overwridden or not, we want to error here + // Regardless of whether the attribute is overridden or not, we want to error here // if there is no valid name. if (name == null && (m_ObsoleteNames == null || m_ObsoleteNames.Length == 0)) { @@ -182,7 +182,7 @@ internal bool TryGetValueFromBagAsString(IUxmlAttributes bag, CreationContext cc /// /// Tries to get the attribute value from the attribute bag. /// - /// A bag containg attributes and their values as strings. + /// A bag contains attributes and their values as strings. /// The context in which the values are retrieved. /// A function to convert a string value to type T. /// The value to return if the attribute is not found in the bag. @@ -747,12 +747,34 @@ public bool TryGetValueFromBag(IUxmlAttributes bag, CreationContext cc, ref T va } static U ConvertValueToEnum(string v, U defaultValue) + where U : struct { - if (v == null || !Enum.IsDefined(typeof(U), v)) - return defaultValue; + try + { + if (string.IsNullOrEmpty(v)) + return defaultValue; - var l = (U)Enum.Parse(typeof(U), v); - return l; + return (U) Enum.Parse(typeof(U), v, true); + } + catch (ArgumentException) + { + Debug.LogError(GetEnumNameErrorMessage(v, typeof(U))); + } + catch (OverflowException) + { + Debug.LogError(GetEnumRangeErrorMessage(v, typeof(U))); + } + return defaultValue; + } + + static string GetEnumNameErrorMessage(string v, Type enumType) + { + return $"The {enumType.Name} enum does not contain the value `{v}`. Value must be in range [{string.Join(" | ", Enum.GetNames(enumType))}]."; + } + + static string GetEnumRangeErrorMessage(string v, Type enumType) + { + return $"{v} is outside of the range of possible values for the {enumType.Name} enum."; } } diff --git a/ModuleOverrides/com.unity.ui/Core/UXML/VisualElementFactoryRegistry.cs b/ModuleOverrides/com.unity.ui/Core/UXML/VisualElementFactoryRegistry.cs index 231e40f016..5c63a2a9f1 100644 --- a/ModuleOverrides/com.unity.ui/Core/UXML/VisualElementFactoryRegistry.cs +++ b/ModuleOverrides/com.unity.ui/Core/UXML/VisualElementFactoryRegistry.cs @@ -101,7 +101,21 @@ static void RegisterEngineFactories() new Foldout.UxmlFactory(), new BindableElement.UxmlFactory(), new TextElement.UxmlFactory(), - new ButtonStripField.UxmlFactory() + new ButtonStripField.UxmlFactory(), + new FloatField.UxmlFactory(), + new DoubleField.UxmlFactory(), + new Hash128Field.UxmlFactory(), + new IntegerField.UxmlFactory(), + new LongField.UxmlFactory(), + new RectField.UxmlFactory(), + new Vector2Field.UxmlFactory(), + new RectIntField.UxmlFactory(), + new Vector3Field.UxmlFactory(), + new Vector4Field.UxmlFactory(), + new Vector2IntField.UxmlFactory(), + new Vector3IntField.UxmlFactory(), + new BoundsField.UxmlFactory(), + new BoundsIntField.UxmlFactory() }; foreach (var factory in factories) diff --git a/ModuleOverrides/com.unity.ui/Core/UXML/VisualTreeAsset.cs b/ModuleOverrides/com.unity.ui/Core/UXML/VisualTreeAsset.cs index 54899f09f8..e79d8160aa 100644 --- a/ModuleOverrides/com.unity.ui/Core/UXML/VisualTreeAsset.cs +++ b/ModuleOverrides/com.unity.ui/Core/UXML/VisualTreeAsset.cs @@ -605,6 +605,29 @@ VisualElement CreateError() return CreateError(); } } + // TODO: Do it differently (UIE-814). + else if (asset.fullTypeName == "UnityEditor.UIElements.FloatField" + || asset.fullTypeName == "UnityEditor.UIElements.DoubleField" + || asset.fullTypeName == "UnityEditor.UIElements.EnumField" + || asset.fullTypeName == "UnityEditor.UIElements.Hash128Field" + || asset.fullTypeName == "UnityEditor.UIElements.IntegerField" + || asset.fullTypeName == "UnityEditor.UIElements.LongField" + || asset.fullTypeName == "UnityEditor.UIElements.RectField" + || asset.fullTypeName == "UnityEditor.UIElements.Vector2Field" + || asset.fullTypeName == "UnityEditor.UIElements.RectIntField" + || asset.fullTypeName == "UnityEditor.UIElements.Vector3Field" + || asset.fullTypeName == "UnityEditor.UIElements.Vector4Field" + || asset.fullTypeName == "UnityEditor.UIElements.Vector2IntField" + || asset.fullTypeName == "UnityEditor.UIElements.Vector3IntField" + || asset.fullTypeName == "UnityEditor.UIElements.BoundsField" + || asset.fullTypeName == "UnityEditor.UIElements.BoundsIntField") + { + string runtimeTypeName = asset.fullTypeName.Replace("UnityEditor", "UnityEngine"); + if (!VisualElementFactoryRegistry.TryGetValue(runtimeTypeName, out factoryList)) + { + return CreateError(); + } + } else if (asset.fullTypeName == UxmlRootElementFactory.k_ElementName) { // Support UXML without namespace for backward compatibility. diff --git a/ModuleOverrides/com.unity.ui/Core/UpgradeConstants.cs b/ModuleOverrides/com.unity.ui/Core/UpgradeConstants.cs new file mode 100644 index 0000000000..d0356355fd --- /dev/null +++ b/ModuleOverrides/com.unity.ui/Core/UpgradeConstants.cs @@ -0,0 +1,12 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +namespace UnityEngine.UIElements +{ + internal class UpgradeConstants + { + public const string EditorNamespace = "UnityEditor.UIElements"; + public const string EditorAssembly = "UnityEditor.UIElementsModule"; + } +} diff --git a/ModuleOverrides/com.unity.ui/Core/VisualElement.cs b/ModuleOverrides/com.unity.ui/Core/VisualElement.cs index b89438925b..01dff6287d 100644 --- a/ModuleOverrides/com.unity.ui/Core/VisualElement.cs +++ b/ModuleOverrides/com.unity.ui/Core/VisualElement.cs @@ -618,6 +618,13 @@ internal bool isWorldBoundingBoxDirty get => (m_Flags & VisualElementFlags.WorldBoundingBoxDirty) == VisualElementFlags.WorldBoundingBoxDirty; set => m_Flags = value ? m_Flags | VisualElementFlags.WorldBoundingBoxDirty : m_Flags & ~VisualElementFlags.WorldBoundingBoxDirty; } + + private const VisualElementFlags worldBoundingBoxDirtyDependencies = + VisualElementFlags.WorldBoundingBoxDirty | VisualElementFlags.BoundingBoxDirty | + VisualElementFlags.WorldTransformDirty; + + internal bool isWorldBoundingBoxOrDependenciesDirty => (m_Flags & worldBoundingBoxDirtyDependencies) != 0; + private Rect m_WorldBoundingBox; internal Rect boundingBox @@ -638,7 +645,7 @@ internal Rect worldBoundingBox { get { - if (isWorldBoundingBoxDirty || isBoundingBoxDirty) + if (isWorldBoundingBoxOrDependenciesDirty) { UpdateWorldBoundingBox(); isWorldBoundingBoxDirty = false; @@ -738,6 +745,12 @@ internal bool isWorldTransformInverseDirty set => m_Flags = value ? m_Flags | VisualElementFlags.WorldTransformInverseDirty : m_Flags & ~VisualElementFlags.WorldTransformInverseDirty; } + private const VisualElementFlags worldTransformInverseDirtyDependencies = + VisualElementFlags.WorldTransformInverseDirty | VisualElementFlags.WorldTransformDirty; + + internal bool isWorldTransformInverseOrDependenciesDirty => + (m_Flags & worldTransformInverseDirtyDependencies) != 0; + private Matrix4x4 m_WorldTransformCache = Matrix4x4.identity; private Matrix4x4 m_WorldTransformInverseCache = Matrix4x4.identity; @@ -776,7 +789,7 @@ internal ref Matrix4x4 worldTransformInverse { get { - if (isWorldTransformDirty || isWorldTransformInverseDirty) + if (isWorldTransformInverseOrDependenciesDirty) UpdateWorldTransformInverse(); return ref m_WorldTransformInverseCache; } @@ -785,7 +798,7 @@ internal ref Matrix4x4 worldTransformInverse internal void UpdateWorldTransform() { // If we are during a layout we don't want to remove the dirty transform flag - // since this could lead to invalid computed transform (see ScopeContentainer.DoMeasure) + // since this could lead to invalid computed transform (see ScopeContentContainer.DoMeasure) if (elementPanel != null && !elementPanel.duringLayoutPhase) { isWorldTransformDirty = false; @@ -1004,6 +1017,43 @@ internal PseudoStates pseudoStates } } + internal int containedPointerIds { get; private set; } + + void UpdateHoverPseudoState() + { + // An element has the hover pseudoState if and only if it has at least one contained pointer which is + // captured by itself or no element. + + // With multi-finger touch events, there can be multiple unrelated elements hovered at once, or a single + // element hovered by multiple fingers. In that case, the hover pseudoState for a given element will match + // a logical OR of the hover state of each finger on that element. + + if (containedPointerIds == 0) + { + pseudoStates &= ~PseudoStates.Hover; + return; + } + + bool hovered = false; + for (var pointerId = 0; pointerId < PointerId.maxPointers; pointerId++) + { + if ((containedPointerIds & (1 << pointerId)) != 0) + { + var capturingElement = panel?.GetCapturingElement(pointerId); + if (capturingElement == null || capturingElement == this) + { + hovered = true; + break; + } + } + } + + if (hovered) + pseudoStates |= PseudoStates.Hover; + else + pseudoStates &= ~PseudoStates.Hover; + } + /// /// Determines if this element can be pick during mouseEvents or queries. /// @@ -1118,7 +1168,8 @@ public VisualElement() } [EventInterest(typeof(MouseOverEvent), typeof(MouseOutEvent), typeof(PointerEnterEvent), - typeof(PointerLeaveEvent), typeof(BlurEvent), typeof(FocusEvent))] + typeof(PointerLeaveEvent), typeof(PointerCaptureEvent), typeof(PointerCaptureOutEvent), + typeof(BlurEvent), typeof(FocusEvent))] protected override void ExecuteDefaultAction(EventBase evt) { base.ExecuteDefaultAction(evt); @@ -1135,16 +1186,27 @@ protected override void ExecuteDefaultAction(EventBase evt) } else if (evt.eventTypeId == PointerEnterEvent.TypeId()) { - var capturingElement = panel?.GetCapturingElement(((IPointerEvent)evt).pointerId); - if (capturingElement == null || capturingElement == this) - pseudoStates |= PseudoStates.Hover; + containedPointerIds |= (1 << ((IPointerEvent)evt).pointerId); + UpdateHoverPseudoState(); } else if (evt.eventTypeId == PointerLeaveEvent.TypeId()) { - // With multi-finger touch events, there can be multiple unrelated elements hovered at once, or a single - // element hovered by multiple fingers. In that case, the hover pseudoState will match the last finger - // to have entered or left the element. - pseudoStates &= ~PseudoStates.Hover; + containedPointerIds &= ~(1 << ((IPointerEvent)evt).pointerId); + UpdateHoverPseudoState(); + } + else if (evt.eventTypeId == PointerCaptureEvent.TypeId() || + evt.eventTypeId == PointerCaptureOutEvent.TypeId()) + { + // Pointer capture changes can influence if an element is hovered or not. + UpdateHoverPseudoState(); + + // Make sure to also reevaluate the hover state of the elements under pointer. + var elementUnderPointer = + elementPanel?.GetTopElementUnderPointer(((IPointerCaptureEventInternal) evt).pointerId); + for (var ve = elementUnderPointer; ve != null && ve != this; ve = ve.parent) + { + ve.UpdateHoverPseudoState(); + } } else if (evt.eventTypeId == BlurEvent.TypeId()) { diff --git a/ModuleOverrides/com.unity.ui/Core/VisualElementFocusRing.cs b/ModuleOverrides/com.unity.ui/Core/VisualElementFocusRing.cs index ccf9a8178d..48fc8b757a 100644 --- a/ModuleOverrides/com.unity.ui/Core/VisualElementFocusRing.cs +++ b/ModuleOverrides/com.unity.ui/Core/VisualElementFocusRing.cs @@ -55,6 +55,7 @@ public static VisualElementFocusChangeTarget GetPooled(Focusable target) protected override void Dispose() { + target = null; Pool.Release(this); } diff --git a/ModuleOverrides/com.unity.ui/Core/VisualElementHierarchy.cs b/ModuleOverrides/com.unity.ui/Core/VisualElementHierarchy.cs index b1998fc21e..73433824f8 100644 --- a/ModuleOverrides/com.unity.ui/Core/VisualElementHierarchy.cs +++ b/ModuleOverrides/com.unity.ui/Core/VisualElementHierarchy.cs @@ -955,18 +955,19 @@ internal VisualElement GetRoot() internal VisualElement GetRootVisualContainer() { + VisualElement topMostRootContainer = null; var hierarchyParent = this; while (hierarchyParent != null) { if (hierarchyParent.isRootVisualContainer) { - return hierarchyParent; + topMostRootContainer = hierarchyParent; } hierarchyParent = hierarchyParent.hierarchy.parent; } - return null; + return topMostRootContainer; } internal VisualElement GetNextElementDepthFirst() diff --git a/ModuleOverrides/com.unity.ui/Core/VisualElementStyleAccess.cs b/ModuleOverrides/com.unity.ui/Core/VisualElementStyleAccess.cs index 9b0fb07c11..44d0f88eec 100644 --- a/ModuleOverrides/com.unity.ui/Core/VisualElementStyleAccess.cs +++ b/ModuleOverrides/com.unity.ui/Core/VisualElementStyleAccess.cs @@ -321,6 +321,32 @@ public bool TryGetValue(CustomStyleProperty property, out VectorIma return false; } + public bool TryGetValue(CustomStyleProperty property, out Object value) + { + if (m_CustomProperties != null && m_CustomProperties.TryGetValue(property.name, out var customProp)) + { + return customProp.sheet.TryReadAssetReference(customProp.handle, out value); + } + + value = null; + return false; + } + + public bool TryGetValue(CustomStyleProperty property, out T value) where T : Object + { + if (m_CustomProperties != null && m_CustomProperties.TryGetValue(property.name, out var customProp)) + { + if (customProp.sheet.TryReadAssetReference(customProp.handle, out Object objValue)) + { + value = objValue as T; + return value != null; + } + } + + value = null; + return false; + } + public bool TryGetValue(CustomStyleProperty property, out string value) { if (m_CustomProperties != null && m_CustomProperties.TryGetValue(property.name, out var customProp)) diff --git a/ModuleOverrides/com.unity.ui/Core/VisualTreeStyleUpdater.cs b/ModuleOverrides/com.unity.ui/Core/VisualTreeStyleUpdater.cs index bedb11a82a..fb0af5b314 100644 --- a/ModuleOverrides/com.unity.ui/Core/VisualTreeStyleUpdater.cs +++ b/ModuleOverrides/com.unity.ui/Core/VisualTreeStyleUpdater.cs @@ -140,7 +140,7 @@ public override void Update() foreach (var ve in m_TransitionPropertyUpdateList) { // Allow for transitions to be cancelled if matching transition property was removed. - if (ve.hasRunningAnimations) + if (ve.hasRunningAnimations || ve.hasCompletedAnimations) { ComputedTransitionUtils.UpdateComputedTransitions(ref ve.computedStyle); m_StyleContextHierarchyTraversal.CancelAnimationsWithNoTransitionProperty(ve, ref ve.computedStyle); diff --git a/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs b/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs index ac6daf1569..02ed9f28b2 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Bindings/BindingExtensions.cs @@ -241,18 +241,19 @@ private void CreateBindingObjectForProperty(VisualElement element, SerializedPro switch (prop.propertyType) { case SerializedPropertyType.Integer: - if (prop.type == "long" | prop.type == "ulong") + if (prop.type == "long" || prop.type == "ulong") { - if (element is INotifyValueChanged ) + if (element is INotifyValueChanged || element is INotifyValueChanged) { DefaultBind(element, prop, SerializedPropertyHelper.GetLongPropertyValue, SerializedPropertyHelper.SetLongPropertyValue, SerializedPropertyHelper.ValueEquals); - }else if (element is INotifyValueChanged) + } + else if (element is INotifyValueChanged) { //This is not sustainable, we must fix this DefaultBind(element, prop, (x) => (ulong) SerializedPropertyHelper.GetLongPropertyValue(x), (x, v) => SerializedPropertyHelper.SetLongPropertyValue(x, (long)v), (a, b, c) => SerializedPropertyHelper.ValueEquals((long)a,b, (x) => (long)c(x))); } - else if (element is INotifyValueChanged || element is INotifyValueChanged) + else if (element is INotifyValueChanged) { DefaultBind(element, prop, SerializedPropertyHelper.GetIntPropertyValue, SerializedPropertyHelper.SetIntPropertyValue, SerializedPropertyHelper.ValueEquals); } @@ -261,12 +262,13 @@ private void CreateBindingObjectForProperty(VisualElement element, SerializedPro DefaultBind(element, prop, SerializedPropertyHelper.GetLongPropertyValueAsFloat, SerializedPropertyHelper.SetFloatPropertyValue, SerializedPropertyHelper.ValueEquals); } } - else + else // prop.type == "int" { if (element is INotifyValueChanged || element is INotifyValueChanged) { DefaultBind(element, prop, SerializedPropertyHelper.GetIntPropertyValue, SerializedPropertyHelper.SetIntPropertyValue, SerializedPropertyHelper.ValueEquals); - }else if (element is INotifyValueChanged) + } + else if (element is INotifyValueChanged) { DefaultBind(element, prop, SerializedPropertyHelper.GetLongPropertyValue, SerializedPropertyHelper.SetLongPropertyValue, SerializedPropertyHelper.ValueEquals); } @@ -291,7 +293,7 @@ private void CreateBindingObjectForProperty(VisualElement element, SerializedPro DefaultBind(element, prop, SerializedPropertyHelper.GetFloatPropertyValue, SerializedPropertyHelper.SetFloatPropertyValue, SerializedPropertyHelper.ValueEquals); } } - else + else // prop.type == "double" { if (element is INotifyValueChanged) { @@ -1795,6 +1797,8 @@ class SerializedDefaultEnumBinding : SerializedObjectBindingToBaseField s_Pool = new ObjectPool(() => new SerializedDefaultEnumBinding(), 32); + private const int kDefaultValueIndex = -1; + //we need to keep a copy of the last value since some fields will allocate when getting the value private int lastFieldValueIndex; @@ -1892,7 +1896,14 @@ protected override void SyncPropertyToField(PopupField c, SerializedProp } int propValueIndex = p.enumValueIndex; - c.index = lastFieldValueIndex = enumIndexToDisplayIndex[propValueIndex]; + if (propValueIndex >= 0 && propValueIndex < enumIndexToDisplayIndex.Count) + { + c.index = lastFieldValueIndex = enumIndexToDisplayIndex[propValueIndex]; + } + else + { + c.index = lastFieldValueIndex = kDefaultValueIndex; + } } protected override void UpdateLastFieldValue() @@ -1909,7 +1920,8 @@ protected override void UpdateLastFieldValue() protected override bool SyncFieldValueToProperty() { - if (boundProperty.enumValueIndex != displayIndexToEnumIndex[lastFieldValueIndex]) + if (lastFieldValueIndex >= 0 && lastFieldValueIndex < displayIndexToEnumIndex.Count + && boundProperty.enumValueIndex != displayIndexToEnumIndex[lastFieldValueIndex]) { boundProperty.enumValueIndex = displayIndexToEnumIndex[lastFieldValueIndex]; boundProperty.m_SerializedObject.ApplyModifiedProperties(); @@ -1947,7 +1959,7 @@ public override void Release() bindingContext = null; boundProperty = null; field = null; - lastFieldValueIndex = -1; + lastFieldValueIndex = kDefaultValueIndex; isReleased = true; ResetCachedValues(); diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/EnumFlagsField.cs b/ModuleOverrides/com.unity.ui/Editor/Controls/EnumFlagsField.cs index d51fa1ff28..adf2dd0a5c 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/EnumFlagsField.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Controls/EnumFlagsField.cs @@ -34,9 +34,7 @@ public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext { base.Init(ve, bag, cc); - Enum resEnumValue; - bool resIncludeObsoleteValues; - if (EnumFieldHelpers.ExtractValue(bag, cc, out resEnumValue, out resIncludeObsoleteValues)) + if (EnumFieldHelpers.ExtractValue(bag, cc, out var resEnumType, out var resEnumValue, out var resIncludeObsoleteValues)) { EnumFlagsField enumField = (EnumFlagsField)ve; enumField.Init(resEnumValue, resIncludeObsoleteValues); diff --git a/ModuleOverrides/com.unity.ui/Editor/Controls/PropertyField.cs b/ModuleOverrides/com.unity.ui/Editor/Controls/PropertyField.cs index 08c8f3cbcd..b61b8404ea 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Controls/PropertyField.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Controls/PropertyField.cs @@ -593,6 +593,8 @@ private VisualElement CreateOrUpdateFieldFromProperty(SerializedProperty propert return ConfigureField(originalField as Toggle, property, () => new Toggle()); case SerializedPropertyType.Float: + if (property.type == "double") + return ConfigureField(originalField as DoubleField, property, () => new DoubleField()); return ConfigureField(originalField as FloatField, property, () => new FloatField()); case SerializedPropertyType.String: @@ -652,19 +654,19 @@ private VisualElement CreateOrUpdateFieldFromProperty(SerializedProperty propert var enumData = enumType != null ? (EnumData?)EnumDataUtility.GetCachedEnumData(enumType) : null; var propertyDisplayNames = EditorGUI.EnumNamesCache.GetEnumDisplayNames(property); var popupEntries = (enumData?.displayNames ?? propertyDisplayNames).ToList(); + int propertyFieldIndex = (property.enumValueIndex < 0 || property.enumValueIndex >= propertyDisplayNames.Length + ? PopupField.kPopupFieldDefaultIndex : (enumData != null + ? Array.IndexOf(enumData.Value.displayNames, propertyDisplayNames[property.enumValueIndex]) + : property.enumValueIndex)); if (originalField != null && originalField is PopupField popupField) { popupField.choices = popupEntries; - popupField.index = enumData != null - ? Array.IndexOf(enumData.Value.displayNames, propertyDisplayNames[property.enumValueIndex]) - : property.enumValueIndex; + popupField.index = propertyFieldIndex; } return ConfigureField, string>(originalField as PopupField, property, () => new PopupField(popupEntries, property.enumValueIndex) { - index = enumData != null - ? Array.IndexOf(enumData.Value.displayNames, propertyDisplayNames[property.enumValueIndex]) - : property.enumValueIndex + index = propertyFieldIndex }); } } diff --git a/ModuleOverrides/com.unity.ui/Editor/Debugger/PanelDebugger.cs b/ModuleOverrides/com.unity.ui/Editor/Debugger/PanelDebugger.cs index 91c9224481..dea5380867 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Debugger/PanelDebugger.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Debugger/PanelDebugger.cs @@ -54,8 +54,19 @@ internal class PanelDebugger : IPanelDebugger protected void TryFocusCorrespondingWindow(ScriptableObject panelOwner) { var hostView = panelOwner as HostView; - if (hostView != null && hostView.actualView != null) - hostView.actualView.Focus(); + EditorWindow correspondingWindow = null; + // If it's a runtime panel, the owner is a PanelSettings and we need to focus the GameView + if (hostView == null && panelOwner is PanelSettings) + { + correspondingWindow = EditorWindow.GetWindowDontShow(); + } + else + { + correspondingWindow = hostView?.actualView; + } + + if (correspondingWindow != null) + correspondingWindow.Focus(); } public IPanelDebug panelDebug { get; set; } diff --git a/ModuleOverrides/com.unity.ui/Editor/EditorPanel.cs b/ModuleOverrides/com.unity.ui/Editor/EditorPanel.cs index 765f9366d7..1094e78226 100644 --- a/ModuleOverrides/com.unity.ui/Editor/EditorPanel.cs +++ b/ModuleOverrides/com.unity.ui/Editor/EditorPanel.cs @@ -64,6 +64,7 @@ public static Panel FindOrCreate(ScriptableObject ownerObject) panelDebug = new PanelDebug(this); standardShader = EditorShader; updateMaterial += OnUpdateMaterial; + uiElementsBridge = new EditorUIElementsBridge(); } static void OnUpdateMaterial(Material mat) diff --git a/ModuleOverrides/com.unity.ui/Editor/EditorUIElementsBridge.cs b/ModuleOverrides/com.unity.ui/Editor/EditorUIElementsBridge.cs new file mode 100644 index 0000000000..eddc602474 --- /dev/null +++ b/ModuleOverrides/com.unity.ui/Editor/EditorUIElementsBridge.cs @@ -0,0 +1,49 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.UIElements; + +namespace UnityEditor.UIElements +{ + internal class EditorUIElementsBridge : UIElementsBridge + { + private static string serializedPropertyCopyName = "SerializedPropertyCopyName"; + public override void SetWantsMouseJumping(int value) + { + EditorGUIUtility.SetWantsMouseJumping(value); + } + + public static void RegisterSerializedPropertyBindCallback + (BaseCompositeField compositeField, TField field) + where TField : TextValueField, new() + { + // TODO: Fix the callback since it is never received by the TField. + field.RegisterCallback(e => + { + if (!(field.GetProperty(serializedPropertyCopyName) is SerializedProperty property)) + return; + var propertyCopy = property.Copy(); + + var k = 0; + while (k <= compositeField.propertyIndex) + { + propertyCopy.Next(k == 0); + k++; + } + + var f = (TField)e.target; + f.SetProperty(serializedPropertyCopyName, propertyCopy); + f.showMixedValue = propertyCopy.hasMultipleDifferentValues; + + compositeField.forceUpdateDisplay = true; + + compositeField.propertyIndex++; + }); + } + } +} diff --git a/ModuleOverrides/com.unity.ui/Editor/Inspector/EditorElement.cs b/ModuleOverrides/com.unity.ui/Editor/Inspector/EditorElement.cs index 67a71763f9..e0fa2bd269 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Inspector/EditorElement.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Inspector/EditorElement.cs @@ -66,10 +66,11 @@ private bool IsEditorValid() VisualElement m_PrefabElement; IMGUIContainer m_Header; - internal InspectorElement m_InspectorElement { get; private set; } + InspectorElement m_InspectorElement; IMGUIContainer m_Footer; - private bool m_WasVisible = false; + bool m_WasVisible; + bool m_IsCulled; static class Styles { @@ -87,6 +88,7 @@ internal EditorElement(int editorIndex, IPropertyView iw, bool isCulled = false) { m_EditorIndex = editorIndex; inspectorWindow = iw; + m_IsCulled = isCulled; pickingMode = PickingMode.Ignore; if (isCulled) @@ -113,14 +115,30 @@ void InitCulled() } } }, name); + Add(container); } void Init() { - var editors = PopulateCache(); + PopulateCache(); m_EditorTarget = editor.targets[0]; - string editorTitle = ObjectNames.GetInspectorTitle(m_EditorTarget); + var editorTitle = ObjectNames.GetInspectorTitle(m_EditorTarget); + + m_Header = BuildHeaderElement(editorTitle); + m_Footer = BuildFooterElement(editorTitle); + + Add(m_Header); + Add(m_Footer); + + if (EditorUIService.disableInspectorElementThrottling) + CreateInspectorElement(); + } + + InspectorElement BuildInspectorElement() + { + var editors = PopulateCache(); + var editorTitle = ObjectNames.GetInspectorTitle(m_EditorTarget); InspectorElement.Mode inspectorElementMode; @@ -138,38 +156,22 @@ void Init() inspectorElementMode = (InspectorElement.Mode) propertyEditor.inspectorElementModeOverride; } - m_InspectorElement = new InspectorElement(editor, inspectorElementMode) + var inspectorElement = new InspectorElement(editor, inspectorElementMode) { - focusable = false + focusable = false, + name = editorTitle + "Inspector", + style = + { + paddingBottom = PropertyEditor.kEditorElementPaddingBottom + } }; - - m_Header = BuildHeaderElement(editorTitle); - m_Footer = BuildFooterElement(editorTitle); - - m_InspectorElement.name = editorTitle + "Inspector"; - m_InspectorElement.style.paddingBottom = InspectorWindow.kEditorElementPaddingBottom; - if (EditorNeedsVerticalOffset(editors, m_EditorTarget)) { - m_InspectorElement.style.overflow = Overflow.Hidden; - } - - UpdateInspectorVisibility(); - - //Need to update the cache for multi-object edit detection. - if (editor.targets.Length != Selection.objects.Length) - inspectorWindow.tracker.RebuildIfNecessary(); - - Add(m_Header); - // If the editor targets contain many target and the multi editing is not supported, we should not add this inspector. - // However, the header and footer are kept since these are showing information regarding this state. - if (editor != null && ((editor.targets.Length <= 1) || (PropertyEditor.IsMultiEditingSupported(editor, editor.target, inspectorWindow.inspectorMode)))) - { - Add(m_InspectorElement); + inspectorElement.style.overflow = Overflow.Hidden; } - Add(m_Footer); + return inspectorElement; } public void ReinitCulled(int editorIndex) @@ -213,30 +215,59 @@ public void Reinit(int editorIndex) m_Header.onGUIHandler = HeaderOnGUI; m_Footer.onGUIHandler = FooterOnGUI; - m_InspectorElement.AssignExistingEditor(editor); name = editorTitle; - m_InspectorElement.name = editorTitle + "Inspector"; m_Header.name = editorTitle + "Header"; m_Footer.name = editorTitle + "Footer"; + if (m_InspectorElement != null) + { + m_InspectorElement.AssignExistingEditor(editor); + m_InspectorElement.name = editorTitle + "Inspector"; + + // InspectorElement should be enabled only if the Editor is open for edit. + m_InspectorElement.SetEnabled(editor.IsOpenForEdit()); + } + UpdateInspectorVisibility(); + } - // InspectorElement should be enabled only if the Editor is open for edit. - m_InspectorElement.SetEnabled(editor.IsOpenForEdit()); + public void CreateInspectorElement() + { + if (null == editor || null != m_InspectorElement || m_IsCulled) + return; + + // Need to update the cache for multi-object edit detection. + if (editor.targets.Length != Selection.objects.Length) + inspectorWindow.tracker.RebuildIfNecessary(); + + // If the editor targets contain many targets and multi editing is not supported, we should not add this inspector. + if (null != editor && (editor.targets.Length <= 1 || PropertyEditor.IsMultiEditingSupported(editor, editor.target, inspectorWindow.inspectorMode))) + { + m_InspectorElement = BuildInspectorElement(); + Insert(IndexOf(m_Header) + 1, m_InspectorElement); + UpdateInspectorVisibility(); + SetElementVisible(m_InspectorElement, m_WasVisible); + } } - private void UpdateInspectorVisibility() + void UpdateInspectorVisibility() { if (editor.CanBeExpandedViaAFoldoutWithoutUpdate()) { - m_Footer.style.marginTop = m_WasVisible ? 0 : -kFooterDefaultHeight; - m_InspectorElement.style.paddingBottom = InspectorWindow.kEditorElementPaddingBottom; + if (m_Footer != null) + m_Footer.style.marginTop = m_WasVisible ? 0 : -kFooterDefaultHeight; + + if (m_InspectorElement != null) + m_InspectorElement.style.paddingBottom = PropertyEditor.kEditorElementPaddingBottom; } else { - m_Footer.style.marginTop = -kFooterDefaultHeight; - m_InspectorElement.style.paddingBottom = 0; + if (m_Footer != null) + m_Footer.style.marginTop = -kFooterDefaultHeight; + + if (m_InspectorElement != null) + m_InspectorElement.style.paddingBottom = 0; } } @@ -284,7 +315,10 @@ void HeaderOnGUI() var editors = PopulateCache(); if (!IsEditorValid()) { - SetElementVisible(m_InspectorElement, false); + if (m_InspectorElement != null) + { + SetElementVisible(m_InspectorElement, false); + } return; } @@ -296,7 +330,10 @@ void HeaderOnGUI() var target = editor.target; if (target == null && !NativeClassExtensionUtilities.ExtendsANativeType(target)) { - SetElementVisible(m_InspectorElement, false); + if (m_InspectorElement != null) + { + SetElementVisible(m_InspectorElement, false); + } return; } @@ -308,7 +345,7 @@ void HeaderOnGUI() if (openForEdit != m_LastOpenForEdit) { m_LastOpenForEdit = openForEdit; - m_InspectorElement.SetEnabled(openForEdit); + m_InspectorElement?.SetEnabled(openForEdit); } } @@ -334,7 +371,7 @@ void HeaderOnGUI() InvalidateIMGUILayouts(this); } - if (m_WasVisible != IsElementVisible(m_InspectorElement)) + if (m_InspectorElement != null && m_WasVisible != IsElementVisible(m_InspectorElement)) { SetElementVisible(m_InspectorElement, m_WasVisible); } @@ -368,9 +405,9 @@ void HeaderOnGUI() MessageType.Warning); } - if (IsElementVisible(m_InspectorElement)) + if (m_WasVisible) { - m_ContentRect = m_InspectorElement.layout; + m_ContentRect = m_InspectorElement?.layout ?? Rect.zero; } else { @@ -553,7 +590,7 @@ void FooterOnGUI() rect.height -= 1; } - EditorGUI.DrawOverrideBackground(rect, true); + EditorGUI.DrawOverrideBackgroundApplicable(rect, true); } } @@ -578,5 +615,10 @@ internal bool EditorNeedsVerticalOffset(Editor[] editors, Object target) { return m_EditorIndex > 0 && IsEditorValid() && editors[m_EditorIndex - 1].target is GameObject && target is Component; } + + internal InspectorElement GetInspectorElementInternal() + { + return m_InspectorElement; + } } } diff --git a/ModuleOverrides/com.unity.ui/Editor/Inspector/InspectorElement.cs b/ModuleOverrides/com.unity.ui/Editor/Inspector/InspectorElement.cs index 313a43db26..befdf5bde5 100644 --- a/ModuleOverrides/com.unity.ui/Editor/Inspector/InspectorElement.cs +++ b/ModuleOverrides/com.unity.ui/Editor/Inspector/InspectorElement.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using Unity.Profiling; using UnityEditor.Profiling; using UnityEngine; using UnityEngine.UIElements; @@ -138,6 +139,9 @@ private set private bool m_IgnoreOnInspectorGUIErrors; + static readonly ProfilerMarker k_Reset = new ProfilerMarker("InspectorElement.Reset"); + static readonly ProfilerMarker k_CreateInspectorGUI = new ProfilerMarker("InspectorElement.CreateInspectorGUI"); + /// /// InspectorElement constructor. /// @@ -270,6 +274,8 @@ internal static Mode GetModeFromInspectorMode(InspectorMode mode) private void Reset(SerializedObject bindObject) { + k_Reset.Begin(); + Clear(); prefabOverrideBlueBarsContainer = new VisualElement(); @@ -298,14 +304,9 @@ private void Reset(SerializedObject bindObject) boundObject = bindObject; - var customInspector = CreateInspectorElementFromEditor(editor); - if (customInspector == null) - { - customInspector = CreateDefaultInspector(bindObject); - } + CreateInspectorGUI(false); - if (customInspector != null && customInspector != this) - hierarchy.Add(customInspector); + k_Reset.End(); } private void PartialReset(SerializedObject bindObject) @@ -317,17 +318,24 @@ private void PartialReset(SerializedObject bindObject) return; } - var customInspector = CreateInspectorElementFromEditor(editor, true); - if (customInspector == null) - { - customInspector = CreateDefaultInspector(boundObject); - } + CreateInspectorGUI(true); + } + + void CreateInspectorGUI(bool updateBinding) + { + k_CreateInspectorGUI.Begin(); Clear(); - if (customInspector != null && customInspector != this) - hierarchy.Add(customInspector); - customInspector?.Bind(boundObject); + var element = CreateInspectorElementFromEditor(editor, true) ?? CreateDefaultInspector(boundObject); + + if (element != null && element != this) + hierarchy.Add(element); + + if (updateBinding) + element?.Bind(boundObject); + + k_CreateInspectorGUI.End(); } [EventInterest(typeof(SerializedObjectBindEvent))] diff --git a/ModuleOverrides/com.unity.ui/Editor/RetainedMode.cs b/ModuleOverrides/com.unity.ui/Editor/RetainedMode.cs index 73f7f23d7b..dd6a66ebf8 100644 --- a/ModuleOverrides/com.unity.ui/Editor/RetainedMode.cs +++ b/ModuleOverrides/com.unity.ui/Editor/RetainedMode.cs @@ -10,6 +10,7 @@ using UnityEngine.UIElements; using UnityEngine.UIElements.StyleSheets; using UnityEngine.Scripting; +using UnityEngine; using UXMLImporterImpl = UnityEditor.UIElements.UXMLImporterImpl; namespace UnityEditor @@ -24,6 +25,13 @@ static RetainedMode() Panel.initEditorUpdaterFunc = EditorPanel.InitEditorUpdater; Panel.loadResourceFunc = StyleSheetResourceUtil.LoadResource; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; + BaseCompositeField.s_SerializedPropertyBindCallback = EditorUIElementsBridge.RegisterSerializedPropertyBindCallback; StylePropertyReader.getCursorIdFunc = UIElementsEditorUtility.GetCursorId; Panel.TimeSinceStartup = () => (long)(EditorApplication.timeSinceStartup * 1000.0f); } diff --git a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportErrors.cs b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportErrors.cs index 7460db3947..84a65d5ad0 100644 --- a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportErrors.cs +++ b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportErrors.cs @@ -32,7 +32,6 @@ enum StyleSheetImportErrorCode InvalidURILocation, InvalidURIScheme, InvalidURIProjectAssetPath, - InvalidURIProjectAssetType, InvalidVarFunction, InvalidHighResolutionImage, } diff --git a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportGlossary.cs b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportGlossary.cs index 9110934325..ab22fb999c 100644 --- a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportGlossary.cs +++ b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImportGlossary.cs @@ -26,7 +26,6 @@ class StyleSheetImportGlossary public readonly string unexpectedTokenInFunction = L10n.Tr("Expected ',', got '{0}'"); public readonly string missingVariablePrefix = L10n.Tr("Variable '{0}' is missing '--' prefix"); public readonly string invalidHighResAssetType = L10n.Tr("Unsupported type {0} for asset at path '{1}' ; only Texture2D is supported for variants with @2x suffix\nSuggestion: verify the import settings of this asset."); - public readonly string invalidAssetType = L10n.Tr("Unsupported type {0} for asset at path '{1}' ; only Font, FontAsset, Sprite, Texture2D and VectorImage are supported\nSuggestion: verify the import settings of this asset."); public readonly string invalidSelectorListDelimiter = L10n.Tr("Invalid selector list delimiter: '{0}'"); public readonly string invalidComplexSelectorDelimiter = L10n.Tr("Invalid complex selector delimiter: '{0}'"); @@ -38,5 +37,6 @@ class StyleSheetImportGlossary public readonly string invalidUriLocation = L10n.Tr("Invalid URI location: '{0}'"); public readonly string invalidUriScheme = L10n.Tr("Invalid URI scheme: '{0}'"); public readonly string invalidAssetPath = L10n.Tr("Invalid asset path: '{0}'"); + public readonly string invalidAssetType = L10n.Tr("Unsupported type {0} for asset at path '{1}' ; only the following types are supported: {2}\nSuggestion: verify the import settings of this asset."); } } diff --git a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImporterImpl.cs b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImporterImpl.cs index d37ba8ffa6..7166c317e4 100644 --- a/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImporterImpl.cs +++ b/ModuleOverrides/com.unity.ui/Editor/StyleSheets/StyleSheetImporterImpl.cs @@ -36,6 +36,7 @@ abstract class StyleValueImporter protected readonly StyleValidator m_Validator; protected string m_AssetPath; protected int m_CurrentLine; + protected string m_CurrentPropertyName; public StyleValueImporter(UnityEditor.AssetImporters.AssetImportContext context) { @@ -448,7 +449,7 @@ protected void VisitUrlFunction(PrimitiveTerm term) spriteAsset = AssetDatabase.LoadAssetAtPath(projectRelativePath); } - if (isTexture || asset is Sprite || asset is Font || asset is FontAsset || asset is VectorImage || asset is RenderTexture) + if (asset != null) { // Looking suffixed images files only if (isTexture) @@ -474,30 +475,50 @@ protected void VisitUrlFunction(PrimitiveTerm term) DeclareDependencyAndLoad(hiResImageLocation); } - m_Builder.AddValue(spriteAsset != null ? spriteAsset : asset); + Object assetToStore = spriteAsset != null ? spriteAsset : asset; + + m_Builder.AddValue(assetToStore); + + if (!disableValidation) + { + var propertyName = new StylePropertyName(m_CurrentPropertyName); + + // Unknown properties (not custom) should beforehand + if (propertyName.id == StylePropertyId.Unknown) + return; + + var allowed = StylePropertyUtil.GetAllowedAssetTypesForProperty(propertyName.id); + + // If no types were returned, it means this property doesn't support assets. + // Normal syntax validation should cover this. + if (!allowed.Any()) + return; + + Type assetType = assetToStore.GetType(); + + // If none of the allowed types are compatible with the asset type, output a warning + if (!allowed.Any(t => t.IsAssignableFrom(assetType))) + { + string allowedTypes = string.Join(", ", allowed.Select(t => t.Name)); + m_Errors.AddValidationWarning( + string.Format(glossary.invalidAssetType, assetType.Name, projectRelativePath, allowedTypes), + m_CurrentLine); + + } + } } else { + // Asset is actually missing OR we couldn't load it for some reason; this should result in + // response.result != URIValidationResult.OK (above) but if assets are deleted while Unity is + // already open, we fall in here instead. + var(_, message) = ConvertErrorCode(URIValidationResult.InvalidURIProjectAssetPath); + // In case of error, we still want to call AddValue, with parameters to indicate the problem, in order // to keep the full layout from being discarded. We also add appropriate warnings to explain to the // user what is wrong. - if (asset == null) - { - // Asset is actually missing OR we couldn't load it for some reason; this should result in - // response.result != URIValidationResult.OK (above) but if assets are deleted while Unity is - // already open, we fall in here instead. - var(_, message) = ConvertErrorCode(URIValidationResult.InvalidURIProjectAssetPath); - - m_Builder.AddValue(path, StyleValueType.MissingAssetReference); - m_Errors.AddValidationWarning(string.Format(message, path), m_CurrentLine); - } - else - { - // Asset is of an unsupported type. We still add a value, of type invalid, in order to keep the - // layout from breaking entirely. - m_Builder.AddValue(path, StyleValueType.Invalid); - m_Errors.AddSemanticWarning(StyleSheetImportErrorCode.InvalidURIProjectAssetType, string.Format(glossary.invalidAssetType, asset.GetType().Name, projectRelativePath), m_CurrentLine); - } + m_Builder.AddValue(path, StyleValueType.MissingAssetReference); + m_Errors.AddValidationWarning(string.Format(message, path), m_CurrentLine); } } } @@ -1001,6 +1022,7 @@ void VisitSheet(ParserStyleSheet styleSheet) foreach (Property property in rule.Declarations) { m_CurrentLine = property.Line; + m_CurrentPropertyName = property.Name; ValidateProperty(property); diff --git a/ModuleOverrides/com.unity.ui/Editor/UIElementsEditorUtility.cs b/ModuleOverrides/com.unity.ui/Editor/UIElementsEditorUtility.cs index 31902a85c0..9bc6773671 100644 --- a/ModuleOverrides/com.unity.ui/Editor/UIElementsEditorUtility.cs +++ b/ModuleOverrides/com.unity.ui/Editor/UIElementsEditorUtility.cs @@ -40,7 +40,7 @@ internal static string GetStyleSheetPathForCurrentFont(string sheetPath) return GetStyleSheetPathForFont(sheetPath, EditorResources.currentFontName); } - internal static StyleSheet LoadSKinnedStyleSheetForFont(int skin, string fontName) + internal static StyleSheet LoadSkinnedStyleSheetForFont(int skin, string fontName) { return EditorGUIUtility.Load(GetStyleSheetPathForFont(skin == EditorResources.darkSkinIndex ? s_DefaultCommonDarkStyleSheetPath : s_DefaultCommonLightStyleSheetPath, fontName)) as StyleSheet; } @@ -54,7 +54,7 @@ internal static StyleSheet GetCommonDarkStyleSheet() { if (s_DefaultCommonDarkStyleSheet == null) { - s_DefaultCommonDarkStyleSheet = LoadSKinnedStyleSheetForFont(EditorResources.darkSkinIndex, EditorResources.currentFontName); + s_DefaultCommonDarkStyleSheet = LoadSkinnedStyleSheetForFont(EditorResources.darkSkinIndex, EditorResources.currentFontName); if (s_DefaultCommonDarkStyleSheet != null) s_DefaultCommonDarkStyleSheet.isDefaultStyleSheet = true; } @@ -71,7 +71,7 @@ internal static StyleSheet GetCommonLightStyleSheet() { if (s_DefaultCommonLightStyleSheet == null) { - s_DefaultCommonLightStyleSheet = LoadSKinnedStyleSheetForFont(EditorResources.normalSkinIndex, EditorResources.currentFontName); + s_DefaultCommonLightStyleSheet = LoadSkinnedStyleSheetForFont(EditorResources.normalSkinIndex, EditorResources.currentFontName); if (s_DefaultCommonLightStyleSheet != null) s_DefaultCommonLightStyleSheet.isDefaultStyleSheet = true; } diff --git a/Modules/Animation/ScriptBindings/Animator.bindings.cs b/Modules/Animation/ScriptBindings/Animator.bindings.cs index 175256c304..157be66e37 100644 --- a/Modules/Animation/ScriptBindings/Animator.bindings.cs +++ b/Modules/Animation/ScriptBindings/Animator.bindings.cs @@ -972,6 +972,15 @@ extern internal Transform avatarRoot public Transform GetBoneTransform(HumanBodyBones humanBoneId) { + if (avatar == null) + throw new InvalidOperationException("Avatar is null."); + + if (!avatar.isValid) + throw new InvalidOperationException("Avatar is not valid."); + + if (!avatar.isHuman) + throw new InvalidOperationException("Avatar is not of type humanoid."); + if (humanBoneId < 0 || humanBoneId >= HumanBodyBones.LastBone) throw new IndexOutOfRangeException("humanBoneId must be between 0 and " + HumanBodyBones.LastBone); diff --git a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs index ecc66b63b0..2ce81adca5 100644 --- a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs +++ b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs @@ -630,6 +630,8 @@ public static void ForceReserializeAssets(IEnumerable assetPaths, ForceR ForceReserializeAssets(guids, options); } + extern internal static System.Type GetTypeFromVisibleGUIDAndLocalFileIdentifier(GUID guid, long localId); + [FreeFunction("AssetDatabase::GetGUIDAndLocalIdentifierInFile")] extern private static bool GetGUIDAndLocalIdentifierInFile(int instanceID, out GUID outGuid, out long outLocalId); @@ -753,8 +755,9 @@ public static void SetImporterOverride(string path) [FreeFunction("AcceleratorClientCanConnectTo")] public extern static bool CanConnectToCacheServer(string ip, UInt16 port); - [FreeFunction()] - public extern static void RefreshSettings(); + [FreeFunction("RefreshSettings")] + private extern static void _RefreshSettings(); + public static void RefreshSettings() => _RefreshSettings(); public static event Action cacheServerConnectionChanged; [RequiredByNativeCode] @@ -768,7 +771,8 @@ private static void OnCacheServerConnectionChanged() } [FreeFunction("AcceleratorClientIsConnected")] - public extern static bool IsConnectedToCacheServer(); + private extern static bool _IsConnectedToCacheServer(); + public static bool IsConnectedToCacheServer() => _IsConnectedToCacheServer(); [FreeFunction("AcceleratorClientResetReconnectTimer")] public extern static void ResetCacheServerReconnectTimer(); @@ -792,7 +796,8 @@ private static void OnCacheServerConnectionChanged() public extern static bool GetCacheServerEnableUpload(); [FreeFunction("AssetDatabase::WaitForPendingCacheServerRequestsToComplete")] - extern internal static void WaitForPendingCacheServerRequestsToComplete(); + private extern static void _WaitForPendingCacheServerRequestsToComplete(); + internal static void WaitForPendingCacheServerRequestsToComplete() => _WaitForPendingCacheServerRequestsToComplete(); [FreeFunction("AssetDatabase::IsDirectoryMonitoringEnabled")] public extern static bool IsDirectoryMonitoringEnabled(); diff --git a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs index f39e5db0b8..6cfa2e61fc 100644 --- a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs +++ b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs @@ -130,7 +130,8 @@ public void ResetDeltas() } } - public extern static AssetDatabaseCounters counters { get; } + private extern static AssetDatabaseCounters GetCounters(); + public static AssetDatabaseCounters counters => GetCounters(); [FreeFunction("CacheServerCountersResetDeltas")] private extern static void CacheServerCountersResetDeltas(); @@ -149,7 +150,9 @@ internal extern static bool VirtualizationEnabled [FreeFunction("Virtualization_IsEnabled")] get; } - public extern static ArtifactID LookupArtifact(ArtifactKey artifactKey); + [FreeFunction("AssetDatabaseExperimental::LookupArtifact")] + private extern static ArtifactID _LookupArtifact(ArtifactKey artifactKey); + public static ArtifactID LookupArtifact(ArtifactKey artifactKey) => _LookupArtifact(artifactKey); public extern static ArtifactID ProduceArtifact(ArtifactKey artifactKey); public extern static ArtifactID ProduceArtifactAsync(ArtifactKey artifactKey); public extern static ArtifactID[] ProduceArtifactsAsync(GUID[] artifactKey, [uei.DefaultValue("null")] Type importerType = null); @@ -243,7 +246,8 @@ public static OnDemandProgress GetOnDemandArtifactProgress(string guid, Type imp return GetOnDemandArtifactProgress(new ArtifactKey(new GUID(guid), importerType)); } - [FreeFunction()] - internal extern static Hash128 GetArtifactStaticDependencyHash(ArtifactID artifactId); + [FreeFunction("AssetDatabase::GetArtifactStaticDependencyHash")] + private extern static Hash128 _GetArtifactStaticDependencyHash(ArtifactID artifactId); + internal static Hash128 GetArtifactStaticDependencyHash(ArtifactID artifactID) => _GetArtifactStaticDependencyHash(artifactID); } } diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs index 4b542d8387..c514e0ed2c 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs @@ -26,6 +26,8 @@ internal class ModelImporterModelEditor : BaseAssetImporterTabUI [CacheProperty] SerializedProperty m_ImportBlendShapes; [CacheProperty] + SerializedProperty m_ImportBlendShapeDeformPercent; + [CacheProperty] SerializedProperty m_ImportVisibility; [CacheProperty] protected SerializedProperty m_ImportCameras; @@ -116,6 +118,7 @@ protected static class Styles public static GUIContent UseFileScale = EditorGUIUtility.TrTextContent("Convert Units", "Convert file units to Unity ones."); public static GUIContent ImportBlendShapes = EditorGUIUtility.TrTextContent("Import BlendShapes", "Should Unity import BlendShapes."); + public static GUIContent ImportBlendShapesDeformPercent = EditorGUIUtility.TrTextContent("Import Deform Percent", "Import BlendShapes deform percent. If disabled, all values will be set to 0."); public static GUIContent ImportVisibility = EditorGUIUtility.TrTextContent("Import Visibility", "Use visibility properties to enable or disable MeshRenderer components."); public static GUIContent ImportCameras = EditorGUIUtility.TrTextContent("Import Cameras"); public static GUIContent ImportLights = EditorGUIUtility.TrTextContent("Import Lights"); @@ -237,6 +240,10 @@ void SceneGUI() EditorGUILayout.PropertyField(m_BakeAxisConversion, Styles.BakeAxisConversion); EditorGUILayout.PropertyField(m_ImportBlendShapes, Styles.ImportBlendShapes); + + if(m_ImportBlendShapes.boolValue) + EditorGUILayout.PropertyField(m_ImportBlendShapeDeformPercent, Styles.ImportBlendShapesDeformPercent); + EditorGUILayout.PropertyField(m_ImportVisibility, Styles.ImportVisibility); EditorGUILayout.PropertyField(m_ImportCameras, Styles.ImportCameras); EditorGUILayout.PropertyField(m_ImportLights, Styles.ImportLights); diff --git a/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs b/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs index 6260f559c7..60b2475385 100644 --- a/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs +++ b/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs @@ -503,6 +503,12 @@ public extern bool importBlendShapes set; } + public extern bool importBlendShapeDeformPercent + { + get; + set; + } + public extern bool importCameras { get; diff --git a/Modules/AssetPipelineEditor/Public/VideoImporter.bindings.cs b/Modules/AssetPipelineEditor/Public/VideoImporter.bindings.cs index d18bfd9a28..d38b67664d 100644 --- a/Modules/AssetPipelineEditor/Public/VideoImporter.bindings.cs +++ b/Modules/AssetPipelineEditor/Public/VideoImporter.bindings.cs @@ -196,6 +196,21 @@ private BuildTargetGroup GetBuildTargetGroup(string methodName, string platform, return platformGroup; } + internal static event Action analyticsSent; + + [RequiredByNativeCode] + private static void VideoClipImporterInvokeAnalyticsSentCallback_Internal(string analytics) + { + if (analyticsSent != null) + analyticsSent(analytics); + } + + [RequiredByNativeCode] + private static bool VideoClipImporterAnalyticsEventHandlerAttached_Internal() + { + return analyticsSent != null; + } + [NativeName("ClearTargetSettings")] internal extern void Internal_ClearTargetSettings(BuildTargetGroup group); diff --git a/Modules/Audio/Public/ScriptBindings/Audio.bindings.cs b/Modules/Audio/Public/ScriptBindings/Audio.bindings.cs index 3ab2555bc1..437abcfec1 100644 --- a/Modules/Audio/Public/ScriptBindings/Audio.bindings.cs +++ b/Modules/Audio/Public/ScriptBindings/Audio.bindings.cs @@ -330,6 +330,8 @@ static public bool Reset(AudioConfiguration config) public delegate void AudioConfigurationChangeHandler(bool deviceWasChanged); static public event AudioConfigurationChangeHandler OnAudioConfigurationChanged; + internal static event Action OnAudioSystemShuttingDown; + internal static event Action OnAudioSystemStartedUp; [RequiredByNativeCode] static internal void InvokeOnAudioConfigurationChanged(bool deviceWasChanged) @@ -338,6 +340,14 @@ static internal void InvokeOnAudioConfigurationChanged(bool deviceWasChanged) OnAudioConfigurationChanged(deviceWasChanged); } + [RequiredByNativeCode] + internal static void InvokeOnAudioSystemShuttingDown() + => OnAudioSystemShuttingDown?.Invoke(); + + [RequiredByNativeCode] + internal static void InvokeOnAudioSystemStartedUp() + => OnAudioSystemStartedUp?.Invoke(); + extern static internal bool unityAudioDisabled { [NativeName("IsAudioDisabled")] @@ -1224,6 +1234,12 @@ extern static public string[] devices get; } + internal static extern bool isAnyDeviceRecording + { + [NativeName("IsAnyRecordDeviceActive")] + get; + } + // Query if a device is currently recording. static public bool IsRecording(string deviceName) { diff --git a/Modules/Audio/Public/ScriptBindings/AudioSampleProviderExtensions.bindings.cs b/Modules/Audio/Public/ScriptBindings/AudioSampleProviderExtensions.bindings.cs new file mode 100644 index 0000000000..16af194e65 --- /dev/null +++ b/Modules/Audio/Public/ScriptBindings/AudioSampleProviderExtensions.bindings.cs @@ -0,0 +1,24 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Runtime.CompilerServices; +using UnityEngine.Bindings; + +[assembly: InternalsVisibleTo("Unity.Audio.Tests")] + +namespace UnityEngine.Experimental.Audio +{ + [NativeHeader("Modules/Audio/Public/ScriptBindings/AudioSampleProviderExtensions.bindings.h")] + [StaticAccessor("AudioSampleProviderExtensionsBindings", StaticAccessorType.DoubleColon)] + internal static class AudioSampleProviderExtensionsInternal + { + public static float GetSpeed(this AudioSampleProvider provider) + { + return InternalGetAudioSampleProviderSpeed(provider.id); + } + + [NativeMethod(IsThreadSafe = true, ThrowsException = true)] + private extern static float InternalGetAudioSampleProviderSpeed(uint providerId); + } +} diff --git a/Modules/Audio/Public/ScriptBindings/ExposeVivox.cs b/Modules/Audio/Public/ScriptBindings/ExposeVivox.cs new file mode 100644 index 0000000000..6cce0378c8 --- /dev/null +++ b/Modules/Audio/Public/ScriptBindings/ExposeVivox.cs @@ -0,0 +1,5 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("VivoxUnity")] diff --git a/Modules/BuildPipeline/Editor/Managed/BuildUsageTagGlobal.cs b/Modules/BuildPipeline/Editor/Managed/BuildUsageTagGlobal.cs index e0486e847e..3d11ca042b 100644 --- a/Modules/BuildPipeline/Editor/Managed/BuildUsageTagGlobal.cs +++ b/Modules/BuildPipeline/Editor/Managed/BuildUsageTagGlobal.cs @@ -19,6 +19,7 @@ public struct BuildUsageTagGlobal internal uint m_LegacyLightmapModesUsed; internal uint m_DynamicLightmapsUsed; internal uint m_FogModesUsed; + internal uint m_BrgShaderStripModeMask; internal bool m_ForceInstancingStrip; internal bool m_ForceInstancingKeep; internal bool m_ShadowMasksUsed; @@ -39,6 +40,7 @@ public struct BuildUsageTagGlobal results.m_ShadowMasksUsed = x.m_ShadowMasksUsed | y.m_ShadowMasksUsed; results.m_SubtractiveUsed = x.m_SubtractiveUsed | y.m_SubtractiveUsed; results.m_HybridRendererPackageUsed = x.m_HybridRendererPackageUsed | y.m_HybridRendererPackageUsed; + results.m_BrgShaderStripModeMask = x.m_BrgShaderStripModeMask | y.m_BrgShaderStripModeMask; results.m_BuildForLivelink = x.m_BuildForLivelink | y.m_BuildForLivelink; results.m_BuildForServer = x.m_BuildForServer | y.m_BuildForServer; return results; diff --git a/Modules/BuildReportingEditor/Managed/BuildReport.bindings.cs b/Modules/BuildReportingEditor/Managed/BuildReport.bindings.cs index 7b5b6c3dbd..10b4fe20cf 100644 --- a/Modules/BuildReportingEditor/Managed/BuildReport.bindings.cs +++ b/Modules/BuildReportingEditor/Managed/BuildReport.bindings.cs @@ -19,7 +19,10 @@ private BuildReport() { } - public extern BuildFile[] files { get; } + [System.Obsolete("Use GetFiles() method instead (UnityUpgradable) -> GetFiles()", true)] + public BuildFile[] files => throw new NotSupportedException(); + + public extern BuildFile[] GetFiles(); [NativeName("BuildSteps")] public extern BuildStep[] steps { get; } diff --git a/Modules/ClusterRenderer/ClusterSerialization.bindings.cs b/Modules/ClusterRenderer/ClusterSerialization.bindings.cs index 34de7a723d..a50b045234 100644 --- a/Modules/ClusterRenderer/ClusterSerialization.bindings.cs +++ b/Modules/ClusterRenderer/ClusterSerialization.bindings.cs @@ -60,22 +60,22 @@ public static bool RestoreClusterInputState(NativeArray buffer) } } - [FreeFunction("ClusterSerialization::SaveTimeManagerState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::SaveTimeManagerState")] private static extern unsafe int SaveTimeManagerStateInternal(void* intBuffer, int bufferSize); - [FreeFunction("ClusterSerialization::RestoreTimeManagerState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::RestoreTimeManagerState")] private static extern unsafe bool RestoreTimeManagerStateInternal(void* buffer, int bufferSize); - [FreeFunction("ClusterSerialization::SaveInputManagerState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::SaveInputManagerState")] private static extern unsafe int SaveInputManagerStateInternal(void* intBuffer, int bufferSize); - [FreeFunction("ClusterSerialization::RestoreInputManagerState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::RestoreInputManagerState")] private static extern unsafe bool RestoreInputManagerStateInternal(void* buffer, int bufferSize); - [FreeFunction("ClusterSerialization::SaveClusterInputState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::SaveClusterInputState")] private static extern unsafe int SaveClusterInputStateInternal(void* intBuffer, int bufferSize); - [FreeFunction("ClusterSerialization::RestoreClusterInputState", ThrowsException = true)] + [FreeFunction("ClusterSerialization::RestoreClusterInputState")] private static extern unsafe bool RestoreClusterInputStateInternal(void* buffer, int bufferSize); } } diff --git a/Modules/DeviceSimulatorEditor/DeviceInfo/DeviceLoader.cs b/Modules/DeviceSimulatorEditor/DeviceInfo/DeviceLoader.cs index 612e0fc6c9..c103ce0583 100644 --- a/Modules/DeviceSimulatorEditor/DeviceInfo/DeviceLoader.cs +++ b/Modules/DeviceSimulatorEditor/DeviceInfo/DeviceLoader.cs @@ -2,10 +2,9 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System; using System.Collections.Generic; using System.IO; -using UnityEditor; +using System.Linq; using UnityEngine; namespace UnityEditor.DeviceSimulation @@ -14,85 +13,17 @@ internal static class DeviceLoader { public static string[] s_BuiltInDevices = { - "Apple iPad (5th generation).device", - "Apple iPad (7th gen).device", - "Apple iPad 6th Gen.device", - "Apple iPad Air (4th generation).device", - "Apple iPad Air 2.device", - "Apple iPad Air.device", - "Apple iPad Mini 2.device", "Apple iPad Mini 4.device", - "Apple iPad Pro 10.15.device", - "Apple iPad Pro 11.device", "Apple iPad Pro 12.9 (2018).device", - "Apple iPhone 6.device", - "Apple iPhone 6S.device", - "Apple iPhone 7 Plus.device", - "Apple iPhone 7.device", - "Apple iPhone 8 Plus.device", - "Apple iPhone 8.device", - "Apple iPhone 11.device", "Apple iPhone 12 mini.device", "Apple iPhone 12 Pro Max.device", - "Apple iPhone 12 Pro.device", "Apple iPhone 12.device", "Apple iPhone SE (2nd generation).device", - "Apple iPhone X.device", - "Apple iPhone XR.device", - "Apple iPhone XS Max.device", - "Apple iPhone XS.device", - "Apple Ipod Touch 6th Gen.device", - "Apple iPod Touch 7th Gen.device", - "Asus ROG Phone.device", - "Google Nexus 4.device", - "Google Pixel 2 XL.device", - "Google Pixel 2.device", - "Google Pixel 3.device", - "Google Pixel 4.device", "Google Pixel 5.device", - "Google Pixel X.device", - "HTC 10.device", - "HTC One M9.device", - "Huawei P9.device", "Huawei P40 Pro.device", - "Lenovo Phab2 Pro.device", - "LG G4.device", - "LG Nexus 5.device", - "LGE LG G3.device", - "Motorola Moto E.device", - "Motorola Moto G7 Power.device", - "Motorola Nexus 6.device", - "Nvidia Shield Tablet.device", - "OnePlus 6T.device", - "OnePlus 7 Pro.device", - "Razer Phone.device", - "Samsung Galaxy J7 (2017).device", - "Samsung Galaxy Note8.device", - "Samsung Galaxy Note9.device", - "Samsung Galaxy Note10.device", - "Samsung Galaxy Note10+ 5G.device", "Samsung Galaxy Note20 Ultra 5G.device", - "Samsung Galaxy S5 Mini.device", - "Samsung Galaxy S5 Neo.device", - "Samsung Galaxy S7.device", - "Samsung Galaxy S8.device", - "Samsung Galaxy S9.device", - "Samsung Galaxy S10 5G.device", - "Samsung Galaxy S10+.device", "Samsung Galaxy S10e.device", - "Samsung Galaxy Z Fold2 5G.device", - "Sony Xperia XZ Premium.device", - "Sony Xperia Z2 Tablet.device", - "vivo NEX 3 5G.device", - "Xiaomi Mi 4i.device", - "Xiaomi Mi 5.device", - "Xiaomi Mi A3.device", - "Xiaomi MI Max.device", - "Xiaomi MI Note Pro.device", - "Xiaomi Redmi 4.device", - "Xiaomi Redmi 6 Pro.device", - "Xiaomi Redmi Note 3.device", - "Xiaomi Redmi Note7.device" + "Samsung Galaxy Z Fold2 5G.device" }; public static DeviceInfoAsset[] LoadDevices() @@ -115,12 +46,15 @@ public static DeviceInfoAsset[] LoadDevices() { var assetDirectory = "DeviceSimulator/DeviceAssets"; var deviceAsset = EditorGUIUtility.Load(Path.Combine(assetDirectory, assetName)) as DeviceInfoAsset; - if (deviceAsset != null && (deviceAsset.parseErrors == null || deviceAsset.parseErrors.Length == 0)) - { - deviceAsset.directory = assetDirectory; - deviceAsset.editorResource = true; - devices.Add(deviceAsset); - } + + // Devices that are not built-in will hide built-in devices with the same name. This way devices from packages can have + // updated or duplicate versions of the same device without causing duplicate devices to appear. + if (deviceAsset == null || deviceAsset.parseErrors != null && deviceAsset.parseErrors.Length != 0 || devices.Any(device => device.deviceInfo.friendlyName == deviceAsset.deviceInfo.friendlyName)) + continue; + + deviceAsset.directory = assetDirectory; + deviceAsset.editorResource = true; + devices.Add(deviceAsset); } devices.Sort((x, y) => string.CompareOrdinal(x.deviceInfo.friendlyName, y.deviceInfo.friendlyName)); diff --git a/Modules/GraphViewEditor/Elements/Node.cs b/Modules/GraphViewEditor/Elements/Node.cs index 320a018c00..2798e2ee92 100644 --- a/Modules/GraphViewEditor/Elements/Node.cs +++ b/Modules/GraphViewEditor/Elements/Node.cs @@ -184,7 +184,7 @@ private int ShowPorts(bool show, IList currentPorts) int count = 0; foreach (var port in currentPorts) { - if ((show || port.connected) && !port.collapsed) + if (port.alwaysVisible || (show || port.connected) && !port.collapsed) { SetElementVisible(port, true); count++; diff --git a/Modules/GraphViewEditor/Elements/Port.cs b/Modules/GraphViewEditor/Elements/Port.cs index 6e4e5d5dbb..d0c31140b1 100644 --- a/Modules/GraphViewEditor/Elements/Port.cs +++ b/Modules/GraphViewEditor/Elements/Port.cs @@ -53,6 +53,8 @@ public string portName set { m_ConnectorText.text = value; } } + internal bool alwaysVisible { get; set; } + private bool m_portCapLit; public bool portCapLit { diff --git a/Modules/IMGUI/Event.bindings.cs b/Modules/IMGUI/Event.bindings.cs index 7252863236..93f6b42f97 100644 --- a/Modules/IMGUI/Event.bindings.cs +++ b/Modules/IMGUI/Event.bindings.cs @@ -19,6 +19,9 @@ partial class Event [NativeProperty("button", false, TargetType.Field)] public extern int button { get; set; } [NativeProperty("modifiers", false, TargetType.Field)] public extern EventModifiers modifiers { get; set; } [NativeProperty("pressure", false, TargetType.Field)] public extern float pressure { get; set; } + [NativeProperty("twist", false, TargetType.Field)] public extern float twist { get; set; } + [NativeProperty("tilt", false, TargetType.Field)] public extern Vector2 tilt { get; set; } + [NativeProperty("penStatus", false, TargetType.Field)] public extern PenStatus penStatus { get; set; } [NativeProperty("clickCount", false, TargetType.Field)] public extern int clickCount { get; set; } [NativeProperty("character", false, TargetType.Field)] public extern char character { get; set; } [NativeProperty("keycode", false, TargetType.Field)] public extern KeyCode keyCode { get; set; } diff --git a/Modules/Input/Private/InputModule.bindings.cs b/Modules/Input/Private/InputModule.bindings.cs index d71dd6b576..b20adf3a68 100644 --- a/Modules/Input/Private/InputModule.bindings.cs +++ b/Modules/Input/Private/InputModule.bindings.cs @@ -16,8 +16,10 @@ internal partial class NativeInputSystem { internal static extern bool hasDeviceDiscoveredCallback { set; } + [NativeProperty(IsThreadSafe = true)] public static extern double currentTime { get; } + [NativeProperty(IsThreadSafe = true)] public static extern double currentTimeOffsetToRealtimeSinceStartup { get; } [FreeFunction("AllocateInputDeviceId")] @@ -31,6 +33,7 @@ public static unsafe void QueueInputEvent(ref TInputEvent inputEven QueueInputEvent((IntPtr)UnsafeUtility.AddressOf(ref inputEvent)); } + [NativeMethod(IsThreadSafe = true)] public static extern void QueueInputEvent(IntPtr inputEvent); public static extern long IOCTL(int deviceId, int code, IntPtr data, int sizeInBytes); diff --git a/Modules/InputLegacy/Input.bindings.cs b/Modules/InputLegacy/Input.bindings.cs index d9708e9e38..04a395d706 100644 --- a/Modules/InputLegacy/Input.bindings.cs +++ b/Modules/InputLegacy/Input.bindings.cs @@ -69,6 +69,35 @@ public struct Touch public float radiusVariance { get { return m_RadiusVariance; } set { m_RadiusVariance = value; } } } + // Matches PenData::PenStatusEnum in native code + [Flags] + public enum PenStatus + { + None = 0x0, + Contact = 0x1, + Barrel = 0x2, + Inverted = 0x4, + Eraser = 0x8, + } + + public enum PenEventType + { + NoContact, + PenDown, + PenUp + } + + public struct PenData + { + public Vector2 position; + public Vector2 tilt; + public PenStatus penStatus; + public float twist; + public float pressure; + public PenEventType contactType; + public Vector2 deltaPos; + } + public enum DeviceOrientation { Unknown = 0, @@ -298,6 +327,14 @@ public class Input [NativeThrows] public extern static Touch GetTouch(int index); [NativeThrows] + public extern static PenData GetPenEvent(int index); + [NativeThrows] + public extern static PenData GetLastPenContactEvent(); + [NativeThrows] + public extern static void ResetPenEvents(); + [NativeThrows] + public extern static void ClearLastPenContactEvent(); + [NativeThrows] public extern static AccelerationEvent GetAccelerationEvent(int index); public static bool GetKey(KeyCode key) @@ -364,6 +401,13 @@ public extern static bool mousePresent [FreeFunction("GetMousePresent")] get; } + + public extern static int penEventCount + { + [FreeFunction("GetPenEventCount")] + get; + } + public extern static int touchCount { [FreeFunction("GetTouchCount")] diff --git a/Modules/PackageManager/Editor/Managed/PackageInfo.cs b/Modules/PackageManager/Editor/Managed/PackageInfo.cs index 031443bfe4..6bcbbeed42 100644 --- a/Modules/PackageManager/Editor/Managed/PackageInfo.cs +++ b/Modules/PackageManager/Editor/Managed/PackageInfo.cs @@ -99,10 +99,6 @@ public sealed partial class PackageInfo [NativeName("author")] private AuthorInfo m_Author = new AuthorInfo(); - [SerializeField] - [NativeName("hasRegistry")] - private bool m_HasRegistry; - [SerializeField] [NativeName("registry")] private RegistryInfo m_Registry = new RegistryInfo(); @@ -155,6 +151,10 @@ public sealed partial class PackageInfo [NativeName("upmReserved")] private string m_UpmReserved = ""; + [SerializeField] + [NativeName("signature")] + private SignatureInfo m_Signature = new SignatureInfo(); + internal PackageInfo() {} public string packageId { get { return m_PackageId; } } @@ -187,14 +187,8 @@ internal PackageInfo() {} internal UnityLifecycleInfo unityLifecycle { get { return m_UnityLifecycle; } } internal string projectDependenciesEntry { get { return m_ProjectDependenciesEntry; } } internal string upmReserved { get { return m_UpmReserved; } } - - public RegistryInfo registry - { - get - { - return m_HasRegistry ? m_Registry : null; - } - } + public RegistryInfo registry { get { return m_Registry; } } + internal SignatureInfo signature { get { return m_Signature ; } } public DateTime? datePublished { diff --git a/Modules/PackageManager/Editor/Managed/SignatureInfo.cs b/Modules/PackageManager/Editor/Managed/SignatureInfo.cs new file mode 100644 index 0000000000..3a77ff1b83 --- /dev/null +++ b/Modules/PackageManager/Editor/Managed/SignatureInfo.cs @@ -0,0 +1,38 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Bindings; +using UnityEngine.Scripting; + +namespace UnityEditor.PackageManager +{ + [Serializable] + [StructLayout(LayoutKind.Sequential)] + [RequiredByNativeCode] + [NativeAsStruct] + internal class SignatureInfo + { + [SerializeField] + [NativeName("status")] + private SignatureStatus m_Status; + + [SerializeField] + [NativeName("reason")] + private string m_Reason; + + public SignatureStatus status => m_Status; + public string reason => m_Reason; + + internal SignatureInfo() : this(SignatureStatus.Unchecked, "") {} + + internal SignatureInfo(SignatureStatus status, string reason) + { + m_Status = status; + m_Reason = reason; + } + } +} diff --git a/Modules/PackageManager/Editor/Managed/SignatureStatus.cs b/Modules/PackageManager/Editor/Managed/SignatureStatus.cs new file mode 100644 index 0000000000..3d8debd282 --- /dev/null +++ b/Modules/PackageManager/Editor/Managed/SignatureStatus.cs @@ -0,0 +1,15 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +namespace UnityEditor.PackageManager +{ + internal enum SignatureStatus + { + Unchecked, + Valid, + Invalid, + Unsigned, + Error + } +} diff --git a/Modules/PackageManagerUI/Editor/Extensions/ExtensionManager.cs b/Modules/PackageManagerUI/Editor/Extensions/ExtensionManager.cs index f22953d765..23dd45ec5d 100644 --- a/Modules/PackageManagerUI/Editor/Extensions/ExtensionManager.cs +++ b/Modules/PackageManagerUI/Editor/Extensions/ExtensionManager.cs @@ -186,13 +186,19 @@ public virtual void OnWindowDestroy() m_EventDispatcher.SendWindowDestroyEvent(); m_DetailsExtensionContainer.Clear(); + m_DetailsExtensionContainer = null; m_DetailsExtensions.Clear(); + m_ToolbarExtensionContainer = null; + m_PackageActionContainer.Clear(); m_PackageActions.Clear(); m_PackageActionContainer.RemoveFromHierarchy(); m_CollapsedPackageActions.RemoveFromHierarchy(); + m_PackageActionContainer = null; + m_CollapsedPackageActions = null; + m_Window = null; } diff --git a/Modules/PackageManagerUI/Editor/Extensions/PackageSelectionArgs.cs b/Modules/PackageManagerUI/Editor/Extensions/PackageSelectionArgs.cs index d3880707b9..03d5a84749 100644 --- a/Modules/PackageManagerUI/Editor/Extensions/PackageSelectionArgs.cs +++ b/Modules/PackageManagerUI/Editor/Extensions/PackageSelectionArgs.cs @@ -10,15 +10,20 @@ namespace UnityEditor.PackageManager.UI internal struct PackageSelectionArgs { /// - /// The selected package + /// The selected package, it will be set to null when there are multiple packages selected /// public IPackage package { get; internal set; } /// - /// The selected package version + /// The selected package version, it will be set to null when there are multiple packages selected /// public IPackageVersion packageVersion { get; internal set; } + /// + /// The selected package versions + /// + public IPackageVersion[] versions { get; internal set; } + /// /// The handle to the Package Manager window /// diff --git a/Modules/PackageManagerUI/Editor/External/EditorGameServiceExtension.cs b/Modules/PackageManagerUI/Editor/External/EditorGameServiceExtension.cs new file mode 100644 index 0000000000..465032515f --- /dev/null +++ b/Modules/PackageManagerUI/Editor/External/EditorGameServiceExtension.cs @@ -0,0 +1,223 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace UnityEditor.PackageManager.UI.Internal +{ + internal class EditorGameServiceExtension : IWindowCreatedHandler, IPackageSelectionChangedHandler + { + public interface ICloudProjectSettings + { + string organizationKey { get; } + string projectId { get; } + } + + internal class CloudProjectSettings : ICloudProjectSettings + { + public string organizationKey => UnityEditor.CloudProjectSettings.organizationKey; + public string projectId => UnityEditor.CloudProjectSettings.projectId; + } + + const string k_GameService = "gameService"; + const string k_ConfigurePath = "configurePath"; + const string k_UseCasesUrl = "useCasesUrl"; + const string k_GenericDashboardUrl = "genericDashboardUrl"; + const string k_ProjectDashboardUrl = "projectDashboardUrl"; + const string k_ProjectDashboardUrlType = "projectDashboardUrlType"; + const string k_OrganizationKeyAndProjectGuid = "OrganizationKeyAndProjectGuid"; + const string k_OrganizationKey = "OrganizationKey"; + const string k_ProjectGuid = "ProjectGuid"; + const string k_PageContentType = "packages and features"; + internal const string k_ServicesConfigPath = "Resources/services.json"; + + internal const int k_ToolsPriority = 100; + internal const int k_ServicesPriority = 200; + + internal static Dictionary groupIndexes = new Dictionary(); + static Dictionary s_GroupMap = new Dictionary(); + internal static ICloudProjectSettings cloudProjectSettings = new CloudProjectSettings(); + + internal static bool FilterToolsPackage(IPackage package) + { + return package?.Is(PackageType.Unity) == true && !FilterServicesPackage(package); + } + + internal static string GetToolsPackageGroupName(IPackage package) + { + return package?.Is(PackageType.Feature) == true ? L10n.Tr("Features") : L10n.Tr("Packages"); + } + + internal static bool FilterServicesPackage(IPackage package) + { + return !string.IsNullOrWhiteSpace(GetServicesPackageGroupName(package)); + } + + internal static string GetServicesPackageGroupName(IPackage package) + { + if (s_GroupMap == null || string.IsNullOrWhiteSpace(package.name) || !s_GroupMap.ContainsKey(package.name)) + return string.Empty; + return s_GroupMap[package.name]; + } + + internal static Dictionary GetEditorGameServiceField(PackageInfo packageInfo) + { + var upmCache = ServicesContainer.instance.Resolve(); + var upmReserved = upmCache.ParseUpmReserved(packageInfo); + if (upmReserved == null) + return null; + if (!upmReserved.ContainsKey(k_GameService)) + return null; + return upmReserved[k_GameService] as Dictionary; + } + + internal static int CompareGroup(string groupA, string groupB) + { + groupIndexes.TryGetValue(groupA, out var indexA); + groupIndexes.TryGetValue(groupB, out var indexB); + return indexA - indexB; + } + + IPackageActionButton m_ConfigureButton; + + public void OnWindowCreated(WindowCreatedArgs args) + { + var configPath = Path.Combine(EditorApplication.applicationContentsPath, k_ServicesConfigPath); + LoadServicesConfig(configPath); + + var pageManager = ServicesContainer.instance.Resolve(); + + pageManager.AddSubPage(PackageFilterTab.UnityRegistry, "tools", L10n.Tr("Tools"), L10n.Tr(k_PageContentType), k_ToolsPriority, FilterToolsPackage, GetToolsPackageGroupName); + pageManager.AddSubPage(PackageFilterTab.UnityRegistry, "services", L10n.Tr("Services"), L10n.Tr(k_PageContentType), k_ServicesPriority, FilterServicesPackage, GetServicesPackageGroupName, CompareGroup); + + pageManager.AddSubPage(PackageFilterTab.InProject, "tools", L10n.Tr("Tools"), L10n.Tr(k_PageContentType), k_ToolsPriority, FilterToolsPackage, GetToolsPackageGroupName); + pageManager.AddSubPage(PackageFilterTab.InProject, "services", L10n.Tr("Services"), L10n.Tr(k_PageContentType), k_ServicesPriority, FilterServicesPackage, GetServicesPackageGroupName, CompareGroup); + + m_ConfigureButton = args.window.AddPackageActionButton(); + m_ConfigureButton.text = L10n.Tr("Configure"); + m_ConfigureButton.action += OnConfigureClicked; + } + + internal bool LoadServicesConfig(string configPath) + { + var configLoaded = false; + + if (File.Exists(configPath)) + { + var jsonString = File.ReadAllText(configPath); + try + { + var configuration = JsonUtility.FromJson(jsonString); + if (configuration != null) + { + configLoaded = true; + foreach (var serviceGrouping in configuration.serviceGroupings) + { + groupIndexes[serviceGrouping.name] = serviceGrouping.index; + foreach (var package in serviceGrouping.packages) + { + s_GroupMap[package] = serviceGrouping.name; + } + } + } + } + catch (Exception) + { + configLoaded = false; + } + } + + return configLoaded; + } + + public void OnPackageSelectionChanged(PackageSelectionArgs args) + { + var packageInfo = args.packageVersion?.packageInfo; + var editorGameService = GetEditorGameServiceField(packageInfo); + var configurePath = GetConfigurePathField(editorGameService); + m_ConfigureButton.visible = !string.IsNullOrEmpty(configurePath); + m_ConfigureButton.enabled = args.packageVersion?.isInstalled ?? false; + } + + private static void OnConfigureClicked(PackageSelectionArgs args) + { + var database = ServicesContainer.instance.Resolve(); + var package = database.GetPackage(args.package.uniqueId); + var installedVersion = package?.versions?.installed; + if (installedVersion == null) + return; + + var editorGameService = GetEditorGameServiceField(installedVersion.packageInfo); + var configurePath = GetConfigurePathField(editorGameService); + if (!string.IsNullOrEmpty(configurePath)) + PackageManagerWindowAnalytics.SendEvent("configureService", args.package.uniqueId); + SettingsService.OpenProjectSettings(configurePath); + } + + internal static string GetConfigurePathField(Dictionary editorGameService) + { + if (editorGameService == null || !editorGameService.ContainsKey(k_ConfigurePath)) + return string.Empty; + return editorGameService[k_ConfigurePath] as string; + } + + public static string GetDashboardUrl(IPackageVersion version) + { + var editorGameService = GetEditorGameServiceField(version?.packageInfo); + if (editorGameService == null) + return string.Empty; + + if (editorGameService.ContainsKey(k_ProjectDashboardUrl)) + { + var dashboardUrl = editorGameService[k_ProjectDashboardUrl] as string; + + if (!string.IsNullOrEmpty(dashboardUrl)) + { + if (editorGameService.ContainsKey(k_ProjectDashboardUrlType)) + { + var dashboardUrlType = editorGameService[k_ProjectDashboardUrlType] as string; + switch (dashboardUrlType) + { + case k_OrganizationKeyAndProjectGuid: + if (!string.IsNullOrEmpty(cloudProjectSettings.projectId) && + !string.IsNullOrEmpty(cloudProjectSettings.organizationKey)) + { + return string.Format(dashboardUrl, cloudProjectSettings.organizationKey, cloudProjectSettings.projectId); + } + break; + case k_OrganizationKey: + if (!string.IsNullOrEmpty(cloudProjectSettings.organizationKey)) + { + return string.Format(dashboardUrl, cloudProjectSettings.organizationKey); + } + break; + case k_ProjectGuid: + if (!string.IsNullOrEmpty(cloudProjectSettings.projectId)) + { + return string.Format(dashboardUrl, cloudProjectSettings.projectId); + } + break; + } + } + } + } + + if (editorGameService.ContainsKey(k_GenericDashboardUrl)) + return editorGameService[k_GenericDashboardUrl] as string; + + return string.Empty; + } + + public static string GetUseCasesUrl(IPackageVersion version) + { + var editorGameService = GetEditorGameServiceField(version?.packageInfo); + if (editorGameService == null || !editorGameService.ContainsKey(k_UseCasesUrl)) + return string.Empty; + return editorGameService[k_UseCasesUrl] as string; + } + } +} diff --git a/Modules/PackageManagerUI/Editor/External/ServicesTab/ServiceGroupingsWrapper.cs b/Modules/PackageManagerUI/Editor/External/ServicesTab/ServiceGroupingsWrapper.cs new file mode 100644 index 0000000000..cea801aebc --- /dev/null +++ b/Modules/PackageManagerUI/Editor/External/ServicesTab/ServiceGroupingsWrapper.cs @@ -0,0 +1,17 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + class ServiceGroupingsWrapper + { + public string name; + public int index; + public List packages; + } +} diff --git a/Modules/PackageManagerUI/Editor/External/ServicesTab/ServicesTabConfiguration.cs b/Modules/PackageManagerUI/Editor/External/ServicesTab/ServicesTabConfiguration.cs new file mode 100644 index 0000000000..e26a6b6182 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/External/ServicesTab/ServicesTabConfiguration.cs @@ -0,0 +1,16 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + class ServicesTabConfiguration + { + public List serviceGroupings; + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreCache.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreCache.cs index 85e3750475..06993cee92 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreCache.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreCache.cs @@ -193,17 +193,17 @@ public virtual void ClearCache() public virtual AssetStorePurchaseInfo GetPurchaseInfo(string productIdString) { - return m_PurchaseInfos.Get(productIdString); + return productIdString != null ? m_PurchaseInfos.Get(productIdString) : null; } public virtual AssetStoreProductInfo GetProductInfo(string productIdString) { - return m_ProductInfos.Get(productIdString); + return productIdString != null ? m_ProductInfos.Get(productIdString) : null; } public virtual AssetStoreLocalInfo GetLocalInfo(string productIdString) { - return m_LocalInfos.Get(productIdString); + return productIdString != null ? m_LocalInfos.Get(productIdString) : null; } public virtual void SetPurchaseInfo(AssetStorePurchaseInfo info) diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreClient.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreClient.cs index 0e3d25017e..31717a4c05 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreClient.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreClient.cs @@ -24,6 +24,8 @@ internal class AssetStoreClient public virtual event Action onListOperation = delegate {}; + public virtual event Action> onUpdateChecked = delegate {}; + [SerializeField] private AssetStoreListOperation m_ListOperation; @@ -143,7 +145,7 @@ private void FetchInternal(long productId, AssetStorePurchaseInfo purchaseInfo) // create a placeholder before fetching data from the cloud for the first time if (m_AssetStoreCache.GetProductInfo(id) == null) - onPackagesChanged?.Invoke(new[] { new PlaceholderPackage(id, purchaseInfo?.displayName ?? string.Empty, PackageType.AssetStore, PackageTag.None, PackageProgress.Refreshing) }); + onPackagesChanged?.Invoke(new[] { new PlaceholderPackage(id, purchaseInfo?.displayName ?? string.Empty, PackageType.AssetStore, PackageTag.Downloadable, PackageProgress.Refreshing) }); FetchDetails(new[] { productId }); onProductFetched?.Invoke(productId); @@ -171,7 +173,7 @@ public virtual void ListPurchases(PurchasesQueryArgs queryArgs) // create a placeholder before fetching data from the cloud for the first time var productInfo = m_AssetStoreCache.GetProductInfo(productIdString); if (productInfo == null) - updatedPackages.Add(new PlaceholderPackage(productIdString, purchaseInfo.displayName, PackageType.AssetStore, PackageTag.None, PackageProgress.Refreshing)); + updatedPackages.Add(new PlaceholderPackage(productIdString, purchaseInfo.displayName, PackageType.AssetStore, PackageTag.Downloadable, PackageProgress.Refreshing)); else if (oldPurchaseInfo != null) { // for now, `tags` is the only component in `purchase info` that can be updated over time, so we only check for changes there @@ -231,7 +233,7 @@ public virtual void FetchDetail(long productId, Action doneCallbackAct var purchaseInfo = m_AssetStoreCache.GetPurchaseInfo(idString); m_AssetStoreCache.RemoveProductInfo(idString); var uiError = new UIError(UIErrorCode.AssetStoreClientError, error); - package = new PlaceholderPackage(idString, purchaseInfo?.displayName ?? string.Empty, PackageType.AssetStore, PackageTag.None, PackageProgress.None, uiError); + package = new PlaceholderPackage(idString, purchaseInfo?.displayName ?? string.Empty, PackageType.AssetStore, PackageTag.Downloadable, PackageProgress.None, uiError); } if (package != null) @@ -367,6 +369,7 @@ public virtual void CheckUpdate(IEnumerable productIds, Action doneCallb } } } + onUpdateChecked?.Invoke(productIds); } doneCallbackAction?.Invoke(); }); diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadManager.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadManager.cs index 2d0d996c27..f0afa27a3c 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadManager.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadManager.cs @@ -5,10 +5,14 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEditorInternal; using UnityEngine; namespace UnityEditor.PackageManager.UI.Internal { + using CachePathConfig = AssetStoreCachePathManager.CachePathConfig; + using ConfigStatus = AssetStoreCachePathManager.ConfigStatus; + [Serializable] internal class AssetStoreDownloadManager : ISerializationCallbackReceiver { @@ -36,13 +40,16 @@ internal class AssetStoreDownloadManager : ISerializationCallbackReceiver private AssetStoreUtils m_AssetStoreUtils; [NonSerialized] private AssetStoreRestAPI m_AssetStoreRestAPI; + [NonSerialized] + private AssetStoreCachePathProxy m_AssetStoreCachePathProxy; public void ResolveDependencies(ApplicationProxy application, HttpClientFactory httpClientFactory, UnityConnectProxy unityConnect, IOProxy ioProxy, AssetStoreCache assetStoreCache, AssetStoreUtils assetStoreUtils, - AssetStoreRestAPI assetStoreRestAPI) + AssetStoreRestAPI assetStoreRestAPI, + AssetStoreCachePathProxy assetStoreCachePathProxy) { m_Application = application; m_UnityConnect = unityConnect; @@ -51,9 +58,10 @@ public void ResolveDependencies(ApplicationProxy application, m_AssetStoreCache = assetStoreCache; m_AssetStoreUtils = assetStoreUtils; m_AssetStoreRestAPI = assetStoreRestAPI; + m_AssetStoreCachePathProxy = assetStoreCachePathProxy; foreach (var operation in m_DownloadOperations.Values) - operation.ResolveDependencies(assetStoreUtils, assetStoreRestAPI); + operation.ResolveDependencies(assetStoreUtils, assetStoreRestAPI, m_AssetStoreCachePathProxy); } // The AssetStoreDownloadManager implementation requires the help of a ScriptableObject to dispatch download progress event. @@ -116,6 +124,11 @@ public virtual bool IsAnyDownloadInProgress() return m_DownloadOperations.Values.Any(d => d.isInProgress); } + public virtual bool IsAnyDownloadInProgressOrPause() + { + return m_DownloadOperations.Values.Any(d => d.isInProgress || d.isInPause); + } + public virtual void Download(IPackage package) { var packageId = package?.uniqueId; @@ -127,7 +140,7 @@ public virtual void Download(IPackage package) if (operation?.isInProgress ?? false) return; - operation = new AssetStoreDownloadOperation(m_AssetStoreUtils, m_AssetStoreRestAPI, packageId, v?.localPath); + operation = new AssetStoreDownloadOperation(m_AssetStoreUtils, m_AssetStoreRestAPI, m_AssetStoreCachePathProxy, packageId, v?.localPath); SetupDownloadOperation(operation); operation.Download(false); } @@ -197,9 +210,10 @@ public virtual void OnDownloadProgress(string downloadId, string message, ulong public virtual void AbortAllDownloads() { - foreach (var operation in m_DownloadOperations.Values) - operation.Abort(); + var operations = m_DownloadOperations.Values.ToList(); m_DownloadOperations.Clear(); + foreach (var operation in operations) + operation.Cancel(); } public virtual void AbortDownload(string productId) @@ -231,6 +245,7 @@ public void OnEnable() { m_Application.onPlayModeStateChanged += OnPlayModeStateChanged; m_UnityConnect.onUserLoginStateChange += OnUserLoginStateChange; + m_AssetStoreCachePathProxy.onConfigChanged += OnAssetStoreCacheConfigChange; if (m_UnityConnect.isUserLoggedIn) RegisterDownloadDelegate(); } @@ -255,6 +270,19 @@ private void OnUserLoginStateChange(bool userInfoReady, bool loggedIn) } } + private void OnAssetStoreCacheConfigChange(CachePathConfig config) + { + if ((config.status == ConfigStatus.Success || config.status == ConfigStatus.ReadOnly) && IsAnyDownloadInProgressOrPause()) + { + if (!m_Application.isBatchMode) + m_Application.DisplayDialog(L10n.Tr("Package Manager"), + L10n.Tr("The Assets Cache location has been changed, all current downloads will be aborted."), + L10n.Tr("Ok")); + + AbortAllDownloads(); + } + } + public void OnBeforeSerialize() { m_SerializedDownloadOperations = m_DownloadOperations.Values.ToArray(); diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadOperation.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadOperation.cs index b2bf531c9f..14a5ea7bf1 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreDownloadOperation.cs @@ -4,19 +4,21 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using UnityEngine; namespace UnityEditor.PackageManager.UI.Internal { + using ConfigStatus = UnityEditorInternal.AssetStoreCachePathManager.ConfigStatus; + [Serializable] internal class AssetStoreDownloadOperation : IOperation { - internal static readonly string k_DownloadErrorMessage = L10n.Tr("The download could not be completed. Please try again."); + internal static readonly string k_DownloadErrorMessage = L10n.Tr("The download could not be completed. See details in console."); internal static readonly string k_AbortErrorMessage = L10n.Tr("The download could not be aborted. Please try again."); internal static readonly string k_AssetStoreDownloadPrefix = "content__"; internal static readonly string k_ForbiddenErrorMessage = L10n.Tr("The Asset Store package you are trying to download is not available to the current Unity account. If you purchased this asset from the Asset Store using a different account, use that Unity account to sign into the Editor."); private static readonly string k_ConsoleLogPrefix = L10n.Tr("[Package Manager Window]"); + [SerializeField] private string m_ProductId; public string packageUniqueId => m_ProductId; @@ -77,20 +79,24 @@ internal class AssetStoreDownloadOperation : IOperation private AssetStoreUtils m_AssetStoreUtils; [NonSerialized] private AssetStoreRestAPI m_AssetStoreRestAPI; + [NonSerialized] + private AssetStoreCachePathProxy m_AssetStoreCachePathProxy; public void ResolveDependencies(AssetStoreUtils assetStoreUtils, - AssetStoreRestAPI assetStoreRestAPI) + AssetStoreRestAPI assetStoreRestAPI, + AssetStoreCachePathProxy assetStoreCachePathProxy) { m_AssetStoreUtils = assetStoreUtils; m_AssetStoreRestAPI = assetStoreRestAPI; + m_AssetStoreCachePathProxy = assetStoreCachePathProxy; } private AssetStoreDownloadOperation() { } - public AssetStoreDownloadOperation(AssetStoreUtils assetStoreUtils, AssetStoreRestAPI assetStoreRestAPI, string productId, string oldPath) + public AssetStoreDownloadOperation(AssetStoreUtils assetStoreUtils, AssetStoreRestAPI assetStoreRestAPI, AssetStoreCachePathProxy assetStoreCachePathProxy, string productId, string oldPath) { - ResolveDependencies(assetStoreUtils, assetStoreRestAPI); + ResolveDependencies(assetStoreUtils, assetStoreRestAPI, assetStoreCachePathProxy); m_ProductId = productId; m_ProductOldPath = oldPath; @@ -140,12 +146,15 @@ public void OnDownloadProgress(string message, ulong bytes, ulong total, int err onOperationProgress?.Invoke(this); } - private void OnErrorMessage(string errorMessage, int operationErrorCode = -1) + private void OnErrorMessage(string errorMessage, int operationErrorCode = -1, UIError.Attribute attr = UIError.Attribute.None) { m_State = DownloadState.Error; - Debug.LogError($"{k_ConsoleLogPrefix} {errorMessage}"); - var attr = UIError.Attribute.None; + if ((attr & UIError.Attribute.IsWarning) != 0) + Debug.LogWarning($"{k_ConsoleLogPrefix} {errorMessage}"); + else + Debug.LogError($"{k_ConsoleLogPrefix} {errorMessage}"); + if (operationErrorCode == 403) { m_ErrorMessage = k_ForbiddenErrorMessage; @@ -175,6 +184,17 @@ public void Pause() Debug.LogError($"{k_ConsoleLogPrefix} {k_AbortErrorMessage}"); } + public void Cancel() + { + if (downloadInfo?.isValid != true) + return; + + m_AssetStoreUtils.AbortDownload(downloadInfo.destination); + m_DownloadedBytes = 0; + m_State = DownloadState.None; + onOperationFinalized?.Invoke(this); + } + public void Abort() { if (downloadInfo?.isValid != true) @@ -199,6 +219,18 @@ public void Abort() public void Download(bool resume) { + var config = m_AssetStoreCachePathProxy.GetConfig(); + if (config.status == ConfigStatus.ReadOnly) + { + OnErrorMessage("The Assets Cache location is read-only, see configuration in Preferences | Package Manager", -1, UIError.Attribute.IsWarning); + return; + } + if (config.status == ConfigStatus.InvalidPath) + { + OnErrorMessage("The Assets Cache location is invalid or inaccessible, see configuration in Preferences | Package Manager", -1, UIError.Attribute.IsWarning); + return; + } + m_State = resume ? DownloadState.ResumeRequested : DownloadState.DownloadRequested; var productId = long.Parse(m_ProductId); m_AssetStoreRestAPI.GetDownloadDetail(productId, downloadInfo => diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreOAuth.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreOAuth.cs index c143ee00fb..47c3b078b8 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreOAuth.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStoreOAuth.cs @@ -256,7 +256,7 @@ private void GetAuthCode(Action doneCallback) } else { - OnOperationError(authCodeResponse.Exception.ToString()); + OnOperationError(string.Format(L10n.Tr("Error while getting auth code: {0}"), authCodeResponse.Exception.ToString())); } }); } @@ -264,7 +264,7 @@ private void GetAuthCode(Action doneCallback) { m_AuthCode = string.Empty; m_AuthCodeRequested = false; - OnOperationError(e.Message); + OnOperationError(string.Format(L10n.Tr("Error while getting auth code: {0}"), e.Message)); } } @@ -279,65 +279,38 @@ private void GetAccessToken(Action doneCallback) // Use refresh token if any if (!string.IsNullOrEmpty(m_AccessToken?.refreshToken)) { - RefreshAccessToken(doneCallback); + GetAccessToken(doneCallback, refreshToken: m_AccessToken.refreshToken); return; } GetAuthCode(authCode => { - GetNewAccessToken(doneCallback, authCode); + GetAccessToken(doneCallback, authCode: authCode); }); } - private void GetNewAccessToken(Action doneCallback, string authCode) + private void GetAccessToken(Action doneCallback, string authCode = null, string refreshToken = null) { m_OnAccessTokenFetched += doneCallback; if (m_AccessTokenRequest != null) return; - m_AccessTokenRequest = m_HttpClientFactory.PostASyncHTTPClient( - $"{host}{k_OAuthUri}", - $"grant_type=authorization_code&code={authCode}&client_id={k_ServiceId}&client_secret={secret}"); - m_AccessTokenRequest.header["Content-Type"] = "application/x-www-form-urlencoded"; - m_AccessTokenRequest.doneCallback = httpClient => + if (string.IsNullOrEmpty(secret)) { - m_AccessTokenRequest = null; - m_AccessToken = null; - - var response = AssetStoreUtils.ParseResponseAsDictionary(httpClient); - if (response != null) - { - if (response.ContainsKey("errorMessage")) - { - OnGetAccessTokenError(response.GetString("errorMessage")); - return; - } - - var accessToken = new AccessToken(response); - if (accessToken.IsValid()) - { - m_AccessToken = accessToken; - m_OnAccessTokenFetched?.Invoke(m_AccessToken); - m_OnAccessTokenFetched = null; - } - else - OnGetAccessTokenError(L10n.Tr("Access token invalid")); - } - }; - m_AccessTokenRequest.Begin(); - } - - private void RefreshAccessToken(Action doneCallback) - { - m_OnAccessTokenFetched += doneCallback; + OnGetAccessTokenError(L10n.Tr("Error while getting access token: invalid configuration from Unity Connect")); + return; + } - if (m_AccessTokenRequest != null) + var authorization = string.Empty; + if (!string.IsNullOrEmpty(authCode)) + authorization = $"grant_type=authorization_code&code={authCode}"; + else if (!string.IsNullOrEmpty(refreshToken)) + authorization = $"grant_type=refresh_token&refresh_token={refreshToken}"; + else return; - m_AccessTokenRequest = m_HttpClientFactory.PostASyncHTTPClient( - $"{host}{k_OAuthUri}", - $"grant_type=refresh_token&refresh_token={m_AccessToken.refreshToken}&client_id={k_ServiceId}&client_secret={secret}"); + m_AccessTokenRequest = m_HttpClientFactory.PostASyncHTTPClient($"{host}{k_OAuthUri}", $"{authorization}&client_id={k_ServiceId}&client_secret={secret}"); m_AccessTokenRequest.header["Content-Type"] = "application/x-www-form-urlencoded"; m_AccessTokenRequest.doneCallback = httpClient => { @@ -349,7 +322,7 @@ private void RefreshAccessToken(Action doneCallback) { if (response.ContainsKey("errorMessage")) { - OnGetAccessTokenError(response.GetString("errorMessage")); + OnGetAccessTokenError(string.Format(L10n.Tr("Error while getting access token: {0}"), response.GetString("errorMessage"))); return; } @@ -393,7 +366,7 @@ private void GetTokenInfo(Action doneCallback) { if (response.ContainsKey("errorMessage")) { - OnOperationError(response.GetString("errorMessage")); + OnOperationError(string.Format(L10n.Tr("Error while getting token info: {0}"), response.GetString("errorMessage"))); return; } @@ -405,7 +378,7 @@ private void GetTokenInfo(Action doneCallback) m_OnTokenInfoFetched = null; } else - OnOperationError(L10n.Tr("TokenInfo invalid")); + OnOperationError(L10n.Tr("Token info invalid")); } }; m_TokenRequest.Begin(); @@ -440,7 +413,7 @@ private void GetUserInfo(Action doneCallback) { if (response.ContainsKey("errorMessage")) { - OnOperationError(response.GetString("errorMessage")); + OnOperationError(string.Format(L10n.Tr("Error while getting user info: {0}"), response.GetString("errorMessage"))); return; } @@ -455,7 +428,7 @@ private void GetUserInfo(Action doneCallback) m_OnError = null; } else - OnOperationError(L10n.Tr("UserInfo invalid")); + OnOperationError(L10n.Tr("User info invalid")); } }; m_UserInfoRequest.Begin(); @@ -472,7 +445,8 @@ private void OnGetAccessTokenError(string errorMessage) private void OnOperationError(string errorMessage) { - m_OnError?.Invoke(new UIError(UIErrorCode.AssetStoreAuthorizationError, errorMessage)); + Debug.LogError(string.Format(L10n.Tr("[Package Manager Window] {0}"), errorMessage)); + m_OnError?.Invoke(new UIError(UIErrorCode.AssetStoreAuthorizationError, errorMessage, UIError.Attribute.IsDetailInConsole)); m_OnError = null; } } diff --git a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStorePackage.cs b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStorePackage.cs index fe6cee6606..2ddc0b6557 100644 --- a/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStorePackage.cs +++ b/Modules/PackageManagerUI/Editor/Services/AssetStore/AssetStorePackage.cs @@ -71,6 +71,8 @@ public AssetStorePackage(AssetStoreUtils assetStoreUtils, IOProxy ioProxy, strin m_Labels = new List(); m_PurchasedTimeTicks = 0; + + LinkPackageAndVersions(); } public AssetStorePackage(AssetStoreUtils assetStoreUtils, IOProxy ioProxy, AssetStorePurchaseInfo purchaseInfo, AssetStoreProductInfo productInfo, AssetStoreLocalInfo localInfo = null) @@ -116,6 +118,8 @@ public AssetStorePackage(AssetStoreUtils assetStoreUtils, IOProxy ioProxy, Asset } m_VersionList.AddVersion(latestVersion); } + + LinkPackageAndVersions(); } public AssetStorePackage(AssetStoreUtils assetStoreUtils, IOProxy ioProxy, AssetStorePurchaseInfo purchaseInfo, AssetStoreProductInfo productInfo, UpmPackage package) @@ -154,11 +158,15 @@ public AssetStorePackage(AssetStoreUtils assetStoreUtils, IOProxy ioProxy, Asset AddError(new UIError(UIErrorCode.AssetStorePackageError, L10n.Tr("Unable to retrieve asset product details."))); else if (string.IsNullOrEmpty(package?.name)) AddError(new UIError(UIErrorCode.AssetStorePackageError, L10n.Tr("Unable to retrieve asset package info."))); + + LinkPackageAndVersions(); } public override IPackage Clone() { - return (IPackage)MemberwiseClone(); + var clone = (BasePackage)MemberwiseClone(); + clone.LinkPackageAndVersions(); + return clone; } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Common/BasePackage.cs b/Modules/PackageManagerUI/Editor/Services/Common/BasePackage.cs index 4603ed0254..d2efecce29 100644 --- a/Modules/PackageManagerUI/Editor/Services/Common/BasePackage.cs +++ b/Modules/PackageManagerUI/Editor/Services/Common/BasePackage.cs @@ -23,14 +23,20 @@ public PackageState state if (progress != PackageProgress.None) return PackageState.InProgress; - if (errors.Any()) + var numErrors = 0; + var numWarnings = 0; + foreach (var error in GetAllErrorsInPackageAndVersions()) { - if (errors.All(error => error.attribute == UIError.Attribute.IsWarning)) - return PackageState.Warning; - else if (errors.Any(error => !error.HasAttribute(UIError.Attribute.IsClearable))) + ++numErrors; + if (error.attribute == UIError.Attribute.IsWarning) + ++numWarnings; + else if (!error.HasAttribute(UIError.Attribute.IsClearable)) return PackageState.Error; } + if (numErrors > 0 && numWarnings == numErrors) + return PackageState.Warning; + var primary = versions.primary; var recommended = versions.recommended; var latestKeyVersion = versions.key.LastOrDefault(); @@ -68,15 +74,16 @@ public PackageProgress progress [SerializeField] protected List m_Errors; - // Combined errors for this package or any version. - // Stop lookup after first error encountered on a version to save time not looking up redundant errors. - public IEnumerable errors + public IEnumerable errors => m_Errors ?? Enumerable.Empty(); + + private IEnumerable GetAllErrorsInPackageAndVersions() { - get - { - var versionErrors = versions.Select(v => v.errors).FirstOrDefault(e => e?.Any() ?? false) ?? Enumerable.Empty(); - return m_Errors == null ? versionErrors : m_Errors.Concat(versionErrors); - } + if (m_Errors != null) + foreach (var error in m_Errors) + yield return error; + foreach (var version in versions.Where(v => v.errors != null)) + foreach (var versionError in version.errors) + yield return versionError; } public bool hasEntitlements => Is(PackageType.Unity) && versions.Any(version => version.hasEntitlements); @@ -134,5 +141,11 @@ public string GetDescriptor(bool isFirstLetterCapitalized = false) { return isFirstLetterCapitalized ? descriptor.First().ToString().ToUpper() + descriptor.Substring(1) : descriptor; } + + public void LinkPackageAndVersions() + { + foreach (var version in versions) + version.package = this; + } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Common/BasePackageVersion.cs b/Modules/PackageManagerUI/Editor/Services/Common/BasePackageVersion.cs index 707ec6e0ae..93931daf19 100644 --- a/Modules/PackageManagerUI/Editor/Services/Common/BasePackageVersion.cs +++ b/Modules/PackageManagerUI/Editor/Services/Common/BasePackageVersion.cs @@ -48,6 +48,17 @@ internal abstract class BasePackageVersion : IPackageVersion, ISerializationCall public DependencyInfo[] resolvedDependencies => packageInfo?.resolvedDependencies; public EntitlementsInfo entitlements => packageInfo?.entitlements; + public virtual RegistryInfo registry => null; + + [NonSerialized] + private IPackage m_Package; + public UI.IPackage package => m_Package; + IPackage IPackageVersion.package + { + get => m_Package; + set { m_Package = value; } + } + [SerializeField] protected PackageTag m_Tag; public bool HasTag(PackageTag tag) @@ -89,6 +100,14 @@ public bool hasEntitlementsError public abstract string versionId { get; } public virtual bool isUnityPackage => false; + public bool IsDifferentVersionThanRequested + => !string.IsNullOrEmpty(packageInfo?.projectDependenciesEntry) && !HasTag(PackageTag.Git | PackageTag.Local | PackageTag.Custom) && + packageInfo.projectDependenciesEntry != versionString; + + public bool IsRequestedButOverriddenVersion + => !string.IsNullOrEmpty(versionString) && !isInstalled && + versionString == m_Package?.versions.primary.packageInfo?.projectDependenciesEntry; + public virtual void OnBeforeSerialize() { // Do nothing diff --git a/Modules/PackageManagerUI/Editor/Services/Common/PlaceholderPackage.cs b/Modules/PackageManagerUI/Editor/Services/Common/PlaceholderPackage.cs index 0c1642a988..da53544fce 100644 --- a/Modules/PackageManagerUI/Editor/Services/Common/PlaceholderPackage.cs +++ b/Modules/PackageManagerUI/Editor/Services/Common/PlaceholderPackage.cs @@ -27,11 +27,14 @@ public PlaceholderPackage(string uniqueId, string displayName, PackageType type m_Progress = progress; m_VersionList = new PlaceholderVersionList(new PlaceholderPackageVersion(uniqueId, uniqueId, displayName, tag, error)); m_Errors = new List(); + LinkPackageAndVersions(); } public override IPackage Clone() { - return (IPackage)MemberwiseClone(); + var clone = (BasePackage)MemberwiseClone(); + clone.LinkPackageAndVersions(); + return clone; } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Common/UIError.cs b/Modules/PackageManagerUI/Editor/Services/Common/UIError.cs index 377e3f1ab0..31e642d29d 100644 --- a/Modules/PackageManagerUI/Editor/Services/Common/UIError.cs +++ b/Modules/PackageManagerUI/Editor/Services/Common/UIError.cs @@ -11,8 +11,22 @@ namespace UnityEditor.PackageManager.UI.Internal internal class UIError : Error { private static readonly string k_EntitlementErrorMessage = L10n.Tr("This package is not available to use because there is no license registered for your user. Please sign in with a licensed account. If the problem persists, please contact your administrator."); + internal static readonly string k_InvalidSignatureWarningMessage = L10n.Tr("This package version doesn't have a valid signature. For your security, install a different version or report a bug to Unity."); + internal static readonly string k_UnsignedUnityPackageWarningMessage = L10n.Tr("This package version has no signature. For your security, install a different version or review your scoped registry and load the package from the Unity registry."); + internal static readonly string k_readMoreDocsUrl = "https://docs.unity3d.com/Manual/upm-errors.html"; public static readonly UIError k_EntitlementError = new UIError(UIErrorCode.Forbidden, k_EntitlementErrorMessage); public static readonly UIError k_EntitlementWarning = new UIError(UIErrorCode.Forbidden, k_EntitlementErrorMessage, Attribute.IsWarning); + internal static readonly UIError k_InvalidSignatureWarning = new UIError( + UIErrorCode.UpmError_InvalidSignature, + k_InvalidSignatureWarningMessage, + Attribute.IsWarning, + readMoreUrl: k_readMoreDocsUrl); + + internal static readonly UIError k_UnsignedUnityPackageWarning = new UIError( + UIErrorCode.UpmError_UnsignedUnityPackage, + k_UnsignedUnityPackageWarningMessage, + Attribute.IsWarning, + readMoreUrl: k_readMoreDocsUrl); [SerializeField] private UIErrorCode m_UIErrorCode; @@ -23,6 +37,11 @@ internal class UIError : Error [SerializeField] private int m_OperationErrorCode; + public string readMoreURL => m_ReadMoreUrl; + + [SerializeField] + private string m_ReadMoreUrl; + [Flags] internal enum Attribute { @@ -45,11 +64,12 @@ public bool HasAttribute(Attribute attribute) public UIError(UIErrorCode errorCode, string message, int operationErrorCode) : this(errorCode, message, Attribute.None, operationErrorCode) {} - public UIError(UIErrorCode errorCode, string message, Attribute attribute = Attribute.None, int operationErrorCode = -1) : base(NativeErrorCode.Unknown, message) + public UIError(UIErrorCode errorCode, string message, Attribute attribute = Attribute.None, int operationErrorCode = -1, string readMoreUrl = "") : base(NativeErrorCode.Unknown, message) { m_UIErrorCode = errorCode; m_Attribute = attribute; m_OperationErrorCode = operationErrorCode; + m_ReadMoreUrl = readMoreUrl; } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Common/UIErrorCode.cs b/Modules/PackageManagerUI/Editor/Services/Common/UIErrorCode.cs index d38534d084..9f2b4c89d3 100644 --- a/Modules/PackageManagerUI/Editor/Services/Common/UIErrorCode.cs +++ b/Modules/PackageManagerUI/Editor/Services/Common/UIErrorCode.cs @@ -23,6 +23,8 @@ internal enum UIErrorCode AssetStoreOperationError, AssetStorePackageError, UpmError, - NetworkError + NetworkError, + UpmError_InvalidSignature, + UpmError_UnsignedUnityPackage } } diff --git a/Modules/PackageManagerUI/Editor/Services/Interfaces/IPackageVersion.cs b/Modules/PackageManagerUI/Editor/Services/Interfaces/IPackageVersion.cs index fa54968594..f3dda7e80c 100644 --- a/Modules/PackageManagerUI/Editor/Services/Interfaces/IPackageVersion.cs +++ b/Modules/PackageManagerUI/Editor/Services/Interfaces/IPackageVersion.cs @@ -24,6 +24,8 @@ internal interface IPackageVersion string packageUniqueId { get; } + IPackage package { get; } + PackageInfo packageInfo { get; } bool isInstalled { get; } @@ -34,6 +36,8 @@ namespace UnityEditor.PackageManager.UI.Internal { internal interface IPackageVersion : UI.IPackageVersion { + new IPackage package { get; set; } + string author { get; } string authorLink { get; } @@ -82,5 +86,11 @@ internal interface IPackageVersion : UI.IPackageVersion IEnumerable sizes { get; } EntitlementsInfo entitlements { get; } + + bool IsDifferentVersionThanRequested { get; } + + bool IsRequestedButOverriddenVersion { get; } + + RegistryInfo registry { get; } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Packages/PackageAndVersionIdPair.cs b/Modules/PackageManagerUI/Editor/Services/Packages/PackageAndVersionIdPair.cs new file mode 100644 index 0000000000..fd4289c059 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Packages/PackageAndVersionIdPair.cs @@ -0,0 +1,21 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class PackageAndVersionIdPair + { + public PackageAndVersionIdPair(string packageUniqueId, string versionUniqueId = null) + { + this.packageUniqueId = packageUniqueId; + this.versionUniqueId = versionUniqueId; + } + + public string packageUniqueId; + public string versionUniqueId; + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/Packages/PackageDatabase.cs b/Modules/PackageManagerUI/Editor/Services/Packages/PackageDatabase.cs index 501ff18dbd..c5d3a7b1fd 100644 --- a/Modules/PackageManagerUI/Editor/Services/Packages/PackageDatabase.cs +++ b/Modules/PackageManagerUI/Editor/Services/Packages/PackageDatabase.cs @@ -13,7 +13,11 @@ namespace UnityEditor.PackageManager.UI.Internal [Serializable] internal class PackageDatabase : ISerializationCallbackReceiver { - public virtual event Action onInstallOrUninstallSuccess = delegate {}; + // Normally package unique Id never changes for a package, but when we are installing a package from git or a tarball + // we only had a temporary unique id at first. For example, for `com.unity.a` is a unique id for a package, but when + // we are installing from git, the only identifier we know is something like `git@example.com/com.unity.a.git`. + // We only know the id `com.unity.a` after the package has been successfully installed, and we'll trigger an event for that. + public virtual event Action onPackageUniqueIdFinalize = delegate {}; public virtual event Action onPackageProgressUpdate = delegate {}; public virtual event Action onVerifiedGitPackageUpToDate = delegate {}; @@ -153,7 +157,7 @@ public virtual void GetPackageAndVersionByIdOrName(string idOrName, out IPackage public virtual IPackage GetPackageByIdOrName(string idOrName) { - GetPackageAndVersionByIdOrName(idOrName, out var package, out var version); + GetPackageAndVersionByIdOrName(idOrName, out var package, out _); return package; } @@ -163,12 +167,9 @@ public virtual void GetPackageAndVersion(string packageUniqueId, string versionU version = package?.versions.FirstOrDefault(v => v.uniqueId == versionUniqueId); } - public virtual IPackageVersion GetPackageVersion(string packageUniqueId, string versionUniqueId) + public virtual void GetPackageAndVersion(PackageAndVersionIdPair pair, out IPackage package, out IPackageVersion version) { - IPackage package; - IPackageVersion version; - GetPackageAndVersion(packageUniqueId, versionUniqueId, out package, out version); - return version; + GetPackageAndVersion(pair?.packageUniqueId, pair?.versionUniqueId, out package, out version); } public virtual void GetPackageAndVersion(DependencyInfo info, out IPackage package, out IPackageVersion version) @@ -244,14 +245,12 @@ public virtual IPackageVersion GetPackageInFeatureVersion(string packageId) public void OnAfterDeserialize() { - foreach (var p in m_SerializedPlaceholderPackages) - m_Packages[p.uniqueId] = p; - - foreach (var p in m_SerializedUpmPackages) - m_Packages[p.uniqueId] = p; - - foreach (var p in m_SerializedAssetStorePackages) + var serializedPackages = m_SerializedPlaceholderPackages.Concat(m_SerializedUpmPackages).Concat(m_SerializedAssetStorePackages); + foreach (var p in serializedPackages) + { + p.LinkPackageAndVersions(); m_Packages[p.uniqueId] = p; + } } public void OnBeforeSerialize() @@ -491,7 +490,7 @@ private void OnPackagesChanged(IEnumerable packages) if (match != null) { - onInstallOrUninstallSuccess?.Invoke(match); + onPackageUniqueIdFinalize?.Invoke(specialUniqueId, match.uniqueId); SetPackageProgress(match, PackageProgress.None); RemoveSpecialInstallation(specialUniqueId); } @@ -507,13 +506,6 @@ private void OnUpmAddAndRemoveOperation(UpmAddAndRemoveOperation operation) foreach (var packageName in operation.packagesNamesToRemove) SetPackageProgress(GetPackage(packageName), PackageProgress.Removing); - operation.onOperationSuccess += (op) => - { - var package = GetPackage(op.packageUniqueId); - if (package != null) - onInstallOrUninstallSuccess?.Invoke(package); - }; - operation.onOperationError += (op, err) => { // For now we all the actions we use `AddAndRemoveOperation` for should have a packageUniqueId @@ -546,7 +538,6 @@ private void OnUpmAddOperation(IOperation operation) return; } SetPackageProgress(GetPackage(operation.packageUniqueId), PackageProgress.Installing); - operation.onOperationSuccess += (op) => onInstallOrUninstallSuccess?.Invoke(GetPackage(op.packageUniqueId)); operation.onOperationError += OnUpmOperationError; operation.onOperationFinalized += OnUpmOperationFinalized; } @@ -566,7 +557,6 @@ private void RemoveSpecialInstallation(string specialUniqueId) private void OnUpmEmbedOperation(IOperation operation) { SetPackageProgress(GetPackage(operation.packageUniqueId), PackageProgress.Installing); - operation.onOperationSuccess += (op) => onInstallOrUninstallSuccess?.Invoke(GetPackage(op.packageUniqueId)); operation.onOperationError += OnUpmOperationError; operation.onOperationFinalized += OnUpmOperationFinalized; } @@ -574,7 +564,6 @@ private void OnUpmEmbedOperation(IOperation operation) private void OnUpmRemoveOperation(IOperation operation) { SetPackageProgress(GetPackage(operation.packageUniqueId), PackageProgress.Removing); - operation.onOperationSuccess += (op) => onInstallOrUninstallSuccess?.Invoke(GetPackage(operation.packageUniqueId)); operation.onOperationError += OnUpmOperationError; operation.onOperationFinalized += OnUpmOperationFinalized; } @@ -593,12 +582,11 @@ private void OnUpmOperationFinalized(IOperation operation) private void OnUpmPackageVersionUpdated(string packageUniqueId, IPackageVersion version) { - var package = GetPackage(packageUniqueId); - var upmVersions = package?.versions as UpmVersionList; - if (upmVersions != null) + var package = GetPackage(packageUniqueId) as UpmPackage; + if (package != null) { var packagePreUpdate = package.Clone(); - upmVersions.UpdateVersion(version as UpmPackageVersion); + package.UpdateVersion(version as UpmPackageVersion); onPackagesChanged?.Invoke(k_EmptyList, k_EmptyList, new[] { packagePreUpdate }, new[] { package }); } } @@ -615,6 +603,14 @@ public virtual void Install(IPackageVersion version) m_UpmClient.AddById(version.uniqueId); } + public virtual void Install(IEnumerable versions) + { + if (versions == null || !versions.Any()) + return; + + m_UpmClient.AddByIds(versions.Select(v => v.uniqueId)); + } + public virtual void Install(string packageId) { m_UpmClient.AddById(packageId); @@ -625,9 +621,9 @@ public virtual void InstallFromUrl(string url) m_UpmClient.AddByUrl(url); } - public virtual void InstallFromPath(string path) + public virtual bool InstallFromPath(string path, out string tempPackageId) { - m_UpmClient.AddByPath(path); + return m_UpmClient.AddByPath(path, out tempPackageId); } public virtual void Uninstall(IPackage package) @@ -637,6 +633,13 @@ public virtual void Uninstall(IPackage package) m_UpmClient.RemoveByName(package.name); } + public virtual void Uninstall(IEnumerable packages) + { + if (packages == null || !packages.Any()) + return; + m_UpmClient.RemoveByNames(packages.Select(p => p.name)); + } + public virtual void InstallAndResetDependencies(IPackageVersion version, IEnumerable dependenciesToReset) { m_UpmClient.AddAndResetDependencies(version.uniqueId, dependenciesToReset?.Select(package => package.name) ?? Enumerable.Empty()); @@ -678,49 +681,73 @@ public virtual bool IsDownloadInPause(IPackageVersion version) return m_AssetStoreDownloadManager.GetDownloadOperation(version.packageUniqueId)?.isInPause ?? false; } - public virtual bool Download(IPackage package) + private bool CheckTermOfServiceAgreement(Action onTosAccepted, Action onError) { - if (!(package is AssetStorePackage)) - return false; - - if (!PlayModeDownload.CanBeginDownload()) - return false; - if (termOfServiceAgreementStatus == TermOfServiceAgreementStatus.NotAccepted) { m_AssetStoreClient.CheckTermOfServiceAgreement(status => { termOfServiceAgreementStatus = status; if (termOfServiceAgreementStatus == TermOfServiceAgreementStatus.Accepted) - Download_Internal(package); - }, error => AddPackageError(package, error)); + onTosAccepted?.Invoke(); + }, error => onError?.Invoke(error)); return false; } - Download_Internal(package); + onTosAccepted?.Invoke(); return true; } + public virtual bool Download(IPackage package) + { + if (!package.Is(PackageType.AssetStore) || !PlayModeDownload.CanBeginDownload()) + return false; + + return CheckTermOfServiceAgreement(() => Download_Internal(package), error => AddPackageError(package, error)); + } + + public virtual void Download(IEnumerable versions) + { + // We need better error handling in this function. + // It will be addressed in https://jira.unity3d.com/browse/PAX-1994. + CheckTermOfServiceAgreement(() => Download_Internal(versions), error => Debug.Log(error)); + } + private void Download_Internal(IPackage package) { - SetPackageProgress(package, PackageProgress.Downloading); - m_AssetStoreDownloadManager.Download(package); // When we start a new download, we want to clear past operation errors to give it a fresh start. // Eventually we want a better design on how to show errors, to be further addressed in https://jira.unity3d.com/browse/PAX-1332 + // We need to clear errors before calling download because Download can fail right away ( package.ClearErrors(e => e.errorCode == UIErrorCode.AssetStoreOperationError); + SetPackageProgress(package, PackageProgress.Downloading); + m_AssetStoreDownloadManager.Download(package); + } + + private void Download_Internal(IEnumerable versions) + { + foreach (var version in versions) + Download_Internal(version.package); } public virtual void AbortDownload(IPackage package) { - if (!(package is AssetStorePackage)) + if (!package.Is(PackageType.AssetStore)) return; SetPackageProgress(package, PackageProgress.None); m_AssetStoreDownloadManager.AbortDownload(package.uniqueId); } + public virtual void AbortDownload(IEnumerable versions) + { + // We need to figure out why the IEnumerable is being altered instead of using ToArray. + // It will be addressed in https://jira.unity3d.com/browse/PAX-1995. + foreach (var version in versions.ToArray()) + AbortDownload(version.package); + } + public virtual void PauseDownload(IPackage package) { - if (!(package is AssetStorePackage)) + if (!package.Is(PackageType.AssetStore)) return; SetPackageProgress(package, PackageProgress.Pausing); m_AssetStoreDownloadManager.PauseDownload(package.uniqueId); @@ -728,7 +755,7 @@ public virtual void PauseDownload(IPackage package) public virtual void ResumeDownload(IPackage package) { - if (!(package is AssetStorePackage)) + if (!package.Is(PackageType.AssetStore)) return; if (!PlayModeDownload.CanBeginDownload()) diff --git a/Modules/PackageManagerUI/Editor/Services/Proxies/ApplicationProxy.cs b/Modules/PackageManagerUI/Editor/Services/Proxies/ApplicationProxy.cs index 1dc5841c91..4a08e44cbf 100644 --- a/Modules/PackageManagerUI/Editor/Services/Proxies/ApplicationProxy.cs +++ b/Modules/PackageManagerUI/Editor/Services/Proxies/ApplicationProxy.cs @@ -32,7 +32,7 @@ internal class ApplicationProxy public virtual bool isBatchMode => Application.isBatchMode; - public virtual bool isUpmRunning => !Application.HasARGV("noUpm"); + public virtual bool isUpmRunning => !EditorApplication.isPackageManagerDisabled; public virtual bool isCompiling { @@ -127,6 +127,11 @@ public virtual string OpenFilePanelWithFilters(string title, string directory, s return EditorUtility.OpenFilePanelWithFilters(title, directory, filters); } + public virtual string OpenFolderPanel(string title, string folder) + { + return EditorUtility.OpenFolderPanel(title, folder, string.Empty); + } + public virtual bool DisplayDialog(string title, string message, string ok, string cancel = "") { return EditorUtility.DisplayDialog(title, message, ok, cancel); diff --git a/Modules/PackageManagerUI/Editor/Services/Proxies/AssetStoreCachePathProxy.cs b/Modules/PackageManagerUI/Editor/Services/Proxies/AssetStoreCachePathProxy.cs new file mode 100644 index 0000000000..584b56b4db --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Proxies/AssetStoreCachePathProxy.cs @@ -0,0 +1,54 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditorInternal; +using UnityEngine; +using CachePathConfig = UnityEditorInternal.AssetStoreCachePathManager.CachePathConfig; +using ConfigStatus = UnityEditorInternal.AssetStoreCachePathManager.ConfigStatus; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class AssetStoreCachePathProxy + { + public virtual event Action onConfigChanged = delegate {}; + + [SerializeField] + private CachePathConfig m_CurrentConfig; + + public virtual CachePathConfig GetDefaultConfig() => AssetStoreCachePathManager.GetDefaultConfig(); + + public virtual CachePathConfig GetConfig() + { + var config = AssetStoreCachePathManager.GetConfig(); + if (m_CurrentConfig == null || + string.Compare(config.path, m_CurrentConfig.path, StringComparison.Ordinal) != 0 || + config.source != m_CurrentConfig.source || + config.status != m_CurrentConfig.status) + { + m_CurrentConfig = config; + onConfigChanged?.Invoke(m_CurrentConfig); + } + + return m_CurrentConfig; + } + + public virtual ConfigStatus SetConfig(string path) + { + var status = AssetStoreCachePathManager.SetConfig(path); + if (status == ConfigStatus.Success) + GetConfig(); + return status; + } + + public virtual ConfigStatus ResetConfig() + { + var status = AssetStoreCachePathManager.ResetConfig(); + if (status == ConfigStatus.Success) + GetConfig(); + return status; + } + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/Proxies/ClientProxy.cs b/Modules/PackageManagerUI/Editor/Services/Proxies/ClientProxy.cs index 67096e82d5..ac71cdc1e8 100644 --- a/Modules/PackageManagerUI/Editor/Services/Proxies/ClientProxy.cs +++ b/Modules/PackageManagerUI/Editor/Services/Proxies/ClientProxy.cs @@ -67,5 +67,20 @@ public virtual UpdateScopedRegistryRequest UpdateScopedRegistry(string registryN { return Client.UpdateScopedRegistry(registryName, options); } + + public virtual GetCacheRootRequest GetCacheRoot() + { + return Client.GetCacheRoot(); + } + + public virtual SetCacheRootRequest SetCacheRoot(string path) + { + return Client.SetCacheRoot(path); + } + + public virtual ClearCacheRootRequest ClearCacheRoot() + { + return Client.ClearCacheRoot(); + } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Proxies/SelectionProxy.cs b/Modules/PackageManagerUI/Editor/Services/Proxies/SelectionProxy.cs index f7388c5b24..1ccde24a36 100644 --- a/Modules/PackageManagerUI/Editor/Services/Proxies/SelectionProxy.cs +++ b/Modules/PackageManagerUI/Editor/Services/Proxies/SelectionProxy.cs @@ -15,6 +15,12 @@ public SelectionProxy() Selection.selectionChanged += OnSelectionChanged; } + public virtual UnityEngine.Object[] objects + { + get { return Selection.objects; } + set { Selection.objects = value; } + } + public virtual UnityEngine.Object activeObject { get { return Selection.activeObject; } diff --git a/Modules/PackageManagerUI/Editor/Services/ServicesContainer.cs b/Modules/PackageManagerUI/Editor/Services/ServicesContainer.cs index 2e66ad24d5..98bcd77d0e 100644 --- a/Modules/PackageManagerUI/Editor/Services/ServicesContainer.cs +++ b/Modules/PackageManagerUI/Editor/Services/ServicesContainer.cs @@ -55,6 +55,9 @@ internal sealed class ServicesContainer : ScriptableSingleton [SerializeField] private AssetStoreDownloadManager m_AssetStoreDownloadManager; + [SerializeField] + private AssetStoreCachePathProxy m_AssetStoreCachePathProxy; + [SerializeField] private UpmCache m_UpmCache; @@ -64,6 +67,9 @@ internal sealed class ServicesContainer : ScriptableSingleton [SerializeField] private UpmRegistryClient m_UpmRegistryClient; + [SerializeField] + private UpmCacheRootClient m_UpmCacheRootClient; + [SerializeField] private PackageFiltering m_PackageFiltering; @@ -116,10 +122,12 @@ public ServicesContainer() m_AssetStoreRestAPI = new AssetStoreRestAPI(); m_AssetStoreDownloadManager = new AssetStoreDownloadManager(); m_AssetStoreCallQueue = new AssetStoreCallQueue(); + m_AssetStoreCachePathProxy = new AssetStoreCachePathProxy(); m_UpmCache = new UpmCache(); m_UpmClient = new UpmClient(); m_UpmRegistryClient = new UpmRegistryClient(); + m_UpmCacheRootClient = new UpmCacheRootClient(); m_PackageFiltering = new PackageFiltering(); m_PackageManagerPrefs = new PackageManagerPrefs(); @@ -147,12 +155,13 @@ private void ResolveDependencies() m_AssetStoreOAuth.ResolveDependencies(m_UnityConnectProxy, m_UnityOAuthProxy, m_HttpClientFactory); m_AssetStoreUtils.ResolveDependencies(m_UnityConnectProxy); m_AssetStoreRestAPI.ResolveDependencies(m_UnityConnectProxy, m_AssetStoreOAuth, m_AssetStoreCache, m_HttpClientFactory); - m_AssetStoreDownloadManager.ResolveDependencies(m_ApplicationProxy, m_HttpClientFactory, m_UnityConnectProxy, m_IOProxy, m_AssetStoreCache, m_AssetStoreUtils, m_AssetStoreRestAPI); + m_AssetStoreDownloadManager.ResolveDependencies(m_ApplicationProxy, m_HttpClientFactory, m_UnityConnectProxy, m_IOProxy, m_AssetStoreCache, m_AssetStoreUtils, m_AssetStoreRestAPI, m_AssetStoreCachePathProxy); m_AssetStoreCallQueue.ResolveDependencies(m_ApplicationProxy, m_UnityConnectProxy, m_PackageFiltering, m_AssetStoreClient, m_AssetStoreCache, m_PageManager); m_UpmCache.ResolveDependencies(m_PackageManagerPrefs); m_UpmClient.ResolveDependencies(m_UpmCache, m_IOProxy, m_SettingsProxy, m_ClientProxy, m_ApplicationProxy); m_UpmRegistryClient.ResolveDependencies(m_UpmCache, m_SettingsProxy, m_ClientProxy, m_ApplicationProxy); + m_UpmCacheRootClient.ResolveDependencies(m_ClientProxy, m_ApplicationProxy); m_PackageFiltering.ResolveDependencies(m_UnityConnectProxy, m_SettingsProxy); @@ -233,10 +242,12 @@ public void RegisterDefaultServices() Register(m_AssetStoreUtils); Register(m_AssetStoreRestAPI); Register(m_AssetStoreCallQueue); + Register(m_AssetStoreCachePathProxy); Register(m_UpmCache); Register(m_UpmClient); Register(m_UpmRegistryClient); + Register(m_UpmCacheRootClient); Register(m_PackageFiltering); Register(m_PackageManagerPrefs); diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmAddAndRemoveOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmAddAndRemoveOperation.cs index 1b3f08026c..14af102bd5 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmAddAndRemoveOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmAddAndRemoveOperation.cs @@ -27,6 +27,24 @@ internal class UpmAddAndRemoveOperation : UpmBaseOperation protected string[] m_PackagesNamesToRemove = new string[0]; public IEnumerable packagesNamesToRemove => m_PackagesNamesToRemove; + public void AddByIds(IEnumerable versionIds) + { + m_PackageIdsToReset = new string[0]; + m_PackageIdsToAdd = (versionIds ?? Enumerable.Empty()).ToArray(); + m_PackagesNamesToRemove = new string[0]; + SetPrimaryPackageNameOrId(); + Start(); + } + + public void RemoveByNames(IEnumerable packagesNames) + { + m_PackageIdsToReset = new string[0]; + m_PackageIdsToAdd = new string[0]; + m_PackagesNamesToRemove = (packagesNames ?? Enumerable.Empty()).ToArray(); + SetPrimaryPackageNameOrId(); + Start(); + } + public void AddAndResetDependencies(string packageId, IEnumerable dependencyPackagesNames) { m_PackageIdsToReset = new string[0]; diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmBaseOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmBaseOperation.cs index 73eac951fa..d9bf855f19 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmBaseOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmBaseOperation.cs @@ -115,7 +115,7 @@ protected void Start() EditorApplication.delayCall += () => { OnError(new UIError(UIErrorCode.UpmError, "UPM server is not running")); - CancelInternal(); + Cancel(); }; return; } @@ -133,7 +133,7 @@ protected void Start() EditorApplication.update += Progress; } - protected void CancelInternal() + public void Cancel() { OnFinalize(); m_Request = null; diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmCache.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmCache.cs index 9c3b9c4282..7a656f1089 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmCache.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmCache.cs @@ -82,6 +82,7 @@ private static bool IsDifferent(PackageInfo p1, PackageInfo p2) p1.dependencies.Length != p2.dependencies.Length || !p1.dependencies.SequenceEqual(p2.dependencies) || p1.resolvedDependencies.Length != p2.resolvedDependencies.Length || !p1.resolvedDependencies.SequenceEqual(p2.resolvedDependencies) || p1.projectDependenciesEntry != p2.projectDependenciesEntry || + p1.signature.status != p2.signature.status || p1.documentationUrl != p2.documentationUrl || p1.changelogUrl != p2.changelogUrl || p1.licensesUrl != p2.licensesUrl) diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmCacheRootClient.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmCacheRootClient.cs new file mode 100644 index 0000000000..7a50755808 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmCacheRootClient.cs @@ -0,0 +1,87 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class UpmCacheRootClient + { + public virtual event Action onGetCacheRootOperationResult = delegate {}; + public virtual event Action onGetCacheRootOperationError = delegate {}; + public virtual event Action onSetCacheRootOperationResult = delegate {}; + public virtual event Action onSetCacheRootOperationError = delegate {}; + public virtual event Action onClearCacheRootOperationResult = delegate {}; + public virtual event Action onClearCacheRootOperationError = delegate {}; + + [SerializeField] + private UpmGetCacheRootOperation m_GetCacheRootOperation; + private UpmGetCacheRootOperation getCacheRootOperation => CreateOperation(ref m_GetCacheRootOperation); + + [SerializeField] + private UpmSetCacheRootOperation m_SetCacheRootOperation; + private UpmSetCacheRootOperation setCacheRootOperation => CreateOperation(ref m_SetCacheRootOperation); + + [SerializeField] + private UpmClearCacheRootOperation m_ClearCacheRootOperation; + private UpmClearCacheRootOperation clearCacheRootOperation => CreateOperation(ref m_ClearCacheRootOperation); + + [NonSerialized] + private ClientProxy m_ClientProxy; + [NonSerialized] + private ApplicationProxy m_ApplicationProxy; + public void ResolveDependencies(ClientProxy clientProxy, + ApplicationProxy applicationProxy) + { + m_ClientProxy = clientProxy; + m_ApplicationProxy = applicationProxy; + + m_GetCacheRootOperation?.ResolveDependencies(m_ClientProxy, m_ApplicationProxy); + m_SetCacheRootOperation?.ResolveDependencies(m_ClientProxy, m_ApplicationProxy); + m_ClearCacheRootOperation?.ResolveDependencies(m_ClientProxy, m_ApplicationProxy); + } + + public virtual void GetCacheRoot() + { + if (m_GetCacheRootOperation?.isInProgress ?? false) + getCacheRootOperation.Cancel(); + + getCacheRootOperation.GetCacheRoot(); + getCacheRootOperation.onProcessResult += req => onGetCacheRootOperationResult?.Invoke(req?.Result); + getCacheRootOperation.onOperationError += (op, error) => onGetCacheRootOperationError?.Invoke(error); + } + + public virtual void SetCacheRoot(string path) + { + if (m_SetCacheRootOperation?.isInProgress ?? true) + setCacheRootOperation.Cancel(); + + setCacheRootOperation.SetCacheRoot(path); + setCacheRootOperation.onProcessResult += req => onSetCacheRootOperationResult?.Invoke(req?.Result); + setCacheRootOperation.onOperationError += (op, error) => onSetCacheRootOperationError?.Invoke(error, path); + } + + public virtual void ClearCacheRoot() + { + if (m_ClearCacheRootOperation?.isInProgress ?? false) + clearCacheRootOperation.Cancel(); + + clearCacheRootOperation.ClearCacheRoot(); + clearCacheRootOperation.onProcessResult += req => onClearCacheRootOperationResult?.Invoke(req?.Result); + clearCacheRootOperation.onOperationError += (op, error) => onClearCacheRootOperationError?.Invoke(error); + } + + private T CreateOperation(ref T operation) where T : UpmBaseOperation, new() + { + if (operation != null) + return operation; + + operation = new T(); + operation.ResolveDependencies(m_ClientProxy, m_ApplicationProxy); + return operation; + } + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmClearCacheRootOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmClearCacheRootOperation.cs new file mode 100644 index 0000000000..3c773560f1 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmClearCacheRootOperation.cs @@ -0,0 +1,25 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor.PackageManager.Requests; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class UpmClearCacheRootOperation : UpmBaseOperation + { + public override RefreshOptions refreshOptions => RefreshOptions.None; + + public void ClearCacheRoot() + { + Start(); + } + + protected override ClearCacheRootRequest CreateRequest() + { + return m_ClientProxy.ClearCacheRoot(); + } + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmClient.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmClient.cs index c5a31667ae..ef3e1f8290 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmClient.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmClient.cs @@ -58,10 +58,6 @@ internal class UpmClient : ISerializationCallbackReceiver private readonly Dictionary m_ExtraFetchOperations = new Dictionary(); - private HashSet m_PackagesToExtraFetchForRegistryVersions = new HashSet(); - [SerializeField] - private string[] m_SerializedPackagesToExtraFetchForRegistryVersions; - [SerializeField] private string[] m_SerializedPRegistriesUrlKeys; @@ -116,15 +112,12 @@ public void OnBeforeSerialize() { m_SerializedPRegistriesUrlKeys = m_RegistriesUrl?.Keys.ToArray() ?? new string[0]; m_SerializedRegistriesUrlValues = m_RegistriesUrl?.Values.ToArray() ?? new bool[0]; - m_SerializedPackagesToExtraFetchForRegistryVersions = m_PackagesToExtraFetchForRegistryVersions.ToArray() ?? new string[0]; } public void OnAfterDeserialize() { for (var i = 0; i < m_SerializedPRegistriesUrlKeys.Length; i++) m_RegistriesUrl[m_SerializedPRegistriesUrlKeys[i]] = m_SerializedRegistriesUrlValues[i]; - foreach (var packageName in m_SerializedPackagesToExtraFetchForRegistryVersions) - m_PackagesToExtraFetchForRegistryVersions.Add(packageName); } public virtual bool isAddRemoveOrEmbedInProgress => (m_AddOperation?.isInProgress ?? false) || @@ -186,10 +179,11 @@ private void OnProcessAddResult(IOperation operation, Request reque List(true); } - public virtual void AddByPath(string path) + public virtual bool AddByPath(string path, out string tempPackageId) { + tempPackageId = string.Empty; if (isAddRemoveOrEmbedInProgress) - return; + return false; try { @@ -205,12 +199,15 @@ public virtual void AddByPath(string path) path = $"../{relativePathToProjectRoot}"; } - addOperation.AddByUrlOrPath($"file:{path}", PackageTag.Local); + tempPackageId = $"file:{path}"; + addOperation.AddByUrlOrPath(tempPackageId, PackageTag.Local); SetupAddOperation(); + return true; } catch (System.IO.IOException e) { Debug.Log($"[Package Manager] Cannot add package {path}: {e.Message}"); + return false; } } @@ -223,6 +220,22 @@ public virtual void AddByUrl(string url) SetupAddOperation(); } + public virtual void AddByIds(IEnumerable versionIds) + { + if (isAddRemoveOrEmbedInProgress) + return; + addAndRemoveOperation.AddByIds(versionIds); + SetupAddAndRemoveOperation(); + } + + public virtual void RemoveByNames(IEnumerable packagesNames) + { + if (isAddRemoveOrEmbedInProgress) + return; + addAndRemoveOperation.RemoveByNames(packagesNames); + SetupAddAndRemoveOperation(); + } + public virtual void AddAndResetDependencies(string packageId, IEnumerable dependencyPackagesNames) { if (isAddRemoveOrEmbedInProgress) @@ -561,14 +574,6 @@ private UpmPackage CreateUpmPackage(PackageInfo searchInfo, PackageInfo installe var registryInfo = installedInfo.registry; var compatibleVersions = installedInfo.versions?.compatible; - - // if main version was installed from outside a registry but has other registry versions, - // need to fetch extra info for the other registry versions so they can be tagged properly - if (result.versions?.installed?.HasTag(PackageTag.Bundled) == false - && registryInfo == null && compatibleVersions?.Count() > 0) - { - ExtraFetchForRegistryVersions(installedInfo.name); - } } else { @@ -581,37 +586,6 @@ private UpmPackage CreateUpmPackage(PackageInfo searchInfo, PackageInfo installe return result; } - public void ExtraFetchForRegistryVersions(string packageName) - { - m_PackagesToExtraFetchForRegistryVersions.Add(packageName); - - var extraFetchOperation = ExtraFetchInternal(packageName); - - if (extraFetchOperation != null) - { - extraFetchOperation.onProcessResult += (request) => OnProcessExtraFetchRegistryVersionsResult(request); - extraFetchOperation.onOperationFinalized += (op) => OnExtraFetchRegistryVersionsFinalized(op.packageUniqueId); - } - } - - private void OnExtraFetchRegistryVersionsFinalized(string packageName) - { - m_PackagesToExtraFetchForRegistryVersions.Remove(packageName); - } - - private void OnProcessExtraFetchRegistryVersionsResult(SearchRequest request) - { - var packageInfo = request.Result.FirstOrDefault(); - var isUnityPackage = IsUnityPackage(packageInfo); - - var existingExtraPackageInfos = m_UpmCache.GetExtraPackageInfos(packageInfo.name); - foreach (var registryVersion in packageInfo.versions.compatible) - { - if (!existingExtraPackageInfos.ContainsKey(registryVersion)) - onPackageVersionUpdated?.Invoke(packageInfo.name, new UpmPackageVersion(packageInfo, false, Scripting.ScriptCompilation.SemVersionParser.Parse(registryVersion), packageInfo.displayName, isUnityPackage)); - } - } - private void UpdateExtraPackageInfos(string packageName, IVersionList versions) { if (!versions.Any()) @@ -696,11 +670,6 @@ private void RestoreInProgressOperations() if (m_SearchOperation?.isInProgress ?? false) SearchAll(); - - foreach (var packageName in m_PackagesToExtraFetchForRegistryVersions) - { - ExtraFetchForRegistryVersions(packageName); - } } public void OnEnable() diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetCacheRootOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetCacheRootOperation.cs new file mode 100644 index 0000000000..c4db8ac8f4 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetCacheRootOperation.cs @@ -0,0 +1,25 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor.PackageManager.Requests; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class UpmGetCacheRootOperation : UpmBaseOperation + { + public override RefreshOptions refreshOptions => RefreshOptions.None; + + public void GetCacheRoot() + { + Start(); + } + + protected override GetCacheRootRequest CreateRequest() + { + return m_ClientProxy.GetCacheRoot(); + } + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetRegistriesOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetRegistriesOperation.cs index 6cf2ca9993..3554a29cc4 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetRegistriesOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmGetRegistriesOperation.cs @@ -21,10 +21,5 @@ protected override GetRegistriesRequest CreateRequest() { return m_ClientProxy.GetRegistries(); } - - public void Cancel() - { - CancelInternal(); - } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmListOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmListOperation.cs index 254a2c77af..28e9bda8a8 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmListOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmListOperation.cs @@ -29,10 +29,5 @@ protected override ListRequest CreateRequest() { return m_ClientProxy.List(isOfflineMode, true); } - - public void Cancel() - { - CancelInternal(); - } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackage.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackage.cs index 9557ae9c56..9bb5523f7e 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackage.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackage.cs @@ -42,7 +42,9 @@ public UpmPackage(string name, bool isDiscoverable, PackageType type) m_VersionList = new UpmVersionList(); m_Errors = new List(); m_Type = type; + RefreshUnityType(); + LinkPackageAndVersions(); } public UpmPackage(PackageInfo info, bool isInstalled, bool isDiscoverable, bool isUnityPackage) @@ -56,20 +58,30 @@ public UpmPackage(PackageInfo info, bool isInstalled, bool isDiscoverable, bool _ = info.type == "feature" ? m_Type |= PackageType.Feature : m_Type &= ~PackageType.Feature; RefreshUnityType(); + LinkPackageAndVersions(); } internal void UpdateVersions(IEnumerable updatedVersions) { m_VersionList = new UpmVersionList(updatedVersions, m_VersionList.lifecycleVersionString, m_VersionList.lifecycleNextVersion); RefreshUnityType(); + LinkPackageAndVersions(); ClearErrors(); } + internal void UpdateVersion(UpmPackageVersion version) + { + m_VersionList.UpdateVersion(version); + RefreshUnityType(); + LinkPackageAndVersions(); + } + // This function is only used to update the object, not to actually perform the add operation public void AddInstalledVersion(UpmPackageVersion newVersion) { m_VersionList.AddInstalledVersion(newVersion); RefreshUnityType(); + LinkPackageAndVersions(); } private void RefreshUnityType() @@ -83,7 +95,9 @@ private void RefreshUnityType() public override IPackage Clone() { - return (IPackage)MemberwiseClone(); + var clone = (BasePackage)MemberwiseClone(); + clone.LinkPackageAndVersions(); + return clone; } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageDocs.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageDocs.cs index bd589f7864..7cb5c1b35f 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageDocs.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageDocs.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -116,6 +117,26 @@ public static string GetOfflineLicenses(IOProxy IOProxy, IPackageVersion version return string.Empty; } + public static string GetUseCasesUrl(IPackageVersion version) + { + return EditorGameServiceExtension.GetUseCasesUrl(version); + } + + public static string GetOfflineUseCasesUrl(IOProxy IOProxy, IPackageVersion version) + { + return string.Empty; + } + + public static string GetDashboardUrl(IPackageVersion version) + { + return EditorGameServiceExtension.GetDashboardUrl(version); + } + + public static string GetOfflineDashboardUrl(IOProxy IOProxy, IPackageVersion version) + { + return string.Empty; + } + public static bool HasDocs(IPackageVersion version) { var upmVersion = version as UpmPackageVersion; @@ -139,5 +160,15 @@ public static bool HasLicenses(IPackageVersion version) return true; return upmVersion != null && !version.HasTag(PackageTag.BuiltIn | PackageTag.Feature); } + + public static bool HasUseCases(IPackageVersion version) + { + return !string.IsNullOrEmpty(EditorGameServiceExtension.GetUseCasesUrl(version)); + } + + public static bool HasDashboard(IPackageVersion version) + { + return !string.IsNullOrEmpty(EditorGameServiceExtension.GetDashboardUrl(version)); + } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageVersion.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageVersion.cs index 7b5ddba054..b0b1fe4a50 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageVersion.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmPackageVersion.cs @@ -24,10 +24,12 @@ internal class UpmPackageVersion : BasePackageVersion public override string category => m_PackageInfo.category; - public override IEnumerable errors => hasEntitlementsError ? new[] { UIError.k_EntitlementError } : m_PackageInfo.errors.Select(error => new UIError((UIErrorCode)error.errorCode, error.message)); - public override bool isDirectDependency => isFullyFetched && m_PackageInfo.isDirectDependency; + [SerializeField] + private List m_Errors; + public override IEnumerable errors => m_Errors; + [SerializeField] private string m_PackageId; public override string uniqueId => m_PackageId; @@ -51,7 +53,8 @@ public override bool isUnityPackage } public bool isRegistryPackage => m_PackageInfo?.source == PackageSource.Registry; - public bool isFromScopedRegistry => this.isRegistryPackage && m_PackageInfo?.registry?.isDefault == false; + public bool isFromScopedRegistry => isRegistryPackage && m_PackageInfo?.registry?.isDefault == false; + public override RegistryInfo registry => isRegistryPackage ? m_PackageInfo.registry : null; [SerializeField] private bool m_IsFullyFetched; @@ -94,6 +97,7 @@ public override bool isInstalled public override string versionId => m_Version.ToString(); + public UpmPackageVersion(PackageInfo packageInfo, bool isInstalled, SemVersion? version, string displayName, bool isUnityPackage) { m_Version = version; @@ -141,6 +145,8 @@ internal void UpdatePackageInfo(PackageInfo newPackageInfo, bool isUnityPackage) m_PackageId = m_PackageInfo.packageId; if (installedFromPath) m_PackageId = m_PackageId.Replace("\\", "/"); + + ProcessSignatureErrors(newPackageInfo); } else { @@ -251,20 +257,24 @@ public static string FormatPackageId(string name, string version) return $"{name.ToLower()}@{version}"; } - public static bool IsDifferentVersionThanRequested(IPackageVersion packageVersion) - { - return !string.IsNullOrEmpty(packageVersion?.packageInfo?.projectDependenciesEntry) && - !packageVersion.HasTag(PackageTag.Git | PackageTag.Local | PackageTag.Custom) && - packageVersion.packageInfo.projectDependenciesEntry != packageVersion.versionString; - } - - public static bool IsRequestedButOverriddenVersion(IPackage package, IPackageVersion version) + private void ProcessSignatureErrors(PackageInfo info) { - var isVersionInProjectManifest = - !string.IsNullOrEmpty(version?.versionString) && - version.versionString == package?.versions.primary.packageInfo?.projectDependenciesEntry; + // Setup the initial value for errors + m_Errors = hasEntitlementsError ? new List {UIError.k_EntitlementError} : info.errors.Select(error => new UIError((UIErrorCode)error.errorCode, error.message)).ToList(); - return isVersionInProjectManifest && !version.isInstalled; + if (info.signature.status == SignatureStatus.Invalid) + { + m_Errors.Add(UIError.k_InvalidSignatureWarning); + } + else if (info.signature.status == SignatureStatus.Unsigned && name.StartsWith(k_UnityPrefix) && + (info.source == PackageSource.LocalTarball || + (info.source == PackageSource.Registry && !info.registry.isDefault))) + { + // Flag Unsigned packages on a non-default registry and local tarballs + // when the name starts with "com.unity." + // to prevent dependency confusion + m_Errors.Add(UIError.k_UnsignedUnityPackageWarning); + } } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmSearchOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmSearchOperation.cs index c663ef4eb6..89f2d58b29 100644 --- a/Modules/PackageManagerUI/Editor/Services/Upm/UpmSearchOperation.cs +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmSearchOperation.cs @@ -71,10 +71,5 @@ protected override SearchRequest CreateRequest() else return m_ClientProxy.Search(m_PackageNameOrId, isOfflineMode); } - - public void Cancel() - { - CancelInternal(); - } } } diff --git a/Modules/PackageManagerUI/Editor/Services/Upm/UpmSetCacheRootOperation.cs b/Modules/PackageManagerUI/Editor/Services/Upm/UpmSetCacheRootOperation.cs new file mode 100644 index 0000000000..b126301ac7 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/Upm/UpmSetCacheRootOperation.cs @@ -0,0 +1,31 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor.PackageManager.Requests; +using UnityEngine; + +namespace UnityEditor.PackageManager.UI.Internal +{ + [Serializable] + internal class UpmSetCacheRootOperation : UpmBaseOperation + { + [SerializeField] + protected string m_Path; + public string path => m_Path; + + public override RefreshOptions refreshOptions => RefreshOptions.None; + + public void SetCacheRoot(string path) + { + m_Path = path; + Start(); + } + + protected override SetCacheRootRequest CreateRequest() + { + return m_ClientProxy.SetCacheRoot(m_Path); + } + } +} diff --git a/Modules/PackageManagerUI/Editor/Services/UserSettings/PackageManagerUserSettingsProvider.cs b/Modules/PackageManagerUI/Editor/Services/UserSettings/PackageManagerUserSettingsProvider.cs new file mode 100644 index 0000000000..a6d96b96a3 --- /dev/null +++ b/Modules/PackageManagerUI/Editor/Services/UserSettings/PackageManagerUserSettingsProvider.cs @@ -0,0 +1,323 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEditor.Utils; +using UnityEditorInternal; +using UnityEngine.UIElements; +using CachePathConfig = UnityEditorInternal.AssetStoreCachePathManager.CachePathConfig; + +namespace UnityEditor.PackageManager.UI.Internal +{ + internal class PackageManagerUserSettingsProvider : SettingsProvider + { + private const string k_UserSettingsStylesheet = "StyleSheets/PackageManager/PackageManagerUserSettings.uss"; + private const string k_CommonStylesheet = "StyleSheets/Extensions/base/common.uss"; + private const string k_DarkStylesheet = "StyleSheets/Extensions/base/dark.uss"; + private const string k_LightStylesheet = "StyleSheets/Extensions/base/light.uss"; + internal const string k_PackageManagerUserSettingsPath = "Preferences/Package Manager"; + private const string k_PackageManagerUserSettingsTemplate = "PackageManagerUserSettings.uxml"; + private const string k_AssetStoreFolder = "Asset Store-5.x"; + + private static readonly string k_OpenFolder = L10n.Tr("Open Containing Folder"); + private static readonly string k_ChangeLocation = L10n.Tr("Change Location"); + private static readonly string k_ResetToDefaultLocation = L10n.Tr("Reset to Default Location"); + + private VisualElement m_RootVisualElement; + + [NonSerialized] + private CachePathConfig m_CurrentAssetStoreConfig = new CachePathConfig(); + [NonSerialized] + private CacheRootConfig m_CurrentPackagesConfig = new CacheRootConfig(); + + private ResourceLoader m_ResourceLoader; + private AssetStoreCachePathProxy m_AssetStoreCachePathProxy; + private UpmCacheRootClient m_UpmCacheRootClient; + private ApplicationProxy m_ApplicationProxy; + private ClientProxy m_ClientProxy; + private AssetStoreDownloadManager m_AssetStoreDownloadManager; + private void ResolveDependencies() + { + var container = ServicesContainer.instance; + m_ResourceLoader = container.Resolve(); + m_AssetStoreCachePathProxy = container.Resolve(); + m_UpmCacheRootClient = container.Resolve(); + m_ApplicationProxy = container.Resolve(); + m_AssetStoreDownloadManager = container.Resolve(); + m_ClientProxy = container.Resolve(); + } + + private PackageManagerUserSettingsProvider(string path, IEnumerable keywords = null) : base(path, SettingsScope.User, keywords) + { + activateHandler = (text, element) => + { + ResolveDependencies(); + + // Create a child to make sure all the style sheets are not added to the root. + m_RootVisualElement = new ScrollView(); + m_RootVisualElement.StretchToParentSize(); + m_RootVisualElement.AddStyleSheetPath(k_UserSettingsStylesheet); + m_RootVisualElement.AddStyleSheetPath(EditorGUIUtility.isProSkin ? k_DarkStylesheet : k_LightStylesheet); + m_RootVisualElement.AddStyleSheetPath(k_CommonStylesheet); + m_RootVisualElement.styleSheets.Add(m_ResourceLoader.packageManagerCommonStyleSheet); + + element.Add(m_RootVisualElement); + + var root = m_ResourceLoader.GetTemplate(k_PackageManagerUserSettingsTemplate); + m_RootVisualElement.Add(root); + m_Cache = new VisualElementCache(root); + + DisplayPackagesCacheSetting(); + DisplayAssetStoreCachePathSetting(); + + EditorApplication.focusChanged += OnEditorApplicationFocusChanged; + }; + deactivateHandler = () => + { + EditorApplication.focusChanged -= OnEditorApplicationFocusChanged; + + if (m_UpmCacheRootClient != null) + { + m_UpmCacheRootClient.onGetCacheRootOperationError -= OnPackagesGetCacheRootOperationError; + m_UpmCacheRootClient.onGetCacheRootOperationResult -= OnPackagesGetCacheRootOperationResult; + m_UpmCacheRootClient.onSetCacheRootOperationError -= OnPackagesSetCacheRootOperationError; + m_UpmCacheRootClient.onSetCacheRootOperationResult -= OnPackagesSetCacheRootOperationResult; + m_UpmCacheRootClient.onClearCacheRootOperationError -= OnPackagesClearCacheRootOperationError; + m_UpmCacheRootClient.onClearCacheRootOperationResult -= OnPackagesSetCacheRootOperationResult; + } + + if (m_AssetStoreCachePathProxy != null) + { + m_AssetStoreCachePathProxy.onConfigChanged -= RefreshAssetStoreCachePathConfig; + } + }; + } + + private void OnEditorApplicationFocusChanged(bool hasFocus) + { + if (hasFocus) + { + if (!m_ApplicationProxy.isBatchMode && m_ApplicationProxy.isUpmRunning) + m_UpmCacheRootClient.GetCacheRoot(); + GetAssetStoreCacheConfig(); + } + } + + private void DisplayPackagesCacheSetting() + { + packagesCacheDropdown.SetIcon("folder"); + var packagesCacheDropdownMenu = new DropdownMenu(); + packagesCacheDropdownMenu.AppendAction(k_OpenFolder, action => + { + if (!string.IsNullOrWhiteSpace(packagesCachePath.text)) + m_ApplicationProxy.RevealInFinder(packagesCachePath.text); + }, action => DropdownMenuAction.Status.Normal, "openLocation"); + packagesCacheDropdownMenu.AppendAction(k_ChangeLocation, action => + { + var path = m_ApplicationProxy.OpenFolderPanel("Select Packages Cache Location", packagesCachePath.text); + if (!string.IsNullOrWhiteSpace(path) && string.CompareOrdinal(path, m_CurrentPackagesConfig.path) != 0) + m_UpmCacheRootClient.SetCacheRoot(path); + }, action => m_CurrentPackagesConfig.source != ConfigSource.Environment ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled, "selectLocation"); + packagesCacheDropdownMenu.AppendAction(k_ResetToDefaultLocation, action => + { + m_UpmCacheRootClient.ClearCacheRoot(); + }, action => m_CurrentPackagesConfig.source == ConfigSource.User ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled, "resetLocation"); + packagesCacheDropdown.menu = packagesCacheDropdownMenu; + + m_UpmCacheRootClient.onGetCacheRootOperationError += OnPackagesGetCacheRootOperationError; + m_UpmCacheRootClient.onGetCacheRootOperationResult += OnPackagesGetCacheRootOperationResult; + m_UpmCacheRootClient.onSetCacheRootOperationError += OnPackagesSetCacheRootOperationError; + m_UpmCacheRootClient.onSetCacheRootOperationResult += OnPackagesSetCacheRootOperationResult; + m_UpmCacheRootClient.onClearCacheRootOperationError += OnPackagesClearCacheRootOperationError; + m_UpmCacheRootClient.onClearCacheRootOperationResult += OnPackagesSetCacheRootOperationResult; + + if (!m_ApplicationProxy.isBatchMode && m_ApplicationProxy.isUpmRunning) + { + packagesCachePath.SetValueWithoutNotify(string.Empty); + packagesCacheDropdown.SetEnabled(false); + + UIUtils.SetElementDisplay(packagesCacheErrorBox, false); + + m_UpmCacheRootClient.GetCacheRoot(); + } + else + { + packagesCachePath.SetValueWithoutNotify(string.Empty); + packagesCacheDropdown.SetEnabled(false); + + DisplayPackagesCacheErrorBox(HelpBoxMessageType.Error, L10n.Tr("Cannot get the Packages Cache location, UPM server is not running.")); + } + } + + private void DisplayAssetStoreCachePathSetting() + { + assetsCacheLocationInfo.enableRichText = true; + assetsCacheLocationInfo.text = string.Format(L10n.Tr("Your assets will be store in {0} subfolder."), k_AssetStoreFolder); + assetsCacheDropdown.SetIcon("folder"); + var assetsCacheDropdownMenu = new DropdownMenu(); + assetsCacheDropdownMenu.AppendAction(k_OpenFolder, action => + { + if (!string.IsNullOrWhiteSpace(assetsCachePath.text)) + m_ApplicationProxy.RevealInFinder(Paths.Combine(assetsCachePath.text, k_AssetStoreFolder)); + }, action => m_CurrentAssetStoreConfig.status == AssetStoreCachePathManager.ConfigStatus.InvalidPath ? DropdownMenuAction.Status.Disabled : DropdownMenuAction.Status.Normal, "openLocation"); + assetsCacheDropdownMenu.AppendAction(k_ChangeLocation, action => + { + var path = m_ApplicationProxy.OpenFolderPanel("Select Assets Cache Location", Paths.Combine(assetsCachePath.text, k_AssetStoreFolder)); + if (!string.IsNullOrWhiteSpace(path)) + { + path = path.NormalizePath(); + if (path.EndsWith(Path.DirectorySeparatorChar + k_AssetStoreFolder)) + path = path.Substring(0, path.Length - k_AssetStoreFolder.Length - 1); + + if (string.CompareOrdinal(path, m_CurrentAssetStoreConfig.path.NormalizePath()) == 0) + return; + + if (!CancelDownloadInProgress()) + return; + + var status = m_AssetStoreCachePathProxy.SetConfig(path); + if (status == AssetStoreCachePathManager.ConfigStatus.Failed) + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Error, L10n.Tr($"Cannot set the Assets Cache location, \"{path}\" is invalid or inaccessible.")); + } + }, action => m_CurrentAssetStoreConfig.source != ConfigSource.Environment ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled, "selectLocation"); + assetsCacheDropdownMenu.AppendAction(k_ResetToDefaultLocation, action => + { + if (!CancelDownloadInProgress()) + return; + + var status = m_AssetStoreCachePathProxy.ResetConfig(); + if (status == AssetStoreCachePathManager.ConfigStatus.Failed) + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Error, L10n.Tr("Cannot reset the Assets Cache location to default.")); + }, action => m_CurrentAssetStoreConfig.source == ConfigSource.User ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled, "resetLocation"); + assetsCacheDropdown.menu = assetsCacheDropdownMenu; + + GetAssetStoreCacheConfig(); + m_AssetStoreCachePathProxy.onConfigChanged += RefreshAssetStoreCachePathConfig; + } + + private bool CancelDownloadInProgress() + { + if (!m_AssetStoreDownloadManager.IsAnyDownloadInProgressOrPause()) + return true; + + if (m_ApplicationProxy.isBatchMode || !m_ApplicationProxy.DisplayDialog(L10n.Tr("Package Manager"), + L10n.Tr("Changing the Assets Cache location will abort all downloads in progress."), + L10n.Tr("Continue"), L10n.Tr("Cancel"))) + return false; + + m_AssetStoreDownloadManager.AbortAllDownloads(); + return true; + } + + private void GetAssetStoreCacheConfig() + { + RefreshAssetStoreCachePathConfig(m_AssetStoreCachePathProxy.GetConfig()); + } + + private void RefreshAssetStoreCachePathConfig(CachePathConfig config) + { + m_CurrentAssetStoreConfig = config; + assetsCachePath.SetValueWithoutNotify(m_CurrentAssetStoreConfig.path.NormalizePath()); + UIUtils.SetElementDisplay(assetsCacheErrorBox, false); + + if (m_CurrentAssetStoreConfig.source == ConfigSource.Environment) + { + if (m_CurrentAssetStoreConfig.status == AssetStoreCachePathManager.ConfigStatus.ReadOnly) + { + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Warning, L10n.Tr("The Assets Cache location set by environment variable ASSETSTORE_CACHE_PATH is read only. Download or update of assets won't be possible.")); + } + else if (m_CurrentAssetStoreConfig.status == AssetStoreCachePathManager.ConfigStatus.InvalidPath) + { + assetsCacheDropdown.SetEnabled(false); + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Error, L10n.Tr("The Assets Cache location set by environment variable ASSETSTORE_CACHE_PATH is invalid or inaccessible.")); + } + else + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Info, L10n.Tr("The Assets Cache location is set by environment variable ASSETSTORE_CACHE_PATH, you cannot change it.")); + } + else + { + if (m_CurrentAssetStoreConfig.status == AssetStoreCachePathManager.ConfigStatus.ReadOnly) + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Warning, L10n.Tr("The Assets Cache location is read only. Download or update of assets won't be possible.")); + else if (m_CurrentAssetStoreConfig.status != AssetStoreCachePathManager.ConfigStatus.Success) + DisplayAssetsCacheErrorBox(HelpBoxMessageType.Error, L10n.Tr("The Assets Cache location is invalid or inaccessible. Change location or reset it to default location.")); + } + } + + private void DisplayAssetsCacheErrorBox(HelpBoxMessageType type, string message) + { + assetsCacheErrorBox.messageType = type; + assetsCacheErrorBox.text = message; + UIUtils.SetElementDisplay(assetsCacheErrorBox, true); + } + + private void OnPackagesGetCacheRootOperationResult(CacheRootConfig config) + { + RefreshCurrentPackagesConfig(config); + if (m_CurrentPackagesConfig.source == ConfigSource.Environment) + DisplayPackagesCacheErrorBox(HelpBoxMessageType.Info, L10n.Tr("The Packages Cache location is set by environment variable UPM_CACHE_ROOT, you cannot change it.")); + } + + private void OnPackagesSetCacheRootOperationResult(CacheRootConfig config) + { + RefreshCurrentPackagesConfig(config); + m_ClientProxy.Resolve(); + } + + private void RefreshCurrentPackagesConfig(CacheRootConfig config) + { + m_CurrentPackagesConfig = config; + packagesCachePath.SetValueWithoutNotify(m_CurrentPackagesConfig.path.NormalizePath()); + packagesCacheDropdown.SetEnabled(true); + UIUtils.SetElementDisplay(packagesCacheErrorBox, false); + } + + private void OnPackagesGetCacheRootOperationError(UIError error) + { + packagesCacheDropdown.SetEnabled(false); + DisplayPackagesCacheErrorBox(HelpBoxMessageType.Error, string.Format(L10n.Tr("Cannot get the Packages Cache location, reason: {0}."), error.message)); + } + + private void OnPackagesSetCacheRootOperationError(UIError error, string path) + { + DisplayPackagesCacheErrorBox(HelpBoxMessageType.Error, string.Format(L10n.Tr("Cannot set the Packages Cache location to '{0}', reason: {1}."), path, error.message)); + } + + private void OnPackagesClearCacheRootOperationError(UIError error) + { + DisplayPackagesCacheErrorBox(HelpBoxMessageType.Error, string.Format(L10n.Tr("Cannot reset the Packages Cache location to default, reason: {0}."), error.message)); + } + + private void DisplayPackagesCacheErrorBox(HelpBoxMessageType type, string message) + { + packagesCacheErrorBox.messageType = type; + packagesCacheErrorBox.text = message; + UIUtils.SetElementDisplay(packagesCacheErrorBox, true); + } + + [SettingsProvider] + public static SettingsProvider CreateUserSettingsProvider() + { + return new PackageManagerUserSettingsProvider(k_PackageManagerUserSettingsPath, new List + { + L10n.Tr("cache"), + L10n.Tr("assetstore"), + L10n.Tr("packages"), + L10n.Tr("UPM_CACHE_ROOT"), + L10n.Tr("ASSETSTORE_CACHE_PATH") + }); + } + + private VisualElementCache m_Cache; + + private HelpBox packagesCacheErrorBox => m_Cache.Get("packagesCacheErrorBox"); + private HelpBox assetsCacheErrorBox => m_Cache.Get("assetsCacheErrorBox"); + private SelectableLabel packagesCachePath => m_Cache.Get("packagesCachePath"); + private SelectableLabel assetsCachePath => m_Cache.Get("assetsCachePath"); + private DropdownButton packagesCacheDropdown => m_Cache.Get("packagesCacheDropdown"); + private DropdownButton assetsCacheDropdown => m_Cache.Get("assetsCacheDropdown"); + private Label assetsCacheLocationInfo => m_Cache.Get

;1m)917Q`?jDYM~8%nf| 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 literal 0 HcmV?d00001 diff --git a/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Rocks.dll b/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.Rocks.dll new file mode 100644 index 0000000000000000000000000000000000000000..22a969d8628448d6678ad64cc554beb3f1f46dce GIT binary patch literal 28672 zcmeHw3w&Hvwf8>f%$zwhNv4^}yR=Q((lX79ypz%geV0JfR|2$9Oed2`J9IK9otc!T zr6J)ZNa0d1@L51rLw<3;_nD~= zC@Y?s+O;{Bsu)O`o08%Fibyz-Fw+%1(Te0?q9T^4ShA|KqTlR|*5>8;PP9y~UMj>2 zMH5e-8tJxcJ0zx6LE+O(6SEb*?ApiMu2oU_ce@U5T_J>#B{x8ymPOa5qubMn&MjSGY*Tq=Z@m|34R+CP#-|1I=%HB>5uPfe8p?o!}yWu;oaObcNQbV8R} z=ni!!Nz1#;iO?)Rg>N%etvD1Q&4M~jgsn={@(x)@Gf#kSb+uJ=qbw?KGbK|qF-ksj zGJz=oGc~iE%H*n=Spg)3hUr=eQKeUVR4wG8%Kog@F$E<}2BSd|XIvIEflgu8WUG@kG9;15L zhcr;^tD3GC*ZVD7)l$o)=_c}<&xD#!FInf)H4_8lYk0o$M!0}M%Xz8BUu@x7$>l&WRAnnr3=OoWwQwFFclQEsAIKot;$ z>h-D+D0HJ@qVx2siJ*{E6w@FoS2dTzffS~TZ-*|OZ$ZblgO(|a`rajm;2%r}CMcoP zA@T)92osJ5fx9w`y#j1Gqov3mYp8T&m#lG0+H5MBWoRYHl6C8??11{o4@^$l0t8Zs zL8Q9EU8`}|RsER021sfxfQhK{N&ZffR-Qux5OoFsSsvX|Re4VNu~Zl2Gt^zk0KOU8 zuCqv+>QM!)#mJ#Nb}6T*21BC`rJ5L3U$vo{>u|5pQ|oa<$_OE;=|0`;#x2KVo&#>K zQP!R3Ev?nPWwp6grABE)4>*q;`*6cr>JpfCw5G#8 zdFj(9N;gd819%Q?%z@zuZlPX)>O58VnCL>E2~t<3?_>wdkMO~cChcfsK+n-gSI^a{ zKA*ZSuZ`xd&OK4!3b-ncq4vh$F#JSi)IYbO`ASvp@Mhov7gGi9pgR-;U7!c_rHE}_ z|38D-b0_d`<02dl7c>J7<9-BJ9(ag#mXUlbu2XR#n0QQog!?+sGjX+@kAg(!Y3`!k(+f->tH!&_g z+AZj9ew#(*B<H*rOx~W{{xH5nyuo z%#5H!3b3A0iBK(+%@e5v4LK@@fJ$Tu-h{woxrABgEAR%qoE!^sf;pTW3vvUwXaMqK zg+!Fv()j|_Nt2{dO~fEM5<~Fs=2F$g9pJX`U36LqO#U`~kld_@xOwHHda0yV7j% zo_gfNk3X(#QE7LMWquoY$T=rqE`1qkDTn6dxZURkP%*ay_}VC;BlRL1V}6=DaLWy< zp`EywEa-$R!@CeXWSsR&u^He89yCv2x#ZmrqEB3b>x;M^#q|qZf5BCV(W9YVfolV< zIIatE?Z$O8uFaUncjNvTuK&dKJ6tXV`b1nvnqnEQ4Y-oHuE0h5|0ma-(0u^cleqp9 z*IT&W$EBkD1YDDF&BE1!Yca0XxV#k)!{a$?fwrv!@C@%llhxwTFm53Xgx+2dP%dW3&oGiP(Ni3tjGcN{c%Vqi!hyD;_>>0k)q2FPe`a|mfg6Yc~`iD%9 zI`qR#Uk%uhph`$jY{Oa3U!G1IKRx`*j29eN+rpK<7GnZC-Q zN0{Di(^V(C`XLyf8GkuR zkrYy@%lu!sRXTK`q!Z&3U8oV0Rt+@)^7B3x3Oc`_XQqv+Nm)=gKL==KzPz9oqAXWF zwQ-)+{b6)}u2GaYxmu2u(Z9RL4mrz0$+{W7;k_spx)H#<34kBCq}aR}bi-#Wk&iX; z1QJ5tC*E9heH3fuvAdBvOrW>vsl@dGqTK6lf` z<#B`>rL=p2mqB3;=(c(=434IB34Axd0Hb-{qQ;2fW(lEm@c6 zU5cLPQyvVDn1-tXSJeVzct3PP^^^~PhB}PlTOIldrf+lTZ!-NwhrR=}w}Q?V=HA4j z+aZ!}$XR?Daiy;{90BTXF*$@e40g=(_=iL9jE2VKQw-_pXn^e7)C&h zu{k+o)9Giaud)8u$LYU|p_e|~PAQjm&_(N)`oN{IE5bDc7X`?vxK`l8ql@UnMRRTh zSKAc;#_)YkyD?ip-|x^!TA;sS(^b2S;cq&`fHC|nhlm)%4>-hG#_)p<(QXVs zVQlJUq*k453}bb-h-m@6e57GgK(81$m7&mEU2m3*3Ev{5K&5)RKV6IW#x_)UM8i0C41+F?=3vjK*g&5#7;tO!U6c^S5fwUqp ziTHrus6fw)IT#Dk_9%cl{9V|T%lkb{gKN?Im_Fdp*E0Q>Lys{1J)5pdsl(rQh(2}r zafev14nN@#E7W1+MtjLpho5wa26gzLL(EWzpK^#&b@*wA$We!XXcHxrzg0fm&PV?i zk4e^5rB0^S&1XXNJ1yse@dK6|LZ9Z7t=-B249*VRTC)bmBv z?+OsJrBsG>)k0MG6IA2VYk=$KPl3~O#`Cyqp%;kyV7#k819uqZ<=Fx%#o2<1YEmyk zFk^%ybT(c^=i*hBGgV%VO4iBqEt*G#$NPy%fUKfdt2p=#EdVClrHMzOkK7Z`3fHLS zOQ@hGUo~IG-TXN~Ni9b;(Z%L30I}M?f?E>NI*>#N41`_HCev;A-akHn{{O+M{v)FQKtC{|uQ=Gtp5#^Dh87 zRh97jD6m}J>PhnhP^#70v<;)aHvb9$%@1*_c}7klSaf!Z_8ck@t*6U2(lhTlXy2H6 zX*8{RtB$MpBM8UWTWB83s`!VWP_f;&ZD-i^x&@Lg&7FW+ay3%0GNV{CDW-P!fw(n< zxbUUXH;V7oqM2$jt7J1}Op{&uOq(W(mO;6o&MkI;E+e~Ra)JvK)^O_tSW96`<#U+| zU?#dv6=VwQIR!rT0>`S zL8V3?&LK^i8ip|?<@Co~#`I4jBvNbt)UmrzTHPQvtejo^3^ICSt7URJV#o zCkW9Fso^WZJl4%qD74gLMbk07hFJi)r(|7@M{9UPCtEl#VVgyCpQfp)VjICZ7!3v2 z6UF_6<6?qpZO+8RHO~35S&Fj!jiq)?tkynNPL+Y{({hS)s|r2Fjd?nM`{Xqzf^C$n z%QZaL#2S9ZUY$U7!@EiH&R@V{A=rrs#KfLLT;vNxzfaY6m4j466@cbcfL(Yfmgi9_ z`AiQK0d*%SVfXP-txGR$^odtJYG^uGc>a@fDb<9YLTp6-FYI_JOe;2VOELn)&7hWXSF^P!Rgy|5~-Ab#5z^@hL>m)OE9Hc zS-#XRUt{Z8T9~UyOVV$(kS!Jas3G`T)%Octqo^$|`1Qpv%C;nI7r3749Lo~&1$FOE z^0#uLJhI1^KSb^>M-SlHRjv<{ojxc();L++NnM-i>BbzjShn9+O zQHy~iD1E!AZ)jLU)j+7;9C%qd4MWEW7`Zls5iqb1lp2hHfnBX+FjAX}Vg8Ju9j?kL zuAMbxw?{K;aaVVuH(k8iYxMO`Rb_1|LCUl>sO(8?0gf+9Na>g!r&)M1m99-~B_&EA zl~Xhm`x1Dnne}w9lyvbih33Pe&eInu^hAjd+!foJYU^qn>l*7RA>-);Hbp5C==5Q1 zRdIiq@XmBHme_CXSkrr*LeE?ShE~F3sUf|QXyK%u~mahPg@uTwm$_e^{gQ5a=DsP80vLk)} zfzPRa*(#q{n)7&pF22R^tX#rh@HG__h<8z;E?&$ze}ayKYJzY3?tpY1a|RiHF< zJgf<*iqp+`wJP+a1 zfi}78`Q?RoD zwfIG-tjzzSxCUY87kk;xeQfhhZt00=mo8o_-dW}svzT*TE^$7{xv$7CE-v9#0P5l` z|IRX9T$g(veB0|KpZDgI{VpyQ=eGN~H!2wS0P129`rj{J(>(6$ zxt|a4NF8xg{{(^|zfY*1wE-QTQ(LyM<7QOlXix2Q9OhWZrvNxpP3g~S0$6KCPd7r(~> zHV@yIbPH{2zW6dGu$W?QmkLD8Q@6(R#DVzujQIz}}wimljxP092TRcPhtn6h=`;_*j0utUc#bo zDlPY@V#uP-HfDG<@i~h+-(BT#3HMZi&mOTiSnqL*#Y~NggGQA{7u^=Mx2)CU5yKX> zs(7Bq5cgQrpS*_KEB-Kztc;51yvsd4(S@B4QBRk4cyh!Zi_(3c^5lsJEULm6^-K`& zSkxll7Eiudf1)hs&fn?@h|gKnwVv&s0x^yD0kC;1^oqnOOg$lP&l^N?K8>jx#0=L( z=polksrih!%u^x?E$VJ@m8VqP%+w8HoAy~xnRwo!K6ZW6Gg17OsXgMW!Ebu76XDMj z?r(U6HpQX7m;00l%e5tYIrk?X?gr3LxPPL&?BV7xwMKp2!)`G(-}4*KNnDCFPxSoJ zGs~fF$os%ko!#b3MnXcc@!RiVQ4l{CUFtUGEg5*`aETkU=|D z`aI$8bk!TPB>}3{J;#_MT1jZV+m5+*l@7)Je_yK+0GyHdxfWz_4+;h%-5~x{6gO6izhFhC`aUd(8>_@-Zqy#}O5PR5YVjmZQpk3rzBPi5&xE)^ zY;gaZu~v*&)G|<=;%=t)h~>r&MwfWjqPDp|Z=5M!wKQ)iyu&zKOm34_+V%U4b%G8| z$mT1>4;kylI;QrBKjeJRI7ghwow!FFglvPj!lKj(KQhh}&s)^)+?S1Ram1q57QAeP zMI28AMMRGOsDB=1D7E-l^WLqS2y!#w>4A%(19R-g<9J zEU_rfJI6aHR$J5`Jxje8hyxb&Q_m{zkT_^jHyLMpcZlbhx|}o7PVo{`mxwpTfU;Bk z+L5`%g~FImz8qG1@JP8!EU>7TODBTLJ(Xmm;y&cYU3?q_P47viGeOm{?6C4Ko|Sfq zR!MmyrB$GoShCt+E2z&|R6Mv4)IO#zH)49XcbB-+qLO+P)V&sUg%$S77lqY54RZ;L6P}w~(D&An(p3)x$uk|7~Iz6GF zm49H_CE{xArN+uG5r45{rOGYdOGID+^^3G}=@=`Qipeay1iQ&EdoL9&S(=xP(Y#D7 zvNWfNr@WVm(=DnC)a7EWMeP9fX+dlJOL(MF#2uvs@5IBmBKErpo{OD;jo(*B_*UK< zOC1ScKq*y3@T4His#q~?+_pv>RfO?KK%D%1Rm9lZJs#pn{tA}9iaof3HIZPCPNn)w z#^VowuLy#wz!LLM$3tABw0{$~SK@!kt{1yb+lPCxxwmoICsJSbs>Ee~5>!Ps_V}__ zZQRGbF&Ax7g~SP}ViNP^DBO-7R=L%h_%H6^496ZRsVU*9T$XecA@OW!W(3tSW1X!t zZ-R;%tGGAju^ob{_!=I{5G{cJ9sUKxk}70bvMl376YF@~v+Md~Tor%i@f|N!MKeb! z@yFs1@OWkG@6*WJ8+nXmv>XrVO?g$^YQ-n%%LtUC=Ca1ik9mjZ5L`O0&*R#U_v2_k z765ePOpoxXfId+Vn2!@gf(rqQ@J#^WYZ$I)7-oKq@vRI43R#$~3?g4HR47m8ii?pE z7b>|pELx~sj0{*Pu0rNpqg;iIx1ROGDwP_71EZYiccc|~yt&RXs+4MXa2 zN5Sc4exP`Z7)9B9v|}rFL|3Zao zw*}SmHrMht4$8NP_rwdqiGW`$dJEqWhlx~LB3t7rl5a7+~X!cuPVz?;B8($ z-~)L@fOoo2P=e>)e^( z_?gpMGE;2eKHR{2{tdjY^|B{%v}Hg^19#&*fcE)m-udqrjb+q(-_s|G1KbY>)#q{_ zR-RLzal66q@I0Yh$QE8wnq4m|S1SI%p8;Idp|9B&7e%k-CFd5Uoe zFsA51PQ6S0An*?GKWOXJ2NhZ^537F$eo(nq7usQU6!>BFNoXEccQD=!4-YD@ zxvIor^-}@jpW`E#$2u#S^Ie@dCzlX>k?}^xcl(Jm%<$hCUdHf7hJ~yvOi;mNqc|J%)A6Kg#eehOaSnv-CFBpTPJbhUF~n zV`wtGnBi3nZw5T51WUpqtW3)zeVS?oyZKo#c8?X`gViOF;xSyN)V(g>zkZ zvyN9CELrUesK3sw5?;`Kzc0i_dbsjl4Gi`xLSFbHu)_9Py91 z?&o;8Ql{=Ji%6u_ZRVUnt8j}SR#ZhGe{2UV7z4wE&ynuWlYY(%v zS?aT{@44EwW4TYc9%h@f)c+`Z*0lzl7hUVM@3`MYE1nDG!(>sJGDV1w6rhw^-qN9&b|;+$(m&hwqDNWmWDUTD|ub?`-!ht-WNO zd#^~L|L;<1um2vThI@$H{ydjm2y2GBo#7h5%iZf49uSo0pJV-Bux5;PwlaK!v)MbG z!H)1b#;A6R>pSjI?L#e$x1#AZ;|TA?kMNns5kBQO!e<&s_%s7JR;44b?*^pocZ9Rw z5kWigJ<3D+A$Wc{;=zS}xC)W;U&!S9#V@sqSX^08bE_uU1SK z(*UdRW_m4thcpLp4(h4J_eh%o&k)-HJH=-J&t-l@>;oPVS}wu9Jc3XAYjKKGmmgvK z-(&bohMGb(PG`87VOU9l6JdOm@k0^5LwsLD78ovO7-6`N;iC+NMztJr z6I`GZ+{kc*p}?8Q``!wMBMkR3d{jb%%Q6&R)?~PV;YNld4EHg7l;I(U_}-N)GhD!M zBg031_kn+i;es5(H!>VyxR2qZ3=ic{>qIWW3Wf_9Ze%#Za38}*8M-EX8=5zWhlQ?8 zRoav_%GZ@g6-Aw<-lFDeCu!~4Ia;rl(spPUA+A){2G>5<0_G4!? zfzQRCEO{0?I8pin;C=c_fP1yq0F#Ap0-jj#2d|3neKkbR2AsL8IKlIv>_$L5M_|{5 zrvpIjCo#^7=mk{qwNW1MK0rTyqE-%g4|ZetsVSn&FTN>e06rj20(?l!0(@9hi7Db_ zu?{c1+#?vUfMmZKlTStz#W&gZE6R_rdv^X@|{=_9`vAWYR8>H7zGufaDB z{p7|8rW<=p18;g5m^C>h#x66>_9lw2t5oAe@jOmI>D#n3@qB`JpDg~#7Qf!&H{xE3 zQ;AaXEnI)an_YXANAPxbtvIONtGutBpmw?^GGnwJfk92o0iKPbO;i1Lxa4N+H$Wpy!sWTl;$0Au}$s`L& ztHILhh^9B2y=<0Qi<8lCI*L;C3s@>a+!ei%?)D}sadtA6jxJ0l!$ag{XKYgtm`usV!i7)R4l>F#XeujdBA5`G5@x-%{BD|*ApO`xqBI_hn#{O_qp?1ySpz)h6f1k@9tg}ON8U`Aq;wZBHh>^)<(m<5?hsMPsC%1 zsHCi>HCXO9Snd-|?l-{N@k6<>K`a|gL~yf;H(JFTt>Q#e@kXiFXjk9TB(kapCCl4p zY`VMIE>PcM%N(RtVEngrx3}4nHi}U(x5Mlmj7R6=DXYUwn6-3$P7zNOy>UnXd(?I3N|jicrcj+ODc+my}csV>qNk^STx=%c+N_6 zuHB~jTe`a!g(F+=MXn`TjGz7=&pj)aiqVWZPW`NKGDfp0b({#UN|SwDJGFh)0H$7| zmwVO5O^avEU9oV0rZBhZOrXg{=AcEcFfYg^(F9~Hr;QegT301wn`llh3a6qOZWhHI zk&$$S(~-^S0E>g9m5MG4r?V7fP5tt=Hi}#uiL!?)k={}RM9F;FjszV}fLz$Sjqlt8 zYomQp3=Y`RW`?$VFT$Y-&;^~*t%F=)SEo6cM8$LG zH+FZYBu*niqs+s=2sfEAIZBRn)c~Wb646CN>8M3@U0@QGvPg3vLdGzAxl2w9r`r1w z$f7;5&D;WhJnD>*-CO||9ekS=LD{)kw9}GirYN#F#+R6bgxV?1A}RViF>+ZFi==kQ zG$ru2ERe07;o?@)xG@K_aRBKn9CtX&uvjp`Q9{EpmV?EmpXCX%VLP zP;`X1L|4ZW3CwCDW#{q~aKu*5umi{8FUkyPR#_SiChdA18HG0!YojSMzAfs|PBXar zg=xIB(KDEqy5!K3Xe5piNNnQL7#Ldo&P?=1lkp*&OYP`HcEMW4yAn3lh0#qo^{S&OmT>BR0&L~I1h(LgL7O>$dNpx22qu_W3vxM>qj;|ve#w499LElj15>f%FP zv2?a-7q$vmMrap#ftlQru_5h7lc&Xcd!vaAf9dvgG(nzcShne9aPcf`ML$v4p6D}^ z{n#i|gdL}a4O}z{LCW&G%gmUUjpveUqw(-|#!?x%UH$4L@=zq55p*Soz>7pvsjU9S z#@`M!VV7KN4h&&Q+ngm@yrPrpjmN@?EH1}BkAKF<+Cfa)er)9X2jE#xEFMb_Wu$V| z>WoGPv7gW8lW}a^kC&t@-R`jCCud<=5i)atDdLY|GlB8!J}Vp_l<5$wg(Ny@MIi1r zhKrK4>yvvvEC8I+IO}xAc0_6U;5(&+eqzuH)SV)%Jw@|rRi9W9PNmzC#2Yc{TM#Xq%iya+;)+x6L8=lB! zVS8$m){{Z!1u^VB1a!9W{$0i&*WZp{OQr|I@$60Z;#f8*&cyC;NbbM0@!GX!WJ{{H zHy($->-yu;9@Z^JIN$IN-KvKYK5xFyOwekLowHcPJ89l3Gn01FtnDmsl>B*R=4C)w zIi9&4vF)*h;5b}@(BtVSdL67i6YjK6&7x#9W-;Vo@(SG-i}1{%5wJo~u3VDa%d42g zY4qfiov>9cGR(=}8Te?Q^~@*i&B&5yAMd!$L}p))jSR*YQx~~G#IkVS+hs~vo4YK= z@m4XGv>D0Lq0z`9dF{-i+vN^0i{mVCS-hp&uxMq`$SVW1C(L3|r>r)yiKkYqG}G-g z!D+3F_AcEXiSpV?{LaCF0W&#<+d*rAy*O5uE+GOy?2yTDv;rP{pbf>C!ze2UWgSn6_VyLl<0cDjoK6>Pe4Bh6wcD{I7T%OFQ?Q)k zA{;d-4DH`o#Vk2FhXp8$!pPDo7#o4aCgHe^T4x*fqQN@@bD%St+!n)9ZaZX)<>nxo zbma1x2`>WizKCWO!Y?&$c>sf4vm!nQ@^7{zOUG)>IF6lzQvBSLp(vy?6qTh+Br9GS z#rX|CvZQFt?4w9_%E_qq^6zxkCrIp7Z-q(kiCYfRUmwg~(|EBue)$sQkMmF~m7G~J zj&E0;wIav@a?~!Yvo0k} z>rNh7HQ5W4RY?qUco3Xrv1AH|KsITQj`eIOk3yny@#8A&rijIZskGVe?2hRv zzt<7k&vy=EoVLUNgr-@2mfgfmX0}f5?9}nMy5#Su{ay3aiGQc8o%X5MvsLHLZ|LsE zV*wp1$|qUgWQZtjHMrXr<6ur=?WvW~3p(Rwnzl;VcSwCYHWzUMw3e@=Kcs1OO&8$^ z#FYL0f)z3dLH>K25$jI=@D?81E^OrGmeSg0(VS#A5YvqJ5Tg_08cBDA6GOrr=w7-N z+h^>M32#r}TtQN_TOV-3nBSZTVtiwA&NH#AF%dWcp*Q9@518v zCQOvj?xR~Q729!-ix|Eyi_vdcEPgxQcOS#gnlk?Km+f@hEdlR)=i2{;8V#2%AtOI$~WBh=ed_3>bQ2x%=YKce&;2jRS3mZp(utM zAW%f8pMVO1>M072+^!S|R|USV17i{~_JZN95SGYYA%Y|OQ8>6z^D*}YB{(|IfS3`K zBGbWzhAac-dEoi+C8+90O(Gc9i-P^&x+_#=QmM-a)a6kEQOE*OH{Os4hMl68ZkV*f znny8EcD*u1poRiLM870J!PU|8Bo$ofw_OX2Tn$0Lg1g&CkUZ#cc~rmQLRHjsLxU%N z1753sP4juQpb;1u4UAldrUGGjnc-220wa4A!$6xE(dEqtL9j`kBBm(l1Bv+H*vR#2 zfhbUPI7esGH7!7qs+hQ4A1*SK^r4UY;2+U3##@D;SmjU6>GW~2SU zXLu$+fo$d*?!d^sfstp7$wqMGIjdKKBaZ|}4!HHnka6EU1HW8k?OtgOCGG{whbtFX z9$6lF5SGywe%vTJ&ZEZYEO`zrD|$x0QQ&c*Tk)FH$eZ}bwZCl-B^b8en-n0Vhaj-^ z*%$U`bQj}q8$u197aV!T$XNIWd_WZ3OA$ZG=W(H3Z~8zRf~o|fBPfjmQR49g*VvY+ zV(E%O(X)oYdHEhKOAfKuqgh&hU|BL9J>G#*7&!)+=w9Q8hifokm?Rjc15Vg?Oa=3L zl|irrx4jDAu7@Ry%E8duczM1`x_gx=h()?l5L}O#w3zr)obaH7W9R*R55nN1;HVN9 zb^8OOUT3O+YxnO*_!SAJA>IJO6d0Y%oi@7H?nV@pia=Pw3m6=EAA<*IwfrNlBu^II zZ}-PX9ARv%lvYWJ~9xoJ%y#CCr>5^7^O*kK^03?VkIwt5XIiE9jo5rM(j;ma2ImmU3I%wPU(r2XpTQl9(DMo=XQ)3-`cU^ ztg@ylhK@IxG~r3IKX-=fZk=|AT&{_4}NyhkpIT-ETLq zZ2Hl`mY;Oqa&*~z&;7rt|NPSrf9u9U-|O)Y-ucOwgI9>JeEr?lSKgo1Sf4k2XxHEw zcbH3-mTcR+{OqkeXYBs*JtZB%tHQz4l-rB%YU-}Ou<6U)RlQrkbmPRMy7I>tR-F6b zc~5sPuj#+1TQl!^dDHoyZ7uxz%unBZ)`6KbUsHsp2N!xN8=`AQz5yy9*8)FrGMR4z zky%p%DyL18ys?6@6x3F*Z604_B_+6&VLQVPhHH31TEqC6Ug*&JLu(hbWBGN8$_yHL zT8TK4wqiYjbdcc?v9#bW8DlD}`GZJLke|n4Idb*%e6qpQm8Y*Y?P;xW*agQ0-xNVH zgtX(b?r!UDSa+Xw&$aG(*4=N&a+9$>vjOz0#R{J1upYEoNLH5CBMx@JBQRmsV0}RP zno9_pr3B~dU>m`?#2xtt?g)R3+ABW%Tu~<1Nto?+o~3nu<1C&)pj^a%u7Qc@) z23vU9N*YErvTnW&VgA7sZiWZ0j7}vQ_ZirVP!+QypFR$)mT%mEKoa~#tGlFvbqk5{1-Uj;46X!!_fN&nCrQy9;RYe=#vlt*v5LbOv0 ziAnAdDtnyaL0^bckgN*qd>6fEg+HQU;3g1PnA%-x@!5Fm2H&(gr-V4mH!nyj(4$m< zT`+#xo_QsO|D5bp=i8Ht$L^|VsHfWB}iq-hSIu^X`LNzZLSMP8(JcL;b^3{A>32n z&;}R6y*&-l-p1D6-oECB*^P~;vA3bIb#`lSYjaaixTU49si~>CzO}WbrLC#8xwW;v zwWp!EEfVSLsjF{o>V=h_miqbzG^ak?T;CF&-PqLJ*AQuqG&Y5Mfc3OAwbqBjv%~e_ zzS(GHeP2Uwb5o?br)PFEd_yZ+8+u!Md+M6|>Ka@6!n1qBEv+yEC+eGe8X8*KT4zU^ zTO#!hEe$Qbc&0kOi#z_+#sB0kjv$K9%Z_3`@%mRB|5M}mxK8fEQETd7o&3-299SV#PYj>vj(mQMQesZ50Sx?}c-9g{aLI=y-J z&X)Tx{pIOPZmwBbH08JN?_9j=2Z@jV`o@7TeJSuOq1W~8Kk&y-pA!7_^|$C9#fig@ zeC%F$&BUupFaG_O2M#WN{@b^|vHn=^cfT6FzV>|OhE+NG1xL5OI&brwy+13g`rz4R z4`1@mZ6Ck>wGaKpmx-T0`}$|6|3Fore3;fG`~SB?%Nzb~kjTFr*Jgn&?~=}!zkl^b z6Mw&`5;$bTE4|%#c_E5-h-4A#olZ^xwFA9979ma z-9Eg%&hN4lhwvuAvv5Ax4Y(BV>vrN-ldEtV*^T>3oJ_7_y+>TXKSmE&_Pg`;oqt9R z4Lp5WTQF8D1>rMe)c^S~73bap6DB3VJ)0QpJ3@M)~OTre@!@_#0E~Bj`#Q#M}G-wPvH!d&MybX)YHLdpC-;k7ej|m zYvaJzf*Zjpr96{t;NL&ktvCyMNk}rj)}cf_YOS>{@_&V(zbHa2rnAx{?)W?3fS4iRu;p%0hFZHY{D5Z&X-|hJg)-3Cau7) z4yb3^fYn%3y=Vq@I{K*sW4;X*WAKGOUF`EJ%Pw)rXS>}*@hR^=3;Cpq>nU;c0O!2brEu#Rj1 literal 0 HcmV?d00001 diff --git a/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.dll b/External/Unity.Cecil/builds/lib/net40/Unity.Cecil.dll new file mode 100644 index 0000000000000000000000000000000000000000..c5b25b8dfb7c29ac985b0125160dbd08b5afdf3d GIT binary patch literal 350720 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 z zCnHXd`6|fy=4-(r=4x=bxi&}7wwY-j+hL}8Y?qnlu{~y*$M%|O9@}TGN1Ov@FL=m2 z6Fh8g0*{zmz@z5b;4yP6c-%Y}JYk*>wwo7#r_9+%;k0=Xgxfe{Z+=rgsU?FR1vyh!^v5=i? zvydh1u#hF}vXCY0v5+O~wNRh#v(W5uz(TXfAq&kOhb=UF9I-rr)Q(ynLu$t?WHZMt zTfh^RhrxCW%^RmIG-I5$yoi>Z7)CuZDeN({;gqo5U`^Owur_QzSQqvZ*ckRI*c^5Q zoD=pII4|ryaADX-;F7R*aCz7l;EJ$sz*S-2gR8?Xfa}730XKyG2W$(Ib4_eZm=W9- zW(9YIIl*0F(cqr2cyMo6BDgQCH+Uc{6+9G{0Ui#^1&@Rc0*{7W0v-!12Ai#=;2i5k z)McKP_81GTm*!a566+Y~mqSKdS*dLgSZO34vQi5lwo(fpu~G{kwNeWovr-Emw^9qA zuu==RTd9RlS*e9jTd9T5SgD22TB(IESgD0CT4@yjW~Fu>VxwG!+bEY}8|5;}M!A&P zD3@_I%B8|axlFWCE|YAO%M=^sQe&fBYHgHDosDv7v^@aZm}8^Wd7h1|dZCT1dWns! zdby3PdWDUwdXcy~jpYz1K!o zz0XEgeZWRmeaJ>ueb`1;eZ)pqebh!)eauEyecVP?eZodo-EJeRK4rTy7vsW4wtdD% zwtdz{wtc~N74#Qv*MPs-$j({#eV`IP85(1FB^VZ71#StaI&KT+BR8Cn+;Bc}!}-V! z=OZ_qkKAxRa>Mz^4d){_oR8daK61nP$PMQsH=K{$a6WRw`N$3DBR8Cn+;Bc}!}-V! z=OZ_qk6e2-%A?q+rbau}G|cXX#%`zjM%byoF?OnNyq)TsV5j=_v{QYP?Nr}1`*bkF z?g4Y`Gr)X%JvhYf1&7;bg2nbGaFo3TEVIuB$JtxK3j17eqJ2I%$-V%bVqXN-*cXGf z_N8E*eHqwjzZq<{-^No%SKjLHiKJ@h)g|&^{#0LHiK9gLXI(4qDM-9Jiq^@ebOV zBsgei($hgZlVrzvFwH^xpA5&Hh?C>E2sz(zH{>A>+7S(R(2k|pK|7XF4%)GlIW{14 zoMR(c;dl_7=-3WUa_j=9IGzM+9M6Kaju*f>$04xM@fz6d_$N5W@eVl8L3cC@9mgRr zaeNFecYFq}aC`->a-0EIJ7`b1&T$U%2FFieo8wn-i-Qe7`#bdD4u=`s