godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Cleanup the Tree API and usage #4579

Open KoBeWi opened 2 years ago

KoBeWi commented 2 years ago

Describe the project you are working on

Godot etc

Describe the problem or limitation you are having in your project

Tree is this huge Control class that displays elements in a hierarchical structure. It's used in many places in the editor and has some limited use in project (mostly for custom tools). Over years it has accumulated lots of bloat functionality. Most of it came from the fact that Tree was previously used for the editor inspector. Then the inspector was replaced with a dedicated class, but the functionality has remained. Many of it isn't used very much or sometimes not at all. Another thing is that TreeItem was written under CPU/memory constrains of old game consoles, so the API doesn't make much sense nowadays.

The tree.cpp is just too big, full of hacks and full of bugs that appear regularly, which just add more hacks to get fixed. The class is in dire need of some refactoring. It should be done before 4.0, so that we can do any required breaking changes.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

At first I was going to list some API changes that just break compatibility, but I eventually came up with an idea that requires much more than that, so I'll just split this section in 2 parts. This applies to both Tree and TreeItem, as they exist together.

Simple renaming changes that could be done (I assume https://github.com/godotengine/godot/pull/47665 is going to be merged):

Other problems beyond simply renaming things:

While the renaming part would be simple to do, the Tree could get more changes that would fix all of the problems. We could split TreeItem into 2 classes: TreeItem and TreeItem cell. So the Tree would be collection of TreeItems and each TreeItem would contain TreeItemCells. The advantage of that is that we could remove most of the methods in TreeItem and make them properties in TreeItemCell. Then add TreeItemCell sub-classes, so that different modes aren't hacked into one class with lots of unrelated properties, but are properly separated. It should make the code much cleaner and less spaghettied; just easier to maintain.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

A TreeItemCell class would be added. idk if cells have some common properties (even text isn't supported in all cell modes), might be worth making it an abstract class. With that, the class would have these subclasses:

TreeItemCells would be only managed by their TreeItem. There wouldn't be any methods that add or remove cells, as each TreeItem would just have columns number of cells. Setting a cell type would remove the old one and instance a new class, clearing data from the old one. All set_* methods in TreeItem would be converted to properties in TreeItemCell. TreeItem would just get a method get_cell(idx) to obtain a cell.

Most of the code for operating on TreeItems and cells could be moved to their classes. The signals should still be emitted from Tree. Maybe items and cells could just have a method called emit_tree_signal(signal, args) to make it simpler (TreeItem and TreeItemCell don't exist without Tree, so coupling like that isn't a problem). Tree would be mostly focused on managing TreeItems and TreeItem on managing cells. Right now the code is intertwined a lot; there should be some way to split it.

This probably doesn't cover everything, so if there is something I forgot, feel free to comment so I can update. This is lots of changes and it should be discussed.

If this enhancement will not be used often, can it be worked around with a few lines of script?

If you divide the number of lines by 1000 then yes.

Is there a reason why this should be core and not an add-on in the asset library?

I know abandoning Tree class in favor of clean custom implementation is tempting, but the core one should be fixed.

fire-forge commented 2 years ago

Another idea I had is to make TreeItem a Node. Right now TreeItems can only be created and edited through code, but if they were nodes then their properties could be edited in the inspector and the hierarchy could be edited in the scene tree. Drawing would still be handled by the Tree node itself.

Then several of the TreeItem methods can be removed in favor of the similar methods that exist in Node:

KoBeWi commented 2 years ago

TreeItem can't be a Node as Nodes are just too expensive. Imagine you have 1000 nodes on your scene and then there is 1000 more in the scene tree dock to represent that. They have lots of useless overhead functionality like pause behavior, processing, groups. TreeItem just doesn't need it.

We could add a custom editor to edit Tree contents in the inspector, but Trees are most often created dynamically, so there is no real use-case for that.

fire-forge commented 2 years ago

@KoBeWi Ok, that's understandable. It's definitely better to keep the more efficient solution we have now then.

We could add a custom editor to edit Tree contents in the inspector, but Trees are most often created dynamically, so there is no real use-case for that.

I agree. It wouldn't be worth it to create a custom editor for TreeItems because of how little it'd be used, but if someone wanted this it could be done with a plugin using the current API.

fire-forge commented 2 years ago

Two more changes I'd make to TreeItem:

YuriSizov commented 2 years ago

Approved in the proposal review meeting! If you want to work on this, we'd love to have it before 4.0, though this does look like a lot of work, so pace yourself :)

KoBeWi commented 2 years ago

I actually started some work: https://github.com/KoBeWi/godot/tree/treework But after seeing the 500-line-long TreeItem drawing method, I have some doubts if it ever gets finished 🙃 So far I added the new classes and the new Tree will draw some broken text when you add items.

me2beats commented 1 year ago

Another idea I had is to make TreeItem a Node. Right now TreeItems can only be created and edited through code, but if they were nodes then their properties could be edited in the inspector and the hierarchy could be edited in the scene tree. Drawing would still be handled by the Tree node itself.

I think this could be solved by implementing a Tree editor like we have for ItemList for example. Would be great especially for prototyping

KoBeWi commented 1 year ago

I just discovered that CELL_MODE_RANGE has double functionality. It's a slider value, but if you give it text, it magically becomes a dropdown 🤦‍♂️In my (now dead) refactor PR I made TreeItemCellRange, but now I see that there needs to be another class, likely TreeItemCellDropdown.

btw this proposal has 5.0 milestone, but it can be implemented in Godot 4 as a separate class (like AnimationTree and AnimationTreePlayer in Godot 3).

Shadowblitz16 commented 2 months ago

TreeItem can't be a Node as Nodes are just too expensive. Imagine you have 1000 nodes on your scene and then there is 1000 more in the scene tree dock to represent that. They have lots of useless overhead functionality like pause behavior, processing, groups. TreeItem just doesn't need it.

We could add a custom editor to edit Tree contents in the inspector, but Trees are most often created dynamically, so there is no real use-case for that.

I don't understand any modern markup gui has separate objects per ui element. This seems like a implementation issue rather then node's just strait up being not suitable.

If node's are too slow then optimize them.

I mean there is wpf and avalonuia ui that treat tree node's as separate tree objects and that's written in C# and not c++, And avalonia ui is known for being really fast.

Also I think they would be more useful if they had the features node's have. Half the time godot is too bare bones for the things I want to do with it.