A log console inside a game. And tweaking the Godot editor.
Describe the problem or limitation you are having in your project
In order to display a long list, there are two options:
ItemList or Tree
Optimized for long lists, but lack of customization. The layout for each row is fixed.
BoxContainer + ScrollContainer
Fully customizable, but poor performance for long lists.
Option 2 is the only way to go if I want to customize row content. But, for example, I have to literally instantiate 10000 rows of controls for the list.
Option 1 also has something that need to be addressed. It's almost a convention in editor code that Trees are cleared and rebuilt once something changes. From the perspective of the API, it's inconvenient to update only a row when something changes. Tree users have to keep track of the mapping between data element and TreeItem.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
The basic idea is that the user provides an Adapter (data source) for the list control.
So the list control can ask the adapter...
how many items are in the list
which kind of view (control / scene) should be used for a specific item
And the adapter should be able to...
Create the view for a specific type
Setup the view for a specific item
The list control reuses the view created previously when possible. Only a few views will be created for a long list.
How the list control arranges views is determined by a similar Layout object (e.g. vertically, horizontally, coverflow, paged, waterfall...).
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
See the reference links above for details.
Demo usage:
@onready var list: RecyclerView = $List
func _ready():
var adapter = UserAdapter.new()
adapter.users = get_users()
list.adapter = adapter
class UserAdapter:
var users: Array[User]
func _get_item_count() -> int:
return users.size()
# Called by RecyclerView when a new view should be created.
# `type` is 0 by default. Override `_get_view_type(position: int) -> int` to use different views.
func _create_view(type: int) -> Control:
return preload("res://user_view.tscn").instantiate()
# Called by RecyclerView when a new row will be shown.
# `view` is a reused control, or newly created by `_create_view()`.
func _bind_view(view: Control, position: int) -> void:
var user_view := view as UserView
var user_data := users[position]
user_view.username.text = user_data.name
user_view.age.text = str(user_data.age)
user_view.load_avatar(user_data.avatar_url)
user_view.removed_pressed.connect(func ():
users.remove_at(position) # Update data model.
list.reload_data() # Refresh the list, or
list.delete_item(position) # Only update row count & rows from position. Animation possible.
)
# Called by RecylerView when a view is just hidden. You can do some cleanup here.
func _recycle_view(view: Control) -> void:
var user_view := view as UserView
user_view.cancel_avatar_loading()
user_view.disconnect_signals()
If this enhancement will not be used often, can it be worked around with a few lines of script?
Not a few lines.
Is there a reason why this should be core and not an add-on in the asset library?
It fills the gap between ItemList/Tree and BoxContainer+ScrollContainer.
Describe the project you are working on
A log console inside a game. And tweaking the Godot editor.
Describe the problem or limitation you are having in your project
In order to display a long list, there are two options:
ItemList
orTree
BoxContainer
+ScrollContainer
Option 2 is the only way to go if I want to customize row content. But, for example, I have to literally instantiate 10000 rows of controls for the list.
Option 1 also has something that need to be addressed. It's almost a convention in editor code that
Tree
s are cleared and rebuilt once something changes. From the perspective of the API, it's inconvenient to update only a row when something changes.Tree
users have to keep track of the mapping between data element andTreeItem
.Describe the feature / enhancement and how it helps to overcome the problem or limitation
Implement something like the Android RecyclerView and iOS UICollectionView (or UITableView which is a simplified version).
The basic idea is that the user provides an Adapter (data source) for the list control.
The list control reuses the view created previously when possible. Only a few views will be created for a long list.
How the list control arranges views is determined by a similar Layout object (e.g. vertically, horizontally, coverflow, paged, waterfall...).
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
See the reference links above for details.
Demo usage:
If this enhancement will not be used often, can it be worked around with a few lines of script?
Not a few lines.
Is there a reason why this should be core and not an add-on in the asset library?
It fills the gap between
ItemList
/Tree
andBoxContainer
+ScrollContainer
.