Skip to content

IconSmooth Refactor#2591

Open
RedFoxIV wants to merge 5 commits intoSimple-Station:masterfrom
RedFoxIV:iconrough
Open

IconSmooth Refactor#2591
RedFoxIV wants to merge 5 commits intoSimple-Station:masterfrom
RedFoxIV:iconrough

Conversation

@RedFoxIV
Copy link
Copy Markdown
Contributor

@RedFoxIV RedFoxIV commented Apr 15, 2026

Description

I was asked to add some smoothing modes for IconSmoothComponent and was displeased with the system's state enough to refactor it.
I believe it's been made much more readable.

Changes:

Removed SmoothEdgeComponent, which was acting just as a boolean toggle for edge smoothing.

Now instead of checking for any sort of toggle, the smooth edge logic is always active. If you don't want to have smoothened edges, just don't add edge layers to the entity sprite.

  • additional boolean toggle to force disable smooth edges can be added on request, i just don't see the point right now

Removed SharedRandomIconSmoothSystem

It was completely empty and only used to give client/server versions of this system a common parent. Legacy code artifact?

Various improvements to IconSmoothSystem

IconSmoothComponent.LastPosition was used to remember the entity's grid position if the entity was unanchored. It was not updated after reanchoring the entity in a different place, which would lead to not updating the surrounding entities after unanchoring it again.

  • This was fixed.

IconSmoothSystem used a generation counter to keep track of entities that have already been processed. This was due to using a Queue<EntityUid> to keep track of entities that potentially need their sprite updated. There was very real potential for two entities both standing next to a third to call DirtyNeighbors() and queue said third entity twice.

  • The Queue<EntityUid> was replaced with HashSet<EntityUid>. Generational counter and relevant check has been removed.

IconSmoothSystem used to pass EntityQuery<TComp> objects to methods that use them, instead of keeping them in private fields.

  • EntityQuery<SpriteComponent>, EntityQuery<TransformComponent> and EntityQuery<IconSmoothComponent> have been moved to a private class field. Arguments that were used to pass these to other parts of the system were removed.
    • There is not much overhead of calling Resolve<TComp>()/TryComp<TComp>()``Comp<TComp>() over calling the respective methods of EntityQuery<TComp>, so these could probably be removed. This optimization is only relevant for extremely hot code paths, which get called many times per frame, every frame. IconSmoothSystem does not qualify.

There was a schizophrenic check at the beginning of CalculateNewSprite(), which, if failed, short-circuited the method to only update the edge layers. This check was also failed if the entity in question did not have IconSmoothComponent, or if it has already been processed before (see Queue<EntityUid> thing above)

  • This check has been broken up into multiple ifs, and the obsolete parts were removed.
  • The relevant edge updating code has been moved into a separate method.

Added new smoothing modes : Horizontal and Vertical
They use the same icon state naming scheme as CardinalFlags mode, but only allows connections to the left and right/front and back of processed entity. The connection candidate must also have the same direction.
The main purpose of this smoothing mode is for stuff like couches and benches.

There also a considerable amount of refactoring, mainly about deduplicating code or making it less cumbersome.
Everything i did not mention probably falls into this category.

This is still not optimal in my opinion, and some parts could still be improved.

The code related to getting the surrounding entities should be moved up from CalculateNewSpriteXXXXX() to CalculateNewSprite()
This would let us drop duplicated code from CalculateNewSpriteXXXXX() methods, while also moving edge updating code to be called only in CalculateNewSprite()
This will also let us drop the UpdateEdges() call from CalculateNewSpriteXXXXX() methods. Currently these methods are responsible for

  1. getting the surrounding entities,
  2. applying the correct icon state and then
  3. passing the surrounding entities information to the smooth edge code.

Ideally, CalculateNewSpriteXXXXX() should only be responsible for the second part.

CalculateNewSpriteXXXXX() methods are also used to handle unanchored entities, instead of having a short-circuit with unified logic. The reason for this is CalculateNewSpriteCorners(), which does not have a default icon state per se, but rather 4, applied to different layers.
This should probably be moved into a separate method, but I am not sure if it's the best way to do it, Hence, this part is left as-is.

Before calling any CalculateNewSpriteXXXXX(), there is a weird check for presence of a MapGridComponent on the entity's parent grid. It's weird, because it's only done if the entity is anchored (which implies being parented to a grid.)
I left it as-is, since I can not confirm nor deny if it actually does anything.


Media

The upper half of this screenshot shows that things using corner smoothing mode are still working, even if the entities have different rotations.

The lower half shows that smooth edges now also work with rotated entities as well (as shown by the top row of rocks.) Previously, rotating an entity with smooth edges would lead to incorrect edges being hidden.
The bottom row of rocks is for comparison.
image

This screenshot shows the work of a new Horizontal smoothing mode.
I re-used AMEShielding entity for this, since it (and puddles) are the only entities currently using CardinalFlags smoothing.
I've drawn red lines to show what connects to what, for clarity.
image

And here's a bunch of random screenshots of MetaStation, to show that smoothing system still works as intended.

Details image image image


Changelog

Should not affect a regular player in any way.
Hence,
:nocl:

@RedFoxIV RedFoxIV requested a review from Remuchi as a code owner April 15, 2026 17:22
@github-actions github-actions bot added Changes: C# Changes any cs files Changes: YML Changes any yml files Status: Needs Review Someone please review this labels Apr 15, 2026
@SimpleStation14 SimpleStation14 changed the title IconSmooth refactor IconSmooth Refactor Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changes: C# Changes any cs files Changes: YML Changes any yml files Status: Needs Review Someone please review this

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant