/// <summary> /// Awakens a list of set indices. /// </summary> /// <param name="setIndices">List of set indices to wake up.</param> /// <param name="threadDispatcher">Thread dispatcher to use when waking the bodies3D. Pass null to run on a single thread.</param> public void AwakenSets(ref QuickList <int> setIndices, IThreadDispatcher threadDispatcher = null) { var uniqueSetIndices = new QuickList <int>(setIndices.Count, pool); var uniqueSet = new IndexSet(pool, bodies3D.Sets.Length); AccumulateUniqueIndices(ref setIndices, ref uniqueSet, ref uniqueSetIndices); uniqueSet.Dispose(pool); //Note that we use the same codepath as multithreading, we just don't use a multithreaded dispatch to execute jobs. //TODO: It would probably be a good idea to add a little heuristic to avoid doing multithreaded dispatches if there are only like 5 total bodies3D. //Shouldn't matter too much- the threaded variant should only really be used when doing big batched changes, so having a fixed constant cost isn't that bad. int threadCount = threadDispatcher == null ? 1 : threadDispatcher.ThreadCount; //Note that direct wakes always reset activity states. I suspect this is sufficiently universal that no one will ever want the alternative, //even though the narrowphase does avoid resetting activity states for the sake of faster resleeping when possible. var(phaseOneJobCount, phaseTwoJobCount) = PrepareJobs(ref uniqueSetIndices, true, threadCount); if (threadCount > 1) { this.jobIndex = -1; this.jobCount = phaseOneJobCount; threadDispatcher.DispatchWorkers(phaseOneWorkerDelegate); } else { for (int i = 0; i < phaseOneJobCount; ++i) { ExecutePhaseOneJob(i); } } if (threadCount > 1) { this.jobIndex = -1; this.jobCount = phaseTwoJobCount; threadDispatcher.DispatchWorkers(phaseTwoWorkerDelegate); } else { for (int i = 0; i < phaseTwoJobCount; ++i) { ExecutePhaseTwoJob(i); } } DisposeForCompletedAwakenings(ref uniqueSetIndices); uniqueSetIndices.Dispose(pool); }