ADR-13: Custom UI modes for builder in world

More details about this document
Latest published version:
https://adr.decentraland.org/adr/ADR-13
Feedback:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on githistory.xyz

Context and Problem Statement

When switching in and out of the builder in world, we need some way to switch the hide/show state of arbitrary UI elements of the explorer.

Right now, the show/hide interface responsibility is defined within the HUDController class.

Currently, HUDController has the following responsibilities:

Kernel <> renderer bridge

Kernel sends messages directly to this class for interaction

HUD Factory

Self-explanatory. Related to instancing the actual HUD elements.

HUD Initialization

Sometimes, special initialization should be performed after the HUDs are instanced.

HUD Composite

The references to the instanced HUD components are stored in this class.







G


cluster_0

HUDController



a0

Bridge



a1

Factory



a0->a1





a2

Composite



a1->a2





a3

HUD Elements



a2->a3





start




Kernel



start->a0





Use cases

Show/hide of UI elements

Despite HUDController existing interface for showing/hiding any HUD element, a lot of times this functionality can't be used because of how this class assembly is referencing every other HUD assembly.

Most of the times we are faced with cyclic assembly references issues and we are forced to work around this issue.

Inter-HUD interaction

In some cases, we want a composite architecture, where one HUD depends on the state of the others.

For instance, when implementing the private chat window we had to write callbacks on HUDController itself to be able to wire the back button to the opening of the friends tab. This broke the encapsulation and made the HUD flow harder to follow.

There are more examples of this kind of responsibility bloat here.

Considered options

Distribute the different HUDController responsibilities to individual systems

This implies a refactor and is the most likely solution that would take care of our use cases niftly, however it would take a bit of design and coding work, because HUDController is pretty intertwined with our current kernel <> renderer communication and the HUD system foundation.







G



start




Kernel



a0

HUD Bridge



start->a0





a1

HUD Factory



a0->a1





a2

HUD Composite



a1->a2





e0

External #1



a2->e0





e1

External #2



a2->e1





e2

External #3



a2->e2





Move the HUD status responsibility to individual ScriptableObjects

This would allow an easy approach to handle the show/hide use case. However, it doesn't fix the issue for Inter-HUD interaction. The idea is to have a single SO for HUD element, and then suscribe from them in HUDController.

Note that this solution places even more responsibility burden on HUDController, however it does so in a way that should easy to handle and move around later when we get to the root improvement.







G



a0

HudController



so1

HUD SO #1



a0->so1





so2

HUD SO #2



a0->so2





ext0

External #1



so1->ext0





so2->ext0





ext1

External #2



so2->ext1





ext2

External #3



so2->ext2





start




Kernel



start->a0





Decision

We agreed upon implementing the ScriptableObjects solution as a first stage, and then perform the responsibility segregation redesign on the HUDController class later.

Consequences

HUDs will be able to be toggled from any part of the project quite easily. HUDController will still suffer from having many responsibilities, however, the decentralized approach of the solution will keep the tech debt manageable

Participants

License

Copyright and related rights waived via CC0-1.0. Withdrawn