-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VGui: Rework #1752
base: master
Are you sure you want to change the base?
VGui: Rework #1752
Conversation
I've been on-and-off working on a framework to replace VGUI as much as possible myself. It has a lot of work to go (it can't even show anything yet!), but I have a vision for how I want it to be used: {
ty = "box",
margin = 5,
fill = true,
{
ty = "box",
align = TOP,
height = 20,
fill = true,
{
ty = "text",
translate = true,
text = "some_text_key",
align = { CENTER, CENTER },
},
},
{
vgui = "DPiPPanelTTT2",
set = { Player = LocalPlayer() },
init = function(pnl) end,
},
} Part of the goal is also to remove the pixel-sizing that is currently pervasive, provide automatic UI scaling, more aggressively cache data, etc. |
Uh, this is also really neat! However, this won't stop my project. In fact, they don't interfere with each other. If you ever come around doing your idea, this rework will probably make it simpler! |
Something in the PR description read as asking for ideas or some such, though I can't see it now. I figured it'd be worth mentioning here that I've been working on that as a result. |
Yes, I asked for feedback. However, this PR is ambitious as it is - I won't start implementing a new UI framework for now :D |
Also, I want to mention something. The changes in this PR bring minimal issues with compatibility. Hooks, functions etc mostly stayed the same, I only introduced a new layer of interacting with them on top. While cleaning up the backend. If any addon actually uses our vgui, it should work without changes, maybe minimal changes |
The first three have a fixed panel size and use text align, the last three have no size defined, only an icon size and padding. The panel size is then derived from these parameters |
Note: That the first three elements look broken is intended. The vertical height is too narrow to fit the content, auto stretch is disabled. |
This PR has many things yet to do, but I wanted to open a draft so it is open to discussion. There are a few things I want to tackle in this PR. It will probably be rather large, but without any meaningful new features. It is mostly renamed, reordered and cleaned up.
Reviewing this is probably hard, therefore the following list explains the changes. As you can see in the diff, it consists mostly of restructuring, deletions and added documentation. Nothing new was added, only some small improvements.
1. Broken Inheritance
The first issue I want to address in this PR is the broken vgui inheritance in TTT2. There are quite a few places in the codebase with code duplications and also many unnecessary vgui elements.
After some investigation I learned that both
PANEL
andLABEL
are defined in the GMod codebase, while every other element with a D prefix is defined in lua. We could use those elements already existing, but there are so many modifications by now, that is is useful to stick to our copied and modied files.However, in our code base
TTT2:DLabel
andTTT2:DPanel
have many duplications because they both inherit from their respective engine defined base. In the engineLABEL
inherits fromPANEL
. We can makeTTT2:DPanel
inherit from TTT2:DLabel`. This drastically cleans up our code and has only a single side effect: the two elements are mostly similar (with some changed default values).2. Repetitive Code
The issue that triggered this rework is the following scenario. This is how it looks if you want to create a button:
When using method chaining this can be cleaned up a lot:
This makes it way more clean and less cluttered.
Note: I chose to do it this way because it adds new possibilities without breaking old code. The old UI code will work as before.
3. Events and Hook Overwrites
It is typical that our custom elements have something like this in their initialize function:
While this does work, it is rather tedious and prone to errors. This has to be done since there is no real inheritance in vgui elements that could use
BaseClasses
, at least not as far as I could tell. Additionally one might want to attach a function to an event after a element was already created. The developer here has to make sure that they don't overwrite an already existing hook.The way the sound was added to buttons is a good example of the issue at hand.
The solution is to introduce a simple system, that mimics hooks. Elements can be registered with
PANEL:On(name, function)
. That supports multiple events on a single event. So we can handle our button sounds internally in a clean way, while also exposing the event to the developer.Similarly
PANEL:After(delay, function)
was introduced to provide a clean wrapper for timers.Adding sound to a button would look like this:
4. Attach
I also noticed that many of our custom elements are only copies of the panel with added setters and getters. We could probably delete quite a few of them, if we just reused existing ones. One solution I suggest is using
PANEL:Attach(identifier, data)
. This is basically a fancy wrapper forPANEL.identifier = data
to be able to attach any data while using method chaining.5. PerformLayout and Caching
Currently, everything is done every frame. Translating, calculating sizes, changing colors. This is changed in the new basic panel by going back to GMods
PANEL:PerformLayout
system.Internally, the base element now looks like this:
This triggers three hooks on all inheriting panels. The first hook updates the cached colors, the second hook updates the cached translations, while the third rebuilds the layout. This also means that the panels will now invalidated on every vskin and language change.
This is done in three different hooks to keep the code tidy, while also making sure that subsequent overwrites do not break the core logic.
The paint hook was changed accordingly. Instead on relying on an individual draw function for every flavor of every element, mutual elements were selected:
This way many code duplications could be removed, while also vastly improving the rendering performance.
An element with many special features now looks like this:
Note: This panel now also supports text align, even in combination with an icon. Use
:SetHorizontalTextAlign()
and:SetVerticalTextAlign
for that. Moreover,:SetFitToContentX(true)
and:SetFitToContentY(true)
can be used to size this element to the size of the text and icons. This also works for buttons, making it really useful when supporting localization.Since everything now properly inherits, the same settings are also available for buttons for example.
6. Documentation
We never added any documentation to vgui. The rewrite aims to add a lot of it - at least to the base classes.
7. Other Ideas
While researching this, I also found this library which seems quite nice: https://github.com/Threebow/better-derma-grid