protected override void OnUpdate() { // UI text conversion Entities.ForEach((TextMeshProUGUI displayText) => { // We are converting an entity (textEntity) and creating another (eSubText). // Why? // We want to use the Rectangle Transform system to also position text, rather // than introduce something special. So we need a parent element that is the frame // of the text (textEntity) and a child element that has a pivet on the text string // itself. Systems later will process the child element. var textEntity = GetPrimaryEntity(displayText); // Sub-text child transform SceneSection sceneSection = DstEntityManager.GetSharedComponentData <SceneSection>(textEntity); var eSubText = DstEntityManager.CreateEntity(); DstEntityManager.AddSharedComponentData(eSubText, sceneSection); DstEntityManager.AddComponentData(eSubText, new Tiny.UI.RectTransform { AnchorMin = 0.5f, AnchorMax = 0.5f, SizeDelta = 1f, AnchoredPosition = 0f, Pivot = 0.5f }); DstEntityManager.AddComponentData(eSubText, new UIName() { Name = displayText.name }); DstEntityManager.AddComponentData(eSubText, new RectParent() { Value = textEntity }); DstEntityManager.AddComponentData(eSubText, new Unity.Tiny.Rendering.CameraMask { mask = (ulong)(1 << displayText.gameObject.layer) }); DstEntityManager.AddComponent <RectTransformResult>(eSubText); var fontAsset = GetPrimaryEntity(displayText.font); DstEntityManager.AddComponentData(eSubText, new Tiny.Text.TextRenderer { FontMaterial = fontAsset, MeshColor = displayText.color.linear.ToTiny(), Size = displayText.fontSize * 10, HorizontalAlignment = ConvertHorizontalAlignment(displayText.alignment), VerticalAlignment = ConvertVerticalAlignment(displayText.alignment), }); var text = displayText.text; DstEntityManager.AddBufferFromString <TextRendererString>(eSubText, text); DstEntityManager.AddComponent <LocalToWorld>(eSubText); }); }
Entity ConstructScreenSpaceCamera(Entity e, UnityEngine.RectTransform urc) { SceneSection sceneSection = DstEntityManager.GetSharedComponentData <SceneSection>(e); Entity eCam = DstEntityManager.CreateEntity(); DstEntityManager.AddSharedComponentData(eCam, sceneSection); var sizeDelta = urc.sizeDelta; var camera = new Unity.Tiny.Rendering.Camera { clearFlags = Tiny.Rendering.CameraClearFlags.DepthOnly, backgroundColor = new Unity.Tiny.Color(0, 0, 0, 0), viewportRect = new Tiny.Rect(0, 0, 1, 1), depth = 0.0f, fov = sizeDelta.y * 0.5f, mode = ProjectionMode.Orthographic, clipZNear = 0, clipZFar = 102, aspect = sizeDelta.x / sizeDelta.y }; DstEntityManager.AddComponentData(eCam, camera); DstEntityManager.AddComponentData(eCam, new Unity.Tiny.Rendering.CameraMask { mask = (ulong)(1 << urc.gameObject.layer) }); // For CameraSettings2D float3 customSortAxisSetting = new float3(0, 0, 1.0f); if (UnityEngine.Rendering.GraphicsSettings.transparencySortMode == UnityEngine.TransparencySortMode.CustomAxis) { customSortAxisSetting = UnityEngine.Rendering.GraphicsSettings.transparencySortAxis; } DstEntityManager.AddComponentData(eCam, new Unity.Tiny.Rendering.CameraSettings2D { customSortAxis = customSortAxisSetting }); // tag the camera as auto aspect DstEntityManager.AddComponentData(eCam, new CameraAutoAspectFromNode { Node = Entity.Null }); DstEntityManager.AddComponentData(eCam, new LocalToWorld { Value = float4x4.identity }); DstEntityManager.AddComponentData(eCam, new Translation { Value = new float3(sizeDelta.x / 2, sizeDelta.y / 2, -10) }); DstEntityManager.AddComponentData(eCam, new Rotation { Value = quaternion.identity }); DstEntityManager.AddComponent <UICamera>(eCam); return(eCam); }
public System.Collections.Generic.List <byte> __encode() { var data = new System.Collections.Generic.List <byte>(); if (this.section == null) { this.section = new SceneSection(); } data.AddRange(this.section.__encode()); return(data); }
void RecursivelySetSection(Transform transform, SceneSection section) { foreach (var entity in GetEntities(transform.gameObject)) { DstEntityManager.SetSharedComponentData(entity, section); } for (int i = 0; i != transform.childCount; i++) { RecursivelySetSection(transform.GetChild(i), section); } }
private void UpdateSceneLoading(out NativeList <SceneSection> sceneSectionsToInit) { NativeList <SceneSection> completeSceneSections = new NativeList <SceneSection>(4, Allocator.Temp); EntityCommandBuffer ecb = _ecbSystem.CreateCommandBuffer(); Entities.WithNone <PersistentSceneSectionLoadComplete>().ForEach((Entity entity, ref RequestPersistentSceneSectionLoaded requestInfo, in SceneSectionData sceneSectionData) => { if (requestInfo.CurrentLoadingStage == RequestPersistentSceneSectionLoaded.Stage.Complete) { return; } SceneSection sceneSection = new SceneSection { Section = sceneSectionData.SubSectionIndex, SceneGUID = sceneSectionData.SceneGUID }; if (requestInfo.CurrentLoadingStage == RequestPersistentSceneSectionLoaded.Stage.InitialStage) { ecb.AddComponent <PersistentSceneSection>(entity); ecb.AddComponent(entity, new RequestSceneLoaded() { LoadFlags = requestInfo.LoadFlags }); requestInfo.CurrentLoadingStage = RequestPersistentSceneSectionLoaded.Stage.WaitingForSceneLoad; } if (requestInfo.CurrentLoadingStage == RequestPersistentSceneSectionLoaded.Stage.WaitingForSceneLoad) { // Pls make SceneSectionStreamingSystem.StreamingState public :) @unity _sceneSectionLoadedCheckQuery.SetSharedComponentFilter(sceneSection); if (_sceneSectionLoadedCheckQuery.CalculateChunkCount() > 0) { completeSceneSections.Add(sceneSection); ecb.AddComponent <PersistentSceneSectionLoadComplete>(entity); requestInfo.CurrentLoadingStage = RequestPersistentSceneSectionLoaded.Stage.Complete; } } }).WithoutBurst().Run(); _sceneSectionLoadedCheckQuery.ResetFilter(); sceneSectionsToInit = completeSceneSections; }
public int __decode(byte[] binData, ref int pos) { this.section = new SceneSection(); this.section.__decode(binData, ref pos); return(pos); }
public SceneSectionNotice(SceneSection section) { this.section = section; }
public SceneSectionNotice() { section = new SceneSection(); }
public static SceneData[] WriteEntityScene(Scene scene, Hash128 sceneGUID, ConversionFlags conversionFlags) { var world = new World("ConversionWorld"); var entityManager = world.EntityManager; ConvertScene(scene, sceneGUID, world, conversionFlags); EntitySceneOptimization.Optimize(world); var sceneSections = new List <SceneData>(); var subSectionList = new List <SceneSection>(); entityManager.GetAllUniqueSharedComponentData(subSectionList); var extRefInfoEntities = new NativeArray <Entity>(subSectionList.Count, Allocator.Temp); NativeArray <Entity> entitiesInMainSection; var sectionQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); var sectionBoundsQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneBoundingVolume>(), ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); { var section = new SceneSection { SceneGUID = sceneGUID, Section = 0 }; sectionQuery.SetFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); sectionBoundsQuery.SetFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); entitiesInMainSection = sectionQuery.ToEntityArray(Allocator.TempJob); var bounds = GetBoundsAndDestroy(entityManager, sectionBoundsQuery); // Each section will be serialized in its own world, entities that don't have a section are part of the main scene. // An entity that holds the array of external references to the main scene is required for each section. // We need to create them all before we start moving entities to section scenes, // otherwise they would reuse entities that have been moved and mess up the remapping tables. for (int sectionIndex = 1; sectionIndex < subSectionList.Count; ++sectionIndex) { if (subSectionList[sectionIndex].Section == 0) { // Main section, the only one that doesn't need an external ref array continue; } var extRefInfoEntity = entityManager.CreateEntity(); entityManager.AddSharedComponentData(extRefInfoEntity, subSectionList[sectionIndex]); extRefInfoEntities[sectionIndex] = extRefInfoEntity; } // Public references array, only on the main section. var refInfoEntity = entityManager.CreateEntity(); entityManager.AddBuffer <PublicEntityRef>(refInfoEntity); entityManager.AddSharedComponentData(refInfoEntity, section); var publicRefs = entityManager.GetBuffer <PublicEntityRef>(refInfoEntity); // entityManager.Debug.CheckInternalConsistency(); //@TODO do we need to keep this index? doesn't carry any additional info for (int i = 0; i < entitiesInMainSection.Length; ++i) { PublicEntityRef.Add(ref publicRefs, new PublicEntityRef { entityIndex = i, targetEntity = entitiesInMainSection[i] }); } Debug.Assert(publicRefs.Length == entitiesInMainSection.Length); // Save main section var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.EntityManager; var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); sectionManager.MoveEntitiesFrom(entityManager, sectionQuery, entityRemapping); // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalQuery, typeof(SceneSection)); var sectionFileSize = WriteEntityScene(sectionManager, sceneGUID, "0"); sceneSections.Add(new SceneData { FileSize = sectionFileSize, SceneGUID = sceneGUID, SharedComponentCount = sectionManager.GetSharedComponentCount() - 1, SubSectionIndex = 0, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } { // Index 0 is the default value of the shared component, not an actual section for (int subSectionIndex = 0; subSectionIndex < subSectionList.Count; ++subSectionIndex) { var subSection = subSectionList[subSectionIndex]; if (subSection.Section == 0) { continue; } sectionQuery.SetFilter(subSection); sectionBoundsQuery.SetFilter(subSection); var bounds = GetBoundsAndDestroy(entityManager, sectionBoundsQuery); var entitiesInSection = sectionQuery.ToEntityArray(Allocator.TempJob); if (entitiesInSection.Length > 0) { // Fetch back the external reference entity we created earlier to not disturb the mapping var refInfoEntity = extRefInfoEntities[subSectionIndex]; entityManager.AddBuffer <ExternalEntityRef>(refInfoEntity); var externRefs = entityManager.GetBuffer <ExternalEntityRef>(refInfoEntity); // Store the mapping to everything in the main section //@TODO maybe we don't need all that? is this worth worrying about? for (int i = 0; i < entitiesInMainSection.Length; ++i) { ExternalEntityRef.Add(ref externRefs, new ExternalEntityRef { entityIndex = i }); } var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); // Entities will be remapped to a contiguous range in the section world, but they will // also come with an unpredictable amount of meta entities. We have the guarantee that // the entities in the main section won't be moved over, so there's a free range of that // size at the end of the remapping table. So we use that range for external references. var externEntityIndexStart = entityRemapping.Length - entitiesInMainSection.Length; entityManager.AddComponentData(refInfoEntity, new ExternalEntityRefInfo { SceneGUID = sceneGUID, EntityIndexStart = externEntityIndexStart }); var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.EntityManager; // Insert mapping for external references, conversion world entity to virtual index in section for (int i = 0; i < entitiesInMainSection.Length; ++i) { EntityRemapUtility.AddEntityRemapping(ref entityRemapping, entitiesInMainSection[i], new Entity { Index = i + externEntityIndexStart, Version = 1 }); } sectionManager.MoveEntitiesFrom(entityManager, sectionQuery, entityRemapping); // Now that all the required entities have been moved over, we can get rid of the gap between // real entities and external references. This allows remapping during load to deal with a // smaller remap table, containing only useful entries. int highestEntityIndexInUse = 0; for (int i = 0; i < externEntityIndexStart; ++i) { var targetIndex = entityRemapping[i].Target.Index; if (targetIndex < externEntityIndexStart && targetIndex > highestEntityIndexInUse) { highestEntityIndexInUse = targetIndex; } } var oldExternEntityIndexStart = externEntityIndexStart; externEntityIndexStart = highestEntityIndexInUse + 1; sectionManager.SetComponentData ( EntityRemapUtility.RemapEntity(ref entityRemapping, refInfoEntity), new ExternalEntityRefInfo { SceneGUID = sceneGUID, EntityIndexStart = externEntityIndexStart } ); // When writing the scene, references to missing entities are set to Entity.Null by default // (but only if they have been used, otherwise they remain untouched) // We obviously don't want that to happen to our external references, so we add explicit mapping // And at the same time, we put them back at the end of the effective range of real entities. for (int i = 0; i < entitiesInMainSection.Length; ++i) { var src = new Entity { Index = i + oldExternEntityIndexStart, Version = 1 }; var dst = new Entity { Index = i + externEntityIndexStart, Version = 1 }; EntityRemapUtility.AddEntityRemapping(ref entityRemapping, src, dst); } // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalQuery, typeof(SceneSection)); var fileSize = WriteEntityScene(sectionManager, sceneGUID, subSection.Section.ToString(), entityRemapping); sceneSections.Add(new SceneData { FileSize = fileSize, SceneGUID = sceneGUID, SharedComponentCount = sectionManager.GetSharedComponentCount() - 1, SubSectionIndex = subSection.Section, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } entitiesInSection.Dispose(); } } { var noSectionQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { None = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); if (noSectionQuery.CalculateLength() != 0) { Debug.LogWarning($"{noSectionQuery.CalculateLength()} entities in the scene '{scene.path}' had no SceneSection and as a result were not serialized at all."); } } sectionQuery.Dispose(); sectionBoundsQuery.Dispose(); entitiesInMainSection.Dispose(); world.Dispose(); // Save the new header var header = ScriptableObject.CreateInstance <SubSceneHeader>(); header.Sections = sceneSections.ToArray(); WriteHeader(sceneGUID, header); return(sceneSections.ToArray()); }
public static SceneSectionData[] WriteEntityScene(Scene scene, GameObjectConversionSettings settings, List <ReferencedUnityObjects> sectionRefObjs = null) { int framesToRetainBlobAssets = RetainBlobAssetsSetting.GetFramesToRetainBlobAssets(settings.BuildConfiguration); var world = new World("ConversionWorld"); var entityManager = world.EntityManager; settings.DestinationWorld = world; bool disposeBlobAssetCache = false; if (settings.BlobAssetStore == null) { settings.BlobAssetStore = new BlobAssetStore(); disposeBlobAssetCache = true; } List <(int, LogEventData)> journalData = null; settings.ConversionWorldPreDispose += conversionWorld => { var mappingSystem = conversionWorld.GetExistingSystem <GameObjectConversionMappingSystem>(); journalData = mappingSystem.JournalData.SelectLogEventsOrdered().ToList(); }; ConvertScene(scene, settings); EntitySceneOptimization.Optimize(world); if (settings.AssetImportContext != null) { using (var allTypes = new NativeHashMap <ComponentType, int>(100, Allocator.Temp)) using (var archetypes = new NativeList <EntityArchetype>(Allocator.Temp)) { entityManager.GetAllArchetypes(archetypes); foreach (var archetype in archetypes) { using (var componentTypes = archetype.GetComponentTypes()) foreach (var componentType in componentTypes) { if (allTypes.TryAdd(componentType, 0)) { TypeDependencyCache.AddDependency(settings.AssetImportContext, componentType); } } } } TypeDependencyCache.AddAllSystemsDependency(settings.AssetImportContext); } var sceneSections = new List <SceneSectionData>(); var subSectionList = new List <SceneSection>(); entityManager.GetAllUniqueSharedComponentData(subSectionList); var extRefInfoEntities = new NativeArray <Entity>(subSectionList.Count, Allocator.Temp); NativeArray <Entity> entitiesInMainSection; var sectionQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); var sectionBoundsQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneBoundingVolume>(), ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); var sceneGUID = settings.SceneGUID; { var section = new SceneSection { SceneGUID = sceneGUID, Section = 0 }; sectionQuery.SetSharedComponentFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); sectionBoundsQuery.SetSharedComponentFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); entitiesInMainSection = sectionQuery.ToEntityArray(Allocator.TempJob); var bounds = GetBoundsAndRemove(entityManager, sectionBoundsQuery); // Each section will be serialized in its own world, entities that don't have a section are part of the main scene. // An entity that holds the array of external references to the main scene is required for each section. // We need to create them all before we start moving entities to section scenes, // otherwise they would reuse entities that have been moved and mess up the remapping tables. for (int sectionIndex = 1; sectionIndex < subSectionList.Count; ++sectionIndex) { if (subSectionList[sectionIndex].Section == 0) { // Main section, the only one that doesn't need an external ref array continue; } var extRefInfoEntity = entityManager.CreateEntity(); entityManager.AddSharedComponentData(extRefInfoEntity, subSectionList[sectionIndex]); extRefInfoEntities[sectionIndex] = extRefInfoEntity; } // Public references array, only on the main section. var refInfoEntity = entityManager.CreateEntity(); entityManager.AddBuffer <PublicEntityRef>(refInfoEntity); entityManager.AddSharedComponentData(refInfoEntity, section); var publicRefs = entityManager.GetBuffer <PublicEntityRef>(refInfoEntity); // entityManager.Debug.CheckInternalConsistency(); //@TODO do we need to keep this index? doesn't carry any additional info for (int i = 0; i < entitiesInMainSection.Length; ++i) { PublicEntityRef.Add(ref publicRefs, new PublicEntityRef { entityIndex = i, targetEntity = entitiesInMainSection[i] }); } UnityEngine.Debug.Assert(publicRefs.Length == entitiesInMainSection.Length); // Save main section var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.EntityManager; var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); sectionManager.MoveEntitiesFrom(entityManager, sectionQuery, entityRemapping); AddRetainBlobAssetsEntity(sectionManager, framesToRetainBlobAssets); // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalQuery, typeof(SceneSection)); var sectionFileSize = WriteEntityScene(sectionManager, sceneGUID, "0", settings, out var objectRefCount, out var objRefs); sectionRefObjs?.Add(objRefs); sceneSections.Add(new SceneSectionData { FileSize = sectionFileSize, SceneGUID = sceneGUID, ObjectReferenceCount = objectRefCount, SubSectionIndex = 0, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } { // Index 0 is the default value of the shared component, not an actual section for (int subSectionIndex = 0; subSectionIndex < subSectionList.Count; ++subSectionIndex) { var subSection = subSectionList[subSectionIndex]; if (subSection.Section == 0) { continue; } sectionQuery.SetSharedComponentFilter(subSection); sectionBoundsQuery.SetSharedComponentFilter(subSection); var bounds = GetBoundsAndRemove(entityManager, sectionBoundsQuery); var entitiesInSection = sectionQuery.ToEntityArray(Allocator.TempJob); if (entitiesInSection.Length > 0) { // Fetch back the external reference entity we created earlier to not disturb the mapping var refInfoEntity = extRefInfoEntities[subSectionIndex]; entityManager.AddBuffer <ExternalEntityRef>(refInfoEntity); var externRefs = entityManager.GetBuffer <ExternalEntityRef>(refInfoEntity); // Store the mapping to everything in the main section //@TODO maybe we don't need all that? is this worth worrying about? for (int i = 0; i < entitiesInMainSection.Length; ++i) { ExternalEntityRef.Add(ref externRefs, new ExternalEntityRef { entityIndex = i }); } var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); // Entities will be remapped to a contiguous range in the section world, but they will // also come with an unpredictable amount of meta entities. We have the guarantee that // the entities in the main section won't be moved over, so there's a free range of that // size at the end of the remapping table. So we use that range for external references. var externEntityIndexStart = entityRemapping.Length - entitiesInMainSection.Length; entityManager.AddComponentData(refInfoEntity, new ExternalEntityRefInfo { SceneGUID = sceneGUID, EntityIndexStart = externEntityIndexStart }); var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.EntityManager; // Insert mapping for external references, conversion world entity to virtual index in section for (int i = 0; i < entitiesInMainSection.Length; ++i) { EntityRemapUtility.AddEntityRemapping(ref entityRemapping, entitiesInMainSection[i], new Entity { Index = i + externEntityIndexStart, Version = 1 }); } sectionManager.MoveEntitiesFrom(entityManager, sectionQuery, entityRemapping); AddRetainBlobAssetsEntity(sectionManager, framesToRetainBlobAssets); // Now that all the required entities have been moved over, we can get rid of the gap between // real entities and external references. This allows remapping during load to deal with a // smaller remap table, containing only useful entries. int highestEntityIndexInUse = 0; for (int i = 0; i < externEntityIndexStart; ++i) { var targetIndex = entityRemapping[i].Target.Index; if (targetIndex < externEntityIndexStart && targetIndex > highestEntityIndexInUse) { highestEntityIndexInUse = targetIndex; } } var oldExternEntityIndexStart = externEntityIndexStart; externEntityIndexStart = highestEntityIndexInUse + 1; sectionManager.SetComponentData ( EntityRemapUtility.RemapEntity(ref entityRemapping, refInfoEntity), new ExternalEntityRefInfo { SceneGUID = sceneGUID, EntityIndexStart = externEntityIndexStart } ); // When writing the scene, references to missing entities are set to Entity.Null by default // (but only if they have been used, otherwise they remain untouched) // We obviously don't want that to happen to our external references, so we add explicit mapping // And at the same time, we put them back at the end of the effective range of real entities. for (int i = 0; i < entitiesInMainSection.Length; ++i) { var src = new Entity { Index = i + oldExternEntityIndexStart, Version = 1 }; var dst = new Entity { Index = i + externEntityIndexStart, Version = 1 }; EntityRemapUtility.AddEntityRemapping(ref entityRemapping, src, dst); } // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalQuery, typeof(SceneSection)); var fileSize = WriteEntityScene(sectionManager, sceneGUID, subSection.Section.ToString(), settings, out var objectRefCount, out var objRefs, entityRemapping); sectionRefObjs?.Add(objRefs); sceneSections.Add(new SceneSectionData { FileSize = fileSize, SceneGUID = sceneGUID, ObjectReferenceCount = objectRefCount, SubSectionIndex = subSection.Section, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } entitiesInSection.Dispose(); } } { var noSectionQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { None = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); if (noSectionQuery.CalculateEntityCount() != 0) { Debug.LogWarning($"{noSectionQuery.CalculateEntityCount()} entities in the scene '{scene.path}' had no SceneSection and as a result were not serialized at all."); } } sectionQuery.Dispose(); sectionBoundsQuery.Dispose(); entitiesInMainSection.Dispose(); world.Dispose(); // Save the new header var sceneSectionsArray = sceneSections.ToArray(); WriteHeader(sceneGUID, sceneSectionsArray, scene.name, settings.AssetImportContext); // If we are writing assets to assets folder directly, then we need to make sure the asset database see them so they can be loaded. if (settings.AssetImportContext == null) { AssetDatabase.Refresh(); } if (disposeBlobAssetCache) { settings.BlobAssetStore.Dispose(); } // Save the log of issues that happened during conversion WriteConversionLog(sceneGUID, journalData, scene.name, settings.AssetImportContext); return(sceneSectionsArray); }
internal static SceneSectionData[] WriteEntitySceneInternal(EntityManager entityManager, Hash128 sceneGUID, string sceneName, AssetImportContext importContext, int framesToRetainBlobAssets, List <ReferencedUnityObjects> sectionRefObjs, WriteEntitySceneSettings writeEntitySceneSettings, ref ConversionJournalData journalData) { using (var allTypes = new NativeHashMap <ComponentType, int>(100, Allocator.Temp)) using (var archetypes = new NativeList <EntityArchetype>(Allocator.Temp)) { entityManager.GetAllArchetypes(archetypes); for (int i = 0; i < archetypes.Length; i++) { var archetype = archetypes[i]; unsafe { if (archetype.Archetype->EntityCount == 0) { continue; } } using (var componentTypes = archetype.GetComponentTypes()) foreach (var componentType in componentTypes) { if (allTypes.TryAdd(componentType, 0)) { if (importContext != null) { TypeDependencyCache.AddDependency(importContext, componentType); } } } } //Add exported types and assets to the journal data using (var types = allTypes.GetKeyArray(Allocator.Temp)) { CheckExportedTypes(writeEntitySceneSettings, true, types.Select(t => TypeManager.GetTypeInfo(t.TypeIndex)), ref journalData); } } if (importContext != null) { TypeDependencyCache.AddAllSystemsDependency(importContext); } var sceneSections = new List <SceneSectionData>(); var subSectionList = new List <SceneSection>(); entityManager.GetAllUniqueSharedComponentData(subSectionList); //Order sections by section id subSectionList.Sort(Comparer <SceneSection> .Create((a, b) => a.Section.CompareTo(b.Section))); var extRefInfoEntities = new NativeArray <Entity>(subSectionList.Count, Allocator.Temp); NativeArray <Entity> entitiesInMainSection; var sectionQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); var sectionBoundsQuery = entityManager.CreateEntityQuery( new EntityQueryDesc { All = new[] { ComponentType.ReadWrite <SceneBoundingVolume>(), ComponentType.ReadWrite <SceneSection>() }, Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled } ); { var section = new SceneSection { SceneGUID = sceneGUID, Section = 0 }; sectionQuery.SetSharedComponentFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); sectionBoundsQuery.SetSharedComponentFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); entitiesInMainSection = sectionQuery.ToEntityArray(Allocator.TempJob); var bounds = GetBoundsAndRemove(entityManager, sectionBoundsQuery); // Each section will be serialized in its own world, entities that don't have a section are part of the main scene. // An entity that holds the array of external references to the main scene is required for each section. // We need to create them all before we start moving entities to section scenes, // otherwise they would reuse entities that have been moved and mess up the remapping tables. for (int sectionIndex = 1; sectionIndex < subSectionList.Count; ++sectionIndex) { if (subSectionList[sectionIndex].Section == 0) { // Main section, the only one that doesn't need an external ref array continue; } var extRefInfoEntity = entityManager.CreateEntity(); entityManager.AddSharedComponentData(extRefInfoEntity, subSectionList[sectionIndex]); extRefInfoEntities[sectionIndex] = extRefInfoEntity; } // Public references array, only on the main section. var refInfoEntity = entityManager.CreateEntity(); entityManager.AddBuffer <PublicEntityRef>(refInfoEntity); entityManager.AddSharedComponentData(refInfoEntity, section); var publicRefs = entityManager.GetBuffer <PublicEntityRef>(refInfoEntity); // entityManager.Debug.CheckInternalConsistency(); //@TODO do we need to keep this index? doesn't carry any additional info for (int i = 0; i < entitiesInMainSection.Length; ++i) { PublicEntityRef.Add(ref publicRefs, new PublicEntityRef { entityIndex = i, targetEntity = entitiesInMainSection[i] }); } UnityEngine.Debug.Assert(publicRefs.Length == entitiesInMainSection.Length); // Save main section var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.EntityManager; var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); sectionManager.MoveEntitiesFrom(entityManager, sectionQuery, entityRemapping); AddRetainBlobAssetsEntity(sectionManager, framesToRetainBlobAssets); // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalQuery, typeof(SceneSection)); var(decompressedSectionFileSize, compressedSectionFileSize) = WriteEntitySceneSection(sectionManager, sceneGUID, "0", importContext, writeEntitySceneSettings, out var objectRefCount, out var objRefs, default);
public static SceneData[] WriteEntityScene(Scene scene, Hash128 sceneGUID, ConversionFlags conversionFlags) { var world = new World("ConversionWorld"); var entityManager = world.GetOrCreateManager <EntityManager>(); var boundsEntity = entityManager.CreateEntity(typeof(SceneBoundingVolume)); entityManager.SetComponentData(boundsEntity, new SceneBoundingVolume { Value = MinMaxAABB.Empty }); ConvertScene(scene, sceneGUID, world, conversionFlags); EntitySceneOptimization.Optimize(world); var bounds = entityManager.GetComponentData <SceneBoundingVolume>(boundsEntity).Value; entityManager.DestroyEntity(boundsEntity); var sceneSections = new List <SceneData>(); var subSectionList = new List <SceneSection>(); entityManager.GetAllUniqueSharedComponentData(subSectionList); var extRefInfoEntities = new NativeArray <Entity>(subSectionList.Count, Allocator.Temp); NativeArray <Entity> entitiesInMainSection; var sectionGrp = entityManager.CreateComponentGroup( new EntityArchetypeQuery { All = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityArchetypeQueryOptions.IncludePrefab | EntityArchetypeQueryOptions.IncludeDisabled } ); { var section = new SceneSection { SceneGUID = sceneGUID, Section = 0 }; sectionGrp.SetFilter(new SceneSection { SceneGUID = sceneGUID, Section = 0 }); entitiesInMainSection = sectionGrp.ToEntityArray(Allocator.TempJob); // Each section will be serialized in its own world, entities that don't have a section are part of the main scene. // An entity that holds the array of external references to the main scene is required for each section. // We need to create them all before we start moving entities to section scenes, // otherwise they would reuse entities that have been moved and mess up the remapping tables. for (int sectionIndex = 1; sectionIndex < subSectionList.Count; ++sectionIndex) { var extRefInfoEntity = entityManager.CreateEntity(); entityManager.AddSharedComponentData(extRefInfoEntity, subSectionList[sectionIndex]); extRefInfoEntities[sectionIndex] = extRefInfoEntity; } // Public references array, only on the main section. var refInfoEntity = entityManager.CreateEntity(); entityManager.AddBuffer <PublicEntityRef>(refInfoEntity); entityManager.AddSharedComponentData(refInfoEntity, section); var publicRefs = entityManager.GetBuffer <PublicEntityRef>(refInfoEntity); // entityManager.Debug.CheckInternalConsistency(); //@TODO do we need to keep this index? doesn't carry any additional info for (int i = 0; i < entitiesInMainSection.Length; ++i) { PublicEntityRef.Add(ref publicRefs, new PublicEntityRef { entityIndex = i, targetEntity = entitiesInMainSection[i] }); } Debug.Assert(publicRefs.Length == entitiesInMainSection.Length); // Save main section var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.GetOrCreateManager <EntityManager>(); var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); sectionManager.MoveEntitiesFrom(entityManager, sectionGrp, entityRemapping); // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalGroup, typeof(SceneSection)); var sectionFileSize = WriteEntityScene(sectionManager, sceneGUID, "0"); sceneSections.Add(new SceneData { FileSize = sectionFileSize, SceneGUID = sceneGUID, SharedComponentCount = sectionManager.GetSharedComponentCount() - 1, SubSectionIndex = 0, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } { // Index 0 is the default value of the shared component, not an actual section for (int subSectionIndex = 0; subSectionIndex < subSectionList.Count; ++subSectionIndex) { var subSection = subSectionList[subSectionIndex]; if (subSection.Section == 0) { continue; } sectionGrp.SetFilter(subSection); var entitiesInSection = sectionGrp.ToEntityArray(Allocator.TempJob); if (entitiesInSection.Length > 0) { // Fetch back the external reference entity we created earlier to not disturb the mapping var refInfoEntity = extRefInfoEntities[subSectionIndex]; entityManager.AddBuffer <ExternalEntityRef>(refInfoEntity); var externRefs = entityManager.GetBuffer <ExternalEntityRef>(refInfoEntity); // Store the mapping to everything in the main section //@TODO maybe we don't need all that? is this worth worrying about? for (int i = 0; i < entitiesInMainSection.Length; ++i) { ExternalEntityRef.Add(ref externRefs, new ExternalEntityRef { entityIndex = i }); } // Entities will be remapped to a contiguous range in the section world, // so any range after that is fine for the external references //@TODO why are we not mapping anything to entity 0? we use the range [1;count], hence +1 var externEntityIndexStart = entitiesInSection.Length + 1; entityManager.AddComponentData(refInfoEntity, new ExternalEntityRefInfo { SceneGUID = sceneGUID, EntityIndexStart = externEntityIndexStart }); var sectionWorld = new World("SectionWorld"); var sectionManager = sectionWorld.GetOrCreateManager <EntityManager>(); var entityRemapping = entityManager.CreateEntityRemapArray(Allocator.TempJob); // Insert mapping for external references, conversion world entity to virtual index in section for (int i = 0; i < entitiesInMainSection.Length; ++i) { EntityRemapUtility.AddEntityRemapping(ref entityRemapping, entitiesInMainSection[i], new Entity { Index = i + externEntityIndexStart, Version = 1 }); } sectionManager.MoveEntitiesFrom(entityManager, sectionGrp, entityRemapping); // When writing the scene, references to missing entities are set to Entity.Null by default // We obviously don't want that to happen to our external references, so we add explicit mapping for (int i = 0; i < entitiesInMainSection.Length; ++i) { var entity = new Entity { Index = i + externEntityIndexStart, Version = 1 }; EntityRemapUtility.AddEntityRemapping(ref entityRemapping, entity, entity); } // The section component is only there to break the conversion world into different sections // We don't want to store that on the disk //@TODO: Component should be removed but currently leads to corrupt data file. Figure out why. //sectionManager.RemoveComponent(sectionManager.UniversalGroup, typeof(SceneSection)); var fileSize = WriteEntityScene(sectionManager, sceneGUID, subSection.Section.ToString(), entityRemapping); sceneSections.Add(new SceneData { FileSize = fileSize, SceneGUID = sceneGUID, SharedComponentCount = sectionManager.GetSharedComponentCount() - 1, SubSectionIndex = subSection.Section, BoundingVolume = bounds }); entityRemapping.Dispose(); sectionWorld.Dispose(); } entitiesInSection.Dispose(); } } { var noSectionGrp = entityManager.CreateComponentGroup( new EntityArchetypeQuery { None = new[] { ComponentType.ReadWrite <SceneSection>() }, Options = EntityArchetypeQueryOptions.IncludePrefab | EntityArchetypeQueryOptions.IncludeDisabled } ); if (noSectionGrp.CalculateLength() != 0) { Debug.LogWarning($"{noSectionGrp.CalculateLength()} entities in the scene '{scene.path}' had no SceneSection and as a result were not serialized at all."); } } sectionGrp.Dispose(); entitiesInMainSection.Dispose(); world.Dispose(); // Save the new header var header = ScriptableObject.CreateInstance <SubSceneHeader>(); header.Sections = sceneSections.ToArray(); WriteHeader(sceneGUID, header); return(sceneSections.ToArray()); }
private unsafe void InitSceneSection(SceneSection sceneSection) { Hash128 containerIdentifier = sceneSection.SceneGUID; PersistencyContainerTag containerTag = new PersistencyContainerTag() { DataIdentifier = containerIdentifier }; if (PersistentDataStorage.IsInitialized(containerIdentifier)) { PersistentDataContainer latestState = PersistentDataStorage.GetReadContainerForLatestWriteIndex(containerIdentifier, out bool isInitial); _beginFrameSystem.RequestApply(latestState); } else { _scenePersistencyInfoQuery.SetSharedComponentFilter(containerTag); if (_scenePersistencyInfoQuery.CalculateEntityCount() != 1) { return; } var scenePersistencyInfoRef = _scenePersistencyInfoQuery.GetSingleton <ScenePersistencyInfoRef>(); ref ScenePersistencyInfo sceneInfo = ref scenePersistencyInfoRef.InfoRef.Value; int offset = 0; var dataLayouts = new NativeArray <PersistencyArchetypeDataLayout>(sceneInfo.PersistencyArchetypes.Length, Allocator.Persistent); for (var i = 0; i < sceneInfo.PersistencyArchetypes.Length; i++) { ref PersistencyArchetype persistencyArchetype = ref sceneInfo.PersistencyArchetypes[i]; var hashFilter = new PersistableTypeCombinationHash { Value = persistencyArchetype.PersistableTypeHandleCombinationHash }; var dataLayout = new PersistencyArchetypeDataLayout() { Amount = persistencyArchetype.AmountEntities, ArchetypeIndexInContainer = (ushort)i, PersistedTypeInfoArrayRef = persistencyArchetype.BuildTypeInfoBlobAsset(PersistencySettings, persistencyArchetype.AmountEntities, out int sizePerEntity), SizePerEntity = sizePerEntity, Offset = offset, PersistableTypeHandleCombinationHash = hashFilter.Value }; offset += persistencyArchetype.AmountEntities * sizePerEntity; dataLayouts[i] = dataLayout; } // BlobData is disposed if the owning entity is destroyed, we need this data even if the scene is unloaded NativeArray <PersistableTypeHandle> allUniqueTypeHandles = new NativeArray <PersistableTypeHandle>(sceneInfo.AllUniqueTypeHandles.Length, Allocator.Persistent); UnsafeUtility.MemCpy(allUniqueTypeHandles.GetUnsafePtr(), sceneInfo.AllUniqueTypeHandles.GetUnsafePtr(), allUniqueTypeHandles.Length * sizeof(PersistableTypeHandle)); // this function takes ownership over the dataLayouts array & allUniqueTypeHandles array PersistentDataStorage.InitializeSceneContainer(containerIdentifier, dataLayouts, allUniqueTypeHandles, out PersistentDataContainer initialStateContainer, out PersistentDataContainer containerToApply); _beginFrameSystem.RequestInitialStatePersist(initialStateContainer); if (containerToApply.IsCreated) { // containerToApply only exists if it was already added as uninitialized raw data beforehand (e.g. read from disk) _beginFrameSystem.RequestApply(containerToApply); } }