From 8f784211558a64496cab68fd21a6bf3d2a59326f Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity.com> Date: Mon, 17 Feb 2020 12:54:22 +0000 Subject: [PATCH] com.unity.entities@0.6.0-preview.24 ## [0.6.0] - 2020-02-17 ### Added * The `[GenerateAuthoringComponent]` attribute is now allowed on structs implementing `IBufferElementData`. An authoring component is automatically generated to support adding a `DynamicBuffer` of the type implementing `IBufferElementData` to an entity. * Added new `SystemBase` base class for component systems. This new way of defining component systems manages dependencies for the user (manual dependency management is still possible by accessing the `SystemBase.Dependency` field directly). * New `ScheduleParallel` methods in `IJobChunk` and `Entities.ForEach` (in `SystemBase`) to make parallel scheduling of jobs explicit. `ScheduleSingle` in `IJobChunk` indicates scheduling work to be done in a non-parallel manner. * New editor workflow to quickly and easily build LiveLink player using the `BuildConfiguration` API. * Adds Live Link support for `GameObject` scenes. * The `SceneSystem` API now also loads `GameObject` scenes via `LoadSceneAsync` API. * Added new build component for LiveLink settings in `Unity.Scenes.Editor` to control how initial scenes are handled (LiveLink all, embed all, embed first). * Users can now inspect post-procssed IL code inside Unity Editor: `DOTS` -> `DOTS Compiler` -> `Open Inspector` ### Changed * The package `com.unity.build` has been merged into the package `com.unity.platforms`. As such, removed the dependency on `com.unity.build@0.1.0-preview` and replaced it with `com.unity.platforms@0.2.1-preview.1`. Please read the changelog of `com.unity.platforms` for more details. * Managed components are now stored in a way that will generate less GC allocations when entities change archetype. * Moved `Unity.Entities.ICustomBootstrap` from Unity.Entities.Hybrid to Unity.Entities. * `World.Dispose()` now completes all reader/writer jobs on the `World`'s `EntityManager` before releasing any resources, to avoid use-after-free errors. * Fix `AssemblyResolveException` when loading a project with dependent packages that are using Burst in static initializers or `InitializeOnLoad`. * `.sceneWithBuildSettings` files that are stored in Assets/SceneDependencyCache are no longer rebuilt constantly. Because they are required for SubScene behaviour to work in the editor, if these are deleted they are recreated by OnValidate of the SubScene in the edited Scene. They should also be recreated on domain reload (restarting unity, entering/exiting playmode, etc). * `EntityQuery.cs`: Overloads of `CreateArchetypeChunkArray`, `ToComponentDataArray`, `ToEntityArray`, and `CopyFromComponentDataArray` that return a JobHandle (allowing the work to be done asynchronously) have been renamed to add `Async` to the title (i.e. `ToComponentDataArrayAsync`). The old overloads have been deprecated and an API Updater clause has been added. * `Entities.WithName` now only accepts names that use letters, digits, and underscores (not starting with a digit, no two consecutive underscores) * Updated package `com.unity.properties` to version `0.10.4-preview`. * Updated package `com.unity.serialization` to version `0.6.4-preview`. * The entity debugger now remembers whether chunk info panel is visible * The entity debugger now displays the full name for nested types in the system list * The entity debugger now sorts previously used filter components to the top of the filter GUI * Bumped burst version to include the new features and fixes including: * Fix an issue with function pointers being corrupted after a domain reload that could lead to hard crashes. * Fix potential deadlock between Burst and the AssetDatabase if burst is being used when building the database. ### Deprecated * Method `GetBuildSettingsComponent` on class `GameObjectConversionSystem` has been renamed to `GetBuildConfigurationComponent`. * Method `TryGetBuildSettingsComponent` on class `GameObjectConversionSystem` has been renamed to `TryGetBuildConfigurationComponent`. * Member `BuildSettings` on class `GameObjectConversionSettings` has been renamed to `BuildConfiguration`. * Member `BuildSettingsGUID` on class `SceneSystem` has been renamed to `BuildConfigurationGUID`. ### Removed * Removed expired API `SceneSectionData.SharedComponentCount` * Removed expired API `struct SceneData` * Removed expired API `SubScene._SceneEntities` * Removed expired API `World.Active` ### Fixed * Ability to open and close SubScenes from the scene hierarchy window (Without having to move cursor to inspector window). * Ability to create a new empty Sub Scene without first creating a game object. * Improve performance of SubScene loading and change tracking in the editor. * Fixed regression where `GetSingleton` would create a new query on every call. * Fixed SubScenes trying to load an already loaded AssetBundle when loaded multiple times on the same player, but with different Worlds. * Make it clear that SubScenes in Prefabs are not supported. * Lambda job codegen tests now fail if the error message does not contain the expected contents. * Improved performance of setting up the world required for game object conversion * The `chunkIndex` parameter passed to `IJobChunk.Execute()` now has the correct value. * Fixed an error which caused entities with `ISystemStateSharedComponentData` components to not be cleaned up correctly. * Managed components containing `Entity` fields will now correctly serialize. * Fixed issue where `BlobAssetVerifier` will throw error if it can't resolve a type. * Exposed the Managed Component extensions for `EntityQuery`. * `Entities.ForEach` now identifies when `this` of the enclosing system is captured due to calling an extension method on it when compilation fails since the lambda was emitted as a member function * `Entities.ForEach` now reports when a field of the outer system is captured and used by reference when compilation fails since the lambda was emitted as a member function * `Entities.ForEach` does not erronously point to calling static functions as the source of the error when compilation fails since the lambda was emitted as a member function * Debugging inside of `Entities.ForEach` with Visual Studio 2017/2019 (some debugging features will need an upcoming update of the com.unity.ide.visualstudio package). * `EntityQuery.ToComponentArray` with `T` deriving from `UnityEngine.Component` now correctly collects all data in a chunk * Fixed an issue with `ComponentSystemBase.GetEntityQuery` and `EntityManager.CreateEntityQuery` calls made with `EntityQueryDesc` not respecting read-only permissions. ## [0.5.1] - 2020-01-28 ### Changed * Constructor-related exceptions thrown during `World.CreateSystem` will now included the inner exception details. * `DefaultWorldInitialization.GetAllSystems` now returns `IReadOnlyList` instead of `List` * `DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups` now takes `IEnumerable` instead of `List` ### Fixed * Fixed an issue where `BlobAssetReference` types was not guaranteed to be 8-byte aligned on all platforms which could result in failing to read Blob data in components correctly on 32-bit platforms. * Fixed issue in `MinMaxAABB.Equals()` comparing `Min` to itself rather than `other`. * `Entities.ForEach` now properly treats `in` parameters of `DynamicBuffer` type as read-only * Fixed potential crash caused by a leaked job after an exception is thrown during a call to `IJobChunk.Schedule`. * Fixed regression in `ComponentSystemBase.GetSingleton()` where a new query would be created every timee the function is called. --- CHANGELOG.md | 110 ++- DocCodeSamples.Tests/DynamicBufferExamples.cs | 16 + Documentation~/dynamic_buffers.md | 24 + Documentation~/gp_overview.md | 27 +- .../uss/LiveLinkConnectionsDropdown.uss | 2 +- Editor/LiveLink/uss/StartLiveLinkWindow.uss | 164 +++++ .../LiveLink/uss/StartLiveLinkWindow.uss.meta | 11 + .../LiveLink/uss/StartLiveLinkWindow_dark.uss | 75 +++ .../uss/StartLiveLinkWindow_dark.uss.meta | 11 + .../uss/StartLiveLinkWindow_light.uss | 74 ++ .../uss/StartLiveLinkWindow_light.uss.meta | 11 + .../uxml/LiveLinkConnectionsDropdown.uxml | 7 +- ...rtLiveLinkWindow.ListViewItemTemplate.uxml | 7 + ...eLinkWindow.ListViewItemTemplate.uxml.meta | 10 + Editor/LiveLink/uxml/StartLiveLinkWindow.uxml | 34 + .../uxml/StartLiveLinkWindow.uxml.meta | 10 + LICENSE.md | 2 +- .../Assets/AndroidHybrid.buildpipeline | 6 - .../Assets/Hybrid.buildpipeline | 10 - .../Assets/HybridLiveLink.buildpipeline | 9 - .../Assets/OSXHybrid.buildpipeline | 6 - .../Assets/OSXHybridLiveLink.buildpipeline | 6 - .../Assets/WindowsHybrid.buildpipeline | 6 - .../WindowsHybridLiveLink.buildpipeline | 6 - .../Settings/ClassicBuildProfile.cs | 96 --- .../Settings/ClassicScriptingSettings.cs | 24 - .../ClassicScriptingSettingsInspector.cs | 35 - .../Settings/GeneralSettings.cs | 8 - .../Settings/GraphicsSettings.cs | 9 - .../Settings/GraphicsSettings.cs.meta | 11 - .../Settings/InternalSourceBuild.cs | 9 - .../Settings/InternalSourceBuild.cs.meta | 11 - .../Settings/OutputBuildDirectory.cs | 51 -- .../Settings/OutputBuildDirectory.cs.meta | 11 - Unity.Build.Common/Settings/SceneList.cs | 48 -- Unity.Build.Common/Settings/SceneList.cs.meta | 11 - .../Steps/Android/RunInstanceAndroid.cs | 18 - .../Steps/Android/RunInstanceAndroid.cs.meta | 11 - .../Steps/Android/RunStepAndroid.cs | 84 --- .../Steps/Android/RunStepAndroid.cs.meta | 11 - .../Steps/BuildArtifactDesktop.cs | 9 - .../Steps/BuildArtifactDesktop.cs.meta | 11 - .../Steps/BuildStepApplyPlayerSettings.cs | 81 --- .../BuildStepApplyPlayerSettings.cs.meta | 11 - .../Steps/BuildStepBuildClassicLiveLink.cs | 49 -- .../Steps/BuildStepBuildClassicPlayer.cs | 163 ----- .../Steps/BuildStepBuildClassicPlayer.cs.meta | 11 - .../Steps/BuildStepSwitchPlatfomClassic.cs | 48 -- .../BuildStepSwitchPlatfomClassic.cs.meta | 11 - .../Steps/RunInstanceDesktop.cs | 21 - .../Steps/RunInstanceDesktop.cs.meta | 11 - Unity.Build.Common/Steps/RunStepDesktop.cs | 60 -- .../Steps/RunStepDesktop.cs.meta | 11 - .../Steps/RunStepNotImplemented.cs | 22 - .../Steps/RunStepNotImplemented.cs.meta | 11 - Unity.Build.Common/TemporaryFileTracker.cs | 68 -- .../TemporaryFileTracker.cs.meta | 11 - Unity.Build.Common/Unity.Build.Common.asmdef | 16 - .../AutoCreateComponentSystemTests.cs | 60 +- Unity.Entities.BuildUtils/TypeUtils.cs | 20 - .../BlobAssetSafetyVerifierTests.cs | 104 ++- Unity.Entities.CodeGen.Tests/Decompiler.cs | 72 -- .../IntegrationTest.cs | 16 +- .../LambdaJobDescriptionConstructionTests.cs | 54 +- .../LambdaJobIntegrationTest.cs | 9 +- .../LambdaJobsLambdaJobsPostProcessorTests.cs | 183 ++++- .../LambdaJobsPostProcessorTestBase.cs | 77 ++- .../Unity.Entities.CodeGen.Tests.asmdef | 16 +- Unity.Entities.CodeGen/AssemblyInfo.cs | 3 + .../AssemblyInfo.cs.meta | 2 +- .../BlobAssetSafetyVerifier.cs | 47 +- .../CecilExtensionMethods.cs | 7 + Unity.Entities.CodeGen/CecilHelpers.cs | 10 +- .../LambdaJobs/EntitiesForEachJobCreator.cs | 27 +- .../InjectAndInitializeEntityQueryField.cs | 24 +- .../LambdaJobDescriptionConstruction.cs | 79 ++- .../LambdaJobs/LambdaJobsPostProcessor.cs | 181 +++-- ...LambdaParamaterValueProviderInformation.cs | 4 +- .../LambdaParameterValueInformations.cs | 2 + .../LambdaJobs/UserError.cs | 77 ++- .../LiveLink/LiveLinkDropdownTests.cs | 91 ++- .../LiveLink/LiveLinkToolbarTests.cs | 2 +- .../LiveLink/StartLiveLinkWindowTests.cs | 158 +++++ .../LiveLink/StartLiveLinkWindowTests.cs.meta | 3 + .../LiveLink/UIElementTestHelpers.cs | 29 + .../LiveLink/UIElementTestHelpers.cs.meta | 3 + .../Unity.Entities.Editor.Tests.asmdef | 7 +- Unity.Entities.Editor/Decompiler.cs | 123 ++++ .../Decompiler.cs.meta | 2 +- .../EntityDebugger/ComponentTypeChooser.cs | 8 +- .../EntityDebugger/ComponentTypeFilterUI.cs | 84 ++- .../EntityDebugger/ComponentTypeListView.cs | 22 +- .../EntityDebugger/EntityDebugger.cs | 13 +- .../EntityDebugger/EntityListView.cs | 2 +- .../EntityDebugger/SystemListView.cs | 11 +- .../EntitySelectionProxyEditor.cs | 5 +- .../LiveLink/LiveLinkConnectionsDropdown.cs | 47 +- .../LiveLink/StartLiveLinkWindow.cs | 630 ++++++++++++++++++ .../LiveLink/StartLiveLinkWindow.cs.meta | 2 +- .../LiveLink/UIElementHelpers.cs | 6 +- .../PostprocessedILInspector.meta | 2 +- .../.ilspyfolder/ilspycmd.exe | Bin 0 -> 2818048 bytes .../PostprocessedILWindow.cs | 446 +++++++++++++ .../PostprocessedILWindow.cs.meta | 2 +- .../TypeDefinitionExtensions.cs | 26 + .../TypeDefinitionExtensions.cs.meta | 2 +- .../Unity.Entities.Editor.asmdef | 19 +- .../AuthoringComponentIntegrationTest.cs | 21 +- .../IBufferElementDataCompileTimeTests.cs | 66 ++ ...IBufferElementDataCompileTimeTests.cs.meta | 11 + ...Unity.Entities.Hybrid.CodeGen.Tests.asmdef | 8 +- .../AuthoringComponentPostProcessor.cs.meta | 11 - ...mponentPostProcessor_IBufferElementData.cs | 107 +++ ...ntPostProcessor_IBufferElementData.cs.meta | 11 + ...gComponentPostProcessor_IComponentData.cs} | 188 +++--- ...ponentPostProcessor_IComponentData.cs.meta | 11 + .../AuthoringComponentPostProcessor_Shared.cs | 66 ++ ...oringComponentPostProcessor_Shared.cs.meta | 11 + .../Unity.Entities.Hybrid.CodeGen.asmdef | 7 +- Unity.Entities.Hybrid.Tests/AssemblyInfo.cs | 2 + .../Conversion/ConversionTestFixtureBase.cs | 2 +- .../Conversion/ConversionTests.cs | 15 + .../GameObjectConversionSettingsTests.cs | 12 +- .../Conversion/SceneConversionTests.cs | 6 +- .../EntityQueryWithComponentTests.cs | 40 ++ .../EntityQueryWithComponentTests.cs.meta | 3 + .../Runtime/MoveEntitiesFromHybridTests.cs | 7 + .../Unity.Entities.Hybrid.Tests.asmdef | 4 +- Unity.Entities.Hybrid/AssemblyInfo.cs | 3 + .../Assets.meta | 2 +- .../Assets/AndroidHybrid.buildpipeline | 7 + .../Assets/AndroidHybrid.buildpipeline.meta | 0 .../Assets/Hybrid.buildpipeline | 11 + .../Assets/Hybrid.buildpipeline.meta | 0 .../Assets/HybridLiveLink.buildpipeline | 10 + .../Assets/HybridLiveLink.buildpipeline.meta | 0 .../Assets/OSXHybrid.buildpipeline | 7 + .../Assets/OSXHybrid.buildpipeline.meta | 0 .../Assets/OSXHybridLiveLink.buildpipeline | 7 + .../OSXHybridLiveLink.buildpipeline.meta | 0 .../Assets/WindowsHybrid.buildpipeline | 7 + .../Assets/WindowsHybrid.buildpipeline.meta | 0 .../WindowsHybridLiveLink.buildpipeline | 7 + .../WindowsHybridLiveLink.buildpipeline.meta | 0 .../BufferElementDataAuthoringComponent.cs | 36 + ...ufferElementDataAuthoringComponent.cs.meta | 11 + .../EntityManagerExtensions.cs | 9 +- .../ConversionSystemFilterSettings.cs | 2 +- .../GameObjectConversionMappingSystem.cs | 50 +- .../GameObjectConversionSettings.cs | 17 +- .../GameObjectConversionSystem.cs | 37 +- .../UnityEngineExtensions.cs | 20 + .../Injection/CompanionGameObject.cs | 92 +-- .../Injection/DefaultWorldInitialization.cs | 15 +- Unity.Entities.Hybrid/ResourceCatalogData.cs | 87 +++ .../ResourceCatalogData.cs.meta | 11 + .../Unity.Entities.Hybrid.asmdef | 4 +- .../EntityRefTestDataAuthoring.cs | 1 + .../JournalTestAuthoring.cs | 1 + Unity.Entities.Tests/AssemblyInfo.cs | 2 +- .../BufferElementDataTests.cs | 2 +- .../ChunkChangeVersionTests.cs | 29 + Unity.Entities.Tests/ChunkComponentTests.cs | 2 + Unity.Entities.Tests/ComponentSystemTests.cs | 48 +- Unity.Entities.Tests/CreateAndDestroyTests.cs | 10 +- .../Diff/EntityDifferTests.cs | 128 ++++ Unity.Entities.Tests/ECSTestsFixture.cs | 70 +- .../EntityCommandBufferTests.cs | 9 +- Unity.Entities.Tests/EntityManagerBugTests.cs | 12 - ...ityManagerComponentGroupOperationsTests.cs | 10 +- Unity.Entities.Tests/EntityQueryTests.cs | 29 + .../EntityRemapUtilityTests.cs | 8 - Unity.Entities.Tests/IJobChunkTests.cs | 46 +- Unity.Entities.Tests/IJobForEachTests.cs | 35 + Unity.Entities.Tests/JobBasicTests.cs | 9 + Unity.Entities.Tests/JobSafetyTests.cs | 6 +- Unity.Entities.Tests/MoveEntitiesFromTests.cs | 21 +- .../Serialization/SerializeTests.cs | 81 +++ .../SystemBaseDependencyTests.cs | 349 ++++++++++ .../SystemBaseDependencyTests.cs.meta | 11 + .../SystemStateComponentTests.cs | 40 ++ Unity.Entities.Tests/TestComponents.cs | 4 +- Unity.Entities.Tests/TypeIndexOrderTests.cs | 24 +- Unity.Entities.Tests/TypeManagerTests.cs | 17 +- Unity.Entities.Tests/WorldTests.cs | 64 ++ Unity.Entities/AssemblyInfo.cs | 1 + Unity.Entities/ChunkDataUtility.cs | 305 +++++---- .../LambdaJobDescription.cs | 114 +++- .../LambdaJobQueryConstructionMethods.gen.cs | 28 + .../LambdaJobQueryConstructionMethods.tt | 2 +- .../LambdaParameterValueProviders.cs | 2 +- Unity.Entities/ComponentSystemBase.cs | 12 +- .../DOTSCompilerGeneratedAttribute.cs | 8 + .../DOTSCompilerGeneratedAttribute.cs.meta | 11 + Unity.Entities/DebugView.cs | 13 - .../DefaultTinyWorldInitialization.cs | 148 ---- .../DefaultTinyWorldInitialization.cs.meta | 11 - Unity.Entities/DeprecatedAPIStubs.cs | 21 - Unity.Entities/DeprecatedAPIStubs.cs.meta | 13 - Unity.Entities/Diff/EntityDiffer.cs | 4 +- .../Diff/EntityDifferComponentChanges.cs | 33 +- .../Diff/EntityDifferCopyAndReplace.cs | 16 +- Unity.Entities/Diff/EntityPatcher.cs | 2 +- Unity.Entities/Diff/EntityPatcherBlobs.cs | 2 +- Unity.Entities/EntityCommandBuffer.cs | 16 +- Unity.Entities/EntityComponentStore.cs | 421 +++++++----- .../EntityComponentStoreChangeArchetype.cs | 50 +- .../EntityComponentStoreCreateArchetype.cs | 26 +- ...tityComponentStoreCreateDestroyEntities.cs | 124 +--- Unity.Entities/EntityComponentStoreDebug.cs | 32 + Unity.Entities/EntityDataAccess.cs | 248 ++++--- Unity.Entities/EntityManager.cs | 24 +- .../EntityManagerAccessComponentData.cs | 28 +- .../EntityManagerChangeArchetype.cs | 31 +- .../EntityManagerCopyEntitiesFrom.cs | 4 +- Unity.Entities/EntityManagerDebug.cs | 2 +- Unity.Entities/EntityManagerMoveEntities.cs | 264 +++++--- Unity.Entities/EntityManagerQuery.cs | 15 +- Unity.Entities/EntityManagerSync.cs | 21 +- Unity.Entities/EntityManagerVersions.cs | 3 + Unity.Entities/EntityRemapUtility.cs | 36 +- Unity.Entities/ExclusiveEntityTransaction.cs | 53 +- .../GenerateAuthoringComponentAttribute.cs | 1 + Unity.Entities/IJobChunk.cs | 126 +++- .../Iterators/ArchetypeChunkArray.cs | 64 +- .../Iterators/ArchetypeChunkIterator.cs | 8 +- .../Iterators/ChunkDataGatherJobs.cs | 45 +- .../Iterators/ChunkIterationUtility.cs | 47 +- .../Iterators/ComponentDataFromEntity.cs | 25 + Unity.Entities/Iterators/EntityQuery.cs | 83 +-- .../Iterators/EntityQueryManager.cs | 65 +- Unity.Entities/JobComponentSystem.cs | 6 +- Unity.Entities/ManagedComponentStore.cs | 559 ++++++---------- .../Serialization/SerializeUtility.cs | 132 ++-- Unity.Entities/SortingUtilities.cs | 16 +- Unity.Entities/SystemBase.cs | 5 +- Unity.Entities/Types/Archetype.cs | 85 ++- Unity.Entities/Types/Chunk.cs | 14 +- Unity.Entities/Types/ComponentType.cs | 2 +- .../Types/ComponentTypeInArchetype.cs | 2 +- Unity.Entities/Types/FastEquality.cs | 3 +- Unity.Entities/Types/SceneTagComponent.cs | 19 +- Unity.Entities/Types/TypeManager.cs | 15 +- Unity.Entities/World.cs | 41 +- .../SubSceneEditorTests.cs | 54 +- Unity.Scenes.Editor/Build.meta | 8 - .../Build/MenuItemBuildSettings.cs | 65 -- .../Build/MenuItemBuildSettings.cs.meta | 11 - .../BuildStepCreateResourceCatalog.cs | 64 ++ .../BuildStepCreateResourceCatalog.cs.meta | 11 + Unity.Scenes.Editor/EditorEntityScenes.cs | 21 +- .../EditorSceneLiveLinkToPlayerSendSystem.cs | 15 +- .../EditorSubSceneLiveLinkSystem.cs | 4 +- Unity.Scenes.Editor/HierarchyOverlay.cs | 60 ++ Unity.Scenes.Editor/HierarchyOverlay.cs.meta | 11 + .../LiveLink/Assets.meta | 2 +- .../LiveLink/Assets/empty.unity | 123 ++++ .../LiveLink/Assets/empty.unity.meta | 7 + .../LiveLink/BuildStepBuildClassicLiveLink.cs | 125 ++++ .../BuildStepBuildClassicLiveLink.cs.meta | 0 .../LiveLinkAssetBundleBuildSystem.cs | 257 +++---- .../LiveLink/LiveLinkBuildImporter.cs | 4 +- .../LiveLink/LiveLinkBuildPipeline.cs | 171 ++++- Unity.Scenes.Editor/LiveLinkConnection.cs | 61 +- Unity.Scenes.Editor/LiveLinkDiffGenerator.cs | 12 +- .../RetainBlobAssetsSetting.cs | 6 +- Unity.Scenes.Editor/SceneImporterData.cs | 57 ++ Unity.Scenes.Editor/SceneImporterData.cs.meta | 11 + Unity.Scenes.Editor/SceneInspector.cs | 29 + Unity.Scenes.Editor/SceneInspector.cs.meta | 11 + .../Steps.meta | 2 +- .../BuildStepSubSceneBundles.cs | 15 +- .../BuildStepSubSceneBundles.cs.meta | 0 Unity.Scenes.Editor/SubSceneContextMenu.cs | 343 ++++++++-- Unity.Scenes.Editor/SubSceneImporter.cs | 106 ++- Unity.Scenes.Editor/SubSceneInspector.cs | 44 +- .../SubSceneInspectorUtility.cs | 14 +- .../SubSceneTransformHierarchyHook.cs | 24 +- .../Unity.Scenes.Editor.asmdef | 10 +- .../Editmode.meta | 2 +- .../{ => Editmode}/DebugStringTests.cs | 0 .../{ => Editmode}/DebugStringTests.cs.meta | 0 .../PatchingEndToEndWithSerialization.cs | 0 .../PatchingEndToEndWithSerialization.cs.meta | 0 .../{ => Editmode}/SaveAndLoadEndToEnd.cs | 0 .../SaveAndLoadEndToEnd.cs.meta | 0 .../SharedComponentSerializeTests.cs | 0 .../SharedComponentSerializeTests.cs.meta | 0 .../{ => Editmode}/SubtractArraysTests.cs | 0 .../SubtractArraysTests.cs.meta | 0 .../Unity.Scenes.Hybrid.Tests.asmdef | 0 .../Unity.Scenes.Hybrid.Tests.asmdef.meta | 0 Unity.Scenes.Hybrid.Tests/Playmode.meta | 8 + .../Playmode/AuthoringWithMaterial.cs | 38 ++ .../Playmode/AuthoringWithMaterial.cs.meta | 11 + .../Playmode/SubSceneTests.cs | 134 ++++ .../Playmode/SubSceneTests.cs.meta | 3 + .../Playmode/TestSceneWithSubScene.meta | 8 + .../Playmode/TestSceneWithSubScene.unity | 350 ++++++++++ .../Playmode/TestSceneWithSubScene.unity.meta | 7 + .../TestSceneWithSubScene/TestSubScene.unity | 167 +++++ .../TestSubScene.unity.meta | 7 + .../Unity.Scenes.Hybrid.Tests.Playmode.asmdef | 28 + ...y.Scenes.Hybrid.Tests.Playmode.asmdef.meta | 2 +- Unity.Scenes.Hybrid.Tests/Test.mat | 2 +- Unity.Scenes.Hybrid/AssemblyInfo.cs | 1 + Unity.Scenes.Hybrid/AssetBundleManager.cs | 133 ++++ .../AssetBundleManager.cs.meta | 3 + .../AsyncLoadSceneOperation.cs | 161 ++--- Unity.Scenes.Hybrid/EntityScenesPaths.cs | 74 +- .../GlobalAssetObjectResolver.cs | 15 +- Unity.Scenes.Hybrid/LiveLink/LiveLinkMsg.cs | 9 +- .../LiveLinkPlayerAssetRefreshSystem.cs | 363 +++++----- .../LiveLink/LiveLinkPlayerSystem.cs | 46 +- .../LiveLinkResolveSceneReferenceSystem.cs | 15 +- .../LiveLink/MessageEventArgsExtensions.cs | 8 +- .../ResolveSceneReferenceSystem.cs | 29 +- Unity.Scenes.Hybrid/SceneSectionBundleTag.cs | 24 +- .../SceneSectionStreamingSystem.cs | 8 +- Unity.Scenes.Hybrid/SceneSystem.cs | 234 ++++++- Unity.Scenes.Hybrid/SubScene.cs | 112 ++-- .../CopyTransformToGameObjectSystem.cs | 2 +- Unity.Transforms.Tests/TransformTests.cs | 377 ++++++++--- Unity.Transforms/LocalToParentSystem.cs | 20 +- Unity.Transforms/ParentSystem.cs | 2 +- package.json | 18 +- 326 files changed, 9732 insertions(+), 4619 deletions(-) create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow.uss create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow.uss.meta create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss.meta create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow_light.uss create mode 100644 Editor/LiveLink/uss/StartLiveLinkWindow_light.uss.meta create mode 100644 Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml create mode 100644 Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml.meta create mode 100644 Editor/LiveLink/uxml/StartLiveLinkWindow.uxml create mode 100644 Editor/LiveLink/uxml/StartLiveLinkWindow.uxml.meta delete mode 100644 Unity.Build.Common/Assets/AndroidHybrid.buildpipeline delete mode 100644 Unity.Build.Common/Assets/Hybrid.buildpipeline delete mode 100644 Unity.Build.Common/Assets/HybridLiveLink.buildpipeline delete mode 100644 Unity.Build.Common/Assets/OSXHybrid.buildpipeline delete mode 100644 Unity.Build.Common/Assets/OSXHybridLiveLink.buildpipeline delete mode 100644 Unity.Build.Common/Assets/WindowsHybrid.buildpipeline delete mode 100644 Unity.Build.Common/Assets/WindowsHybridLiveLink.buildpipeline delete mode 100644 Unity.Build.Common/Settings/ClassicBuildProfile.cs delete mode 100644 Unity.Build.Common/Settings/ClassicScriptingSettings.cs delete mode 100644 Unity.Build.Common/Settings/ClassicScriptingSettingsInspector.cs delete mode 100644 Unity.Build.Common/Settings/GeneralSettings.cs delete mode 100644 Unity.Build.Common/Settings/GraphicsSettings.cs delete mode 100644 Unity.Build.Common/Settings/GraphicsSettings.cs.meta delete mode 100644 Unity.Build.Common/Settings/InternalSourceBuild.cs delete mode 100644 Unity.Build.Common/Settings/InternalSourceBuild.cs.meta delete mode 100644 Unity.Build.Common/Settings/OutputBuildDirectory.cs delete mode 100644 Unity.Build.Common/Settings/OutputBuildDirectory.cs.meta delete mode 100644 Unity.Build.Common/Settings/SceneList.cs delete mode 100644 Unity.Build.Common/Settings/SceneList.cs.meta delete mode 100644 Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs delete mode 100644 Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs.meta delete mode 100644 Unity.Build.Common/Steps/Android/RunStepAndroid.cs delete mode 100644 Unity.Build.Common/Steps/Android/RunStepAndroid.cs.meta delete mode 100644 Unity.Build.Common/Steps/BuildArtifactDesktop.cs delete mode 100644 Unity.Build.Common/Steps/BuildArtifactDesktop.cs.meta delete mode 100644 Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs delete mode 100644 Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs.meta delete mode 100644 Unity.Build.Common/Steps/BuildStepBuildClassicLiveLink.cs delete mode 100644 Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs delete mode 100644 Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs.meta delete mode 100644 Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs delete mode 100644 Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs.meta delete mode 100644 Unity.Build.Common/Steps/RunInstanceDesktop.cs delete mode 100644 Unity.Build.Common/Steps/RunInstanceDesktop.cs.meta delete mode 100644 Unity.Build.Common/Steps/RunStepDesktop.cs delete mode 100644 Unity.Build.Common/Steps/RunStepDesktop.cs.meta delete mode 100644 Unity.Build.Common/Steps/RunStepNotImplemented.cs delete mode 100644 Unity.Build.Common/Steps/RunStepNotImplemented.cs.meta delete mode 100644 Unity.Build.Common/TemporaryFileTracker.cs delete mode 100644 Unity.Build.Common/TemporaryFileTracker.cs.meta delete mode 100644 Unity.Build.Common/Unity.Build.Common.asmdef delete mode 100644 Unity.Entities.CodeGen.Tests/Decompiler.cs create mode 100644 Unity.Entities.CodeGen/AssemblyInfo.cs rename Unity.Build.Common/Settings/ClassicScriptingSettings.cs.meta => Unity.Entities.CodeGen/AssemblyInfo.cs.meta (83%) create mode 100644 Unity.Entities.Editor.Tests/LiveLink/StartLiveLinkWindowTests.cs create mode 100644 Unity.Entities.Editor.Tests/LiveLink/StartLiveLinkWindowTests.cs.meta create mode 100644 Unity.Entities.Editor.Tests/LiveLink/UIElementTestHelpers.cs create mode 100644 Unity.Entities.Editor.Tests/LiveLink/UIElementTestHelpers.cs.meta create mode 100644 Unity.Entities.Editor/Decompiler.cs rename {Unity.Entities.CodeGen.Tests => Unity.Entities.Editor}/Decompiler.cs.meta (83%) create mode 100644 Unity.Entities.Editor/LiveLink/StartLiveLinkWindow.cs rename Unity.Build.Common/Settings/ClassicScriptingSettingsInspector.cs.meta => Unity.Entities.Editor/LiveLink/StartLiveLinkWindow.cs.meta (83%) rename Unity.Build.Common.meta => Unity.Entities.Editor/PostprocessedILInspector.meta (77%) create mode 100644 Unity.Entities.Editor/PostprocessedILInspector/.ilspyfolder/ilspycmd.exe create mode 100644 Unity.Entities.Editor/PostprocessedILInspector/PostprocessedILWindow.cs rename Unity.Build.Common/Settings/GeneralSettings.cs.meta => Unity.Entities.Editor/PostprocessedILInspector/PostprocessedILWindow.cs.meta (83%) create mode 100644 Unity.Entities.Editor/PostprocessedILInspector/TypeDefinitionExtensions.cs rename Unity.Build.Common/Settings/ClassicBuildProfile.cs.meta => Unity.Entities.Editor/PostprocessedILInspector/TypeDefinitionExtensions.cs.meta (83%) create mode 100644 Unity.Entities.Hybrid.CodeGen.Tests/AuthoringComponent/IBufferElementDataCompileTimeTests.cs create mode 100644 Unity.Entities.Hybrid.CodeGen.Tests/AuthoringComponent/IBufferElementDataCompileTimeTests.cs.meta delete mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor.cs.meta create mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor_IBufferElementData.cs create mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor_IBufferElementData.cs.meta rename Unity.Entities.Hybrid.CodeGen/AuthoringComponent/{AuthoringComponentPostProcessor.cs => AuthoringComponentPostProcessor_IComponentData.cs} (73%) create mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor_IComponentData.cs.meta create mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor_Shared.cs create mode 100644 Unity.Entities.Hybrid.CodeGen/AuthoringComponent/AuthoringComponentPostProcessor_Shared.cs.meta create mode 100644 Unity.Entities.Hybrid.Tests/EntityQueryWithComponentTests.cs create mode 100644 Unity.Entities.Hybrid.Tests/EntityQueryWithComponentTests.cs.meta rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets.meta (77%) create mode 100644 Unity.Entities.Hybrid/Assets/AndroidHybrid.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/AndroidHybrid.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/Hybrid.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/Hybrid.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/HybridLiveLink.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/HybridLiveLink.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/OSXHybrid.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/OSXHybrid.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/OSXHybridLiveLink.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/OSXHybridLiveLink.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/WindowsHybrid.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/WindowsHybrid.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/Assets/WindowsHybridLiveLink.buildpipeline rename {Unity.Build.Common => Unity.Entities.Hybrid}/Assets/WindowsHybridLiveLink.buildpipeline.meta (100%) create mode 100644 Unity.Entities.Hybrid/BufferElementDataAuthoringComponent.cs create mode 100644 Unity.Entities.Hybrid/BufferElementDataAuthoringComponent.cs.meta create mode 100644 Unity.Entities.Hybrid/ResourceCatalogData.cs create mode 100644 Unity.Entities.Hybrid/ResourceCatalogData.cs.meta create mode 100644 Unity.Entities.Tests/SystemBaseDependencyTests.cs create mode 100644 Unity.Entities.Tests/SystemBaseDependencyTests.cs.meta create mode 100644 Unity.Entities/DOTSCompilerGeneratedAttribute.cs create mode 100644 Unity.Entities/DOTSCompilerGeneratedAttribute.cs.meta delete mode 100644 Unity.Entities/DefaultTinyWorldInitialization.cs delete mode 100644 Unity.Entities/DefaultTinyWorldInitialization.cs.meta delete mode 100644 Unity.Entities/DeprecatedAPIStubs.cs delete mode 100644 Unity.Entities/DeprecatedAPIStubs.cs.meta delete mode 100644 Unity.Scenes.Editor/Build.meta delete mode 100644 Unity.Scenes.Editor/Build/MenuItemBuildSettings.cs delete mode 100644 Unity.Scenes.Editor/Build/MenuItemBuildSettings.cs.meta create mode 100644 Unity.Scenes.Editor/BuildStepCreateResourceCatalog.cs create mode 100644 Unity.Scenes.Editor/BuildStepCreateResourceCatalog.cs.meta create mode 100644 Unity.Scenes.Editor/HierarchyOverlay.cs create mode 100644 Unity.Scenes.Editor/HierarchyOverlay.cs.meta rename Unity.Build.Common/Settings.meta => Unity.Scenes.Editor/LiveLink/Assets.meta (77%) create mode 100644 Unity.Scenes.Editor/LiveLink/Assets/empty.unity create mode 100644 Unity.Scenes.Editor/LiveLink/Assets/empty.unity.meta create mode 100644 Unity.Scenes.Editor/LiveLink/BuildStepBuildClassicLiveLink.cs rename {Unity.Build.Common/Steps => Unity.Scenes.Editor/LiveLink}/BuildStepBuildClassicLiveLink.cs.meta (100%) create mode 100644 Unity.Scenes.Editor/SceneImporterData.cs create mode 100644 Unity.Scenes.Editor/SceneImporterData.cs.meta create mode 100644 Unity.Scenes.Editor/SceneInspector.cs create mode 100644 Unity.Scenes.Editor/SceneInspector.cs.meta rename {Unity.Build.Common => Unity.Scenes.Editor}/Steps.meta (77%) rename Unity.Scenes.Editor/{Build => Steps}/BuildStepSubSceneBundles.cs (89%) rename Unity.Scenes.Editor/{Build => Steps}/BuildStepSubSceneBundles.cs.meta (100%) rename Unity.Build.Common/Steps/Android.meta => Unity.Scenes.Hybrid.Tests/Editmode.meta (77%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/DebugStringTests.cs (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/DebugStringTests.cs.meta (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/PatchingEndToEndWithSerialization.cs (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/PatchingEndToEndWithSerialization.cs.meta (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SaveAndLoadEndToEnd.cs (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SaveAndLoadEndToEnd.cs.meta (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SharedComponentSerializeTests.cs (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SharedComponentSerializeTests.cs.meta (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SubtractArraysTests.cs (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/SubtractArraysTests.cs.meta (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/Unity.Scenes.Hybrid.Tests.asmdef (100%) rename Unity.Scenes.Hybrid.Tests/{ => Editmode}/Unity.Scenes.Hybrid.Tests.asmdef.meta (100%) create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/AuthoringWithMaterial.cs create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/AuthoringWithMaterial.cs.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/SubSceneTests.cs create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/SubSceneTests.cs.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/TestSceneWithSubScene.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/TestSceneWithSubScene.unity create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/TestSceneWithSubScene.unity.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/TestSceneWithSubScene/TestSubScene.unity create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/TestSceneWithSubScene/TestSubScene.unity.meta create mode 100644 Unity.Scenes.Hybrid.Tests/Playmode/Unity.Scenes.Hybrid.Tests.Playmode.asmdef rename Unity.Build.Common/Unity.Build.Common.asmdef.meta => Unity.Scenes.Hybrid.Tests/Playmode/Unity.Scenes.Hybrid.Tests.Playmode.asmdef.meta (76%) create mode 100644 Unity.Scenes.Hybrid/AssetBundleManager.cs create mode 100644 Unity.Scenes.Hybrid/AssetBundleManager.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 33c82481..fc9941b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,90 @@ # Change log -## [0.5.1] - 2020-01-28 +## [0.6.0] - 2020-02-17 + +### Added + +* The `[GenerateAuthoringComponent]` attribute is now allowed on structs implementing `IBufferElementData`. An authoring component is automatically generated to support adding a `DynamicBuffer` of the type implementing `IBufferElementData` to an entity. +* Added new `SystemBase` base class for component systems. This new way of defining component systems manages dependencies for the user (manual dependency management is still possible by accessing the `SystemBase.Dependency` field directly). +* New `ScheduleParallel` methods in `IJobChunk` and `Entities.ForEach` (in `SystemBase`) to make parallel scheduling of jobs explicit. `ScheduleSingle` in `IJobChunk` indicates scheduling work to be done in a non-parallel manner. +* New editor workflow to quickly and easily build LiveLink player using the `BuildConfiguration` API. +* Adds Live Link support for `GameObject` scenes. +* The `SceneSystem` API now also loads `GameObject` scenes via `LoadSceneAsync` API. +* Added new build component for LiveLink settings in `Unity.Scenes.Editor` to control how initial scenes are handled (LiveLink all, embed all, embed first). +* Users can now inspect post-procssed IL code inside Unity Editor: `DOTS` -> `DOTS Compiler` -> `Open Inspector` + +### Changed + + * The package `com.unity.build` has been merged into the package `com.unity.platforms`. As such, removed the dependency on `com.unity.build@0.1.0-preview` and replaced it with `com.unity.platforms@0.2.1-preview.1`. Please read the changelog of `com.unity.platforms` for more details. +* Managed components are now stored in a way that will generate less GC allocations when entities change archetype. +* Moved `Unity.Entities.ICustomBootstrap` from Unity.Entities.Hybrid to Unity.Entities. +* `World.Dispose()` now completes all reader/writer jobs on the `World`'s `EntityManager` before releasing any resources, to avoid use-after-free errors. +* Fix `AssemblyResolveException` when loading a project with dependent packages that are using Burst in static initializers or `InitializeOnLoad`. +* `.sceneWithBuildSettings` files that are stored in Assets/SceneDependencyCache are no longer rebuilt constantly. Because they are required for SubScene behaviour to work in the editor, if these are deleted they are recreated by OnValidate of the SubScene in the edited Scene. They should also be recreated on domain reload (restarting unity, entering/exiting playmode, etc). +* `EntityQuery.cs`: Overloads of `CreateArchetypeChunkArray`, `ToComponentDataArray`, `ToEntityArray`, and `CopyFromComponentDataArray` that return a JobHandle (allowing the work to be done asynchronously) have been renamed to add `Async` to the title (i.e. `ToComponentDataArrayAsync`). The old overloads have been deprecated and an API Updater clause has been added. + * `Entities.WithName` now only accepts names that use letters, digits, and underscores (not starting with a digit, no two consecutive underscores) + * Updated package `com.unity.properties` to version `0.10.4-preview`. + * Updated package `com.unity.serialization` to version `0.6.4-preview`. + * The entity debugger now remembers whether chunk info panel is visible + * The entity debugger now displays the full name for nested types in the system list + * The entity debugger now sorts previously used filter components to the top of the filter GUI + * Bumped burst version to include the new features and fixes including: + * Fix an issue with function pointers being corrupted after a domain reload that could lead to hard crashes. + * Fix potential deadlock between Burst and the AssetDatabase if burst is being used when building the database. + +### Deprecated + + * Method `GetBuildSettingsComponent` on class `GameObjectConversionSystem` has been renamed to `GetBuildConfigurationComponent`. + * Method `TryGetBuildSettingsComponent` on class `GameObjectConversionSystem` has been renamed to `TryGetBuildConfigurationComponent`. + * Member `BuildSettings` on class `GameObjectConversionSettings` has been renamed to `BuildConfiguration`. + * Member `BuildSettingsGUID` on class `SceneSystem` has been renamed to `BuildConfigurationGUID`. + +### Removed + + * Removed expired API `SceneSectionData.SharedComponentCount` + * Removed expired API `struct SceneData` + * Removed expired API `SubScene._SceneEntities` + * Removed expired API `World.Active` ### Fixed +* Ability to open and close SubScenes from the scene hierarchy window (Without having to move cursor to inspector window). +* Ability to create a new empty Sub Scene without first creating a game object. +* Improve performance of SubScene loading and change tracking in the editor. +* Fixed regression where `GetSingleton` would create a new query on every call. +* Fixed SubScenes trying to load an already loaded AssetBundle when loaded multiple times on the same player, but with different Worlds. +* Make it clear that SubScenes in Prefabs are not supported. +* Lambda job codegen tests now fail if the error message does not contain the expected contents. +* Improved performance of setting up the world required for game object conversion +* The `chunkIndex` parameter passed to `IJobChunk.Execute()` now has the correct value. +* Fixed an error which caused entities with `ISystemStateSharedComponentData` components to not be cleaned up correctly. +* Managed components containing `Entity` fields will now correctly serialize. +* Fixed issue where `BlobAssetVerifier` will throw error if it can't resolve a type. +* Exposed the Managed Component extensions for `EntityQuery`. +* `Entities.ForEach` now identifies when `this` of the enclosing system is captured due to calling an extension method on it when compilation fails since the lambda was emitted as a member function +* `Entities.ForEach` now reports when a field of the outer system is captured and used by reference when compilation fails since the lambda was emitted as a member function +* `Entities.ForEach` does not erronously point to calling static functions as the source of the error when compilation fails since the lambda was emitted as a member function +* Debugging inside of `Entities.ForEach` with Visual Studio 2017/2019 (some debugging features will need an upcoming update of the com.unity.ide.visualstudio package). +* `EntityQuery.ToComponentArray` with `T` deriving from `UnityEngine.Component` now correctly collects all data in a chunk +* Fixed an issue with `ComponentSystemBase.GetEntityQuery` and `EntityManager.CreateEntityQuery` calls made with `EntityQueryDesc` not respecting read-only permissions. + + +## [0.5.1] - 2020-01-28 + +### Changed + * Constructor-related exceptions thrown during `World.CreateSystem` will now included the inner exception details. -* Fixed an issue where `BlobAssetReference` types was not guaranteed to be 8-byte aligned on all platforms which could result in failing to read Blob data in components correctly on 32-bit platforms. -* Fixed issue in MinMaxAABB Equals() comparing Min to itself rather than other. -* `Entities.ForEach` now properly treats `in` parameters of `DynamicBuffer` type as read-only -* Fixed potential crash caused by a leaked job after an exception is thrown during a call to `IJobChunk.Schedule`. * `DefaultWorldInitialization.GetAllSystems` now returns `IReadOnlyList` instead of `List` * `DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups` now takes `IEnumerable` instead of `List` -### Changed +### Fixed -* Updated dependencies for this package. +* Fixed an issue where `BlobAssetReference` types was not guaranteed to be 8-byte aligned on all platforms which could result in failing to read Blob data in components correctly on 32-bit platforms. +* Fixed issue in `MinMaxAABB.Equals()` comparing `Min` to itself rather than `other`. +* `Entities.ForEach` now properly treats `in` parameters of `DynamicBuffer` type as read-only +* Fixed potential crash caused by a leaked job after an exception is thrown during a call to `IJobChunk.Schedule`. +* Fixed regression in `ComponentSystemBase.GetSingleton()` where a new query would be created every timee the function is called. ## [0.5.0] - 2020-01-16 @@ -23,7 +92,6 @@ ### Added * Added AndroidHybrid.buildpipeline with RunStepAndroid -* EntityManager.MoveEntitiesFrom now has the full method overload combination of output, filter, remapping parameters. ### Changed @@ -31,18 +99,19 @@ * Log entries emitted during subscene conversion without a context object are now displayed in the subscene inspector instead of discarded ### Deprecated - + * Adding removal dates to the API that have been deprecated but did not have the date set. * `BlobAssetReference`: `Release()` was deprecated, use `Dispose()` instead. - + ### Removed -* `EntityQuery.cs`: Removed expired API `CalculateLength()`, `SetFilter()` and `SetFilterChanged()`. + * Adding removal dates to the API that have been deprecated but did not have the date set. + * `BlobAssetReference`: `Release()` was deprecated, use `Dispose()` instead. + * `EntityQuery.cs`: Removed expired API `CalculateLength()`, `SetFilter()` and `SetFilterChanged()`. ### Fixed - * Fixed an issue where trying to perform EntityRemapping on Managed Components could throw if a component field was null. -* EntityManager.MoveEntitiesFrom with query was not bumping shared component versions, order versions or dirty versions correctly. Now it does. +* `EntityManager.MoveEntitiesFrom` with query was not bumping shared component versions, order versions or dirty versions correctly. Now it does. * Fixed that adding a Sub Scene component from the Add Components dropdown was not reflected in the Hierarchy. * Fixed so that Undo/Redo of changes to SceneAsset objectfield in the Sub Scene Inspector is reflected in the Hierarchy. * Make it clear when Sub Scene duplicates are present: shown in Hierarchy and by showing a warning box in the Inspector. @@ -51,9 +120,9 @@ * Keep sibling order for new Sub Scene when created using 'New Sub Scene From Selection' (prevents the new Sub Scene from ending as the last sibling). * Handle if selection contains part of a Prefab instance when creating Sub Scene from Selection. * Fix dangling loaded Sub Scenes not visualized in the Hierarchy when removing Scene Asset reference in Sub Scene component. -* Fixed an issue with invalid IL generated by Entities.ForEach when structs are captured as locals from two different scopes and their fields are accessed. +* Fixed an issue with invalid IL generated by `Entities.ForEach` when structs are captured as locals from two different scopes and their fields are accessed. * Make it clear in the Hierarchy and Sub Scene Inspector that nesting Sub Scenes is not yet supported. -* Fixed an issue with BinaryWriter where serializing a System.String[] with a single element would throw an exception. +* Fixed an issue with `BinaryWriter` where serializing a `System.String[]` with a single element would throw an exception. * Fixed an issue with `ComponentSystem.GetEntityQuery` and `JobComponentSystem.GetEntityQuery` which caused improper caching of queries when using "None" or "Any" fields. @@ -62,21 +131,19 @@ **This version requires Unity 2019.3.0f1+** ### New Features + * Two new methods added to the public API: * `void EntityCommandBuffer.AddComponent(EntityQuery entityQuery)` * `void EntityCommandBuffer.RemoveComponent(EntityQuery entityQuery)` * BlobArray, BlobString & BlobPtr are not allowed to be copied by value since they carry offset pointers that aree relative to the location of the memory. This could easily result in programming mistakes. The compiler now prevents incorrect usage by enforcing any type attributed with [MayOnlyLiveInBlobStorage] to never be copied by value. - -### Upgrade guide - ### Changes -* Deprecates `TypeManager.CreateTypeIndexForComponent` and it's other component type variants. Types can be dynamically added (in Editor builds) by instead passing the new unregistered types to `TypeManager.AddNewComponentTypes` instead. +* Deprecates `TypeManager.CreateTypeIndexForComponent` and it's other component type variants. Types can be dynamically added (in Editor builds) by instead passing the new unregistered types to `TypeManager.AddNewComponentTypes` instead. * `RequireForUpdate(EntityQuery)` and `RequireSingletonForUpdate` on a system with `[AlwaysUpdate]` will now throw an exception instead of being ignored. * ChangeVersionUtility.IncrementGlobalSystemVersion & ChangeVersionUtility.InitialGlobalSystemVersion is now internal. They were accidentally public previously. * Entity inspector now shows entity names and allows to rename the selected entity -* Improved entity debugger UI +* Improved entity debugger UI * Create WorldRenderBounds for prefabs and disabled entities with renderers during conversion, this make instantiation of those entities significantly faster. * Reduced stack depth of System.Update / OnUpdate method (So it looks better in debugger) * Assert when using EntityQuery from another world @@ -84,11 +151,10 @@ * Structural changes now go through a bursted codepath and are significantly faster * DynamicBuffer.Capacity is now settable - ### Fixes * Remove unnecessary & incorrect warning in DeclareReferencedPrefab when the referenced game object is a scene object -* GameObjects with ConvertAndInject won't get detached from a non-converted parent (fixes regression) +* GameObjects with ConvertAndInject won't get detached from a non-converted parent (fixes regression) * Fixed a crash that could occur when destroying an entity with an empty LinkedEntityGroup. * Updated performance package dependency to 1.3.2 which fixes an obsoletion warning * The `EntityCommandBuffer` can be replayed repeatedly. diff --git a/DocCodeSamples.Tests/DynamicBufferExamples.cs b/DocCodeSamples.Tests/DynamicBufferExamples.cs index 3264118b..3b656a2c 100644 --- a/DocCodeSamples.Tests/DynamicBufferExamples.cs +++ b/DocCodeSamples.Tests/DynamicBufferExamples.cs @@ -90,6 +90,22 @@ DynamicBuffer dynamicBuffer buffer.RemoveAt(0); #endregion + + #region invalidation + + var entity1 = EntityManager.CreateEntity(); + var entity2 = EntityManager.CreateEntity(); + + DynamicBuffer buffer1 + = EntityManager.AddBuffer(entity1); + // This line causes a structural change and invalidates + // the previously acquired dynamic buffer + DynamicBuffer buffer2 + = EntityManager.AddBuffer(entity1); + // This line will cause an error: + buffer1.Add(17); + + #endregion } #region add-in-job diff --git a/Documentation~/dynamic_buffers.md b/Documentation~/dynamic_buffers.md index bf28cc40..140dcc36 100644 --- a/Documentation~/dynamic_buffers.md +++ b/Documentation~/dynamic_buffers.md @@ -38,6 +38,27 @@ To add a buffer to an entity, add the IBufferElementData struct that defines the [!code-cs[declare](../package/DocCodeSamples.Tests/DynamicBufferExamples.cs#add-with-archetype)] +### Using the `[GenerateAuthoringComponent]` attribute + +You can use `[GenerateAuthoringComponent]`to generate authoring components for simple IBufferElementData implementations that contain only one field. Setting this attribute allows you add an ECS IBufferElementData component to a GameObject so that you can set the buffer elements in the Editor. + +For example, if you declare the following type, you can add it directly to a GameObject in the Editor: + +``` +[GenerateAuthoringComponent] +public struct IntBufferElement: IBufferElementData +{ + public int Value; +} +``` + +In the background, Unity generates a class named `IntBufferElementAuthoring` (which inherits from `MonoBehaviour`), which exposes a public field of `List` type. When the GameObject containing this generated authoring component is converted into an entity, the list is converted into `DynamicBuffer`, and then added to the converted entity. + +Note the following restrictions: +- Only one component in a single C# file can have a generated authoring component, and the C# file must not have another MonoBehaviour in it. +- `IBufferElementData` authoring components cannot be automatically generated for types that contain more than one field. +- `IBufferElementData` authoring components cannot be automatically generated for types that have an explicit layout. + ### Using an [EntityCommandBuffer](xref:Unity.Entities.EntityCommandBuffer) You can add or set a buffer component when adding commands to an entity command buffer. Use [AddBuffer](xref:Unity.Entities.EntityCommandBuffer.AddBuffer``1(Unity.Entities.Entity)) to create a new buffer for the entity, changing the entity's archetype. Use [SetBuffer](xref:Unity.Entities.EntityCommandBuffer.SetBuffer``1(Unity.Entities.Entity)) to wipe out the existing buffer (which must exist) and create a new, empty buffer in its place. Both functions return a [DynamicBuffer](xref:Unity.Entities.DynamicBuffer`1) instance that you can use to populate the new buffer. You can add elements to the buffer immediately, but they are not otherwise accessible until the buffer is actually added to the entity when the command buffer is executed. @@ -110,4 +131,7 @@ others. Note that the reinterpret function only enforces that the types involved have the same length; you could alias a `uint` and `float` buffer without raising an error since both types are 32-bits long. It is your responsibility to make sure that the reinterpretation makes sense logically. +## Buffer Reference Invalidation +Every [structural change](sync_points.md#structural-changes) invalidates all references to dynamic buffers. Structural changes generally cause entities to move from one chunk to another. Small dynamic buffers can reference memory within a chunk (as opposed to from main memory) and hence need to be reacquired after a structural change. +[!code-cs[declare](../package/DocCodeSamples.Tests/DynamicBufferExamples.cs#invalidation)] \ No newline at end of file diff --git a/Documentation~/gp_overview.md b/Documentation~/gp_overview.md index e2ce38c5..1156d0fa 100644 --- a/Documentation~/gp_overview.md +++ b/Documentation~/gp_overview.md @@ -13,11 +13,11 @@ The systems include: ## Authoring Overview -You can use the Unity Editor (with the required DOTS packages) to create DOTS-based games. In the Editor, you author a scene using GameObjects as normal and the ECS code converts the scene GameObjects to entities. The biggest difference when using DOTS is that instead of writing your own MonoBehaviours to store instance data and implement custom game logic, you would typically define ECS components to store the data at runtime and write systems for the custom logic. +You can use the Unity Editor (with the required DOTS packages) to create DOTS-based games. In the Editor, you author a scene using GameObjects as normal and the ECS code converts the scene GameObjects to entities. The biggest difference when using DOTS is that instead of writing your own MonoBehaviours to store instance data and implement custom game logic, you would typically define ECS components to store the data at runtime and write systems for the custom logic. ### GameObject conversion -During GameObject conversion, various conversion systems handle the MonoBehaviour components that they recognize and convert them into ECS-based components. For example, one of the the Unity.Transforms conversion systems examines the UnityEngine.Transform component and adds ECS components, such as [LocalToWorld](xref:Unity.Transforms.LocalToWorld), to replace it. You can implement an [IConvertGameObjectToEntity](xref:Unity.Entities.IConvertGameObjectToEntity) MonoBehaviour component to specify custom conversion steps. There often will not be a one-to-one relationship between the number of GameObjects converted and the number of entities created; nor between the number of MonoBehaviours on a GameObject and the number of ECS components added to an entity. +During GameObject conversion, various conversion systems handle the MonoBehaviour components that they recognize and convert them into ECS-based components. For example, one of the the Unity.Transforms conversion systems examines the UnityEngine.Transform component and adds ECS components, such as [LocalToWorld](xref:Unity.Transforms.LocalToWorld), to replace it. You can implement an [IConvertGameObjectToEntity](xref:Unity.Entities.IConvertGameObjectToEntity) MonoBehaviour component to specify custom conversion steps. There often will not be a one-to-one relationship between the number of GameObjects converted and the number of entities created; nor between the number of MonoBehaviours on a GameObject and the number of ECS components added to an entity. ![](images/CreatingGameplay.png) @@ -29,7 +29,8 @@ Unity recommends using standard MonoBehaviours for authoring and using IConvertG ## Generated Authoring Components -Unity can automatically generate authoring components for simple [IComponentData](xref:Unity.Entities.IComponentData) components. Generating an autjoring component allows you to add an IComponentData directly to a GameObject in a scene within the Unity Editor. You can then set the initial values for the component using the Inspector window. +### With IComponentData +Unity can automatically generate authoring components for simple [IComponentData](xref:Unity.Entities.IComponentData) components. Generating an authoring component allows you to add an IComponentData directly to a GameObject in a scene within the Unity Editor. You can then set the initial values for the component using the Inspector window. To do this, add the `[GenerateAuthoringComponent]` attribute to your component definition. Unity automatically generates a MonoBehaviour for you that contains the public fields of your component and provides a Conversion method that converts those fields over into runtime component data. @@ -45,4 +46,22 @@ Note that the following restrictions: - Only one component in a single C# file can have a generated authoring component, and the C# file must not have another MonoBehaviour in it. - Only public fields are reflected and they will have the same name as that specified in the component. -- Fields of an Entity type in the IComponentData are reflected as fields of GameObject types in the generated MonoBehaviour. GameObjects or Prefabs you assign to these fields are converted as referenced prefabs. +- Fields of an Entity type in the IComponentData are reflected as fields of GameObject types in the generated MonoBehaviour. GameObjects or Prefabs you assign to these fields are converted as referenced prefabs. + +### With IBufferElementData +Authoring components can also be automatically generated for types that implement `IBufferElementData` by adding the `[GenerateAuthoringComponent]` attribute. E.g., if you declare the following type: + +``` +[GenerateAuthoringComponent] +public struct IntBufferElement: IBufferElementData +{ + public int Value; +} +``` + +A class named `IntBufferElementAuthoring` (which inherits from `MonoBehaviour`) will be generated, exposing a public field of `List` type. During conversion, this list will be converted into `DynamicBuffer`, and then added to the converted entity. + +Note the following restrictions: +- Only one component in a single C# file can have a generated authoring component, and the C# file must not have another MonoBehaviour in it. +- `IBufferElementData` authoring components cannot be automatically generated for types that contain 2 or more fields. +- `IBufferElementData` authoring components cannot be automatically generated for types that have an explicit layout. \ No newline at end of file diff --git a/Editor/LiveLink/uss/LiveLinkConnectionsDropdown.uss b/Editor/LiveLink/uss/LiveLinkConnectionsDropdown.uss index 94e549c8..d2affb9d 100644 --- a/Editor/LiveLink/uss/LiveLinkConnectionsDropdown.uss +++ b/Editor/LiveLink/uss/LiveLinkConnectionsDropdown.uss @@ -5,7 +5,7 @@ .live-link-connections-dropdown__all-connections-actions-section { padding-top: 2px; padding-bottom: 2px; - /*border-bottom-width: 1px;*/ + border-bottom-width: 1px; border-top-width: 1px; } diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow.uss b/Editor/LiveLink/uss/StartLiveLinkWindow.uss new file mode 100644 index 00000000..3f714dcf --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow.uss @@ -0,0 +1,164 @@ +#start-live-link { + padding: 15px; + flex-shrink: 0; + flex-grow: 1; +} + +#start-live-link__header-title { + font-size: 20px; +} + +#start-live-link__body { + margin-top: 15px; + flex-grow: 1; + flex-basis: auto; + flex-direction: column; + flex-shrink: 0; +} + +#start-live-link__body__search { + margin: 0; + padding-left: 0; + width: auto; +} + +#start-live-link__body__empty-message { + margin-top: 10px; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 1px; + min-height: 100px; + flex-grow: 1; + flex-shrink: 0; + padding: 5px; +} +#start-live-link__body__empty-message Label { + white-space: normal; +} + +#start-live-link__body__configurations-list { + margin-top: 10px; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 1px; + flex-grow: 1; + flex-shrink: 0; + display: none; +} + +#start-live-link__body__new-build-button { + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 0; + border-bottom-width: 1px; + border-radius: 0; + margin: 0; + padding: 3px 3px 4px 3px; + background-color: rgba(93, 93, 93, 0); + -unity-text-align: middle-left; + flex-direction: row; +} + +#start-live-link__body__new-build-button__icon { + width: 16px; + height: 16px; + margin-left: 2px; + margin-right: 2px; +} + +#start-live-link__build-message { + margin-top: 15px; + flex-direction: row-reverse; +} + +#start-live-link__footer { + margin-top: 15px; + flex-direction: row-reverse; +} + +#start-live-link__footer__start-button { + width: 110px; + border-radius: 4px; +} + +#start-live-link__footer__build-mode-container { + flex-shrink: 0; + width: 140px; +} + +.start-live-link__item-template { + flex-direction: row; +} + +.start-live-link__item-template Image { + width: 16px; + height: 16px; +} + +.start-live-link__item-template__device-icon { + margin: 2px 1px 2px 2px; +} + +.start-live-link__item-template__error-icon { + margin: 2px; +} + +.start-live-link__item-template Label { + flex: 1; + -unity-text-align: middle-left; +} + +#start-live-link__message { + margin-top: 10px; + border-radius: 3px; + border-width: 1px; + flex-direction: row; + padding: 3px 5px; +} + +#start-live-link__message Image { + margin: 0; + width: 32px; + height: 32px; + flex-shrink: 0; +} + +#start-live-link__message Label { + flex-shrink: 1; + white-space: normal; + -unity-text-align: middle-left; +} + +#start-live-link__new-build-name { + flex-direction: row; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 0; + border-bottom-width: 1px; + margin: 0; + padding: 3px; + -unity-text-align: middle-left; +} + +#start-live-link__new-build-name TextField { + flex-grow: 1; + padding: 0; + margin: 0; +} + +#start-live-link__new-build-name__submit { + margin: 0 0 0 3px; +} +#start-live-link__new-build-name__cancel { + margin: 0; +} + +#start-live-link__new-build-name Button { + width: 16px; + height: 16px; + border-width: 0; + padding: 0; + background-color: rgba(0,0,0,0); +} \ No newline at end of file diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow.uss.meta b/Editor/LiveLink/uss/StartLiveLinkWindow.uss.meta new file mode 100644 index 00000000..eca4e2ed --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4643d5fd547f13a499e796851acc9d81 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss b/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss new file mode 100644 index 00000000..5be3042b --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss @@ -0,0 +1,75 @@ + +#start-live-link__body__configurations-list { + border-color: #232323; +} + +#start-live-link__body__empty-message { + border-color: #232323; +} + +#start-live-link__body__new-build-button { + border-color: #232323; +} +#start-live-link__body__new-build-button:hover { + background-color: rgb(86, 86, 86); +} + +#start-live-link__body__new-build-button__icon { + background-image: resource('d_Toolbar Plus'); +} + +.start-live-link__item-template__error-icon { + background-image: resource("d_console.erroricon.png"); +} + +#start-live-link__footer__start-button { + background-color: #4271AD; + color: #EEEEEE; + border-top-color: #3B659B; + border-left-color: #3B659B; + border-right-color: #3B659B; + border-bottom-color: #223A59; +} +#start-live-link__footer__start-button:hover { + background-color: #4678B9; +} +#start-live-link__footer__start-button:active { + background-color: #416EAA; +} + +.start-live-link__item-template__icon-noTarget { background-image: resource("d_BuildSettings.Standalone.png"); } +.start-live-link__item-template__icon-windows { background-image: resource("d_BuildSettings.Metro.png"); } +.start-live-link__item-template__icon-xboxOne { background-image: resource("d_BuildSettings.XboxOne.png"); } +.start-live-link__item-template__icon-standalone { background-image: resource("d_BuildSettings.Standalone.png"); } +.start-live-link__item-template__icon-iOS { background-image: resource("d_BuildSettings.iPhone.png"); } +.start-live-link__item-template__icon-android { background-image: resource("d_BuildSettings.Android.png"); } +.start-live-link__item-template__icon-webGL { background-image: resource("d_BuildSettings.WebGL.png"); } +.start-live-link__item-template__icon-ps4 { background-image: resource("d_BuildSettings.PS4.png"); } +.start-live-link__item-template__icon-tvOS { background-image: resource("d_BuildSettings.tvOS.png"); } +.start-live-link__item-template__icon-switch { background-image: resource("d_BuildSettings.Switch.png"); } +.start-live-link__item-template__icon-lumin { background-image: resource("d_BuildSettings.Lumin.png"); } +.start-live-link__item-template__icon-stadia { background-image: resource("d_BuildSettings.Stadia.png"); } + +#start-live-link__message { + border-color: #232323; +} + +.start-live-link__message__icon-error { + background-image: resource("d_console.erroricon@2x.png"); +} +.start-live-link__message__icon-info { + background-image: resource("d_console.infoicon@2x.png"); +} +#start-live-link__new-build-name { + border-color: #232323; + } + +#start-live-link__new-build-name__cancel { + background-image: resource("d_winbtn_win_close.png"); +} +#start-live-link__new-build-name__submit { + background-image: resource("d_Toolbar Plus"); +} +#start-live-link__new-build-name Button:hover { + background-color: rgb(86, 86, 86); +} \ No newline at end of file diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss.meta b/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss.meta new file mode 100644 index 00000000..fcb5c432 --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow_dark.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89f0f0669a0907d4bbafdda7cfdc63c6 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss b/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss new file mode 100644 index 00000000..39a32de2 --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss @@ -0,0 +1,74 @@ + +#start-live-link__body__configurations-list { + border-color: #A9A9A9; +} + +#start-live-link__body__empty-message { + border-color: #A9A9A9; +} + +#start-live-link__body__new-build-button { + border-color: #A9A9A9; +} +#start-live-link__body__new-build-button:hover { + background-color: #DFDFDF; +} + +#start-live-link__body__new-build-button__icon { + background-image: resource('Toolbar Plus'); +} + +.start-live-link__item-template__error-icon { + background-image: resource("console.erroricon.png"); +} + +#start-live-link__footer__start-button { + background-color: #4672AB; + color: #EEEEEE; + border-top-color: #3E6599; + border-left-color: #3E6599; + border-right-color: #3E6599; + border-bottom-color: #294465; +} +#start-live-link__footer__start-button:hover { + background-color: #4E7BB6; +} +#start-live-link__footer__start-button:active { + background-color: #446FA6; +} + +.start-live-link__item-template__icon-noTarget { background-image: resource("BuildSettings.Standalone.png"); } +.start-live-link__item-template__icon-windows { background-image: resource("BuildSettings.Metro.png"); } +.start-live-link__item-template__icon-xboxOne { background-image: resource("BuildSettings.XboxOne.png"); } +.start-live-link__item-template__icon-standalone { background-image: resource("BuildSettings.Standalone.png"); } +.start-live-link__item-template__icon-iOS { background-image: resource("BuildSettings.iPhone.png"); } +.start-live-link__item-template__icon-android { background-image: resource("BuildSettings.Android.png"); } +.start-live-link__item-template__icon-webGL { background-image: resource("BuildSettings.WebGL.png"); } +.start-live-link__item-template__icon-ps4 { background-image: resource("BuildSettings.PS4.png"); } +.start-live-link__item-template__icon-tvOS { background-image: resource("BuildSettings.tvOS.png"); } +.start-live-link__item-template__icon-switch { background-image: resource("BuildSettings.Switch.png"); } +.start-live-link__item-template__icon-lumin { background-image: resource("BuildSettings.Lumin.png"); } +.start-live-link__item-template__icon-stadia { background-image: resource("BuildSettings.Stadia.png"); } + +#start-live-link__message { + border-color: #A9A9A9; +} + +.start-live-link__message__icon-error { + background-image: resource("console.erroricon@2x.png"); +} +.start-live-link__message__icon-info { + background-image: resource("console.infoicon@2x.png"); +} +#start-live-link__new-build-name { + border-color: #A9A9A9; +} +#start-live-link__new-build-name__cancel { + background-image: resource("winbtn_win_close.png"); +} +#start-live-link__new-build-name__submit { + background-image: resource("Toolbar Plus"); +} +#start-live-link__new-build-name Button:hover { + background-color: #DFDFDF; +} \ No newline at end of file diff --git a/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss.meta b/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss.meta new file mode 100644 index 00000000..18ed0840 --- /dev/null +++ b/Editor/LiveLink/uss/StartLiveLinkWindow_light.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 348cdd2a060ae1740b9d5463e13fdb07 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor/LiveLink/uxml/LiveLinkConnectionsDropdown.uxml b/Editor/LiveLink/uxml/LiveLinkConnectionsDropdown.uxml index 32c54423..6a73ca80 100644 --- a/Editor/LiveLink/uxml/LiveLinkConnectionsDropdown.uxml +++ b/Editor/LiveLink/uxml/LiveLinkConnectionsDropdown.uxml @@ -6,9 +6,8 @@ - - - - + + + diff --git a/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml b/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml new file mode 100644 index 00000000..62884598 --- /dev/null +++ b/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml.meta b/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml.meta new file mode 100644 index 00000000..1853badc --- /dev/null +++ b/Editor/LiveLink/uxml/StartLiveLinkWindow.ListViewItemTemplate.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: d69dc6c76f1ab704baf11b3b43facf1c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml b/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml new file mode 100644 index 00000000..77fbcfe4 --- /dev/null +++ b/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml.meta b/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml.meta new file mode 100644 index 00000000..e42058e1 --- /dev/null +++ b/Editor/LiveLink/uxml/StartLiveLinkWindow.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2eeaa18da16aee949992c91a77576421 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/LICENSE.md b/LICENSE.md index 9a3f87a4..a569e0fb 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,5 +1,5 @@ Unity Companion License (“License”) -Software Copyright © 2017-20 Unity Technologies ApS +Software Copyright © 2017-2020 Unity Technologies ApS Unity Technologies ApS (“Unity”) grants to you a worldwide, non-exclusive, no-charge, and royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute the software that is made available under this License (“Software”), subject to the following terms and conditions: diff --git a/Unity.Build.Common/Assets/AndroidHybrid.buildpipeline b/Unity.Build.Common/Assets/AndroidHybrid.buildpipeline deleted file mode 100644 index 180d252f..00000000 --- a/Unity.Build.Common/Assets/AndroidHybrid.buildpipeline +++ /dev/null @@ -1,6 +0,0 @@ -{ - "BuildSteps": [ - "GlobalObjectId_V1-1-99fe1e2a22b18e14d9dd5dacc75a0212-93214019566545601-0" - ], - "RunStep": "Unity.Build.Common.RunStepAndroid, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/Hybrid.buildpipeline b/Unity.Build.Common/Assets/Hybrid.buildpipeline deleted file mode 100644 index 6617dc8d..00000000 --- a/Unity.Build.Common/Assets/Hybrid.buildpipeline +++ /dev/null @@ -1,10 +0,0 @@ -{ - "BuildSteps": [ - "Unity.Build.Common.SaveScenesAndAssets, Unity.Build.Common", - "Unity.Build.Common.BuildStepApplyPlayerSettings, Unity.Build.Common", - "Unity.Build.Common.BuildStepSwitchPlatfomClassic, Unity.Build.Common", - "Unity.Scenes.Editor.BuildStepSubSceneBundles, Unity.Scenes.Editor", - "Unity.Build.Common.BuildStepBuildClassicPlayer, Unity.Build.Common" - ], - "RunStep": "Unity.Build.Common.RunStepNotImplemented, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/HybridLiveLink.buildpipeline b/Unity.Build.Common/Assets/HybridLiveLink.buildpipeline deleted file mode 100644 index d847e0c4..00000000 --- a/Unity.Build.Common/Assets/HybridLiveLink.buildpipeline +++ /dev/null @@ -1,9 +0,0 @@ -{ - "BuildSteps": [ - "Unity.Build.Common.SaveScenesAndAssets, Unity.Build.Common", - "Unity.Build.Common.BuildStepApplyPlayerSettings, Unity.Build.Common", - "Unity.Build.Common.BuildStepSwitchPlatfomClassic, Unity.Build.Common", - "Unity.Build.Common.BuildStepBuildClassicLiveLink, Unity.Build.Common" - ], - "RunStep": "Unity.Build.Common.RunStepNotImplemented, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/OSXHybrid.buildpipeline b/Unity.Build.Common/Assets/OSXHybrid.buildpipeline deleted file mode 100644 index b96087a6..00000000 --- a/Unity.Build.Common/Assets/OSXHybrid.buildpipeline +++ /dev/null @@ -1,6 +0,0 @@ -{ - "BuildSteps": [ - "GlobalObjectId_V1-1-99fe1e2a22b18e14d9dd5dacc75a0212-93214019566545601-0" - ], - "RunStep": "Unity.Build.Common.RunStepDesktop, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/OSXHybridLiveLink.buildpipeline b/Unity.Build.Common/Assets/OSXHybridLiveLink.buildpipeline deleted file mode 100644 index 69e6995e..00000000 --- a/Unity.Build.Common/Assets/OSXHybridLiveLink.buildpipeline +++ /dev/null @@ -1,6 +0,0 @@ -{ - "BuildSteps": [ - "GlobalObjectId_V1-1-b08acfa97ea29e84597342a6a2afa6b2-93214019566545601-0" - ], - "RunStep": "Unity.Build.Common.RunStepDesktop, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/WindowsHybrid.buildpipeline b/Unity.Build.Common/Assets/WindowsHybrid.buildpipeline deleted file mode 100644 index b96087a6..00000000 --- a/Unity.Build.Common/Assets/WindowsHybrid.buildpipeline +++ /dev/null @@ -1,6 +0,0 @@ -{ - "BuildSteps": [ - "GlobalObjectId_V1-1-99fe1e2a22b18e14d9dd5dacc75a0212-93214019566545601-0" - ], - "RunStep": "Unity.Build.Common.RunStepDesktop, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Assets/WindowsHybridLiveLink.buildpipeline b/Unity.Build.Common/Assets/WindowsHybridLiveLink.buildpipeline deleted file mode 100644 index 69e6995e..00000000 --- a/Unity.Build.Common/Assets/WindowsHybridLiveLink.buildpipeline +++ /dev/null @@ -1,6 +0,0 @@ -{ - "BuildSteps": [ - "GlobalObjectId_V1-1-b08acfa97ea29e84597342a6a2afa6b2-93214019566545601-0" - ], - "RunStep": "Unity.Build.Common.RunStepDesktop, Unity.Build.Common" -} \ No newline at end of file diff --git a/Unity.Build.Common/Settings/ClassicBuildProfile.cs b/Unity.Build.Common/Settings/ClassicBuildProfile.cs deleted file mode 100644 index bc354c49..00000000 --- a/Unity.Build.Common/Settings/ClassicBuildProfile.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using PropertyAttribute = Unity.Properties.PropertyAttribute; - -namespace Unity.Build.Common -{ - public sealed class ClassicBuildProfile : IBuildPipelineComponent - { - BuildTarget m_Target; - List m_ExcludedAssemblies; - - /// - /// Retrieve for this build profile. - /// - public BuildTypeCache TypeCache { get; } = new BuildTypeCache(); - - /// - /// Gets or sets which this profile is going to use for the build. - /// Used for building classic Unity standalone players. - /// - [Property] - public BuildTarget Target - { - get => m_Target; - set - { - m_Target = value; - TypeCache.PlatformName = m_Target.ToString(); - } - } - - /// - /// Gets or sets which this profile is going to use for the build. - /// - [Property] - public BuildConfiguration Configuration { get; set; } = BuildConfiguration.Develop; - - [Property] - public BuildPipeline Pipeline { get; set; } - - /// - /// List of assemblies that should be explicitly excluded for the build. - /// - [Property, HideInInspector] - public List ExcludedAssemblies - { - get => m_ExcludedAssemblies; - set - { - m_ExcludedAssemblies = value; - TypeCache.ExcludedAssemblies = value; - } - } - - public ClassicBuildProfile() - { - Target = BuildTarget.NoTarget; - ExcludedAssemblies = new List(); - } - - internal string GetExecutableExtension() - { -#pragma warning disable CS0618 - switch (m_Target) - { - case BuildTarget.StandaloneOSX: - case BuildTarget.StandaloneOSXIntel: - case BuildTarget.StandaloneOSXIntel64: - return ".app"; - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - return ".exe"; - case BuildTarget.NoTarget: - case BuildTarget.StandaloneLinux64: - case BuildTarget.Stadia: - return string.Empty; - case BuildTarget.Android: - if (EditorUserBuildSettings.exportAsGoogleAndroidProject) - return ""; - else if (EditorUserBuildSettings.buildAppBundle) - return ".aab"; - else - return ".apk"; - case BuildTarget.Lumin: - return ".mpk"; - case BuildTarget.iOS: - case BuildTarget.tvOS: - default: - return ""; - } -#pragma warning restore CS0618 - } - } -} diff --git a/Unity.Build.Common/Settings/ClassicScriptingSettings.cs b/Unity.Build.Common/Settings/ClassicScriptingSettings.cs deleted file mode 100644 index e1ad0e0b..00000000 --- a/Unity.Build.Common/Settings/ClassicScriptingSettings.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using UnityEditor; -using PropertyAttribute = Unity.Properties.PropertyAttribute; - -namespace Unity.Build.Common -{ - public sealed class ClassicScriptingSettings : IBuildSettingsComponent - { - [Property] - public ScriptingImplementation ScriptingBackend { get; set; } = ScriptingImplementation.Mono2x; - - [Property] - public Il2CppCompilerConfiguration Il2CppCompilerConfiguration { get; set; } = Il2CppCompilerConfiguration.Release; - - [Property] - public bool UseIncrementalGC { get; set; } = false; - - // Note: We haven't exposed ScriptingDefineSymbols, ApiCompatibilityLevel, AllowUnsafeCode. Because those affect scripting compilation pipeline, this raises few questions: - // - Editor will not reflect the same set compilation result as building to player, which is not very good. - // - We need to either decide to have somekind of global project settings (used both in Editor and while building to player) or have - // "active build settings" property which would be used as information what kind of enviromnent to simulate, in this it may make sense to but 'ScriptingDefineSymbols, ApiCompatibilityLevel, AllowUnsafeCode' here - } -} diff --git a/Unity.Build.Common/Settings/ClassicScriptingSettingsInspector.cs b/Unity.Build.Common/Settings/ClassicScriptingSettingsInspector.cs deleted file mode 100644 index ff7eb08e..00000000 --- a/Unity.Build.Common/Settings/ClassicScriptingSettingsInspector.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using JetBrains.Annotations; -using Unity.Properties.Editor; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine.UIElements; - -namespace Unity.Build.Common -{ - [UsedImplicitly] - sealed class ClassicScriptingSettingsInspector : IInspector - { - EnumField m_ScriptingBackend; - VisualElement m_Il2CppCompilerConfiguration; - - public VisualElement Build(InspectorContext context) - { - var root = new VisualElement(); - context.DoDefaultGui(root, nameof(ClassicScriptingSettings.ScriptingBackend)); - context.DoDefaultGui(root, nameof(ClassicScriptingSettings.Il2CppCompilerConfiguration)); - context.DoDefaultGui(root, nameof(ClassicScriptingSettings.UseIncrementalGC)); - - m_ScriptingBackend = root.Q(nameof(ClassicScriptingSettings.ScriptingBackend)); - m_Il2CppCompilerConfiguration = root.Q(nameof(ClassicScriptingSettings.Il2CppCompilerConfiguration)); - - return root; - } - - public void Update(InspectorContext context) - { - m_Il2CppCompilerConfiguration.SetEnabled((ScriptingImplementation)m_ScriptingBackend.value == ScriptingImplementation.IL2CPP); - } - } -} \ No newline at end of file diff --git a/Unity.Build.Common/Settings/GeneralSettings.cs b/Unity.Build.Common/Settings/GeneralSettings.cs deleted file mode 100644 index 338d7a53..00000000 --- a/Unity.Build.Common/Settings/GeneralSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Unity.Build.Common -{ - public sealed class GeneralSettings : IBuildSettingsComponent - { - public string ProductName = "Product Name"; - public string CompanyName = "Company Name"; - } -} diff --git a/Unity.Build.Common/Settings/GraphicsSettings.cs b/Unity.Build.Common/Settings/GraphicsSettings.cs deleted file mode 100644 index 4eca9346..00000000 --- a/Unity.Build.Common/Settings/GraphicsSettings.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UnityEngine; - -namespace Unity.Build.Common -{ - public sealed class GraphicsSettings : IBuildSettingsComponent - { - public ColorSpace ColorSpace = ColorSpace.Uninitialized; - } -} diff --git a/Unity.Build.Common/Settings/GraphicsSettings.cs.meta b/Unity.Build.Common/Settings/GraphicsSettings.cs.meta deleted file mode 100644 index aaf1ed36..00000000 --- a/Unity.Build.Common/Settings/GraphicsSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e818cf6af23e93744985e740691d0e70 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Settings/InternalSourceBuild.cs b/Unity.Build.Common/Settings/InternalSourceBuild.cs deleted file mode 100644 index b73063ba..00000000 --- a/Unity.Build.Common/Settings/InternalSourceBuild.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Unity.Properties; - -namespace Unity.Build.Common -{ - internal sealed class InternalSourceBuildConfiguration : IBuildSettingsComponent - { - [Property] public bool Enabled { get; set; } - } -} diff --git a/Unity.Build.Common/Settings/InternalSourceBuild.cs.meta b/Unity.Build.Common/Settings/InternalSourceBuild.cs.meta deleted file mode 100644 index f90cc929..00000000 --- a/Unity.Build.Common/Settings/InternalSourceBuild.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a49d0b947ebd38d4f95b006994001925 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Settings/OutputBuildDirectory.cs b/Unity.Build.Common/Settings/OutputBuildDirectory.cs deleted file mode 100644 index 88cf9add..00000000 --- a/Unity.Build.Common/Settings/OutputBuildDirectory.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Unity.Build.Internals; -using Unity.Properties; - -namespace Unity.Build.Common -{ - /// - /// Overrides the default output directory of Builds/NameOfBuildSettingsAsset to an arbitrary location. - /// - public class OutputBuildDirectory : IBuildSettingsComponent - { - [Property] public string OutputDirectory { get; set; } - } - - public static class BuildSettingsExtensions - { - /// - /// Get the output build directory for this . - /// The output build directory can be overridden using a component. - /// - /// This build settings. - /// The output build directory. - public static string GetOutputBuildDirectory(this BuildSettings settings) - { - if (settings.TryGetComponent(out var outBuildDir)) - { - return outBuildDir.OutputDirectory; - } - return $"Builds/{settings.name}"; - } - } - - public static class BuildStepExtensions - { - /// - /// Get the output build directory for this . - /// The output build directory can be overridden using a component. - /// - /// This build step. - /// The build context used throughout this build. - /// The output build directory. - public static string GetOutputBuildDirectory(this BuildStep step, BuildContext context) - { - if (step.HasOptionalComponent(context)) - { - return step.GetOptionalComponent(context).OutputDirectory; - } - var settings = BuildContextInternals.GetBuildSettings(context); - return $"Builds/{settings.name}"; - } - } -} diff --git a/Unity.Build.Common/Settings/OutputBuildDirectory.cs.meta b/Unity.Build.Common/Settings/OutputBuildDirectory.cs.meta deleted file mode 100644 index bd46c715..00000000 --- a/Unity.Build.Common/Settings/OutputBuildDirectory.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0b47bf9f276beab40b2b309e9392ec74 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Settings/SceneList.cs b/Unity.Build.Common/Settings/SceneList.cs deleted file mode 100644 index fd035cea..00000000 --- a/Unity.Build.Common/Settings/SceneList.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Unity.Properties; -using UnityEditor; -using UnityEditor.SceneManagement; - -namespace Unity.Build.Common -{ - public sealed class SceneList : IBuildSettingsComponent - { - readonly int m_CurrentPickerWindow; - - [Property] - public bool BuildCurrentScene { get; set; } - - [Property, AssetGuid(typeof(SceneAsset))] - public List Scenes { get; set; } = new List(); - - public string[] GetScenePathsForBuild() - { - if (BuildCurrentScene) - { - // Build a list of the root scenes - var rootScenes = new List(); - for (int i = 0; i != EditorSceneManager.sceneCount; i++) - { - var scene = EditorSceneManager.GetSceneAt(i); - if (scene.isSubScene) - continue; - if (!scene.isLoaded) - continue; - if (EditorSceneManager.IsPreviewScene(scene)) - continue; - if (string.IsNullOrEmpty(scene.path)) - continue; - - rootScenes.Add(scene.path); - } - - return rootScenes.ToArray(); - } - else - { - return Scenes.Select(id => id.assetGUID.ToString()).Select(AssetDatabase.GUIDToAssetPath).ToArray(); - } - } - } -} diff --git a/Unity.Build.Common/Settings/SceneList.cs.meta b/Unity.Build.Common/Settings/SceneList.cs.meta deleted file mode 100644 index 1c9ab0e7..00000000 --- a/Unity.Build.Common/Settings/SceneList.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 30e0a7c39228e064eaeb75311b288905 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs b/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs deleted file mode 100644 index 9df175c9..00000000 --- a/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Diagnostics; - -namespace Unity.Build.Common -{ - // This is just a placeholder until we implement RunStepAndroid in com.unity.platforms - sealed class RunInstanceAndroid : IRunInstance - { - public bool IsRunning => true; - - public RunInstanceAndroid() - { - } - - public void Dispose() - { - } - } -} diff --git a/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs.meta b/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs.meta deleted file mode 100644 index 74b87e12..00000000 --- a/Unity.Build.Common/Steps/Android/RunInstanceAndroid.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91e933c12c147ed468efad9433a6a941 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/Android/RunStepAndroid.cs b/Unity.Build.Common/Steps/Android/RunStepAndroid.cs deleted file mode 100644 index e7bb50f6..00000000 --- a/Unity.Build.Common/Steps/Android/RunStepAndroid.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Diagnostics; -using System.IO; -using System; -using UnityEditor; -#if UNITY_ANDROID -using UnityEditor.Android; -#endif - -namespace Unity.Build.Common -{ - // This is just a placeholder until we implement RunStepAndroid in com.unity.platforms - sealed class RunStepAndroid : RunStep - { - public override bool CanRun(BuildSettings settings, out string reason) - { - var artifact = BuildArtifacts.GetBuildArtifact(settings); - if (artifact == null) - { - reason = $"Could not retrieve build artifact '{nameof(BuildArtifactDesktop)}'."; - return false; - } - - if (artifact.OutputTargetFile == null) - { - reason = $"{nameof(BuildArtifactDesktop.OutputTargetFile)} is null."; - return false; - } - - reason = null; - return true; - } - - public override RunStepResult Start(BuildSettings settings) - { - var artifact = BuildArtifacts.GetBuildArtifact(settings); - var fileName = artifact.OutputTargetFile.FullName; - if (Path.GetExtension(fileName) != ".apk") - return Failure(settings, $"Expected .apk in path, but got '{fileName}'."); - - var path = $"\"{Path.GetFullPath(fileName)}\""; -#if UNITY_ANDROID - EditorUtility.DisplayProgressBar("Installing", $"Installing {path}", 0.3f); - var adb = ADB.GetInstance(); - try - { - adb.Run(new[] {"install", "-r", "-d", path}, $"Failed to install '{fileName}'"); - } - catch (Exception ex) - { - EditorUtility.ClearProgressBar(); - return Failure(settings, ex.Message); - } - - UnityEngine.Debug.Log($"{path} successfully installed."); - var runTarget = $"\"{PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.Android)}/com.unity3d.player.UnityPlayerActivity\""; - EditorUtility.DisplayProgressBar("Launching", $"Launching {runTarget}", 0.6f); - try - { - adb.Run(new[] - { - "shell", "am", "start", - "-a", "android.intent.action.MAIN", - "-c", "android.intent.category.LAUNCHER", - "-f", "0x10200000", - "-S", - "-n", runTarget - }, - $"Failed to launch {runTarget}"); - } - catch (Exception ex) - { - EditorUtility.ClearProgressBar(); - return Failure(settings, ex.Message); - } - - UnityEngine.Debug.Log($"{runTarget} successfully launched."); - EditorUtility.ClearProgressBar(); - return Success(settings, new RunInstanceAndroid()); -#else - return Failure(settings, $"Active Editor platform has to be set to Android."); -#endif - } - } -} diff --git a/Unity.Build.Common/Steps/Android/RunStepAndroid.cs.meta b/Unity.Build.Common/Steps/Android/RunStepAndroid.cs.meta deleted file mode 100644 index 608ad60a..00000000 --- a/Unity.Build.Common/Steps/Android/RunStepAndroid.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 35d33d90e9c20e443bfbf0c28df72ff7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/BuildArtifactDesktop.cs b/Unity.Build.Common/Steps/BuildArtifactDesktop.cs deleted file mode 100644 index 42ed4f8c..00000000 --- a/Unity.Build.Common/Steps/BuildArtifactDesktop.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.IO; - -namespace Unity.Build.Common -{ - public sealed class BuildArtifactDesktop : IBuildArtifact - { - public FileInfo OutputTargetFile; - } -} diff --git a/Unity.Build.Common/Steps/BuildArtifactDesktop.cs.meta b/Unity.Build.Common/Steps/BuildArtifactDesktop.cs.meta deleted file mode 100644 index 386911d7..00000000 --- a/Unity.Build.Common/Steps/BuildArtifactDesktop.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 69d886edb4f1cb247b445857aaf54ec4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs b/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs deleted file mode 100644 index a267ac28..00000000 --- a/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using UnityEditor; - -namespace Unity.Build.Common -{ - [BuildStep(description = k_Description, category = "Classic")] - public sealed class BuildStepApplyPlayerSettings : BuildStep - { - const string k_Description = "Apply Player Settings"; - - public override string Description => k_Description; - - public override Type[] RequiredComponents => new[] - { - typeof(ClassicBuildProfile), - typeof(GeneralSettings), - typeof(ClassicScriptingSettings) - }; - - class PlayerSettingsState - { - public string Contents { set; get; } - public bool IsDirty { set; get; } - public static PlayerSettings Target => AssetDatabase.LoadAssetAtPath("ProjectSettings/ProjectSettings.asset"); - } - - private BuildStepResult FindProperty(SerializedObject serializedObject, string name, out SerializedProperty serializedProperty) - { - serializedProperty = serializedObject.FindProperty(name); - if (serializedProperty == null) - { - return Failure($"Failed to find: {name}"); - } - return Success(); - } - - public override BuildStepResult RunBuildStep(BuildContext context) - { - context.SetValue(new PlayerSettingsState() - { - Contents = EditorJsonUtility.ToJson(PlayerSettingsState.Target), - IsDirty = EditorUtility.GetDirtyCount(PlayerSettingsState.Target) > 0 - }); - - var serializedObject = new SerializedObject(PlayerSettingsState.Target); - var profile = GetRequiredComponent(context); - var generalSettings = GetRequiredComponent(context); - var scriptingSettings = GetRequiredComponent(context); - var targetGroup = UnityEditor.BuildPipeline.GetBuildTargetGroup(profile.Target); - - // Get serialized properties for things which don't have API exposed - SerializedProperty gcIncremental; - var result = FindProperty(serializedObject, nameof(gcIncremental), out gcIncremental); - if (result.Failed) - return result; - - PlayerSettings.productName = generalSettings.ProductName; - PlayerSettings.companyName = generalSettings.CompanyName; - - // Scripting Settings - PlayerSettings.SetScriptingBackend(targetGroup, scriptingSettings.ScriptingBackend); - PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, scriptingSettings.Il2CppCompilerConfiguration); - gcIncremental.boolValue = scriptingSettings.UseIncrementalGC; - - EditorUtility.ClearDirty(PlayerSettingsState.Target); - - return Success(); - } - public override BuildStepResult CleanupBuildStep(BuildContext context) - { - var savedState = context.GetValue(); - // Note: EditorJsonUtility.FromJsonOverwrite doesn't dirty PlayerSettings - EditorJsonUtility.FromJsonOverwrite(savedState.Contents, PlayerSettingsState.Target); - if (savedState.IsDirty) - EditorUtility.SetDirty(PlayerSettingsState.Target); - - return Success(); - } - } - -} diff --git a/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs.meta b/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs.meta deleted file mode 100644 index 57584716..00000000 --- a/Unity.Build.Common/Steps/BuildStepApplyPlayerSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0b6bd951231b43c4bb2c0e63c65ba6ff -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/BuildStepBuildClassicLiveLink.cs b/Unity.Build.Common/Steps/BuildStepBuildClassicLiveLink.cs deleted file mode 100644 index cb4206a4..00000000 --- a/Unity.Build.Common/Steps/BuildStepBuildClassicLiveLink.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using UnityEditor; - -namespace Unity.Build.Common -{ - [BuildStep(description = k_Description, category = "Classic")] - public sealed class BuildStepBuildClassicLiveLink : BuildStep - { - const string k_Description = "Build LiveLink Player"; - - TemporaryFileTracker m_TemporaryFileTracker; - - public override string Description => k_Description; - - public override Type[] RequiredComponents => new[] - { - typeof(ClassicBuildProfile), - typeof(SceneList), - typeof(GeneralSettings) - }; - - public override Type[] OptionalComponents => new[] - { - typeof(OutputBuildDirectory), - typeof(InternalSourceBuildConfiguration) - }; - - public override BuildStepResult RunBuildStep(BuildContext context) - { - m_TemporaryFileTracker = new TemporaryFileTracker(); - if (!BuildStepBuildClassicPlayer.Prepare(context, this, true, m_TemporaryFileTracker, out var failure, out var buildPlayerOptions)) - { - return failure; - } - - //@TODO: Allow debugging should be based on profile... - buildPlayerOptions.options = BuildOptions.Development | BuildOptions.AllowDebugging | BuildOptions.ConnectToHost; - - var report = UnityEditor.BuildPipeline.BuildPlayer(buildPlayerOptions); - return BuildStepBuildClassicPlayer.ReturnBuildPlayerResult(context, this, report); - } - - public override BuildStepResult CleanupBuildStep(BuildContext context) - { - m_TemporaryFileTracker.Dispose(); - return Success(); - } - } -} diff --git a/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs b/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs deleted file mode 100644 index ebede1fc..00000000 --- a/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.IO; -using Unity.Build.Internals; -using UnityEditor; -using UnityEditor.Build.Reporting; - -namespace Unity.Build.Common -{ - [BuildStep(description = k_Description, category = "Classic")] - sealed class BuildStepBuildClassicPlayer : BuildStep - { - const string k_Description = "Build Player"; - const string k_BootstrapFilePath = "Assets/StreamingAssets/livelink-bootstrap.txt"; - - TemporaryFileTracker m_TemporaryFileTracker; - - public override string Description => k_Description; - - public override Type[] RequiredComponents => new[] - { - typeof(ClassicBuildProfile), - typeof(SceneList), - typeof(GeneralSettings) - }; - - public override Type[] OptionalComponents => new[] - { - typeof(OutputBuildDirectory), - typeof(InternalSourceBuildConfiguration) - }; - - /// - /// Returns true if we need to use BuildOptions.AutoRunPlayer. - /// For ex., when platform doesn't have RunStep implemented yet. - /// This function should be removed when we'll have run steps implemented for all platforms - /// - /// - /// - private static bool UseAutoRunPlayer(BuildContext context) - { - var settings = BuildContextInternals.GetBuildSettings(context); - var pipeline = settings.GetComponent().Pipeline; - var runStep = pipeline.RunStep; - - // RunStep is provided no need to use AutoRunPlayer - if (runStep != null && runStep.GetType() != typeof(RunStepNotImplemented)) - return false; - - // See dots\Samples\Library\PackageCache\com.unity.build@0.1.0-preview.1\Editor\Unity.Build\BuildSettingsScriptedImporterEditor.cs - const string k_CurrentActionKey = "BuildAction-CurrentAction"; - if (!EditorPrefs.HasKey(k_CurrentActionKey)) - return false; - - var value = EditorPrefs.GetInt(k_CurrentActionKey); - return value == 1; - } - - public static bool Prepare(BuildContext context, BuildStep step, bool liveLink, TemporaryFileTracker tracker, out BuildStepResult failure, out BuildPlayerOptions buildPlayerOptions) - { - buildPlayerOptions = default; - var profile = step.GetRequiredComponent(context); - if (profile.Target <= 0) - { - failure = BuildStepResult.Failure(step, $"Invalid build target '{profile.Target.ToString()}'."); - return false; - } - - if (profile.Target != EditorUserBuildSettings.activeBuildTarget) - { - failure = BuildStepResult.Failure(step, $"{nameof(EditorUserBuildSettings.activeBuildTarget)} must be switched before {nameof(BuildStepBuildClassicPlayer)} step."); - return false; - } - - var scenesList = step.GetRequiredComponent(context).GetScenePathsForBuild(); - if (scenesList.Length == 0) - { - failure = BuildStepResult.Failure(step, "There are no scenes to build."); - return false; - } - - var outputPath = step.GetOutputBuildDirectory(context); - if (!Directory.Exists(outputPath)) - { - Directory.CreateDirectory(outputPath); - } - - var productName = step.GetRequiredComponent(context).ProductName; - var extension = profile.GetExecutableExtension(); - var locationPathName = Path.Combine(outputPath, productName + extension); - - buildPlayerOptions = new BuildPlayerOptions() - { - scenes = scenesList, - target = profile.Target, - locationPathName = locationPathName, - targetGroup = UnityEditor.BuildPipeline.GetBuildTargetGroup(profile.Target), - }; - - buildPlayerOptions.options = BuildOptions.None; - switch (profile.Configuration) - { - case BuildConfiguration.Debug: - buildPlayerOptions.options |= BuildOptions.AllowDebugging | BuildOptions.Development; - break; - case BuildConfiguration.Develop: - buildPlayerOptions.options |= BuildOptions.Development; - break; - } - - var sourceBuild = step.GetOptionalComponent(context); - if (sourceBuild.Enabled) - { - buildPlayerOptions.options |= BuildOptions.InstallInBuildFolder; - } - - if (UseAutoRunPlayer(context)) - { - UnityEngine.Debug.Log($"Using BuildOptions.AutoRunPlayer, since RunStep is not provided for {profile.Target}"); - buildPlayerOptions.options |= BuildOptions.AutoRunPlayer; - } - - if (liveLink) - { - File.WriteAllText(tracker.TrackFile(k_BootstrapFilePath), BuildContextInternals.GetBuildSettingsGUID(context)); - } - else - { - // Make sure we didn't leak a bootstrap file from a previous crashed build - tracker.EnsureFileDoesntExist(k_BootstrapFilePath); - } - - failure = default; - return true; - } - - public static BuildStepResult ReturnBuildPlayerResult(BuildContext context, BuildStep step, BuildReport report) - { - var result = new BuildStepResult(step, report); - if (result.Succeeded) - { - var artifact = context.GetOrCreateValue(); - artifact.OutputTargetFile = new FileInfo(report.summary.outputPath); - } - return result; - } - - public override BuildStepResult RunBuildStep(BuildContext context) - { - m_TemporaryFileTracker = new TemporaryFileTracker(); - if (!Prepare(context, this, false, m_TemporaryFileTracker, out var failure, out var options)) - return failure; - - var report = UnityEditor.BuildPipeline.BuildPlayer(options); - return ReturnBuildPlayerResult(context, this, report); - } - - public override BuildStepResult CleanupBuildStep(BuildContext context) - { - m_TemporaryFileTracker.Dispose(); - return Success(); - } - } -} diff --git a/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs.meta b/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs.meta deleted file mode 100644 index 96d02d3d..00000000 --- a/Unity.Build.Common/Steps/BuildStepBuildClassicPlayer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91624dad03586427e8366cddd9ec6595 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs b/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs deleted file mode 100644 index e1836170..00000000 --- a/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using UnityEditor; -using UnityEditor.SceneManagement; - -namespace Unity.Build.Common -{ - sealed class BuildStepSwitchPlatfomClassic : BuildStep - { - public override string Description => "Switch Active Platform (Classic)"; - - public override Type[] RequiredComponents => new[] - { - typeof(ClassicBuildProfile) - }; - - public override BuildStepResult RunBuildStep(BuildContext context) - { - var profile = GetRequiredComponent(context); - if (profile.Target == BuildTarget.NoTarget) - { - return Failure($"Invalid build target '{profile.Target.ToString()}'."); - } - - if (EditorUserBuildSettings.activeBuildTarget == profile.Target) - { - return Success(); - } - - if (EditorUserBuildSettings.SwitchActiveBuildTarget(UnityEditor.BuildPipeline.GetBuildTargetGroup(profile.Target), profile.Target)) - return Failure("Editor's active Build Target needed to be switched. Please wait for switch to complete and then build again."); - else - return Failure($"Editor's active Build Target could not be switched. Look in the console or the editor log for additional errors."); - } - } - - sealed class SaveScenesAndAssets : BuildStep - { - public override string Description => "Save Scenes and Assets"; - - public override BuildStepResult RunBuildStep(BuildContext context) - { - if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - return Failure($"All Scenes and Assets must be saved before a build can be started"); - - return Success(); - } - } -} diff --git a/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs.meta b/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs.meta deleted file mode 100644 index 7f6b0b71..00000000 --- a/Unity.Build.Common/Steps/BuildStepSwitchPlatfomClassic.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 514ccf3551ac2c84da05fee42e5bef8b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/RunInstanceDesktop.cs b/Unity.Build.Common/Steps/RunInstanceDesktop.cs deleted file mode 100644 index 825c08c2..00000000 --- a/Unity.Build.Common/Steps/RunInstanceDesktop.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Diagnostics; - -namespace Unity.Build.Common -{ - public sealed class RunInstanceDesktop : IRunInstance - { - Process m_Process; - - public bool IsRunning => !m_Process.HasExited; - - public RunInstanceDesktop(Process process) - { - m_Process = process; - } - - public void Dispose() - { - m_Process.Dispose(); - } - } -} diff --git a/Unity.Build.Common/Steps/RunInstanceDesktop.cs.meta b/Unity.Build.Common/Steps/RunInstanceDesktop.cs.meta deleted file mode 100644 index c8cc4b44..00000000 --- a/Unity.Build.Common/Steps/RunInstanceDesktop.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dc2a3ae3e52ce064a9af0dd1423e74fc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/RunStepDesktop.cs b/Unity.Build.Common/Steps/RunStepDesktop.cs deleted file mode 100644 index c7d850fe..00000000 --- a/Unity.Build.Common/Steps/RunStepDesktop.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Diagnostics; -using System.IO; - -namespace Unity.Build.Common -{ - public sealed class RunStepDesktop : RunStep - { - public override bool CanRun(BuildSettings settings, out string reason) - { - var artifact = BuildArtifacts.GetBuildArtifact(settings); - if (artifact == null) - { - reason = $"Could not retrieve build artifact '{nameof(BuildArtifactDesktop)}'."; - return false; - } - - if (artifact.OutputTargetFile == null) - { - reason = $"{nameof(BuildArtifactDesktop.OutputTargetFile)} is null."; - return false; - } - -#if UNITY_EDITOR_OSX - // On macOS, the output target is a .app directory structure - if (!Directory.Exists(artifact.OutputTargetFile.FullName)) -#else - if (!File.Exists(artifact.OutputTargetFile.FullName)) -#endif - { - reason = $"Output target file '{artifact.OutputTargetFile.FullName}' not found."; - return false; - } - - reason = null; - return true; - } - - public override RunStepResult Start(BuildSettings settings) - { - var artifact = BuildArtifacts.GetBuildArtifact(settings); - var process = new Process(); -#if UNITY_EDITOR_OSX - process.StartInfo.FileName = "open"; - process.StartInfo.Arguments = '\"' + artifact.OutputTargetFile.FullName.Trim('\"') + '\"'; -#else - process.StartInfo.FileName = artifact.OutputTargetFile.FullName; -#endif - process.StartInfo.WorkingDirectory = artifact.OutputTargetFile.Directory?.FullName ?? string.Empty; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.UseShellExecute = true; - - if (!process.Start()) - { - return Failure(settings, $"Failed to start process at '{process.StartInfo.FileName}'."); - } - - return Success(settings, new RunInstanceDesktop(process)); - } - } -} diff --git a/Unity.Build.Common/Steps/RunStepDesktop.cs.meta b/Unity.Build.Common/Steps/RunStepDesktop.cs.meta deleted file mode 100644 index 35d2eeb1..00000000 --- a/Unity.Build.Common/Steps/RunStepDesktop.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9636b0c1d50d99c4db3e02dfd2e372a3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Steps/RunStepNotImplemented.cs b/Unity.Build.Common/Steps/RunStepNotImplemented.cs deleted file mode 100644 index 1bec2717..00000000 --- a/Unity.Build.Common/Steps/RunStepNotImplemented.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Diagnostics; -using System.IO; - -namespace Unity.Build.Common -{ - /// - /// Dummy run step, which instructs BuildStepBuildClassicPlayer to use BuildOptions.AutoRunPlayer since there's no run step implementation - /// - sealed class RunStepNotImplemented : RunStep - { - public override bool CanRun(BuildSettings settings, out string reason) - { - reason = null; - return true; - } - - public override RunStepResult Start(BuildSettings settings) - { - return Success(settings, null); - } - } -} diff --git a/Unity.Build.Common/Steps/RunStepNotImplemented.cs.meta b/Unity.Build.Common/Steps/RunStepNotImplemented.cs.meta deleted file mode 100644 index 8e17a617..00000000 --- a/Unity.Build.Common/Steps/RunStepNotImplemented.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d06e2f0d22a83244c9677243b5601300 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/TemporaryFileTracker.cs b/Unity.Build.Common/TemporaryFileTracker.cs deleted file mode 100644 index bc9649f8..00000000 --- a/Unity.Build.Common/TemporaryFileTracker.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using UnityEditor; - -namespace Unity.Build.Common -{ - public class TemporaryFileTracker : IDisposable - { - readonly List m_CreatedDirectories = new List(); - readonly List m_TrackedFiles = new List(); - - public void CreateDirectory(string path) - { - var parent = path; - while (!Directory.Exists(parent)) - { - m_CreatedDirectories.Add(parent); - parent = Path.GetDirectoryName(parent); - } - - Directory.CreateDirectory(path); - } - - public string TrackFile(string path, bool ensureDoesntExist = true) - { - CreateDirectory(Path.GetDirectoryName(path)); - m_TrackedFiles.Add(path); - - if (ensureDoesntExist) - EnsureFileDoesntExist(path); - - return path; - } - - public void EnsureFileDoesntExist(string path) - { - if (!File.Exists(path)) - return; - - FileUtil.DeleteFileOrDirectory(path); - FileUtil.DeleteFileOrDirectory(path + ".meta"); - } - - public void Clear() - { - m_CreatedDirectories.Clear(); - m_TrackedFiles.Clear(); - } - - public void Dispose() - { - foreach (var file in m_TrackedFiles) - { - FileUtil.DeleteFileOrDirectory(file); - FileUtil.DeleteFileOrDirectory(file + ".meta"); - } - - foreach (var directory in m_CreatedDirectories) - { - FileUtil.DeleteFileOrDirectory(directory); - FileUtil.DeleteFileOrDirectory(directory + ".meta"); - } - - Clear(); - } - } -} \ No newline at end of file diff --git a/Unity.Build.Common/TemporaryFileTracker.cs.meta b/Unity.Build.Common/TemporaryFileTracker.cs.meta deleted file mode 100644 index 2f7b1cbe..00000000 --- a/Unity.Build.Common/TemporaryFileTracker.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6b1716c3bbe88b34d85b44aa17976c27 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Unity.Build.Common/Unity.Build.Common.asmdef b/Unity.Build.Common/Unity.Build.Common.asmdef deleted file mode 100644 index 3deabc3b..00000000 --- a/Unity.Build.Common/Unity.Build.Common.asmdef +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "Unity.Build.Common", - "references": [ - "Unity.Build", - "Unity.Build.Internals", - "Unity.Properties", - "Unity.Properties.Editor", - "Unity.Serialization" - ], - "optionalUnityReferences": [], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false -} \ No newline at end of file diff --git a/Unity.Entities.AutoCreation.Tests/AutoCreateComponentSystemTests.cs b/Unity.Entities.AutoCreation.Tests/AutoCreateComponentSystemTests.cs index e7c2327a..d0500320 100644 --- a/Unity.Entities.AutoCreation.Tests/AutoCreateComponentSystemTests.cs +++ b/Unity.Entities.AutoCreation.Tests/AutoCreateComponentSystemTests.cs @@ -5,13 +5,65 @@ using Unity.Collections; using Unity.Entities; using Unity.Jobs; +#if UNITY_DOTSPLAYER +using Unity.Tiny; +#endif namespace Unity.Entities.Tests { -#if !UNITY_EDITOR - // Editor manages its own SystemGroups, so this test case is meaningless there. + public class AutoCreateComponentSystemTestsFixture + { + protected World m_PreviousWorld; + protected World World; + protected EntityManager m_Manager; + protected EntityManager.EntityManagerDebug m_ManagerDebug; + + protected int StressTestEntityCount = 1000; - class Issue1792 : ECSTestsFixture + [SetUp] + public void Setup() + { + m_PreviousWorld = World.DefaultGameObjectInjectionWorld; + const string kTestWorldName = "Test World"; +#if UNITY_DOTSPLAYER + // Tiny always runs outside of process from the Editor, as such we need to + // invoke the tiny bootstrapping for worlds manually + World = DefaultWorldInitialization.Initialize(kTestWorldName); +#else + World = World.DefaultGameObjectInjectionWorld = new World(kTestWorldName); +#endif + + m_Manager = World.EntityManager; + m_ManagerDebug = new EntityManager.EntityManagerDebug(m_Manager); + } + + [TearDown] + public void TearDown() + { + if (m_Manager != null && m_Manager.IsCreated) + { + // Clean up systems before calling CheckInternalConsistency because we might have filters etc + // holding on SharedComponentData making checks fail + while (World.Systems.ToArray().Length > 0) + { + World.DestroySystem(World.Systems.ToArray()[0]); + } + + m_ManagerDebug.CheckInternalConsistency(); + + World.Dispose(); + World = null; + + World.DefaultGameObjectInjectionWorld = m_PreviousWorld; + m_PreviousWorld = null; + m_Manager = null; + } + } + } + + // Editor manages its own SystemGroups, so this test case is meaningless there. +#if !UNITY_EDITOR + class Issue1792 : AutoCreateComponentSystemTestsFixture { static bool aCreated = false; static bool bCreated = false; @@ -64,7 +116,7 @@ public void Test1792() } #endif - class AutoCreateComponentSystemTests : ECSTestsFixture + class AutoCreateComponentSystemTests : AutoCreateComponentSystemTestsFixture { internal class SystemA : ComponentSystem diff --git a/Unity.Entities.BuildUtils/TypeUtils.cs b/Unity.Entities.BuildUtils/TypeUtils.cs index 6d5db641..4cf8ea9f 100644 --- a/Unity.Entities.BuildUtils/TypeUtils.cs +++ b/Unity.Entities.BuildUtils/TypeUtils.cs @@ -299,26 +299,6 @@ public static void PreprocessTypeFields(TypeReference valuetype, int bits) ValueTypeIsComplex[bits].Add(valuetype, isComplex); } - public static void IterateFieldsRecurse(Action processFunc, TypeReference type) - { - var typeResolver = TypeResolver.For(type); - foreach (var f in type.Resolve().Fields) - { - var fieldReference = typeResolver.Resolve(f); - var fieldType = typeResolver.Resolve(f.FieldType); - - processFunc(fieldReference, fieldType); - - // Excluding statics for recursion covers: - // 1) enums which infinitely recurse because the values in the enum are of the same enum type - // 2) statics which infinitely recurse themselves (Such as vector3.zero.zero.zero.zero) - if (fieldType.IsValueType && !fieldType.IsPrimitive && !f.IsStatic) - { - IterateFieldsRecurse(processFunc, fieldType); - } - } - } - internal static void GetFieldOffsetsOfRecurse(Func match, int offset, TypeReference type, List list, int bits) { int in_type_offset = 0; diff --git a/Unity.Entities.CodeGen.Tests/BlobAssetSafetyVerifier/BlobAssetSafetyVerifierTests.cs b/Unity.Entities.CodeGen.Tests/BlobAssetSafetyVerifier/BlobAssetSafetyVerifierTests.cs index 1e06ff8a..92f7537b 100644 --- a/Unity.Entities.CodeGen.Tests/BlobAssetSafetyVerifier/BlobAssetSafetyVerifierTests.cs +++ b/Unity.Entities.CodeGen.Tests/BlobAssetSafetyVerifier/BlobAssetSafetyVerifierTests.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Mono.Cecil; using NUnit.Framework; using Unity.CompilationPipeline.Common.Diagnostics; +using Unity.Entities.CodeGen.Tests.TestTypes; namespace Unity.Entities.CodeGen.Tests { @@ -52,27 +54,109 @@ public void LoadFieldFromBlobAssetReference() " error MayOnlyLiveInBlobStorageViolation: You may only access .myfloats by ref, as it may only live in blob storage. try `ref BlobArray yourVariable = ref yourMyBlob.myfloats`"); } - void AssertProducesError(Type typeWithCodeUnderTest, string shouldContain) + class WithReferenceToValidType_Class { - var methodToAnalyze = MethodDefinitionForOnlyMethodOf(typeWithCodeUnderTest); - var errors = new List(); + BoidInAnotherAssembly someField; + void Method() + { + this.someField = new BoidInAnotherAssembly(); + EnsureNotOptimizedAway(this.someField); + } + } + + [Test] + public void FailResolveWithWarning() + { + AssertProducesWarning(typeof(WithReferenceToValidType_Class), + failResolve: true, + "ResolveFailureWarning: Unable to resolve type Unity.Entities.CodeGen.Tests.TestTypes.BoidInAnotherAssembly for verification"); + } + + class ClassWithValidBlobReferenceUsage + { + public class GenericTypeWithVolatile + { + public volatile T[] buffer; + public T this[int i] { get { return buffer[i]; } set { buffer[i] = value; } } + } + GenericTypeWithVolatile _intGeneric; + BoidInAnotherAssembly _someField; + BlobAssetReference _blobAssetReference; + + void Method() + { + _intGeneric = new GenericTypeWithVolatile(); + _intGeneric.buffer = new[] {32, 12, 41}; + EnsureNotOptimizedAway(_intGeneric.buffer); + + _someField = new BoidInAnotherAssembly(); + EnsureNotOptimizedAway(_someField); + + ref BlobArray myFloats = ref _blobAssetReference.Value.myfloats; + EnsureNotOptimizedAway(myFloats.Length); + + ref MyBlob blob = ref _blobAssetReference.Value; + EnsureNotOptimizedAway(blob.myfloats.Length); + } + } + + [Test] + public void ValidBlobReferenceUsageSucceeds() + { + AssertProducesNoError(typeof(ClassWithValidBlobReferenceUsage)); + } + + private void AssertProducesNoError(Type typeWithCodeUnderTest) + { + Assert.DoesNotThrow(() => + { + var methodToAnalyze = MethodDefinitionForOnlyMethodOf(typeWithCodeUnderTest); + var diagnosticMessages = new List(); + + try + { + var verifyDiagnosticMessages = BlobAssetSafetyVerifier.VerifyMethod(methodToAnalyze, new HashSet()); + diagnosticMessages.AddRange(verifyDiagnosticMessages); + } + catch (FoundErrorInUserCodeException exc) + { + diagnosticMessages.AddRange(exc.DiagnosticMessages); + } + + Assert.AreEqual(0, diagnosticMessages.Count); + }); + } + + protected override void AssertProducesInternal( + Type typeWithCodeUnderTest, + DiagnosticType diagnosticType, + string[] shouldContains, + bool failResolve = false) + { + var methodToAnalyze = MethodDefinitionForOnlyMethodOf(typeWithCodeUnderTest, failResolve); + var diagnosticMessages = new List(); try { - BlobAssetSafetyVerifier.VerifyMethod(methodToAnalyze, new HashSet()); + var verifyDiagnosticMessages = BlobAssetSafetyVerifier.VerifyMethod(methodToAnalyze, new HashSet()); + diagnosticMessages.AddRange(verifyDiagnosticMessages); } catch (FoundErrorInUserCodeException exc) { - errors.AddRange(exc.DiagnosticMessages); + diagnosticMessages.AddRange(exc.DiagnosticMessages); } - Assert.AreEqual(1, errors.Count); - Assert.AreEqual(DiagnosticType.Error, errors[0].DiagnosticType); + Assert.AreEqual(1, diagnosticMessages.Count); + Assert.AreEqual(diagnosticType, diagnosticMessages.Single().DiagnosticType); - foreach(var error in errors) - StringAssert.Contains(shouldContain, error.MessageData); + StringAssert.Contains(shouldContains.Single(), diagnosticMessages.Single().MessageData); - AssertDiagnosticHasSufficientFileAndLineInfo(errors); + AssertDiagnosticHasSufficientFileAndLineInfo(diagnosticMessages); + } + + private void AssertProducesWarning(Type systemType, bool failResolve, params string[] shouldContainErrors) + { + AssertProducesInternal(systemType, DiagnosticType.Warning, shouldContainErrors, failResolve); } } } \ No newline at end of file diff --git a/Unity.Entities.CodeGen.Tests/Decompiler.cs b/Unity.Entities.CodeGen.Tests/Decompiler.cs deleted file mode 100644 index 24bb43d3..00000000 --- a/Unity.Entities.CodeGen.Tests/Decompiler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using Mono.Cecil; -using Mono.Cecil.Cil; -using UnityEditor; -using UnityEngine; - -namespace Unity.Entities.CodeGen.Tests -{ - internal static class Decompiler - { - public static string DecompileIntoString(TypeReference typeReference) - { - var assemblyDefinition = typeReference.Module.Assembly; - - var tempFolder = Path.GetTempPath(); - var fileName = $@"{tempFolder}TestAssembly.dll"; - var fileNamePdb = $@"{tempFolder}TestAssembly.pdb"; - var peStream = new FileStream(fileName, FileMode.Create); - var symbolStream = new FileStream(fileNamePdb, FileMode.Create); - - assemblyDefinition.Write(peStream,new WriterParameters() {SymbolStream = symbolStream, SymbolWriterProvider = new PortablePdbWriterProvider(), WriteSymbols = true}); - peStream.Close(); - symbolStream.Close(); - - var sb = new StringBuilder(); - - var processed = new HashSet(); - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a=>!a.IsDynamic && !string.IsNullOrEmpty(a.Location))) - { - string path; - try - { - path = Path.GetDirectoryName(assembly.Location); - } - catch (ArgumentException) - { - UnityEngine.Debug.Log("Unexpected path: " + assembly.Location); - continue; - } - - if (processed.Contains(path)) - continue; - processed.Contains(path); - sb.Append($"--referencepath \"{path}\" "); - } - - - var isWin = Environment.OSVersion.Platform == PlatformID.Win32Windows || Environment.OSVersion.Platform == PlatformID.Win32NT; - var ilspycmd = Path.GetFullPath("Packages/com.unity.entities/Unity.Entities.CodeGen.Tests/.tools/ilspycmd.exe"); - if (isWin) - ilspycmd = ilspycmd.Replace("/","\\"); - var psi = new ProcessStartInfo() - { - UseShellExecute = false, - CreateNoWindow = true, - - FileName = isWin ? ilspycmd : $"{EditorApplication.applicationPath}/Contents/MonoBleedingEdge/bin/mono", - Arguments = $"{(isWin ? "" : ilspycmd)} \"{fileName}\" -t {typeReference.FullName.Replace("/","+")} {sb}", - RedirectStandardOutput = true - }; - - var p = new Process() {StartInfo = psi}; - p.Start(); - return p.StandardOutput.ReadToEnd(); - } - } -} \ No newline at end of file diff --git a/Unity.Entities.CodeGen.Tests/IntegrationTest.cs b/Unity.Entities.CodeGen.Tests/IntegrationTest.cs index df222b63..9868cae4 100644 --- a/Unity.Entities.CodeGen.Tests/IntegrationTest.cs +++ b/Unity.Entities.CodeGen.Tests/IntegrationTest.cs @@ -6,6 +6,8 @@ using System.Text.RegularExpressions; using Mono.Cecil; using NUnit.Framework; +using Unity.Entities.Editor; +using Unity.Entities.Hybrid; namespace Unity.Entities.CodeGen.Tests { @@ -14,19 +16,14 @@ public abstract class IntegrationTest : LambdaJobsPostProcessorTestBase { // Make sure to not check this in with true or your tests will always pass! public static bool overwriteExpectationWithReality = false; - + protected abstract string ExpectedPath { get; } - protected virtual string AdditionalIL { get { return string.Empty; } } + protected virtual string AdditionalIL => string.Empty; static bool IsAssemblyBuiltAsDebug() { var debuggableAttributes = typeof(IntegrationTest).Assembly.GetCustomAttributes(typeof(DebuggableAttribute), false); - foreach (var debuggableAttribute in debuggableAttributes) - { - if (((System.Diagnostics.DebuggableAttribute) debuggableAttribute).IsJITTrackingEnabled) - return true; - } - return false; + return debuggableAttributes.Any(debuggableAttribute => ((DebuggableAttribute) debuggableAttribute).IsJITTrackingEnabled); } protected void RunTest(TypeReference type) @@ -37,8 +34,7 @@ protected void RunTest(TypeReference type) UnityEngine.Debug.LogWarning("Integration tests should only be run with release code optimizations turned on for consistent codegen. Switch your settings in Preferences->External Tools->Editor Attaching (in 2019.3) or Preferences->General->Code Optimization On Startup (in 2020.1+) to be able to run these tests."); var expectationFile = Path.GetFullPath($"{ExpectedPath}/{GetType().Name}.expectation.txt"); - - var jobCSharp = Decompiler.DecompileIntoString(type); + var jobCSharp = Decompiler.DecompileIntoCSharpAndIL(type, DecompiledLanguage.CSharpOnly).CSharpCode; var actualLines = jobCSharp.Split('\n').Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); var shouldOverWrite = overwriteExpectationWithReality || !File.Exists(expectationFile); diff --git a/Unity.Entities.CodeGen.Tests/LambdaJobDescriptionConstructionTests.cs b/Unity.Entities.CodeGen.Tests/LambdaJobDescriptionConstructionTests.cs index 11f78004..f6977457 100644 --- a/Unity.Entities.CodeGen.Tests/LambdaJobDescriptionConstructionTests.cs +++ b/Unity.Entities.CodeGen.Tests/LambdaJobDescriptionConstructionTests.cs @@ -84,7 +84,7 @@ public void SingleJobTest() { nameof(LambdaJobDescriptionConstructionMethods.WithBurst), nameof(LambdaJobDescriptionConstructionMethods.WithName), - nameof(LambdaSimpleJobDescriptionConstructionMethods.WithCode), + nameof(LambdaSingleJobDescriptionConstructionMethods.WithCode), }, icm.Select(i => i.MethodName)); CollectionAssert.AreEqual(new[] @@ -218,8 +218,60 @@ protected override JobHandle OnUpdate(JobHandle inputDeps) .Schedule(inputDeps); } } + + [Test] + public void InvalidJobNamesThrow() + { + AssertProducesError(typeof(InvalidJobNameWithSpaces), nameof(UserError.DC0039), "WithName"); + AssertProducesError(typeof(InvalidJobNameStartsWithDigit), nameof(UserError.DC0039), "WithName"); + AssertProducesError(typeof(InvalidJobNameCompilerReservedName), nameof(UserError.DC0039), "WithName"); + } + + public class InvalidJobNameWithSpaces : JobComponentSystem + { + protected override JobHandle OnUpdate(JobHandle inputDeps) + { + return Entities + .WithName("This name may not contain spaces") + .ForEach( + (ref Translation translation, ref Boid boid, in Velocity velocity) => + { + translation.Value += velocity.Value; + }) + .Schedule(inputDeps); + } + } + public class InvalidJobNameStartsWithDigit : JobComponentSystem + { + protected override JobHandle OnUpdate(JobHandle inputDeps) + { + return Entities + .WithName("1job") + .ForEach( + (ref Translation translation, ref Boid boid, in Velocity velocity) => + { + translation.Value += velocity.Value; + }) + .Schedule(inputDeps); + } + } + public class InvalidJobNameCompilerReservedName : JobComponentSystem + { + protected override JobHandle OnUpdate(JobHandle inputDeps) + { + return Entities + .WithName("__job") + .ForEach( + (ref Translation translation, ref Boid boid, in Velocity velocity) => + { + translation.Value += velocity.Value; + }) + .Schedule(inputDeps); + } + } + [Test] public void ForgotToAddForEachTest() { diff --git a/Unity.Entities.CodeGen.Tests/LambdaJobs/Infrastructure/LambdaJobIntegrationTest.cs b/Unity.Entities.CodeGen.Tests/LambdaJobs/Infrastructure/LambdaJobIntegrationTest.cs index f3a8d51d..60e54128 100644 --- a/Unity.Entities.CodeGen.Tests/LambdaJobs/Infrastructure/LambdaJobIntegrationTest.cs +++ b/Unity.Entities.CodeGen.Tests/LambdaJobs/Infrastructure/LambdaJobIntegrationTest.cs @@ -2,8 +2,10 @@ using System.IO; using System.Linq; using System.Text; +using System.Collections.Generic; using Mono.Cecil; using NUnit.Framework; +using Unity.CompilationPipeline.Common.Diagnostics; namespace Unity.Entities.CodeGen.Tests.LambdaJobs.Infrastructure { @@ -26,8 +28,11 @@ protected void RunTest(Type type) var methodToAnalyze = MethodDefinitionForOnlyMethodOf(type); var forEachDescriptionConstructions = LambdaJobDescriptionConstruction.FindIn(methodToAnalyze); JobStructForLambdaJob jobStructForLambdaJob = null; - foreach(var forEachDescriptionConstruction in forEachDescriptionConstructions) - jobStructForLambdaJob = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction, null); + foreach (var forEachDescriptionConstruction in forEachDescriptionConstructions) + { + List diagnosticMessages; + (jobStructForLambdaJob, diagnosticMessages) = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction); + } _methodIL = new StringBuilder(); if (methodToAnalyze != null) diff --git a/Unity.Entities.CodeGen.Tests/LambdaJobsLambdaJobsPostProcessorTests.cs b/Unity.Entities.CodeGen.Tests/LambdaJobsLambdaJobsPostProcessorTests.cs index c8c6be50..78544746 100644 --- a/Unity.Entities.CodeGen.Tests/LambdaJobsLambdaJobsPostProcessorTests.cs +++ b/Unity.Entities.CodeGen.Tests/LambdaJobsLambdaJobsPostProcessorTests.cs @@ -127,14 +127,91 @@ void Test() .Schedule(default); } } + + [Test] + public void WithNoneWithInvalidGenericParameterTest() + { + AssertProducesError(typeof(WithNoneWithInvalidGenericParameter), nameof(UserError.DC0025), "TValue"); + } + class WithNoneWithInvalidGenericParameter : TestJobComponentSystem + { + void Test() where TValue : struct + { + Entities + .WithNone() + .ForEach((in Boid translation) => { }) + .Schedule(default); + } + } + + [Test] + public void WithNoneWithInvalidGenericTypeTest() + { + AssertProducesError(typeof(WithNoneWithInvalidGenericType), nameof(UserError.DC0025), "GenericType`1"); + } + class WithNoneWithInvalidGenericType : TestJobComponentSystem + { + struct GenericType : IComponentData {} + void Test() + { + Entities + .WithNone>() + .ForEach((in Boid translation) => { }) + .Schedule(default); + } + } + + [Test] + public void ParameterWithInvalidGenericParameterTest() + { + AssertProducesError(typeof(ParameterWithInvalidGenericParameter), nameof(UserError.DC0025), "TValue"); + } + class ParameterWithInvalidGenericParameter : TestJobComponentSystem + { + void Test() where TValue : struct + { + Entities + .ForEach((in TValue generic) => { }) + .Schedule(default); + } + } + + [Test] + public void ParameterWithInvalidGenericTypeTest() + { + AssertProducesError(typeof(ParameterWithInvalidGenericType), nameof(UserError.DC0025), "GenericType`1"); + } + class ParameterWithInvalidGenericType : TestJobComponentSystem + { + struct GenericType : IComponentData {} + void Test() + { + Entities + .ForEach((in GenericType generic) => { }) + .Schedule(default); + } + } + [Test] + public void InGenericSystemTypeTest() + { + AssertProducesError(typeof(InGenericSystemType<>), nameof(UserError.DC0025), "InGenericSystemType`1"); + } + public class InGenericSystemType : SystemBase + where T : struct, IComponentData + { + protected override void OnUpdate() + { + Entities.WithNone().ForEach((Entity e, ref T n) => { }).Run(); + } + } + [Test] public void WithReadOnly_IllegalArgument_Test() { AssertProducesError(typeof(WithReadOnly_IllegalArgument), nameof(UserError.DC0012)); } - class WithReadOnly_IllegalArgument : TestJobComponentSystem { void Test() @@ -264,6 +341,76 @@ void Test() } } + [Test] + public void InvokeExtensionMethodOnRefTypeInBurstLambdaTest() + { + AssertProducesError(typeof(InvokeExtensionMethodOnRefTypeInBurstLambda), nameof(UserError.DC0002), nameof(TestJobComponentSystemExtensionMethods.MyTestExtension)); + } + + class InvokeExtensionMethodOnRefTypeInBurstLambda : TestJobComponentSystem + { + void Test() + { + Entities.ForEach((ref Translation t) => { this.MyTestExtension(); }).Run(); + } + } + + [Test] + public void InvokeInterfaceExtensionMethodOnRefTypeInBurstLambdaTest() + { + AssertProducesError(typeof(InvokeInterfaceExtensionMethodOnRefTypeInBurstLambda), nameof(UserError.DC0002), nameof(TestJobComponentSystemExtensionMethods.MyTestExtensionInterface)); + } + + class InvokeInterfaceExtensionMethodOnRefTypeInBurstLambda : TestJobComponentSystem, TestJobComponentSystemExtensionMethods.ITestInterface + { + void Test() + { + Entities.ForEach((ref Translation t) => { this.MyTestExtensionInterface(); }).Run(); + } + } + + [Test] + public void InvokeStaticFunctionOnRefTypeInBurstLambdaTest() + { + AssertProducesError(typeof(InvokeStaticFunctionOnRefTypeInBurstLambda), nameof(UserError.DC0002), nameof(InvokeStaticFunctionOnRefTypeInBurstLambda.ActualProblem)); + } + + class InvokeStaticFunctionOnRefTypeInBurstLambda : TestJobComponentSystem + { + void Test() + { + Entities.ForEach((ref Translation t) => + { + NotAProblem(); + ActualProblem(this); + }).Run(); + } + + static void NotAProblem() { } + internal static void ActualProblem(JobComponentSystem s) { } + } + + [Test] + public void InvokeStaticFunctionOnValueTypeInBurstLambdaTest() + { + AssertProducesError(typeof(InvokeStaticFunctionOnValueTypeInBurstLambda), nameof(UserError.DC0002), nameof(InvokeStaticFunctionOnValueTypeInBurstLambda.ActualProblem)); + } + + class InvokeStaticFunctionOnValueTypeInBurstLambda : TestJobComponentSystem + { + void Test() + { + Entities.ForEach((ref Translation t) => + { + NotAProblem(t.Value); + ActualProblem(); + }).Run(); + } + + static void NotAProblem(float x) { } + internal void ActualProblem() {} + } + [Test] public void UseSharedComponentData_UsingSchedule_ProducesError() { @@ -308,7 +455,7 @@ void Test() [Test] public void CustomStructArgumentThatDoesntImplementSupportedInterfaceTest() { - AssertProducesError(typeof(CustomStructArgumentThatDoesntImplementSupportedInterface), nameof(UserError.DC0021), "parameter t has type ForgotToAddInterface. This type is not a"); + AssertProducesError(typeof(CustomStructArgumentThatDoesntImplementSupportedInterface), nameof(UserError.DC0021), "parameter 't' has type ForgotToAddInterface. This type is not a"); } class CustomStructArgumentThatDoesntImplementSupportedInterface : TestJobComponentSystem @@ -368,7 +515,25 @@ void Test() } } - + [Test] + public void CaptureFieldByRefTest() + { + AssertProducesError(typeof(CaptureFieldByRef), nameof(UserError.DC0001), "m_MyField"); + } + + class CaptureFieldByRef : TestJobComponentSystem + { + int m_MyField = 123; + + void Test() + { + Entities + .ForEach((ref Translation t) => { NotAProblem(ref m_MyField); }) + .Schedule(default); + } + + static void NotAProblem(ref int a) { } + } [Test] public void InvokeInstanceMethodInCapturingLambdaTest() @@ -775,7 +940,9 @@ public void ParameterNamesHaveStablePath() // The important part here is everything following {jobName}.Data. var methodToAnalyze = MethodDefinitionForOnlyMethodOf(typeof(ParameterNamesPath)); var forEachDescriptionConstructions = LambdaJobDescriptionConstruction.FindIn(methodToAnalyze); - JobStructForLambdaJob jobStructForLambdaJob = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstructions.First(), null); + var (jobStructForLambdaJob, diagnosticMessages) = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstructions.First()); + + Assert.IsEmpty(diagnosticMessages); const string valueProviderFieldName = "_lambdaParameterValueProviders"; var valueProvidersField = jobStructForLambdaJob.TypeDefinition.Fields.FirstOrDefault(f => f.Name == valueProviderFieldName); @@ -949,4 +1116,12 @@ struct UserStruct } } } + + public static class TestJobComponentSystemExtensionMethods + { + public interface ITestInterface { } + + public static void MyTestExtension(this TestJobComponentSystem test) { } + public static void MyTestExtensionInterface(this ITestInterface test) { } + } } diff --git a/Unity.Entities.CodeGen.Tests/LambdaJobsPostProcessorTestBase.cs b/Unity.Entities.CodeGen.Tests/LambdaJobsPostProcessorTestBase.cs index e5d77b03..c1b71ec8 100644 --- a/Unity.Entities.CodeGen.Tests/LambdaJobsPostProcessorTestBase.cs +++ b/Unity.Entities.CodeGen.Tests/LambdaJobsPostProcessorTestBase.cs @@ -14,13 +14,24 @@ namespace Unity.Entities.CodeGen.Tests { - public class PostProcessorTestBase + public abstract class PostProcessorTestBase { - protected AssemblyDefinition AssemblyDefinitionFor(Type type) + class FailResolver : IAssemblyResolver + { + public void Dispose() { } + public AssemblyDefinition Resolve(AssemblyNameReference name) { return null; } + public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) { return null; } + } + + protected AssemblyDefinition AssemblyDefinitionFor(Type type, bool useFailResolver = false) { var assemblyLocation = type.Assembly.Location; - var resolver = new LambdaJobsPostProcessorTestBase.OnDemandResolver(); + IAssemblyResolver resolver; + if (useFailResolver) + resolver = new FailResolver(); + else + resolver = new LambdaJobsPostProcessorTestBase.OnDemandResolver(); var ad = AssemblyDefinition.ReadAssembly(new MemoryStream(File.ReadAllBytes(assemblyLocation)), new ReaderParameters(ReadingMode.Immediate) @@ -38,24 +49,24 @@ protected AssemblyDefinition AssemblyDefinitionFor(Type type) return ad; } - protected TypeDefinition TypeDefinitionFor(Type type) + protected TypeDefinition TypeDefinitionFor(Type type, bool useFailResolver = false) { - var ad = AssemblyDefinitionFor(type); + var ad = AssemblyDefinitionFor(type, useFailResolver); var fullName = type.FullName.Replace("+", "/"); return ad.MainModule.GetType(fullName).Resolve(); } - protected TypeDefinition TypeDefinitionFor(string typeName, Type nextToType) + protected TypeDefinition TypeDefinitionFor(string typeName, Type nextToType, bool useFailResolver = false) { - var ad = AssemblyDefinitionFor(nextToType); + var ad = AssemblyDefinitionFor(nextToType, useFailResolver); var fullName = nextToType.FullName.Replace("+", "/"); fullName = fullName.Replace(nextToType.Name, typeName); return ad.MainModule.GetType(fullName).Resolve(); } - protected MethodDefinition MethodDefinitionForOnlyMethodOf(Type type) + protected MethodDefinition MethodDefinitionForOnlyMethodOf(Type type, bool useFailResolver = false) { - return MethodDefinitionForOnlyMethodOfDefinition(TypeDefinitionFor(type)); + return MethodDefinitionForOnlyMethodOfDefinition(TypeDefinitionFor(type, useFailResolver)); } protected MethodDefinition MethodDefinitionForOnlyMethodOfDefinition(TypeDefinition typeDefinition) @@ -97,6 +108,18 @@ public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters p } } + protected abstract void AssertProducesInternal(Type systemType, DiagnosticType type, string[] shouldContains, bool useFailResolver = false); + + protected void AssertProducesWarning(Type systemType, params string[] shouldContainErrors) + { + AssertProducesInternal(systemType, DiagnosticType.Warning, shouldContainErrors); + } + + protected void AssertProducesError(Type systemType, params string[] shouldContainErrors) + { + AssertProducesInternal(systemType, DiagnosticType.Error, shouldContainErrors); + } + protected static void AssertDiagnosticHasSufficientFileAndLineInfo(List errors) { string diagnostic = errors.Select(dm=>dm.MessageData).SeparateByComma(); @@ -108,7 +131,7 @@ protected static void AssertDiagnosticHasSufficientFileAndLineInfo(List 1000) + if (line > 2000) Assert.Fail("Unreasonable line number in errormessage: " + diagnostic); } } @@ -129,7 +152,9 @@ protected void AssertProducesNoError(Type systemType) { foreach (var forEachDescriptionConstruction in LambdaJobDescriptionConstruction.FindIn(methodToAnalyze)) { - LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction, null); + var (jobStructForLambdaJob, diagnosticMessages) = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction); + foreach (var diagnosticMessage in diagnosticMessages) + Assert.AreNotEqual(DiagnosticType.Error, diagnosticMessage.DiagnosticType); } } @@ -145,37 +170,35 @@ protected void AssertProducesNoError(Type systemType) }); } - void AssertProducesInternal(Type systemType, DiagnosticType type, string[] shouldContains) + protected override void AssertProducesInternal( + Type systemType, + DiagnosticType type, + string[] shouldContains, + bool useFailResolver = false) { var methodToAnalyze = MethodDefinitionForOnlyMethodOf(systemType); - var errors = new List(); + var diagnosticMessages = new List(); try { foreach (var forEachDescriptionConstruction in LambdaJobDescriptionConstruction.FindIn(methodToAnalyze)) { - LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction, errors); + var (_, rewriteMessages) = LambdaJobsPostProcessor.Rewrite(methodToAnalyze, forEachDescriptionConstruction); + diagnosticMessages.AddRange(rewriteMessages); } } catch (FoundErrorInUserCodeException exc) { - errors.AddRange(exc.DiagnosticMessages); + diagnosticMessages.AddRange(exc.DiagnosticMessages); } - Assert.AreEqual(type, errors[0].DiagnosticType); - - - AssertDiagnosticHasSufficientFileAndLineInfo(errors); - } + Assert.AreEqual(1, diagnosticMessages.Count); + Assert.AreEqual(type, diagnosticMessages[0].DiagnosticType); - protected void AssertProducesWarning(Type systemType, params string[] shouldContainErrors) - { - AssertProducesInternal(systemType, DiagnosticType.Warning, shouldContainErrors); - } + foreach (var str in shouldContains) + Assert.That(diagnosticMessages[0].MessageData.Contains(str), $"Error message \"{diagnosticMessages[0].MessageData}\" does not contain \"{str}\"."); - protected void AssertProducesError(Type systemType, params string[] shouldContainErrors) - { - AssertProducesInternal(systemType, DiagnosticType.Error, shouldContainErrors); + AssertDiagnosticHasSufficientFileAndLineInfo(diagnosticMessages); } } } \ No newline at end of file diff --git a/Unity.Entities.CodeGen.Tests/Unity.Entities.CodeGen.Tests.asmdef b/Unity.Entities.CodeGen.Tests/Unity.Entities.CodeGen.Tests.asmdef index d8d59921..93e5a51f 100644 --- a/Unity.Entities.CodeGen.Tests/Unity.Entities.CodeGen.Tests.asmdef +++ b/Unity.Entities.CodeGen.Tests/Unity.Entities.CodeGen.Tests.asmdef @@ -6,10 +6,11 @@ "Unity.Entities.CodeGen", "Unity.Entities.CodeGen.Tests.TestTypes", "Unity.Burst", - "Unity.Properties" - ], - "optionalUnityReferences": [ - "TestAssemblies" + "Unity.Properties", + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "Unity.Entities.Hybrid", + "Unity.Entities.Editor" ], "includePlatforms": [ "Editor" @@ -21,8 +22,13 @@ "Mono.Cecil.dll", "Mono.Cecil.Rocks.dll", "Mono.Cecil.Pdb.dll", + "nunit.framework.dll", "nunit.framework.dll" ], "autoReferenced": false, - "versionDefines": [] + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false } \ No newline at end of file diff --git a/Unity.Entities.CodeGen/AssemblyInfo.cs b/Unity.Entities.CodeGen/AssemblyInfo.cs new file mode 100644 index 00000000..0e1eb866 --- /dev/null +++ b/Unity.Entities.CodeGen/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(assemblyName: "Unity.Entities.Hybrid.CodeGen.Tests")] diff --git a/Unity.Build.Common/Settings/ClassicScriptingSettings.cs.meta b/Unity.Entities.CodeGen/AssemblyInfo.cs.meta similarity index 83% rename from Unity.Build.Common/Settings/ClassicScriptingSettings.cs.meta rename to Unity.Entities.CodeGen/AssemblyInfo.cs.meta index 0ae7b5fb..328f4166 100644 --- a/Unity.Build.Common/Settings/ClassicScriptingSettings.cs.meta +++ b/Unity.Entities.CodeGen/AssemblyInfo.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: af1667adf172f5d44b34cc03f3d19b10 +guid: a5a75e524efe2c64587928a3cc01ff05 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Unity.Entities.CodeGen/BlobAssetSafety/BlobAssetSafetyVerifier.cs b/Unity.Entities.CodeGen/BlobAssetSafety/BlobAssetSafetyVerifier.cs index f8cd625b..a21d8bd9 100644 --- a/Unity.Entities.CodeGen/BlobAssetSafety/BlobAssetSafetyVerifier.cs +++ b/Unity.Entities.CodeGen/BlobAssetSafety/BlobAssetSafetyVerifier.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; using System.Text; using JetBrains.Annotations; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; +using Unity.CompilationPipeline.Common.Diagnostics; namespace Unity.Entities.CodeGen { @@ -24,7 +26,7 @@ protected override bool PostProcessImpl() void AssertNoBlobAssetLeavesBlobAssetStorage() { HashSet _nonRestrictedTypes = new HashSet(); - + foreach (var type in AssemblyDefinition.MainModule.GetAllTypes()) { if (!type.HasMethods) @@ -33,14 +35,17 @@ void AssertNoBlobAssetLeavesBlobAssetStorage() { if (!method.HasBody) continue; - - VerifyMethod(method, _nonRestrictedTypes); + + var verifyDiagnosticMessages = VerifyMethod(method, _nonRestrictedTypes); + _diagnosticMessages.AddRange(verifyDiagnosticMessages); } } } - public static void VerifyMethod(MethodDefinition method, HashSet _nonRestrictedTypes) + public static List VerifyMethod(MethodDefinition method, HashSet _nonRestrictedTypes) { + var diagnosticMessages = new List(); + bool IsTypeRestrictedToBlobAssetStorage(TypeReference tr) { if (tr.IsPrimitive) @@ -51,8 +56,11 @@ bool IsTypeRestrictedToBlobAssetStorage(TypeReference tr) return false; if (tr is ArrayType) return false; - if (tr is GenericInstanceType) + if (tr is RequiredModifierType || tr is GenericInstanceType) + { tr = tr.GetElementType(); + return IsTypeRestrictedToBlobAssetStorage(tr); + } if (_nonRestrictedTypes.Contains(tr)) return false; @@ -61,7 +69,18 @@ bool IsTypeRestrictedToBlobAssetStorage(TypeReference tr) anr.Name == "System.Private.CoreLib") return false; - var td = tr.CheckedResolve(); + // Don't do a CheckedResolve here. If we somehow fail we don't want to block the user. + var td = tr.Resolve(); + if (td == null) + { + diagnosticMessages.Add( + UserError.MakeWarning("ResolveFailureWarning", + $"Unable to resolve type {tr.FullName} for verification.", + method, method.Body.Instructions.FirstOrDefault())); + _nonRestrictedTypes.Add(tr); + + return false; + } if (td.IsValueType()) { @@ -94,9 +113,10 @@ bool IsTypeRestrictedToBlobAssetStorage(TypeReference tr) string error = $"ref {fancyName} yourVariable = ref your{fieldReference.DeclaringType.Name}.{fieldReference.Name}"; - UserError.MakeError("MayOnlyLiveInBlobStorageViolation", - $"You may only access .{fieldReference.Name} by ref, as it may only live in blob storage. try `{error}`", - method, instruction).Throw(); + diagnosticMessages.Add( + UserError.MakeError("MayOnlyLiveInBlobStorageViolation", + $"You may only access .{fieldReference.Name} by ref, as it may only live in blob storage. try `{error}`", + method, instruction)); } } @@ -114,12 +134,15 @@ bool IsTypeRestrictedToBlobAssetStorage(TypeReference tr) error = $"ref {tr.Name} yourVariable = ref your{typeName}.{fr.Name}"; } - UserError.MakeError("MayOnlyLiveInBlobStorageViolation", - $"{tr.Name} may only live in blob storage. Access it by ref instead: `{error}`", method, - instruction).Throw(); + diagnosticMessages.Add( + UserError.MakeError("MayOnlyLiveInBlobStorageViolation", + $"{tr.Name} may only live in blob storage. Access it by ref instead: `{error}`", method, + instruction)); } } } + + return diagnosticMessages; } private static string FancyNameFor(TypeReference typeReference) diff --git a/Unity.Entities.CodeGen/CecilExtensionMethods.cs b/Unity.Entities.CodeGen/CecilExtensionMethods.cs index 67a0da83..b3b11667 100644 --- a/Unity.Entities.CodeGen/CecilExtensionMethods.cs +++ b/Unity.Entities.CodeGen/CecilExtensionMethods.cs @@ -64,6 +64,13 @@ public static bool TypeImplements(this TypeReference typeReference, Type interfa i.InterfaceType.FullName == typeReference.Module.ImportReference(interfaceType).FullName); } + public static bool TypeImplements(this TypeReference typeReference, TypeReference interfaceType) + { + var resolvedType = typeReference.Resolve(); + if (resolvedType == null) return false; + return resolvedType.Interfaces.Any(i => i.InterfaceType == interfaceType); + } + public static TypeReference StripRef(this TypeReference tr) => tr is ByReferenceType brt ? brt.ElementType : tr; public static bool IsVoid(this TypeReference type) diff --git a/Unity.Entities.CodeGen/CecilHelpers.cs b/Unity.Entities.CodeGen/CecilHelpers.cs index a4365976..6cd086a3 100644 --- a/Unity.Entities.CodeGen/CecilHelpers.cs +++ b/Unity.Entities.CodeGen/CecilHelpers.cs @@ -250,6 +250,14 @@ public static (MethodDefinition[], Dictionary AllTypeArgumentsOfMethod(string methodName) foreach (var m in invokedConstructionMethods) { - foreach (var t in m.TypeArguments.Select(t=>t.Resolve())) + foreach (var argumentType in m.TypeArguments) { - if (!LambdaParamaterValueProviderInformation.IsTypeValidForEntityQuery(t)) - UserError.DC0025($"Type {t.Name} cannot be used with {m.MethodName} as it is not a supported component type", descriptionConstruction.ContainingMethod, m.InstructionInvokingMethod).Throw(); + if (argumentType.IsGenericParameter || argumentType.IsGenericInstance) + UserError.DC0025($"Type {argumentType.Name} cannot be used with {m.MethodName} as generic types and parameters are not allowed", descriptionConstruction.ContainingMethod, m.InstructionInvokingMethod).Throw(); + var argumentTypeDefinition = argumentType.Resolve(); + if (!LambdaParamaterValueProviderInformation.IsTypeValidForEntityQuery(argumentTypeDefinition)) + UserError.DC0025($"Type {argumentType.Name} cannot be used with {m.MethodName} as it is not a supported component type", descriptionConstruction.ContainingMethod, m.InstructionInvokingMethod).Throw(); - result.Add(moduleDefinition.ImportReference(t)); + result.Add(moduleDefinition.ImportReference(argumentType)); } } return result; } - + var withNoneTypes = AllTypeArgumentsOfMethod(nameof(LambdaJobQueryConstructionMethods.WithNone)); var withAllTypes = AllTypeArgumentsOfMethod(nameof(LambdaJobQueryConstructionMethods.WithAll)); var withSharedComponentFilterTypes = AllTypeArgumentsOfMethod(nameof(LambdaJobQueryConstructionMethods.WithSharedComponentFilter)); @@ -174,6 +177,17 @@ List AllTypeArgumentsOfMethod(string methodName) var localVarOfEQD = new VariableDefinition(moduleDefinition.ImportReference(typeof(EntityQueryDesc))); var localVarOfResult = new VariableDefinition(moduleDefinition.ImportReference(typeof(EntityQuery))); + foreach (var closureParameter in closureParameters) + { + var parameterElementType = closureParameter.ParameterType.GetElementType(); + if (parameterElementType.IsGenericInstance || parameterElementType.IsGenericParameter || + (parameterElementType.HasGenericParameters && !parameterElementType.IsDynamicBufferOfT())) + { + UserError.DC0025($"Type {closureParameter.ParameterType.Name} cannot be used as an Entities.ForEach parameter as generic types and generic parameters are not supported in Entities.ForEach", + descriptionConstruction.ContainingMethod, descriptionConstruction.InvokedConstructionMethods.First().InstructionInvokingMethod).Throw(); + } + } + body.Variables.Add(arrayOfSingleEQDVariable); body.Variables.Add(localVarOfEQD); body.Variables.Add(localVarOfResult); diff --git a/Unity.Entities.CodeGen/LambdaJobs/LambdaJobDescriptionConstruction.cs b/Unity.Entities.CodeGen/LambdaJobs/LambdaJobDescriptionConstruction.cs index e84a19bf..6822a114 100644 --- a/Unity.Entities.CodeGen/LambdaJobs/LambdaJobDescriptionConstruction.cs +++ b/Unity.Entities.CodeGen/LambdaJobs/LambdaJobDescriptionConstruction.cs @@ -20,6 +20,7 @@ enum LambdaJobDescriptionKind internal enum ExecutionMode { Schedule, + ScheduleParallel, Run } @@ -79,10 +80,38 @@ public bool UsesBurst } } - public ExecutionMode ExecutionMode => - ((MethodReference) ScheduleOrRunInvocationInstruction.Operand).Name == "Run" - ? ExecutionMode.Run - : ExecutionMode.Schedule; + public bool IsInSystemBase => ContainingMethod.DeclaringType.TypeReferenceEqualsOrInheritsFrom(ContainingMethod.Module.ImportReference(typeof(SystemBase))); + + public ExecutionMode ExecutionMode + { + get + { + if (IsInSystemBase) + { + switch (((MethodReference) ScheduleOrRunInvocationInstruction.Operand).Name) + { + case nameof(ExecutionMode.Run): return ExecutionMode.Run; + case nameof(ExecutionMode.Schedule): return ExecutionMode.Schedule; + case nameof(ExecutionMode.ScheduleParallel): return ExecutionMode.ScheduleParallel; + default: throw new ArgumentOutOfRangeException(); + } + } + else + { + switch (((MethodReference) ScheduleOrRunInvocationInstruction.Operand).Name) + { + case nameof(ExecutionMode.Run): return ExecutionMode.Run; + case nameof(ExecutionMode.Schedule): return ExecutionMode.Schedule; + default: throw new ArgumentOutOfRangeException(); + } + } + } + } + + + public bool UseImplicitSystemDependency => IsInSystemBase && + (ExecutionMode == CodeGen.ExecutionMode.Schedule || ExecutionMode == CodeGen.ExecutionMode.ScheduleParallel) && + ((MethodReference) ScheduleOrRunInvocationInstruction.Operand).ReturnType.IsVoid(); public bool AllowReferenceTypes => ExecutionMode == ExecutionMode.Run && !UsesBurst; @@ -126,9 +155,9 @@ public static List FindLambdaJobStatementStartingInstructions(IEnum return false; var mr = (MethodReference) i.Operand; - if (mr.Name == EntitiesGetterName && mr.ReturnType.Name == nameof(ForEachLambdaJobDescription)) + if (mr.Name == EntitiesGetterName && (mr.ReturnType.Name == nameof(ForEachLambdaJobDescription) || mr.ReturnType.Name == nameof(ForEachLambdaJobDescriptionJCS))) return true; - if (mr.Name == JobGetterName && mr.DeclaringType.Name == nameof(JobComponentSystem)) + if (mr.Name == JobGetterName && (mr.DeclaringType.Name == nameof(JobComponentSystem) || mr.DeclaringType.Name == nameof(SystemBase))) return true; #if ENABLE_DOTS_COMPILER_CHUNKS if (mr.Name == "get_" + nameof(JobComponentSystem.Chunks) && mr.DeclaringType.Name == nameof(JobComponentSystem)) @@ -157,6 +186,21 @@ public static IEnumerable FindIn(MethodDefinit } } + static bool VerifyLambdaName(string jobName) + { + if (jobName.Length == 0) + return false; + if (char.IsDigit(jobName[0])) + return false; + for (int i = 0; i < jobName.Length; i++) + { + if (jobName[i] != '_' && !char.IsLetterOrDigit(jobName[i])) + return false; + } + // names with __ are reserved for the compiler by convention + return !jobName.Contains("__"); + } + static LambdaJobDescriptionConstruction AnalyzeLambdaJobStatement(MethodDefinition method, Instruction getEntitiesOrJobInstruction, int lambdaNumber) { List modifiers = new List(); @@ -169,15 +213,20 @@ static LambdaJobDescriptionConstruction AnalyzeLambdaJobStatement(MethodDefiniti var mr = cursor?.Operand as MethodReference; - if (mr.Name == nameof(LambdaJobDescriptionConstructionMethods.Schedule) || mr.Name == nameof(LambdaJobDescriptionConstructionMethods.Run)) + if (mr.Name == nameof(LambdaJobDescriptionExecutionMethods.Schedule) || + mr.Name == nameof(LambdaJobDescriptionExecutionMethods.ScheduleParallel) || + mr.Name == nameof(LambdaJobDescriptionExecutionMethods.Run)) { var withNameModifier = modifiers.FirstOrDefault(m => m.MethodName == nameof(LambdaJobDescriptionConstructionMethods.WithName)); - var lambdaJobName = withNameModifier?.Arguments.OfType().Single() ?? $"{method.Name}_LambdaJob{lambdaNumber}"; + var givenName = withNameModifier?.Arguments.OfType().Single(); + var lambdaJobName = givenName ?? $"{method.Name}_LambdaJob{lambdaNumber}"; + if (givenName != null && !VerifyLambdaName(givenName)) + UserError.DC0039(method, givenName, getEntitiesOrJobInstruction).Throw(); var hasWithStructuralChangesModifier = modifiers.Any(m => m.MethodName == nameof(LambdaJobDescriptionConstructionMethods.WithStructuralChanges)); - if (hasWithStructuralChangesModifier && mr.Name != nameof(LambdaJobDescriptionConstructionMethods.Run)) + if (hasWithStructuralChangesModifier && mr.Name != nameof(LambdaJobDescriptionExecutionMethods.Run)) UserError.DC0028(method, getEntitiesOrJobInstruction).Throw(); FieldReference storeQueryInField = null; @@ -211,7 +260,7 @@ LambdaJobDescriptionKind FindLambdaDescriptionKind() } if (modifiers.All(m => m.MethodName != nameof(LambdaForEachDescriptionConstructionMethods.ForEach) && - m.MethodName != nameof(LambdaSimpleJobDescriptionConstructionMethods.WithCode))) + m.MethodName != nameof(LambdaSingleJobDescriptionConstructionMethods.WithCode))) { DiagnosticMessage MakeDiagnosticMessage() { @@ -230,9 +279,12 @@ DiagnosticMessage MakeDiagnosticMessage() MakeDiagnosticMessage().Throw(); } + + if (method.DeclaringType.HasGenericParameters) + UserError.DC0025($"Entities.ForEach cannot be used in system {method.DeclaringType.Name} as Entities.ForEach in generic system types are not supported.", method, getEntitiesOrJobInstruction).Throw(); var withCodeInvocationInstruction = modifiers - .Single(m => m.MethodName == nameof(LambdaForEachDescriptionConstructionMethods.ForEach) || m.MethodName == nameof(LambdaSimpleJobDescriptionConstructionMethods.WithCode)) + .Single(m => m.MethodName == nameof(LambdaForEachDescriptionConstructionMethods.ForEach) || m.MethodName == nameof(LambdaSingleJobDescriptionConstructionMethods.WithCode)) .InstructionInvokingMethod; return new LambdaJobDescriptionConstruction() { @@ -314,6 +366,7 @@ private static Instruction FindNextConstructionMethod(MethodDefinition method, I return null; } + static bool HasAllowMultipleAttribute(MethodDefinition mr) => mr.HasCustomAttributes && mr.CustomAttributes.Any(c => c.AttributeType.Name == nameof(LambdaJobDescriptionConstructionMethods.AllowMultipleInvocationsAttribute)); @@ -348,7 +401,9 @@ private static object OperandObjectFor(Instruction argumentPushingInstruction) return null; } - static bool IsLambdaJobDescriptionConstructionMethod(MethodReference mr) =>mr.DeclaringType.Name.EndsWith("ConstructionMethods") &&(mr.DeclaringType.Namespace == "Unity.Entities" || mr.DeclaringType.Namespace == ""); + static bool IsLambdaJobDescriptionConstructionMethod(MethodReference mr) => + (mr.DeclaringType.Name.EndsWith("ConstructionMethods") || mr.DeclaringType.Name.EndsWith("ExecutionMethods") || mr.DeclaringType.Name.EndsWith("ExecutionMethodsJCS")) + && (mr.DeclaringType.Namespace == "Unity.Entities" || mr.DeclaringType.Namespace == ""); public static CecilHelpers.DelegateProducingSequence AnalyzeForEachInvocationInstruction(MethodDefinition methodToAnalyze, Instruction withCodeInvocationInstruction) { diff --git a/Unity.Entities.CodeGen/LambdaJobs/LambdaJobsPostProcessor.cs b/Unity.Entities.CodeGen/LambdaJobs/LambdaJobsPostProcessor.cs index aafedabe..865928d9 100644 --- a/Unity.Entities.CodeGen/LambdaJobs/LambdaJobsPostProcessor.cs +++ b/Unity.Entities.CodeGen/LambdaJobs/LambdaJobsPostProcessor.cs @@ -193,7 +193,8 @@ protected override bool PostProcessImpl() foreach (var description in lambdaJobDescriptionConstructions) { madeChange = true; - Rewrite(m, description, _diagnosticMessages); + var (jobStructForLambdaJob, rewriteDiagnosticMessages) = Rewrite(m, description); + _diagnosticMessages.AddRange(rewriteDiagnosticMessages); } } catch (PostProcessException ppe) @@ -238,19 +239,17 @@ private static MethodDefinition InjectOnCreateForCompiler(TypeDefinition typeDef if (typeDefinition.Name == nameof(ComponentSystemBase) && typeDefinition.Namespace == "Unity.Entities") return null; - var name = OnCreateForCompilerName; - - var pre_existing_method = typeDefinition.Methods.FirstOrDefault(m => m.Name == name); - if (pre_existing_method != null) - UserError.DC0026($"It's not allowed to implement {OnCreateForCompilerName}'", pre_existing_method).Throw(); + var preExistingMethod = typeDefinition.Methods.FirstOrDefault(m => m.Name == OnCreateForCompilerName); + if (preExistingMethod != null) + UserError.DC0026($"It's not allowed to implement {OnCreateForCompilerName}'", preExistingMethod).Throw(); var typeSystemVoid = typeDefinition.Module.TypeSystem.Void; - var newMethod = new MethodDefinition(name,MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeSystemVoid); + var newMethod = new MethodDefinition(OnCreateForCompilerName,MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeSystemVoid); typeDefinition.Methods.Add(newMethod); var ilProcessor = newMethod.Body.GetILProcessor(); ilProcessor.Emit(OpCodes.Ldarg_0); - ilProcessor.Emit(OpCodes.Call, new MethodReference(name, typeSystemVoid, typeDefinition.BaseType) { HasThis = true}); + ilProcessor.Emit(OpCodes.Call, new MethodReference(OnCreateForCompilerName, typeSystemVoid, typeDefinition.BaseType) { HasThis = true}); ilProcessor.Emit(OpCodes.Ret); return newMethod; } @@ -262,10 +261,12 @@ public static MethodDefinition GetOrMakeOnCreateForCompilerMethod(TypeDefinition private static bool keepUnmodifiedVersionAroundForDebugging = false; - public static JobStructForLambdaJob Rewrite(MethodDefinition methodContainingLambdaJob, LambdaJobDescriptionConstruction lambdaJobDescriptionConstruction, List warnings) + public static (JobStructForLambdaJob, List) Rewrite(MethodDefinition methodContainingLambdaJob, LambdaJobDescriptionConstruction lambdaJobDescriptionConstruction) { + var diagnosticMessages = new List(); + if (methodContainingLambdaJob.DeclaringType.CustomAttributes.Any(c => (c.AttributeType.Name == "ExecuteAlways" && c.AttributeType.Namespace == "UnityEngine"))) - warnings.Add(UserError.DC0032(methodContainingLambdaJob.DeclaringType, methodContainingLambdaJob, lambdaJobDescriptionConstruction.ScheduleOrRunInvocationInstruction)); + diagnosticMessages.Add(UserError.DC0032(methodContainingLambdaJob.DeclaringType, methodContainingLambdaJob, lambdaJobDescriptionConstruction.ScheduleOrRunInvocationInstruction)); if (keepUnmodifiedVersionAroundForDebugging) CecilHelpers.CloneMethodForDiagnosingProblems(methodContainingLambdaJob); @@ -281,23 +282,58 @@ public static JobStructForLambdaJob Rewrite(MethodDefinition methodContainingLam if (methodLambdaWasEmittedAs.DeclaringType.TypeReferenceEquals(methodContainingLambdaJob.DeclaringType) && !lambdaJobDescriptionConstruction.AllowReferenceTypes) { - //sometimes roslyn emits the lambda as an instance method in the same type of the method that contains the lambda expression. - //it does this only in the situation where the lambda captures a field _and_ does not capture any locals. in this case - //there's no displayclass being created. We should figure out exactly what instruction caused this behaviour, and tell the user - //she can't read a field like that. + // Sometimes roslyn emits the lambda as an instance method in the same type of the method that contains the lambda expression. + // it does this only in the situation where the lambda captures a field _and_ does not capture any locals. In this case + // there's no displayclass being created. We should figure out exactly what instruction caused this behaviour, and tell the user + // she can't read a field like that. - var illegalFieldRead = methodLambdaWasEmittedAs.Body.Instructions.FirstOrDefault(i => i.OpCode == OpCodes.Ldfld && i.Previous?.OpCode == OpCodes.Ldarg_0); + // Here is an example: https://sharplab.io/#v2:D4AQTAjAsAUCDMACciDCiDetE8QMwBsB7AQwBd8BLAUwIBNEBeReAOgAY8BubXXnBMgAsiACoALSgGcA4tQB21AE7lqUgLLUAtgCNlIAKxlKReVIAUASiwwAkLYD0DsZKmICJXXRKIA7pQICRABzBWVVRB8tbT0lfABXeQBjY1NENLJxamQwNFYXbKVqEik06QAuWHsnHABaAvdPHW90+QIAT0QkkgAHMniitx88Gnp8gEkzMmKGIjwu3v6lSnlgxEzpRGoADx6CSiTKMg6AGirHZ1xfbO75ELCVacjEaMyiWbv0MiJEPS3t6hJeLTBgrKTTEh0fi4HAAESIIAgYHMViYAD4bDCsThUKZSgRqKwAOrLabmEa0OiWLiIaEwgC+1LpfBg2JwNQkmw8Xh8/kC90Uj2yURiygSyVSdwyWRyeQaRRKZSklVZbJqiHqEmy3OaPlMHUQRQAjvFKINEAByDZSC2ReQMHolKRqRBHdY/YaJFImeSsZlwhFIlGWdGYtm4eGc1YWa1M1XYxk8eOIelVaGCEAiTmyB6qKQAQVQHikFhDNmqzi1zvWvh+Ou8biyRQF4SePnA+S1huKpTumxK+CIgSIvmV53V9Uy2WdSVMDHrPm6fQGLp8xG6QRI9vW4nIg6USRdU66RC0PQCYu+Wy0R3Hlxw7dyV5IKXiJECnXEQ4Yx/BETmO7akQG53nUgFUEo4KNDyrQGkuSyrlQlJ2j+MqzmeF5xLW8T0Ig8RSG+H6IAAVvhZCgbg2huiKuhingXqSpEbgrOBIyQRQ3TOicvzAogUgrIegHNu+Cp0J00gUQ+sp4EQcQLkM8jtL4JDtNxbp8kE/FngaRT4dkmR7qYhLnPCiLIqijAYucti4mYQ6EiSRzUOSoxUjS/opnG4YeSsFDbEwiDsEm4amUGFlWXY9i2fiDmks5FL0NStKRTZeL2cScXmNsXlsom0Kpsm6YiKFyJmZEKRlgVMLphAABswiIJGkjRuY6BJJVsD0kAA= + + var illegalFieldRead = methodLambdaWasEmittedAs.Body.Instructions.FirstOrDefault(IsIllegalFieldRead); if (illegalFieldRead != null) UserError.DC0001(methodContainingLambdaJob, illegalFieldRead, (FieldReference) illegalFieldRead.Operand).Throw(); - var illegalInvocation = methodLambdaWasEmittedAs.Body.Instructions.FirstOrDefault(i => i.IsInvocation() && methodContainingLambdaJob.DeclaringType.TypeReferenceEqualsOrInheritsFrom(((MethodReference)i.Operand).DeclaringType)); + // Similarly, we could end up here because the lambda captured neither a field nor a local but simply + // uses the this-reference. This could be the case if the user calls a function that takes this as a + // parameter, either explicitly (static) or implicitly (extension or member method). + var illegalInvocation = methodLambdaWasEmittedAs.Body.Instructions.FirstOrDefault(IsIllegalInvocation); if (illegalInvocation != null) - UserError.DC0002(methodContainingLambdaJob, illegalInvocation, (MethodReference)illegalInvocation.Operand).Throw(); + UserError.DC0002(methodContainingLambdaJob, illegalInvocation, (MethodReference)illegalInvocation.Operand, methodLambdaWasEmittedAs.DeclaringType).Throw(); - //this should never hit, but is here to make sure that in case we have a bug in detecting why roslyn emitted it like this, we can at least report an error, instead of silently generating invalid code. + // This should never hit, but is here to make sure that in case we have a bug in detecting + // why roslyn emitted it like this, we can at least report an error, instead of silently generating invalid code. InternalCompilerError.DCICE001(methodContainingLambdaJob).Throw(); + + bool IsIllegalFieldRead(Instruction i) + { + if (i.Previous == null) + return false; + if (i.OpCode != OpCodes.Ldfld && i.OpCode != OpCodes.Ldflda) + return false; + return i.Previous.OpCode == OpCodes.Ldarg_0; + } + + bool IsIllegalInvocation(Instruction i) + { + if (!i.IsInvocation()) + return false; + var declaringType = methodContainingLambdaJob.DeclaringType; + var method = (MethodReference)i.Operand; + // is it an instance method? + var resolvedMethod = method.Resolve(); + if (declaringType.TypeReferenceEqualsOrInheritsFrom(method.DeclaringType) && !resolvedMethod.IsStatic) + return true; + + // is it a method that potentially takes this as a parameter? + foreach (var param in method.Parameters) + { + if (declaringType.TypeReferenceEqualsOrInheritsFrom(param.ParameterType) || declaringType.TypeImplements(param.ParameterType)) + return true; + } + return false; + } } - + var moduleDefinition = methodContainingLambdaJob.Module; var body = methodContainingLambdaJob.Body; @@ -307,8 +343,7 @@ public static JobStructForLambdaJob Rewrite(MethodDefinition methodContainingLam if (lambdaJobDescriptionConstruction.DelegateProducingSequence.CapturesLocals) { bool allDelegatesAreGuaranteedNotToOutliveMethod = lambdaJobDescriptionConstruction.DisplayClass.IsValueType() || CecilHelpers.AllDelegatesAreGuaranteedNotToOutliveMethodFor(methodContainingLambdaJob); - - + displayClassVariable = body.Variables.Single(v => v.VariableType.TypeReferenceEquals(lambdaJobDescriptionConstruction.DisplayClass)); //in this step we want to get rid of the heap allocation for the delegate. In order to make the rest of the code easier to reason about and write, @@ -366,14 +401,25 @@ IEnumerable InstructionsToReplaceScheduleInvocationWith() var newJobStructVariable = new VariableDefinition(generatedJobStruct.TypeDefinition); body.Variables.Add(newJobStructVariable); + bool storeJobHandleInVariable = (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule || + lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.ScheduleParallel); VariableDefinition tempStorageForJobHandle = null; - if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) + + if (storeJobHandleInVariable) { tempStorageForJobHandle = new VariableDefinition(moduleDefinition.ImportReference(typeof(JobHandle))); body.Variables.Add(tempStorageForJobHandle); - //since we're replacing the .Schedule() function on the description, the lambdajobdescription and the jobhandle argument to that function will be on the stack. - //we're going to need the jobhandle later when we call JobChunkExtensions.Schedule(), so lets stuff it in a variable. + // If we aren't using an implicit system dependency and we're replacing the .Schedule() function on the description, + // the lambdajobdescription and the jobhandle argument to that function will be on the stack. + // we're going to need the jobhandle later when we call JobChunkExtensions.Schedule(), so lets stuff it in a variable. + + // If we are using implicit system dependency, lets put that in our temp instead. + if (lambdaJobDescriptionConstruction.UseImplicitSystemDependency) + { + yield return Instruction.Create(OpCodes.Ldarg_0); + yield return Instruction.Create(OpCodes.Call, moduleDefinition.ImportReference(typeof(SystemBase).GetMethod("get_Dependency", BindingFlags.Instance | BindingFlags.NonPublic))); + } yield return Instruction.Create(OpCodes.Stloc, tempStorageForJobHandle); } @@ -401,18 +447,58 @@ MethodInfo FindRunOrScheduleMethod() { case LambdaJobDescriptionKind.Entities: case LambdaJobDescriptionKind.Chunk: - if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) - return typeof(JobChunkExtensions).GetMethod(nameof(JobChunkExtensions.Schedule)); - return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunJobChunk)); + if (lambdaJobDescriptionConstruction.IsInSystemBase) + { + switch (lambdaJobDescriptionConstruction.ExecutionMode) + { + case ExecutionMode.Run: + return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunJobChunk)); + case ExecutionMode.Schedule: + return typeof(JobChunkExtensions).GetMethod(nameof(JobChunkExtensions.ScheduleSingle)); + case ExecutionMode.ScheduleParallel: + return typeof(JobChunkExtensions).GetMethod(nameof(JobChunkExtensions.ScheduleParallel)); + default: + throw new ArgumentOutOfRangeException(); + } + } + else + { + // Keep legacy behaviour in JobComponentSystems intact (aka "Schedule" equals "ScheduleParallel") + if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) + return typeof(JobChunkExtensions).GetMethod(nameof(JobChunkExtensions.ScheduleParallel)); + return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunJobChunk)); + } case LambdaJobDescriptionKind.Job: - if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) - return typeof(IJobExtensions).GetMethod(nameof(IJobExtensions.Schedule)); - return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunIJob)); + if (lambdaJobDescriptionConstruction.IsInSystemBase) + { + switch (lambdaJobDescriptionConstruction.ExecutionMode) + { + case ExecutionMode.Run: + return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunIJob)); + case ExecutionMode.Schedule: + return typeof(IJobExtensions).GetMethod(nameof(IJobExtensions.Schedule)); + default: + throw new ArgumentOutOfRangeException(); + } + } + else + { + if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) + return typeof(IJobExtensions).GetMethod(nameof(IJobExtensions.Schedule)); + return typeof(InternalCompilerInterface).GetMethod(nameof(InternalCompilerInterface.RunIJob)); + } default: throw new ArgumentOutOfRangeException(); } } + // Call CompleteDependency method to complete previous dependencies if we are running in SystemBase + if (lambdaJobDescriptionConstruction.IsInSystemBase && lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Run) + { + yield return Instruction.Create(OpCodes.Ldarg_0); + yield return Instruction.Create(OpCodes.Call, + moduleDefinition.ImportReference(typeof(SystemBase).GetMethod("CompleteDependency", BindingFlags.Instance | BindingFlags.NonPublic))); + } MethodReference runOrScheduleMethod; if (lambdaJobDescriptionConstruction.WithStructuralChanges) @@ -451,8 +537,15 @@ MethodInfo FindRunOrScheduleMethod() break; } - if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) + // Store returned JobHandle in temp varaible or back in SystemBase.depenedency + if (storeJobHandleInVariable) yield return Instruction.Create(OpCodes.Ldloc, tempStorageForJobHandle); + else if (lambdaJobDescriptionConstruction.UseImplicitSystemDependency) + { + yield return Instruction.Create(OpCodes.Ldarg_0); + yield return Instruction.Create(OpCodes.Call, + moduleDefinition.ImportReference(typeof(SystemBase).GetMethod("get_Dependency", BindingFlags.Instance | BindingFlags.NonPublic))); + } if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Run && !lambdaJobDescriptionConstruction.WithStructuralChanges) @@ -472,9 +565,18 @@ MethodInfo FindRunOrScheduleMethod() yield return finalBranchDestination; } } - + yield return Instruction.Create(OpCodes.Call, runOrScheduleMethod); + if (lambdaJobDescriptionConstruction.UseImplicitSystemDependency) + { + yield return Instruction.Create(OpCodes.Stloc, tempStorageForJobHandle); + yield return Instruction.Create(OpCodes.Ldarg_0); + yield return Instruction.Create(OpCodes.Ldloc, tempStorageForJobHandle); + yield return Instruction.Create(OpCodes.Call, + moduleDefinition.ImportReference(typeof(SystemBase).GetMethod("set_Dependency", BindingFlags.Instance | BindingFlags.NonPublic))); + } + if (lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Run && generatedJobStruct.WriteToDisplayClassMethod != null && lambdaJobDescriptionConstruction.DelegateProducingSequence.CapturesLocals) { @@ -501,14 +603,16 @@ MethodInfo FindRunOrScheduleMethod() if (invokedMethod.MethodName == nameof(LambdaJobQueryConstructionMethods.WithSharedComponentFilter)) { - var setSharedComponentFilterOnQueryMethod = moduleDefinition.ImportReference( (lambdaJobDescriptionConstruction.Kind == LambdaJobDescriptionKind.Entities ? typeof(ForEachLambdaJobDescription_SetSharedComponent) : typeof(LambdaJobChunkDescription_SetSharedComponent)).GetMethod( - nameof(LambdaJobChunkDescription_SetSharedComponent - .SetSharedComponentFilterOnQuery))); + nameof(LambdaJobChunkDescription_SetSharedComponent.SetSharedComponentFilterOnQuery))); + var callingTypeReference = lambdaJobDescriptionConstruction.IsInSystemBase + ? moduleDefinition.ImportReference(typeof(ForEachLambdaJobDescription)) + : moduleDefinition.ImportReference(typeof(ForEachLambdaJobDescriptionJCS)); MethodReference genericSetSharedComponentFilterOnQueryMethod - = setSharedComponentFilterOnQueryMethod.MakeGenericInstanceMethod(invokedMethod.TypeArguments); + = setSharedComponentFilterOnQueryMethod.MakeGenericInstanceMethod( + new TypeReference[] { callingTypeReference }.Concat(invokedMethod.TypeArguments).ToArray()); // Change invocation to invocation of helper method and add EntityQuery parameter to be modified var setSharedComponentFilterOnQueryInstructions = new List @@ -518,8 +622,7 @@ MethodReference genericSetSharedComponentFilterOnQueryMethod Instruction.Create(OpCodes.Call, genericSetSharedComponentFilterOnQueryMethod) }; - ilProcessor.Replace(invokedMethod.InstructionInvokingMethod, - setSharedComponentFilterOnQueryInstructions); + ilProcessor.Replace(invokedMethod.InstructionInvokingMethod, setSharedComponentFilterOnQueryInstructions); } } } @@ -530,7 +633,7 @@ MethodReference genericSetSharedComponentFilterOnQueryMethod var codegenInitializeMethod = GetOrMakeOnCreateForCompilerMethod(lambdaJobDescriptionConstruction.ContainingMethod.DeclaringType); - return generatedJobStruct; + return (generatedJobStruct, diagnosticMessages); } static void ChangeAllDisplayClassesToStructs(MethodDefinition methodContainingLambdaJob) diff --git a/Unity.Entities.CodeGen/LambdaJobs/LambdaParamaterValueProviderInformation.cs b/Unity.Entities.CodeGen/LambdaJobs/LambdaParamaterValueProviderInformation.cs index 21a267c3..bced2caa 100644 --- a/Unity.Entities.CodeGen/LambdaJobs/LambdaParamaterValueProviderInformation.cs +++ b/Unity.Entities.CodeGen/LambdaJobs/LambdaParamaterValueProviderInformation.cs @@ -138,7 +138,9 @@ public static LambdaParamaterValueProviderInformation ElementProviderInformation // class IComponentData / UnityEngine.Object if (resolvedParameterType.IsIComponentDataClass() || resolvedParameterType.IsUnityEngineObject()) { - if (lambdaJobDescriptionConstruction.UsesBurst || lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule) + if (lambdaJobDescriptionConstruction.UsesBurst || + lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.Schedule || + lambdaJobDescriptionConstruction.ExecutionMode == ExecutionMode.ScheduleParallel) UserError.DC0023(lambdaJobDescriptionConstruction.ContainingMethod, parameterType, lambdaJobDescriptionConstruction.WithCodeInvocationInstruction).Throw(); bool readOnly = false; diff --git a/Unity.Entities.CodeGen/LambdaJobs/LambdaParameterValueInformations.cs b/Unity.Entities.CodeGen/LambdaJobs/LambdaParameterValueInformations.cs index 99a43708..009b74df 100644 --- a/Unity.Entities.CodeGen/LambdaJobs/LambdaParameterValueInformations.cs +++ b/Unity.Entities.CodeGen/LambdaJobs/LambdaParameterValueInformations.cs @@ -83,6 +83,8 @@ void InjectIntoJobChunkType() _lambdaParameterValueProvidersType.Fields.Add(parameterFieldDefinition); var runtimeFieldDefinition = new FieldDefinition($"runtime_{provider.Name}", FieldAttributes.Public, provider.ProviderRuntime); + if (_lambdaJobDescriptionConstruction.UsesBurst && LambdaJobDescriptionConstruction.UsesNoAlias) + runtimeFieldDefinition.CustomAttributes.Add(new CustomAttribute(burstNoAliasAttributeConstructor)); RuntimesType.Fields.Add(runtimeFieldDefinition); _elementProviderToFields.Add(provider, (parameterFieldDefinition, runtimeFieldDefinition)); diff --git a/Unity.Entities.CodeGen/LambdaJobs/UserError.cs b/Unity.Entities.CodeGen/LambdaJobs/UserError.cs index 6196c40a..2d5b989d 100644 --- a/Unity.Entities.CodeGen/LambdaJobs/UserError.cs +++ b/Unity.Entities.CodeGen/LambdaJobs/UserError.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using System.Text; +using System.Runtime.CompilerServices; using Mono.Cecil; using Mono.Cecil.Cil; using Unity.Collections.LowLevel.Unsafe; @@ -53,9 +51,9 @@ public static DiagnosticMessage DC0001(MethodDefinition method, Instruction inst return MakeError(nameof(DC0001),$"Entities.ForEach Lambda expression uses field '{fr.Name}'. Either assign the field to a local outside of the lambda expression and use that instead, or use .WithoutBurst() and .Run()", method, instruction); } - public static DiagnosticMessage DC0002(MethodDefinition method, Instruction instruction, MethodReference mr) + public static DiagnosticMessage DC0002(MethodDefinition method, Instruction instruction, MethodReference mr, TypeReference argument) { - return MakeError(nameof(DC0002),$"Entities.ForEach Lambda expression invokes '{mr.Name}' on a {mr.DeclaringType.Name} which is a reference type. This is only allowed with .WithoutBurst() and .Run().", method, instruction); + return MakeError(nameof(DC0002),$"Entities.ForEach Lambda expression invokes '{mr.Name}' on a {argument.Name} which is a reference type. This is only allowed with .WithoutBurst() and .Run().", method, instruction); } public static DiagnosticMessage DC0003(string name, MethodDefinition method, Instruction instruction) @@ -80,7 +78,7 @@ public static DiagnosticMessage DC0006(MethodDefinition method, Instruction inst public static DiagnosticMessage DC0017(MethodDefinition method, Instruction instruction) { - return MakeError(nameof(DC0006),$"Scheduling an Lambda job requires a .{nameof(LambdaSimpleJobDescriptionConstructionMethods.WithCode)} invocation", method, instruction); + return MakeError(nameof(DC0006),$"Scheduling an Lambda job requires a .{nameof(LambdaSingleJobDescriptionConstructionMethods.WithCode)} invocation", method, instruction); } public static DiagnosticMessage DC0018(MethodDefinition method, Instruction instruction) @@ -90,7 +88,7 @@ public static DiagnosticMessage DC0018(MethodDefinition method, Instruction inst public static DiagnosticMessage DC0007(MethodDefinition method, Instruction instruction) { - return MakeError(nameof(DC0007),$"Unexpected code structure in Entities/Job query. Make sure to immediately end each ForEach query with a .Schedule() or .Run() call", method, instruction); + return MakeError(nameof(DC0007),$"Unexpected code structure in Entities/Job query. Make sure to immediately end each ForEach query with a .Schedule(), .ScheduleParallel() or .Run() call.", method, instruction); } public static DiagnosticMessage DC0008(MethodDefinition method, Instruction instruction, MethodReference mr) @@ -110,7 +108,7 @@ public static DiagnosticMessage DC0010(MethodDefinition method, Instruction inst public static DiagnosticMessage DC0011(MethodDefinition method, Instruction instruction) { - return MakeError(nameof(DC0011),$"Every Entities.ForEach statement needs to end with a .Schedule() or .Run() invocation", method, instruction); + return MakeError(nameof(DC0011),$"Every Entities.ForEach statement needs to end with a .Schedule(), .ScheduleParallel() or .Run() invocation.", method, instruction); } public static DiagnosticMessage DC0012(MethodDefinition methodToAnalyze, LambdaJobDescriptionConstruction.InvokedConstructionMethod constructionMethod) @@ -120,7 +118,7 @@ public static DiagnosticMessage DC0012(MethodDefinition methodToAnalyze, LambdaJ public static DiagnosticMessage DC0013(FieldReference fieldReference, MethodDefinition method, Instruction instruction) { - return MakeError(nameof(DC0013), $"Entities.ForEach Lambda expression writes to captured variable '{fieldReference.Name}'. This is only supported when you use .Run() instead of .Schedule()", method, instruction); + return MakeError(nameof(DC0013), $"Entities.ForEach Lambda expression writes to captured variable '{fieldReference.Name}'. This is only supported when you use .Run().", method, instruction); } public static DiagnosticMessage DC0014(MethodDefinition method, Instruction instruction, ParameterDefinition parameter, string[] supportedParameters) @@ -169,8 +167,8 @@ public static DiagnosticMessage DC0024(MethodDefinition containingMethod, TypeRe { return MakeError(nameof(DC0024),$"Entities.ForEach uses managed IComponentData {componentType.Name} by ref. To get write access, receive it without the ref modifier." ,containingMethod, instruction); } - - //$"Type {t.Name} cannot be used with {m.MethodName} as it is not a supported component type" + + // Invalid type used as LambdaJob parameter or in With method invocation. public static DiagnosticMessage DC0025(string message, MethodDefinition containingMethod, Instruction instruction) { return MakeError(nameof(DC0025), message, containingMethod, instruction); @@ -194,7 +192,7 @@ public static DiagnosticMessage DC0027(MethodDefinition method, Instruction inst public static DiagnosticMessage DC0028(MethodDefinition method, Instruction instruction) { - return MakeError(nameof(DC0028), $"Entities.ForEach Lambda expression makes a structural change with a .Schedule() call. Structural changes are only supported with .Run().", method, instruction); + return MakeError(nameof(DC0028), $"Entities.ForEach Lambda expression makes a structural change with a Schedule call. Structural changes are only supported with .Run().", method, instruction); } public static DiagnosticMessage DC0029(MethodDefinition method, Instruction instruction) @@ -246,6 +244,52 @@ public static DiagnosticMessage DC0038(MethodDefinition containingMethod, FieldD { return MakeError(nameof(DC0038),$"Entities.{constructionMethod.MethodName} is called with an invalid argument {field.DeclaringType.Name}.{field.Name}. You cannot use Entities.{constructionMethod.MethodName} with fields of user-defined types as the argument. Please assign the field to a local variable and use that instead.", containingMethod, constructionMethod.InstructionInvokingMethod); } + + public static DiagnosticMessage DC0039(TypeReference bufferElementDataType, int numFieldsFound) + { + return MakeError( + nameof(DC0039), + messageData: $"Structs implementing IBufferElementData and marked with a {nameof(GenerateAuthoringComponentAttribute)} attribute should have exactly" + + $" one field specifying its element type. However, '{bufferElementDataType.Name}' contains {numFieldsFound} fields." + + "Please implement your own authoring component.", + method: null, + instruction: null); + } + + public static DiagnosticMessage DC0040(TypeReference bufferElementDataType) + { + return MakeError( + nameof(DC0040), + messageData: "Structs implementing IBufferElementData may only contain fields of either primitive or blittable types. However," + + $" '{bufferElementDataType.Name}' has an element type which is NOT a primitive or blittable type.", + method: null, + instruction: null); + } + + public static DiagnosticMessage DC0041(TypeDefinition bufferElementDataType) + { + return MakeError( + nameof(DC0041), + messageData: $"IBufferElementData can only be implemented by structs. '{bufferElementDataType.Name}' is a class." + + $"Please change {bufferElementDataType} to a struct.", + method: null, + instruction: null); + } + + public static DiagnosticMessage DC0042(TypeDefinition bufferElementDataType) + { + return MakeError( + nameof(DC0042), + messageData: $"Structs implementing IBufferElementData and marked with a {nameof(GenerateAuthoringComponentAttribute)} attribute cannot have an explicit layout." + + $"{bufferElementDataType} has an explicit layout. Please implement your own authoring component.", + method: null, + instruction: null); + } + + public static DiagnosticMessage DC0039(MethodDefinition containingMethod, string name, Instruction instruction) + { + return MakeError(nameof(DC0039),$"Entities.{nameof(LambdaJobDescriptionConstructionMethods.WithName)} cannot be used with name '{name}'. The given name must consist of letters, digits, and underscores only, and may not contain two consecutive underscores.", containingMethod, instruction); + } static DiagnosticMessage MakeInternal(DiagnosticType type, string errorCode, string messageData, MethodDefinition method, Instruction instruction) { @@ -255,7 +299,7 @@ static DiagnosticMessage MakeInternal(DiagnosticType type, string errorCode, str if (errorCode.Contains("ICE")) { - messageData = messageData + " Seeing this error indicates a bug in the dots compiler. We'd appreciate a bug report (About->Report a Problem). Thnx! <3"; + messageData = messageData + " Seeing this error indicates a bug in the dots compiler. We'd appreciate a bug report (About->Report a Bug...). Thnx! <3"; } messageData = $"error {errorCode}: {messageData}"; @@ -264,7 +308,11 @@ static DiagnosticMessage MakeInternal(DiagnosticType type, string errorCode, str result.File = seq.Document.Url; result.Column = seq.StartColumn; result.Line = seq.StartLine; - result.MessageData = $"{seq.Document.Url}:({seq.StartLine},{seq.StartColumn}) {messageData}"; +#if !UNITY_DOTSPLAYER + result.MessageData = $"{seq.Document.Url}({seq.StartLine},{seq.StartColumn}): {messageData}"; +#else + result.MessageData = messageData; +#endif } else { @@ -287,6 +335,5 @@ public static void Throw(this DiagnosticMessage dm) { throw new FoundErrorInUserCodeException(new[] { dm}); } - } } \ No newline at end of file diff --git a/Unity.Entities.Editor.Tests/LiveLink/LiveLinkDropdownTests.cs b/Unity.Entities.Editor.Tests/LiveLink/LiveLinkDropdownTests.cs index bdf7dedd..c4f34624 100644 --- a/Unity.Entities.Editor.Tests/LiveLink/LiveLinkDropdownTests.cs +++ b/Unity.Entities.Editor.Tests/LiveLink/LiveLinkDropdownTests.cs @@ -3,10 +3,9 @@ using System.Collections.ObjectModel; using System.Linq; using NUnit.Framework; -using UnityEngine; using UnityEngine.UIElements; -namespace Unity.Entities.Editor.Tests.LiveLink +namespace Unity.Entities.Editor.Tests { [TestFixture] class LiveLinkDropdownTests @@ -16,33 +15,33 @@ public void LiveLinkConnection_PublishEvents() { var nameChanges = new List(); var statusChanges = new List<(LiveLinkConnectionsDropdown.LiveLinkConnection, LiveLinkConnectionsDropdown.LiveLinkConnectionStatus)>(); - var buildSettingsChanges = new List(); + var buildConfigurationChanges = new List(); var c = new LiveLinkConnectionsDropdown.LiveLinkConnection(1, "name", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, new Hash128(Guid.NewGuid().ToString("N"))); c.NameChanged += sender => nameChanges.Add(sender); c.StatusChanged += (sender, previousStatus) => statusChanges.Add((sender, previousStatus)); - c.BuildSettingsGuidChanged += sender => buildSettingsChanges.Add(sender); + c.BuildConfigurationGuidChanged += sender => buildConfigurationChanges.Add(sender); c.Name = "another name"; Assert.That(nameChanges, Is.EquivalentTo(new[] { c })); Assert.That(c.Name, Is.EqualTo("another name")); Assert.That(statusChanges, Is.Empty); - Assert.That(buildSettingsChanges, Is.Empty); + Assert.That(buildConfigurationChanges, Is.Empty); nameChanges.Clear(); c.Status = LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Disabled; Assert.That(statusChanges, Is.EquivalentTo(new[] { (c, LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected) })); Assert.That(c.Status, Is.EqualTo(LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Disabled)); Assert.That(nameChanges, Is.Empty); - Assert.That(buildSettingsChanges, Is.Empty); + Assert.That(buildConfigurationChanges, Is.Empty); statusChanges.Clear(); - var otherBuildSettingsGuid = new Hash128(Guid.NewGuid().ToString("N")); - c.BuildSettingsGuid = otherBuildSettingsGuid; - Assert.That(buildSettingsChanges, Is.EquivalentTo(new[] { c })); - Assert.That(c.BuildSettingsGuid, Is.EqualTo(otherBuildSettingsGuid)); + var otherBuildConfigurationGuid = new Hash128(Guid.NewGuid().ToString("N")); + c.BuildConfigurationGuid = otherBuildConfigurationGuid; + Assert.That(buildConfigurationChanges, Is.EquivalentTo(new[] { c })); + Assert.That(c.BuildConfigurationGuid, Is.EqualTo(otherBuildConfigurationGuid)); Assert.That(statusChanges, Is.Empty); Assert.That(nameChanges, Is.Empty); - buildSettingsChanges.Clear(); + buildConfigurationChanges.Clear(); } [Test] @@ -51,23 +50,23 @@ public void LiveLinkConnection_DontPublishEventsWhenNothingChanges() var c = new LiveLinkConnectionsDropdown.LiveLinkConnection(1, "name", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, new Hash128(Guid.NewGuid().ToString("N"))); c.NameChanged += delegate { Assert.Fail($"{nameof(c.NameChanged)} event shouldn't be fired"); }; c.StatusChanged += delegate { Assert.Fail($"{nameof(c.StatusChanged)} event shouldn't be fired"); }; - c.BuildSettingsGuidChanged += delegate { Assert.Fail($"{nameof(c.BuildSettingsGuidChanged)} event shouldn't be fired"); }; + c.BuildConfigurationGuidChanged += delegate { Assert.Fail($"{nameof(c.BuildConfigurationGuidChanged)} event shouldn't be fired"); }; c.Name = c.Name; c.Status = c.Status; - c.BuildSettingsGuid = c.BuildSettingsGuid; + c.BuildConfigurationGuid = c.BuildConfigurationGuid; } [Test] public void LiveLinkConnectionsView_GenerateValidUI() { - var settingGuid1 = new Hash128(Guid.NewGuid().ToString("N")); - var settingGuid2 = new Hash128(Guid.NewGuid().ToString("N")); + var configurationGuid1 = new Hash128(Guid.NewGuid().ToString("N")); + var configurationGuid2 = new Hash128(Guid.NewGuid().ToString("N")); var connections = new ObservableCollection { - new LiveLinkConnectionsDropdown.LiveLinkConnection(1, "player 1", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, settingGuid1), - new LiveLinkConnectionsDropdown.LiveLinkConnection(2, "player 2", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, settingGuid1), - new LiveLinkConnectionsDropdown.LiveLinkConnection(3, "player 3", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, settingGuid2), + new LiveLinkConnectionsDropdown.LiveLinkConnection(1, "player 1", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, configurationGuid1), + new LiveLinkConnectionsDropdown.LiveLinkConnection(2, "player 2", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, configurationGuid1), + new LiveLinkConnectionsDropdown.LiveLinkConnection(3, "player 3", LiveLinkConnectionsDropdown.LiveLinkConnectionStatus.Connected, configurationGuid2), }; var view = new LiveLinkConnectionsDropdown.LiveLinkConnectionsView(connections, hash128 => hash128.ToString()); @@ -75,24 +74,24 @@ public void LiveLinkConnectionsView_GenerateValidUI() view.BuildFullUI(root); // Ensure groups are visible and empty message hidden - var groupsContainer = GetItem(root, "live-link-connections-dropdown__Groups"); + var groupsContainer = root.GetItem("live-link-connections-dropdown__Groups"); Assert.That(groupsContainer.style.display.value, Is.EqualTo(DisplayStyle.Flex)); - Assert.That(GetItem(root, "live-link-connections-dropdown__EmptyMessage").style.display.value, Is.EqualTo(DisplayStyle.None)); + Assert.That(root.GetItem("live-link-connections-dropdown__EmptyMessage").style.display.value, Is.EqualTo(DisplayStyle.None)); // Ensure there are 2 groups and they have the correct names - var groups = GetItems(groupsContainer, className: "live-link-connections-dropdown__groups__item"); + var groups = groupsContainer.GetItems(className: "live-link-connections-dropdown__groups__item"); Assert.That(groups.Count, Is.EqualTo(2)); var groupsNames = groupsContainer.Query(className: "live-link-connections-dropdown__groups__item__title").Children