- FrozenActorsInRegion now filters for valid and (optionally) visible FAs
- Add new FrozenActorsInCircle to mirror World.FindActorsInCircle.
The first change means that SupportPowerDecision now correctly ignores
FrozenActors that the AI has not discovered.
- Rename Bits<T> to BitSet<T>.
- Implement set based helpers for BitSet<T>.
- When representing TargetTypes of ITargetable in various traits, use a BitSet<TargetableType> instead of HashSet<string> for better performance & reduced memory usage.
- Fix FieldLoader to trim input values when generating a BitSet<T>.
- Require T in BitSet<T> and BitSetAllocator<T> to be a class since it's just a marker value. This allows the JIT to instantiate generic code for these classes once, as they don't benefit from specialized code for T. (Typically JITs will generate shared code for all reference types, and unique code for every value type encountered).
This reverts commit 2eb090f153.
This fixes flicker for the actor->frozen transition, but then introduces the same flicker for the frozen->actor transition instead.
The render bounds for an actor now include the area covered
by bibs, shadows, and any other widgets. In many cases this
area is much larger than we really want to consider for
tooltips and mouse selection.
An optional Margin is added to Selectable to support cases
like infantry, where we want the mouse area of the actor
to be larger than the drawn selection box.
This avoids the allocations caused by LINQ when using traits.FirstOrDefault(Exts.IsTraitEnabled). This is important in FrozenActorLayer.RefreshState which is called very often. We apply the new helper method to all areas using the old pattern. An overload that takes an array allows arrays to be enumerated without causing allocations.
Additionally, internally renamed VisualBounds to SelectionOverlayBounds to avoid confusion with RenderBounds.
This step was necessary to prevent actors with selectable area smaller than their graphics to be removed too early from ScreenMap even though part of the graphics should still be visible.
RA cruisers were a prime example, but to a lesser extent several other actors were affected as well.
This separation also serves as preparation to determine the final RenderBounds from multiple source bounds later, to fix the remaining ScreenMap issues (building 'bibs', aircraft shadows).
If a cell lacked any valid projected cells, then it is off the map entirely. The previous logic would think such a cell was within the map as none of projected cells were out of bounds (as there were no projected cells to fail the check).
The IRemoveFrozenActor interface is replaced with a Remove method on FrozenActorLayer. IRemoveFrozenActor is a performance problem for FrozenActorLayer.Tick as it incurs a large cache miss penalty in order to load and enumerate the array of these interfaces for every frozen actor. Instead, we invert control and allow traits to remove frozen actors directly which eliminates the performance penalty.
The size of the bounds was too small (as rectangle has exclusive edges on the right and bottom). This meant some intersection tests would fail and thus the frozen actor was not found when searching the partition bins.
Track changes in the shroud in a spatial partition in frozen actor layer. This allows us to run the expensive visibility updates only on frozen actors with a footprint in affected partitions, rather than on all frozen actors every time.
This can be used to avoid several lookups for these traits, as well as allow Actor to provide specialised methods to deal with target types efficiently. This also reduces some code duplication.
The previous lazy rendering means the snapshot of the render state might be more up to date then when the frozen actor actually did become visible. Now, we take this snapshot as soon as needed. We still retain the performance of only doing this rendering when needed by avoiding extra rendering until the visibility cycles again.