diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ad8f06..ab13c05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ Versioning](http://semver.org/spec/v2.0.0.html). You can find changelogs for the individual modules inside the Documentation\~ directory. +## [0.7.3] – 2023-6-10 + +Officially supports Entities [1.0.10] + +### Changed + +- Updated Core to v0.7.3 +- Updated Psyshock to v0.7.3 + ## [0.7.2] – 2023-6-4 Officially supports Entities [1.0.10] diff --git a/Core/Authoring/SmartBaker.cs b/Core/Authoring/SmartBaker.cs index 047c20e..273f3fc 100644 --- a/Core/Authoring/SmartBaker.cs +++ b/Core/Authoring/SmartBaker.cs @@ -75,8 +75,9 @@ public sealed override void Bake(TAuthoring authoring) } } - void ICreateSmartBakerSystem.Create(World world, ComponentSystemGroup addToThis) + unsafe void ICreateSmartBakerSystem.Create(World world, ComponentSystemGroup addToThis) { + TypeManager.GetSystemTypeIndex(typeof(SmartBakerSystem)); var system = world.GetOrCreateSystemManaged >(); system.runInBurst = RunPostProcessInBurst(); addToThis.AddSystemToUpdateList(system); diff --git a/Core/Authoring/SmartBlobberAPI.cs b/Core/Authoring/SmartBlobberAPI.cs index 1004333..191fbe0 100644 --- a/Core/Authoring/SmartBlobberAPI.cs +++ b/Core/Authoring/SmartBlobberAPI.cs @@ -257,6 +257,7 @@ public void Register(World managedWorld) { if (managedWorld.GetExistingSystemManaged >() != null) return; + TypeManager.GetSystemTypeIndex(typeof(Systems.SmartBlobberTypedPostProcessBakingSystem)); var system = managedWorld.GetOrCreateSystemManaged >(); var group = managedWorld.GetExistingSystemManaged(); group.AddSystemToUpdateListSafe(system.SystemHandle); diff --git a/Core/Containers/DestroyCommandBuffer.cs b/Core/Containers/DestroyCommandBuffer.cs index d2a7fda..e6c81c5 100644 --- a/Core/Containers/DestroyCommandBuffer.cs +++ b/Core/Containers/DestroyCommandBuffer.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Jobs; @@ -70,19 +71,7 @@ public void Add(Entity entity, int sortKey = int.MaxValue) public void Playback(EntityManager entityManager) { CheckDidNotPlayback(); - bool ran = false; - NativeList entities = default; - RunPrepInJob(ref ran, ref entities); - if (ran) - { - entityManager.DestroyEntity(entities.AsArray()); - entities.Dispose(); - } - else - { - entityManager.DestroyEntity(m_entityOperationCommandBuffer.GetEntities(Allocator.Temp)); - } - m_playedBack.Value = true; + Playbacker.Playback((DestroyCommandBuffer*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager)); } /// @@ -112,23 +101,14 @@ void CheckDidNotPlayback() } #region PlaybackJobs - [BurstDiscard] - private unsafe void RunPrepInJob(ref bool ran, ref NativeList entities) - { - ran = true; - entities = new NativeList(0, Allocator.TempJob); - new PrepJob { eocb = m_entityOperationCommandBuffer, entities = entities }.Run(); - } - [BurstCompile] - private struct PrepJob : IJob + static class Playbacker { - [ReadOnly] public EntityOperationCommandBuffer eocb; - public NativeList entities; - - public void Execute() + [BurstCompile] + public static unsafe void Playback(DestroyCommandBuffer* dcb, EntityManager* em) { - eocb.GetEntities(ref entities); + em->DestroyEntity(dcb->m_entityOperationCommandBuffer.GetEntities(Allocator.Temp)); + dcb->m_playedBack.Value = true; } } #endregion diff --git a/Core/Containers/DisableCommandBuffer.cs b/Core/Containers/DisableCommandBuffer.cs index c9999f7..ccde09b 100644 --- a/Core/Containers/DisableCommandBuffer.cs +++ b/Core/Containers/DisableCommandBuffer.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Jobs; @@ -10,6 +11,7 @@ namespace Latios /// A specialized variant of the EntityCommandBuffer exclusively for disabling entities. /// Disabled entities automatically account for LinkedEntityGroup at the time of playback. /// + [BurstCompile] public unsafe struct DisableCommandBuffer : INativeDisposable { #region Structure @@ -67,22 +69,11 @@ public void Add(Entity entity, int sortKey = int.MaxValue) /// /// The EntityManager with which to play back the DisableCommandBuffer /// A ReadOnly accessor to the entities' LinkedEntityGroup - public void Playback(EntityManager entityManager, BufferLookup linkedFEReadOnly) + public unsafe void Playback(EntityManager entityManager, BufferLookup linkedFEReadOnly) { CheckDidNotPlayback(); - bool ran = false; - NativeList entities = default; - RunPrepInJob(linkedFEReadOnly, ref ran, ref entities); - if (ran) - { - entityManager.RemoveComponent(entities.AsArray()); - entities.Dispose(); - } - else - { - entityManager.RemoveComponent(m_entityOperationCommandBuffer.GetLinkedEntities(linkedFEReadOnly, Allocator.Temp)); - } - m_playedBack.Value = true; + Playbacker.Playback((DisableCommandBuffer*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager), + (BufferLookup*)UnsafeUtility.AddressOf(ref linkedFEReadOnly)); } /// @@ -112,24 +103,14 @@ void CheckDidNotPlayback() } #region PlaybackJobs - [BurstDiscard] - private void RunPrepInJob(BufferLookup linkedFE, ref bool ran, ref NativeList entities) - { - ran = true; - entities = new NativeList(0, Allocator.TempJob); - new PrepJob { linkedFE = linkedFE, eocb = m_entityOperationCommandBuffer, entities = entities }.Run(); - } - [BurstCompile] - private struct PrepJob : IJob + static class Playbacker { - [ReadOnly] public BufferLookup linkedFE; - [ReadOnly] public EntityOperationCommandBuffer eocb; - public NativeList entities; - - public void Execute() + [BurstCompile] + public static unsafe void Playback(DisableCommandBuffer* dcb, EntityManager* em, BufferLookup* lookup) { - eocb.GetLinkedEntities(linkedFE, ref entities); + em->AddComponent(dcb->m_entityOperationCommandBuffer.GetLinkedEntities(*lookup, Allocator.Temp)); + dcb->m_playedBack.Value = true; } } #endregion diff --git a/Core/Containers/EnableCommandBuffer.cs b/Core/Containers/EnableCommandBuffer.cs index a0ad5a2..a7e8062 100644 --- a/Core/Containers/EnableCommandBuffer.cs +++ b/Core/Containers/EnableCommandBuffer.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Jobs; @@ -10,6 +11,7 @@ namespace Latios /// A specialized variant of the EntityCommandBuffer exclusively for enabling entities. /// Enabled entities automatically account for LinkedEntityGroup at the time of playback. /// + [BurstCompile] public unsafe struct EnableCommandBuffer : INativeDisposable { #region Structure @@ -67,22 +69,11 @@ public void Add(Entity entity, int sortKey = int.MaxValue) /// /// The EntityManager with which to play back the EnableCommandBuffer /// A ReadOnly accessor to the entities' LinkedEntityGroup - public void Playback(EntityManager entityManager, BufferLookup linkedFEReadOnly) + public unsafe void Playback(EntityManager entityManager, BufferLookup linkedFEReadOnly) { CheckDidNotPlayback(); - bool ran = false; - NativeList entities = default; - RunPrepInJob(linkedFEReadOnly, ref ran, ref entities); - if (ran) - { - entityManager.RemoveComponent(entities.AsArray()); - entities.Dispose(); - } - else - { - entityManager.RemoveComponent(m_entityOperationCommandBuffer.GetLinkedEntities(linkedFEReadOnly, Allocator.Temp)); - } - m_playedBack.Value = true; + Playbacker.Playback((EnableCommandBuffer*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager), + (BufferLookup*)UnsafeUtility.AddressOf(ref linkedFEReadOnly)); } /// @@ -112,25 +103,14 @@ void CheckDidNotPlayback() } #region PlaybackJobs - [BurstDiscard] - private void RunPrepInJob(BufferLookup linkedFE, ref bool ran, ref NativeList entities) - { - ran = true; - entities = new NativeList(0, Allocator.TempJob); - new PrepJob { linkedFE = linkedFE, eocb = m_entityOperationCommandBuffer, entities = entities }.Run(); - entities.Dispose(); - } - [BurstCompile] - private struct PrepJob : IJob + static class Playbacker { - [ReadOnly] public BufferLookup linkedFE; - [ReadOnly] public EntityOperationCommandBuffer eocb; - public NativeList entities; - - public void Execute() + [BurstCompile] + public static unsafe void Playback(EnableCommandBuffer* ecb, EntityManager* em, BufferLookup* lookup) { - eocb.GetLinkedEntities(linkedFE, ref entities); + em->RemoveComponent(ecb->m_entityOperationCommandBuffer.GetLinkedEntities(*lookup, Allocator.Temp)); + ecb->m_playedBack.Value = true; } } #endregion diff --git a/Core/Containers/InstantiateCommandBuffer.cs b/Core/Containers/InstantiateCommandBuffer.cs index 49c3369..5c4b9b6 100644 --- a/Core/Containers/InstantiateCommandBuffer.cs +++ b/Core/Containers/InstantiateCommandBuffer.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using Unity.Burst; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Jobs; @@ -10,6 +11,7 @@ namespace Latios /// A specialized variant of the EntityCommandBuffer exclusively for instantiating entities. /// This variant does not perform any additional initialization after instantiation. /// + [BurstCompile] public struct InstantiateCommandBuffer : INativeDisposable { #region Structure @@ -66,13 +68,10 @@ public void Add(Entity entity, int sortKey = int.MaxValue) /// Plays back the InstantiateCommandBuffer. /// /// The EntityManager with which to play back the InstantiateCommandBuffer - public void Playback(EntityManager entityManager) + public unsafe void Playback(EntityManager entityManager) { CheckDidNotPlayback(); - var eet = entityManager.BeginExclusiveEntityTransaction(); - new PlaybackJob { eocb = m_entityOperationCommandBuffer, eet = eet }.Run(); - eet.EntityManager.EndExclusiveEntityTransaction(); - m_playedBack.Value = true; + Playbacker.Playback((InstantiateCommandBuffer*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager)); } /// @@ -103,14 +102,12 @@ void CheckDidNotPlayback() #region PlaybackJobs [BurstCompile] - private struct PlaybackJob : IJob + static class Playbacker { - [ReadOnly] public EntityOperationCommandBuffer eocb; - public ExclusiveEntityTransaction eet; - - public void Execute() + [BurstCompile] + public static unsafe void Playback(InstantiateCommandBuffer* icb, EntityManager* em) { - var prefabs = eocb.GetEntitiesSortedByEntity(Allocator.Temp); + var prefabs = icb->m_entityOperationCommandBuffer.GetEntitiesSortedByEntity(Allocator.Temp); int i = 0; while (i < prefabs.Length) { @@ -122,23 +119,9 @@ public void Execute() i++; count++; } - eet.EntityManager.Instantiate(prefab, count, Allocator.Temp); + em->Instantiate(prefab, count, Allocator.Temp); } - } - - public void RunOrExecute() - { - bool ran = false; - TryRun(ref ran); - if (!ran) - Execute(); - } - - [BurstDiscard] - void TryRun(ref bool ran) - { - this.Run(); - ran = true; + icb->m_playedBack.Value = true; } } #endregion diff --git a/Core/Framework/BlackboardEntity.cs b/Core/Framework/BlackboardEntity.cs index e06edb0..f9a2d6b 100644 --- a/Core/Framework/BlackboardEntity.cs +++ b/Core/Framework/BlackboardEntity.cs @@ -1,5 +1,4 @@ -using Unity.Burst; -using Unity.Entities; +using Unity.Entities; using Unity.Jobs; namespace Latios diff --git a/Core/Internal/InstantiateCommandBufferUntyped.cs b/Core/Internal/InstantiateCommandBufferUntyped.cs index fb0d913..af106ea 100644 --- a/Core/Internal/InstantiateCommandBufferUntyped.cs +++ b/Core/Internal/InstantiateCommandBufferUntyped.cs @@ -12,6 +12,7 @@ namespace Latios { [NativeContainer] + [BurstCompile] internal unsafe struct InstantiateCommandBufferUntyped : INativeDisposable { #region Structure @@ -240,60 +241,7 @@ public void Playback(EntityManager entityManager) { CheckWriteAccess(); CheckHasNotPlayedBack(); - var chunkRanges = new NativeList(Allocator.TempJob); - var chunks = new NativeList(Allocator.TempJob); - var indicesInChunks = new NativeList(Allocator.TempJob); - var componentDataPtrs = new NativeList(Allocator.TempJob); - entityManager.CompleteAllTrackedJobs(); - //var eet = entityManager.BeginExclusiveEntityTransaction(); - //Run job that instantiates entities and populates hashmap - var job0 = new InstantiateAndBuildListsJob - { - icb = this, - //eet = eet, - em = entityManager, - chunks = chunks, - chunkRanges = chunkRanges, - indicesInChunks = indicesInChunks, - componentDataPtrs = componentDataPtrs - }; - job0.RunOrExecute(); - //entityManager.EndExclusiveEntityTransaction(); - //Schedule parallel job to populate data - var chunkJob = new WriteComponentDataJob - { - icb = this, - chunks = chunks.AsArray(), - chunkRanges = chunkRanges.AsArray(), - indicesInChunks = indicesInChunks.AsArray(), - componentDataPtrs = componentDataPtrs.AsArray(), - entityHandle = entityManager.GetEntityTypeHandle(), - t0 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite(m_state->typesWithData[0])) - }; - if (m_state->typesWithData.Length > 1) - chunkJob.t1 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite(m_state->typesWithData[1])); - if (m_state->typesWithData.Length > 2) - chunkJob.t2 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite(m_state->typesWithData[2])); - if (m_state->typesWithData.Length > 3) - chunkJob.t3 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite(m_state->typesWithData[3])); - if (m_state->typesWithData.Length > 4) - chunkJob.t4 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite(m_state->typesWithData[4])); - //The remaining types apparently need to be initialized. So set them to the dummy types. - if (m_state->typesWithData.Length <= 1) - chunkJob.t1 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite()); - if (m_state->typesWithData.Length <= 2) - chunkJob.t2 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite()); - if (m_state->typesWithData.Length <= 3) - chunkJob.t3 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite()); - if (m_state->typesWithData.Length <= 4) - chunkJob.t4 = entityManager.GetDynamicComponentTypeHandle(ComponentType.ReadWrite()); - //chunkJob.ScheduleParallel(chunks.Length, 1, default).Complete(); - chunkJob.RunOrExecute(chunks.Length); - m_state->playedBack = true; - chunks.Dispose(); - chunkRanges.Dispose(); - indicesInChunks.Dispose(); - componentDataPtrs.Dispose(); + Playbacker.Playback((InstantiateCommandBufferUntyped*)UnsafeUtility.AddressOf(ref this), (EntityManager*)UnsafeUtility.AddressOf(ref entityManager)); } public void SetTags(ComponentTypeSet types) @@ -346,313 +294,318 @@ public ParallelWriter AsParallelWriter() #region Implementation [BurstCompile] - private struct InstantiateAndBuildListsJob : IJob + static class Playbacker { - [ReadOnly] public InstantiateCommandBufferUntyped icb; - //public ExclusiveEntityTransaction eet; - public EntityManager em; + [BurstCompile] + public static void Playback(InstantiateCommandBufferUntyped* icb, EntityManager* em) + { + var chunkRanges = new NativeList(Allocator.Temp); + var chunks = new NativeList(Allocator.Temp); + var indicesInChunks = new NativeList(Allocator.Temp); + var componentDataPtrs = new NativeList(Allocator.Temp); + em->CompleteAllTrackedJobs(); - public NativeList chunks; - public NativeList chunkRanges; - public NativeList indicesInChunks; - public NativeList componentDataPtrs; + var job0 = new InstantiateAndBuildListsJob + { + icb = *icb, + em = *em, + chunks = chunks, + chunkRanges = chunkRanges, + indicesInChunks = indicesInChunks, + componentDataPtrs = componentDataPtrs + }; + job0.Execute(); + + var chunkJob = new WriteComponentDataJob + { + icb = *icb, + chunks = chunks.AsArray(), + chunkRanges = chunkRanges.AsArray(), + indicesInChunks = indicesInChunks.AsArray(), + componentDataPtrs = componentDataPtrs.AsArray(), + entityHandle = em->GetEntityTypeHandle(), + t0 = em->GetDynamicComponentTypeHandle(ComponentType.ReadWrite(icb->m_state->typesWithData[0])) + }; + if (icb->m_state->typesWithData.Length > 1) + chunkJob.t1 = em->GetDynamicComponentTypeHandle(ComponentType.ReadWrite(icb->m_state->typesWithData[1])); + if (icb->m_state->typesWithData.Length > 2) + chunkJob.t2 = em->GetDynamicComponentTypeHandle(ComponentType.ReadWrite(icb->m_state->typesWithData[2])); + if (icb->m_state->typesWithData.Length > 3) + chunkJob.t3 = em->GetDynamicComponentTypeHandle(ComponentType.ReadWrite(icb->m_state->typesWithData[3])); + if (icb->m_state->typesWithData.Length > 4) + chunkJob.t4 = em->GetDynamicComponentTypeHandle(ComponentType.ReadWrite(icb->m_state->typesWithData[4])); + //chunkJob.ScheduleParallel(chunks.Length, 1, default).Complete(); + for (int i = 0; i < chunks.Length; i++) + chunkJob.Execute(i); + icb->m_state->playedBack = true; + } - public void Execute() + private struct InstantiateAndBuildListsJob { - //Step 1: Get the prefabs and sort keys - int count = icb.Count(); - var prefabSortkeyArray = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); - icb.m_prefabSortkeyBlockList->GetElementValues(prefabSortkeyArray); - //Step 2: Get the componentData pointers - var unsortedComponentDataPtrs = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); - icb.m_componentDataBlockList->GetElementPtrs(unsortedComponentDataPtrs); - //Step 3: Sort the arrays by sort key and collapse unique entities - var ranks = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); - RadixSort.RankSortInt3(ranks, prefabSortkeyArray); - var sortedPrefabs = new NativeList(count, Allocator.Temp); - var sortedPrefabCounts = new NativeList(count, Allocator.Temp); - var sortedComponentDataPtrs = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); - Entity lastEntity = Entity.Null; - for (int i = 0; i < count; i++) + [ReadOnly] public InstantiateCommandBufferUntyped icb; + public EntityManager em; + + public NativeList chunks; + public NativeList chunkRanges; + public NativeList indicesInChunks; + public NativeList componentDataPtrs; + + public void Execute() { - var entity = prefabSortkeyArray[ranks[i]].prefab; - sortedComponentDataPtrs[i] = unsortedComponentDataPtrs[ranks[i]]; - if (entity != lastEntity) - { - sortedPrefabs.AddNoResize(entity); - sortedPrefabCounts.AddNoResize(1); - lastEntity = entity; - } - else + //Step 1: Get the prefabs and sort keys + int count = icb.Count(); + var prefabSortkeyArray = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + icb.m_prefabSortkeyBlockList->GetElementValues(prefabSortkeyArray); + //Step 2: Get the componentData pointers + var unsortedComponentDataPtrs = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + icb.m_componentDataBlockList->GetElementPtrs(unsortedComponentDataPtrs); + //Step 3: Sort the arrays by sort key and collapse unique entities + var ranks = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + RadixSort.RankSortInt3(ranks, prefabSortkeyArray); + var sortedPrefabs = new NativeList(count, Allocator.Temp); + var sortedPrefabCounts = new NativeList(count, Allocator.Temp); + var sortedComponentDataPtrs = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + Entity lastEntity = Entity.Null; + for (int i = 0; i < count; i++) { - ref var c = ref sortedPrefabCounts.ElementAt(sortedPrefabCounts.Length - 1); - c++; + var entity = prefabSortkeyArray[ranks[i]].prefab; + sortedComponentDataPtrs[i] = unsortedComponentDataPtrs[ranks[i]]; + if (entity != lastEntity) + { + sortedPrefabs.AddNoResize(entity); + sortedPrefabCounts.AddNoResize(1); + lastEntity = entity; + } + else + { + ref var c = ref sortedPrefabCounts.ElementAt(sortedPrefabCounts.Length - 1); + c++; + } } - } - //Step 4: Instantiate the prefabs - var instantiatedEntities = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); - var typesWithDataToAdd = BuildComponentTypesFromFixedList(icb.m_state->typesWithData); - int startIndex = 0; - for (int i = 0; i < sortedPrefabs.Length; i++) - { - //var firstEntity = eet.Instantiate(sortedPrefabs[i]); - //eet.EntityManager.AddComponents(firstEntity, typesWithDataToAdd); - //eet.EntityManager.AddComponents(firstEntity, icb.m_state->tagsToAdd); - var firstEntity = em.Instantiate(sortedPrefabs[i]); - em.AddComponent(firstEntity, typesWithDataToAdd); - em.AddComponent(firstEntity, icb.m_state->tagsToAdd); - instantiatedEntities[startIndex] = firstEntity; - startIndex++; - - if (sortedPrefabCounts[i] - 1 > 0) + //Step 4: Instantiate the prefabs + var instantiatedEntities = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); + var typesWithDataToAdd = BuildComponentTypesFromFixedList(icb.m_state->typesWithData); + int startIndex = 0; + for (int i = 0; i < sortedPrefabs.Length; i++) { - var subArray = instantiatedEntities.GetSubArray(startIndex, sortedPrefabCounts[i] - 1); - //eet.Instantiate(firstEntity, subArray); - em.Instantiate(firstEntity, subArray); - startIndex += subArray.Length; + //var firstEntity = eet.Instantiate(sortedPrefabs[i]); + //eet.EntityManager.AddComponents(firstEntity, typesWithDataToAdd); + //eet.EntityManager.AddComponents(firstEntity, icb.m_state->tagsToAdd); + var firstEntity = em.Instantiate(sortedPrefabs[i]); + em.AddComponent(firstEntity, typesWithDataToAdd); + em.AddComponent(firstEntity, icb.m_state->tagsToAdd); + instantiatedEntities[startIndex] = firstEntity; + startIndex++; + + if (sortedPrefabCounts[i] - 1 > 0) + { + var subArray = instantiatedEntities.GetSubArray(startIndex, sortedPrefabCounts[i] - 1); + //eet.Instantiate(firstEntity, subArray); + em.Instantiate(firstEntity, subArray); + startIndex += subArray.Length; + } } - } - //Step 5: Get locations of new entities - var locations = new NativeArray(count, Allocator.Temp); - for (int i = 0; i < count; i++) - { - //locations[i] = eet.EntityManager.GetEntityLocationInChunk(instantiatedEntities[i]); - locations[i] = em.GetStorageInfo(instantiatedEntities[i]); - } - //Step 6: Sort chunks and build final lists - RadixSort.RankSortInt3(ranks, locations.Reinterpret()); - chunks.Capacity = count; - chunkRanges.Capacity = count; - indicesInChunks.ResizeUninitialized(count); - componentDataPtrs.ResizeUninitialized(count); - ArchetypeChunk lastChunk = default; - for (int i = 0; i < count; i++) - { - var loc = locations[ranks[i]]; - indicesInChunks[i] = loc.IndexInChunk; - componentDataPtrs[i] = sortedComponentDataPtrs[ranks[i]]; - if (loc.Chunk != lastChunk) + //Step 5: Get locations of new entities + var locations = new NativeArray(count, Allocator.Temp); + for (int i = 0; i < count; i++) { - chunks.AddNoResize(loc.Chunk); - chunkRanges.AddNoResize(new int2(i, 1)); - lastChunk = loc.Chunk; + //locations[i] = eet.EntityManager.GetEntityLocationInChunk(instantiatedEntities[i]); + locations[i] = em.GetStorageInfo(instantiatedEntities[i]); } - else + //Step 6: Sort chunks and build final lists + RadixSort.RankSortInt3(ranks, locations.Reinterpret()); + chunks.Capacity = count; + chunkRanges.Capacity = count; + indicesInChunks.ResizeUninitialized(count); + componentDataPtrs.ResizeUninitialized(count); + ArchetypeChunk lastChunk = default; + for (int i = 0; i < count; i++) { - ref var c = ref chunkRanges.ElementAt(chunkRanges.Length - 1); - c.y++; + var loc = locations[ranks[i]]; + indicesInChunks[i] = loc.IndexInChunk; + componentDataPtrs[i] = sortedComponentDataPtrs[ranks[i]]; + if (loc.Chunk != lastChunk) + { + chunks.AddNoResize(loc.Chunk); + chunkRanges.AddNoResize(new int2(i, 1)); + lastChunk = loc.Chunk; + } + else + { + ref var c = ref chunkRanges.ElementAt(chunkRanges.Length - 1); + c.y++; + } } } - } - struct WrappedEntityLocationInChunk : IRadixSortableInt3 - { - public EntityStorageInfo elic; - - public int3 GetKey3() + struct WrappedEntityLocationInChunk : IRadixSortableInt3 { - var c = elic.Chunk.GetChunkPtrAsUlong(); - int x = (int)(c >> 32); - int y = (int)(c & 0xFFFFFFFF); - int z = elic.IndexInChunk; - return new int3(x, y, z); - } - } + public EntityStorageInfo elic; - public void RunOrExecute() - { - bool ran = false; - TryRun(ref ran); - if (!ran) - Execute(); - } - - [BurstDiscard] - void TryRun(ref bool ran) - { - this.Run(); - ran = true; - } - } - - [BurstCompile] - private struct WriteComponentDataJob : IJobParallelFor - { - [ReadOnly] public InstantiateCommandBufferUntyped icb; - [ReadOnly] public NativeArray chunks; - [ReadOnly] public NativeArray chunkRanges; - [ReadOnly] public NativeArray indicesInChunks; - [ReadOnly] public NativeArray componentDataPtrs; - [ReadOnly] public EntityTypeHandle entityHandle; - public DynamicComponentTypeHandle t0; - public DynamicComponentTypeHandle t1; - public DynamicComponentTypeHandle t2; - public DynamicComponentTypeHandle t3; - public DynamicComponentTypeHandle t4; - - public void Execute(int i) - { - var chunk = chunks[i]; - var range = chunkRanges[i]; - var indices = indicesInChunks.GetSubArray(range.x, range.y); - var ptrs = componentDataPtrs.GetSubArray(range.x, range.y); - switch(icb.m_state->typesSizes.Length) - { - case 1: DoT0(chunk, indices, ptrs); return; - case 2: DoT1(chunk, indices, ptrs); return; - case 3: DoT2(chunk, indices, ptrs); return; - case 4: DoT3(chunk, indices, ptrs); return; - case 5: DoT4(chunk, indices, ptrs); return; + public int3 GetKey3() + { + var c = elic.Chunk.GetChunkPtrAsUlong(); + int x = (int)(c >> 32); + int y = (int)(c & 0xFFFFFFFF); + int z = elic.IndexInChunk; + return new int3(x, y, z); + } } } - void DoT0(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) + private struct WriteComponentDataJob { - var entities = chunk.GetNativeArray(entityHandle); - var t0Size = icb.m_state->typesSizes[0]; - var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); - byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); - for (int i = 0; i < indices.Length; i++) + [ReadOnly] public InstantiateCommandBufferUntyped icb; + [ReadOnly] public NativeArray chunks; + [ReadOnly] public NativeArray chunkRanges; + [ReadOnly] public NativeArray indicesInChunks; + [ReadOnly] public NativeArray componentDataPtrs; + [ReadOnly] public EntityTypeHandle entityHandle; + public DynamicComponentTypeHandle t0; + public DynamicComponentTypeHandle t1; + public DynamicComponentTypeHandle t2; + public DynamicComponentTypeHandle t3; + public DynamicComponentTypeHandle t4; + + public void Execute(int i) { - var index = indices[i]; - var dataPtr = dataPtrs[i].ptr; - UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + var chunk = chunks[i]; + var range = chunkRanges[i]; + var indices = indicesInChunks.GetSubArray(range.x, range.y); + var ptrs = componentDataPtrs.GetSubArray(range.x, range.y); + switch (icb.m_state->typesSizes.Length) + { + case 1: DoT0(chunk, indices, ptrs); return; + case 2: DoT1(chunk, indices, ptrs); return; + case 3: DoT2(chunk, indices, ptrs); return; + case 4: DoT3(chunk, indices, ptrs); return; + case 5: DoT4(chunk, indices, ptrs); return; + } } - } - void DoT1(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) - { - var entities = chunk.GetNativeArray(entityHandle); - var t0Size = icb.m_state->typesSizes[0]; - var t1Size = icb.m_state->typesSizes[1]; - var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); - var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); - byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); - byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); - for (int i = 0; i < indices.Length; i++) + void DoT0(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) { - var index = indices[i]; - var dataPtr = dataPtrs[i].ptr; - UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); - dataPtr += t0Size; - UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); + var entities = chunk.GetNativeArray(entityHandle); + var t0Size = icb.m_state->typesSizes[0]; + var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); + byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); + for (int i = 0; i < indices.Length; i++) + { + var index = indices[i]; + var dataPtr = dataPtrs[i].ptr; + UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + } } - } - void DoT2(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) - { - var entities = chunk.GetNativeArray(entityHandle); - var t0Size = icb.m_state->typesSizes[0]; - var t1Size = icb.m_state->typesSizes[1]; - var t2Size = icb.m_state->typesSizes[2]; - var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); - var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); - var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); - byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); - byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); - byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); - - for (int i = 0; i < indices.Length; i++) + void DoT1(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) { - var index = indices[i]; - var dataPtr = dataPtrs[i].ptr; - UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); - dataPtr += t0Size; - UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); - dataPtr += t1Size; - UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); + var entities = chunk.GetNativeArray(entityHandle); + var t0Size = icb.m_state->typesSizes[0]; + var t1Size = icb.m_state->typesSizes[1]; + var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); + var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); + byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); + byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); + for (int i = 0; i < indices.Length; i++) + { + var index = indices[i]; + var dataPtr = dataPtrs[i].ptr; + UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + dataPtr += t0Size; + UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); + } } - } - void DoT3(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) - { - var entities = chunk.GetNativeArray(entityHandle); - var t0Size = icb.m_state->typesSizes[0]; - var t1Size = icb.m_state->typesSizes[1]; - var t2Size = icb.m_state->typesSizes[2]; - var t3Size = icb.m_state->typesSizes[3]; - var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); - var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); - var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); - var t3Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t3, t3Size); - byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); - byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); - byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); - byte* t3Ptr = (byte*)t3Array.GetUnsafePtr(); - for (int i = 0; i < indices.Length; i++) + void DoT2(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) { - var index = indices[i]; - var dataPtr = dataPtrs[i].ptr; - UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); - dataPtr += t0Size; - UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); - dataPtr += t1Size; - UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); - dataPtr += t2Size; - UnsafeUtility.MemCpy(t3Ptr + index * t3Size, dataPtr, t3Size); + var entities = chunk.GetNativeArray(entityHandle); + var t0Size = icb.m_state->typesSizes[0]; + var t1Size = icb.m_state->typesSizes[1]; + var t2Size = icb.m_state->typesSizes[2]; + var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); + var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); + var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); + byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); + byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); + byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); + + for (int i = 0; i < indices.Length; i++) + { + var index = indices[i]; + var dataPtr = dataPtrs[i].ptr; + UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + dataPtr += t0Size; + UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); + dataPtr += t1Size; + UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); + } } - } - void DoT4(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) - { - var entities = chunk.GetNativeArray(entityHandle); - var t0Size = icb.m_state->typesSizes[0]; - var t1Size = icb.m_state->typesSizes[1]; - var t2Size = icb.m_state->typesSizes[2]; - var t3Size = icb.m_state->typesSizes[3]; - var t4Size = icb.m_state->typesSizes[4]; - var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); - var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); - var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); - var t3Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t3, t3Size); - var t4Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t4, t4Size); - byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); - byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); - byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); - byte* t3Ptr = (byte*)t3Array.GetUnsafePtr(); - byte* t4Ptr = (byte*)t4Array.GetUnsafePtr(); - for (int i = 0; i < indices.Length; i++) + void DoT3(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) { - var index = indices[i]; - var dataPtr = dataPtrs[i].ptr; - UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); - dataPtr += t0Size; - UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); - dataPtr += t1Size; - UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); - dataPtr += t2Size; - UnsafeUtility.MemCpy(t3Ptr + index * t3Size, dataPtr, t3Size); - dataPtr += t3Size; - UnsafeUtility.MemCpy(t4Ptr + index * t4Size, dataPtr, t4Size); + var entities = chunk.GetNativeArray(entityHandle); + var t0Size = icb.m_state->typesSizes[0]; + var t1Size = icb.m_state->typesSizes[1]; + var t2Size = icb.m_state->typesSizes[2]; + var t3Size = icb.m_state->typesSizes[3]; + var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); + var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); + var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); + var t3Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t3, t3Size); + byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); + byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); + byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); + byte* t3Ptr = (byte*)t3Array.GetUnsafePtr(); + for (int i = 0; i < indices.Length; i++) + { + var index = indices[i]; + var dataPtr = dataPtrs[i].ptr; + UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + dataPtr += t0Size; + UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); + dataPtr += t1Size; + UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); + dataPtr += t2Size; + UnsafeUtility.MemCpy(t3Ptr + index * t3Size, dataPtr, t3Size); + } } - } - public void RunOrExecute(int length) - { - bool ran = false; - TryRun(length, ref ran); - if (!ran) + void DoT4(ArchetypeChunk chunk, NativeArray indices, NativeArray dataPtrs) { - for (int i = 0; i < length; i++) - Execute(i); + var entities = chunk.GetNativeArray(entityHandle); + var t0Size = icb.m_state->typesSizes[0]; + var t1Size = icb.m_state->typesSizes[1]; + var t2Size = icb.m_state->typesSizes[2]; + var t3Size = icb.m_state->typesSizes[3]; + var t4Size = icb.m_state->typesSizes[4]; + var t0Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t0, t0Size); + var t1Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t1, t1Size); + var t2Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t2, t2Size); + var t3Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t3, t3Size); + var t4Array = chunk.GetDynamicComponentDataArrayReinterpret(ref t4, t4Size); + byte* t0Ptr = (byte*)t0Array.GetUnsafePtr(); + byte* t1Ptr = (byte*)t1Array.GetUnsafePtr(); + byte* t2Ptr = (byte*)t2Array.GetUnsafePtr(); + byte* t3Ptr = (byte*)t3Array.GetUnsafePtr(); + byte* t4Ptr = (byte*)t4Array.GetUnsafePtr(); + for (int i = 0; i < indices.Length; i++) + { + var index = indices[i]; + var dataPtr = dataPtrs[i].ptr; + UnsafeUtility.MemCpy(t0Ptr + index * t0Size, dataPtr, t0Size); + dataPtr += t0Size; + UnsafeUtility.MemCpy(t1Ptr + index * t1Size, dataPtr, t1Size); + dataPtr += t1Size; + UnsafeUtility.MemCpy(t2Ptr + index * t2Size, dataPtr, t2Size); + dataPtr += t2Size; + UnsafeUtility.MemCpy(t3Ptr + index * t3Size, dataPtr, t3Size); + dataPtr += t3Size; + UnsafeUtility.MemCpy(t4Ptr + index * t4Size, dataPtr, t4Size); + } } } - - [BurstDiscard] - void TryRun(int length, ref bool ran) - { - this.Run(length); - ran = true; - } } -#pragma warning disable CS0649 - private struct DummyTypeT1 : IComponentData { public int dummy; } - private struct DummyTypeT2 : IComponentData { public int dummy; } - private struct DummyTypeT3 : IComponentData { public int dummy; } - private struct DummyTypeT4 : IComponentData { public int dummy; } -#pragma warning restore CS0649 - static ComponentTypeSet BuildComponentTypesFromFixedList(FixedList64Bytes types) { switch (types.Length) diff --git a/EntitiesExposed/Editor.meta b/EntitiesExposed/Editor.meta deleted file mode 100644 index 0e0f60c..0000000 --- a/EntitiesExposed/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2f56f6e29a6079c449275271aa66b795 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs b/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs new file mode 100644 index 0000000..5334ce3 --- /dev/null +++ b/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs @@ -0,0 +1,124 @@ +using System.Collections; +using System.Collections.Generic; +using Unity.Mathematics; + +namespace Latios.Psyshock +{ + public static partial class Physics + { + /// + /// Creates an enumerator that divides up a timestep into substeps, where each substep returns a substep time. + /// Use this in a foreach loop to perform the same routine over each substep in a simulation. + /// + /// The time to divide into substeps + /// The number of substeps to divide deltaTime into + /// An enumerator that can be iterated upon in a foreach statement + public static SubstepEnumerator Substep(float deltaTime, int numSubsteps) => new SubstepEnumerator(deltaTime, numSubsteps); + + public struct SubstepEnumerator : IEnumerator, IEnumerable + { + float substepTime; + float deltaTime; + float accumulatedTime; + int currentSubstep; + int totalSubsteps; + + internal SubstepEnumerator(float deltaTime, int substeps) + { + this.deltaTime = deltaTime; + totalSubsteps = substeps; + accumulatedTime = 0f; + substepTime = deltaTime / substeps; + currentSubstep = 0; + } + + internal int substepIndex => currentSubstep - 1; + + public float Current => substepTime; + + object IEnumerator.Current => substepTime; + + /// + /// Modifies the enumerator to additionally return the index of the substep along with the timestep. + /// Use as follows: + /// foreach ((float timestep, int substepIndex) in Physics.Substep(deltaTime, numSubsteps).WithIndex()) + /// + /// An enumerator that can be iterated upon in a foreach statement + public SubstepWithIndexEnumerator WithIndex() => new SubstepWithIndexEnumerator(this); + + public void Dispose() + { + } + + public bool MoveNext() + { + if (currentSubstep + 1 < totalSubsteps) + { + accumulatedTime += substepTime; + currentSubstep++; + return true; + } + else if (currentSubstep < totalSubsteps) + { + substepTime = deltaTime - accumulatedTime; + currentSubstep++; + return true; + } + + return false; + } + + public void Reset() + { + this = new SubstepEnumerator(deltaTime, totalSubsteps); + } + + public SubstepEnumerator GetEnumerator() => this; + + IEnumerator IEnumerable.GetEnumerator() => this; + + IEnumerator IEnumerable.GetEnumerator() => this; + } + + public struct SubstepWithIndex + { + public float substepTimeDuration; + public int substepIndex; + + public void Deconstruct(out float time, out float index) + { + time = substepTimeDuration; + index = substepIndex; + } + } + + public struct SubstepWithIndexEnumerator : IEnumerator, IEnumerable + { + SubstepEnumerator m_enumerator; + + public SubstepWithIndexEnumerator(SubstepEnumerator enumerator) + { + m_enumerator = enumerator; + } + + public SubstepWithIndex Current => new SubstepWithIndex { substepTimeDuration = m_enumerator.Current, substepIndex = m_enumerator.substepIndex }; + + object IEnumerator.Current => new SubstepWithIndex { substepTimeDuration = m_enumerator.Current, substepIndex = m_enumerator.substepIndex }; + + public void Dispose() + { + } + + public bool MoveNext() => m_enumerator.MoveNext(); + + public void Reset() => m_enumerator.Reset(); + + public SubstepWithIndexEnumerator GetEnumerator() => this; + + IEnumerator IEnumerable.GetEnumerator() => this; + + IEnumerator IEnumerable.GetEnumerator() => this; + } + } +} + diff --git a/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs.meta b/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs.meta new file mode 100644 index 0000000..73fddad --- /dev/null +++ b/PsyshockPhysics/Physics/Dynamics/Physics.Substep.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 47898294e1de3284795155c92540ccbe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PsyshockPhysics/Physics/Types/PhysicsComponentLookup.cs b/PsyshockPhysics/Physics/Types/PhysicsComponentLookup.cs index fad2b64..c3788c6 100644 --- a/PsyshockPhysics/Physics/Types/PhysicsComponentLookup.cs +++ b/PsyshockPhysics/Physics/Types/PhysicsComponentLookup.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; +using Latios.Transforms; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; @@ -60,6 +61,19 @@ public T this[SafeEntity safeEntity] } } + /// + /// Acquires a RefRW to the component on the entity represented by safeEntity. + /// When safety checks are enabled, this throws when parallel safety cannot + /// be guaranteed. + /// + /// A safeEntity representing an entity that may be safe to access + /// A RefRW that provides direct access to component storage. + public RefRW GetRW(SafeEntity safeEntity) + { + ValidateSafeEntityIsSafe(safeEntity); + return lookup.GetRefRW(safeEntity); + } + /// /// Fetches the component on the entity represented by safeEntity if the entity has the component. /// When safety checks are enabled, this throws when parallel safety cannot @@ -252,5 +266,69 @@ static void ValidateSafeEntityIsSafe(SafeEntity safeEntity) #endif } } + +#if !LATIOS_TRANSFORMS_UNCACHED_QVVS && !LATIOS_TRANSFORMS_UNITY + /// + /// A lookup struct for performing read/write access on a TransformAspect via SafeEntity + /// when it is safe to do so. + /// + public struct PhysicsTransformAspectLookup + { + [NativeDisableParallelForRestriction] ComponentLookup m_localTransformLookup; + [ReadOnly] ComponentLookup m_parentToWorldLookup; + [NativeDisableParallelForRestriction] ComponentLookup m_worldTransformLookup; + + /// + /// Create the aspect lookup from an system state. + /// + /// The system state to create the aspect lookup from. + public PhysicsTransformAspectLookup(ref SystemState state) + { + m_localTransformLookup = state.GetComponentLookup(false); + m_parentToWorldLookup = state.GetComponentLookup(true); + m_worldTransformLookup = state.GetComponentLookup(false); + } + + /// + /// Update the lookup container. + /// Must be called every frames before using the lookup. + /// + /// The system state the aspect lookup was created from. + public void Update(ref SystemState state) + { + m_localTransformLookup.Update(ref state); + m_parentToWorldLookup.Update(ref state); + m_worldTransformLookup.Update(ref state); + } + + /// + /// Gets the TransformAspect instance corresponding to the entity represented by safeEntity. + /// When safety checks are enabled, this throws when parallel safety cannot be guaranteed. + /// + /// The entity to create the aspect struct from. + /// Instance of the aspect struct pointing at a specific entity's components data. + public TransformAspect this[SafeEntity entity] + { + get + { + ValidateSafeEntityIsSafe(entity); + return new TransformAspect(m_localTransformLookup.GetRefRWOptional(entity), + m_parentToWorldLookup.GetRefROOptional(entity), + m_worldTransformLookup.GetRefRW(entity)); + } + } + + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] + static void ValidateSafeEntityIsSafe(SafeEntity safeEntity) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (safeEntity.entity.Index < 0) + { + throw new InvalidOperationException("PhysicsBufferFromEntity cannot be used inside a RunImmediate context. Use BufferFromEntity instead."); + } +#endif + } + } +#endif } diff --git a/README.md b/README.md index 1262899..5de0d2e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![](https://github.com/Dreaming381/Latios-Framework-Documentation/media/bf2cb606139bb3ca01fe1c4c9f92cdf7.png) -# Latios Framework for Unity ECS – [0.7.2] +# Latios Framework for Unity ECS – [0.7.3] The Latios Framework is a powerful suite of high-performance low-level APIs and feature-sets for Unity’s ECS which aims to give you back control over your diff --git a/package.json b/package.json index 4beda9d..7879f44 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.latios.latiosframework", "displayName": "Latios Framework for ECS", - "version": "0.7.2", + "version": "0.7.3", "unity": "2022.3", "description": "Latios Framework for ECS is a collection of tools, algorithms, and API extensions developed by a hardcore hobbyist game developer.\n\nThis package includes all of the following modules:\n\u25aa Core\n\u25aa QVVS Transforms\n\u25aa Psyshock Physics\n\u25aa Myri Audio\n\u25aa Kinemation Animation and Rendering\n\nExamples: \n\u25aa Latios Space Shooter Sample - https://github.com/Dreaming381/lsss-wip\n\u25aa Mini Demos - https://github.com/Dreaming381/LatiosFrameworkMiniDemos", "documentationURL": "https://github.com/Dreaming381/Latios-Framework-Documentation",