Druid - Component GUI Framework

Hey!

Hmmm, so.… My previous post may have been unclear with too many useless comments (since it wasn’t super clear in my mind)… but this time I’ll try to keep it short and focus on the objective/use case.

I restarted my test project from the “scrolling list + checkbox” example, and here is a major difference with what I want to do:

1/ In the “checkboxes” example, the user can have several checkboxes checked (…) at the same time. Which means that selecting/unselecting a checkbox has no impact on the other checkbox nodes of the scrolling list. I don’t need to know if a node is deleted or not.

2/ In my case, I want to have only ONE node selected at a time. When clicking a new node, I also want to unselect (= change the animation of) the previously selected node. If I don’t, I’ll have to wait that the previous node is deleted and created again (like in the video below).

How to have only 1 node visually selected at a time?
Is there an example somewhere that I may have missed?

Note: I implemented the node animation update in the update() function during my tests, but as expected, if the previously selected node is already deleted (off-list), I get a “Deleted node” error message when trying to update its animation… And at this point, I don’t know how to detect if the element in question is deleted or not.

PS: as a feature, I feel like this is something really common/standard, but after many many tests (this message is the super short story), I’m still stuck so… Any help is welcome… @Insality , @britzl @AGulev … or anyone having worked with Druid… I can’t imagine being the first one to implement something like this with Druid.

1 Like

I’m currently without any laptop to add an example or fully answer on your question. I will answer to you soon as possible :wink:

Probably here are 2 ways: add events to components and react on some click event.
Or it’s really will be useful to iterate over all visible components in data list. (current its possible to iterate over data_list._data_visual field. I will add get_components function in next release.

It’s filled now in this way:

 self._data_visual[index] = {
 	node = node,
 	component = instance
  }
2 Likes

I’m not familiar with Druid, but with my own UI setup, when I wanted a single “selected” button like this, I used a group of radio buttons and themed the “checked” button to appear highlighted.

2 Likes

Hi @Insality !

I’d have a “quick question” about how to build scrolling lists containting “conditional” content. I’d like to have your opinion about which method I should choose.

(PS : I’m asking Insality but anyone can share their experience, of course… :pray:)


My use case:

Scrolling_list 1 (item categories) = the user clicks a button to select a category.
Scrolling_list 2 (items) = items are displayed consistently with the selected category.

image

In Defold, I have a table that contains all the items, for each category.

But technically, with Druid, what would be the best method to display the item list with the right items?


Option 1
When I click a category button, I destroy the previous item list and create a new one.

Option 2
I create all the item lists when the scene is launched.
And then, when I click a category button, I show only the right item list (and hide the others).

Option 3
I have only ONE big item list containing all the items (of all categories).
When I tap a category button, I refresh the “big” item list to display only the items that should be displayed (I don’t know how I would do that, but perhaps it’s possible).


At first sight, which approach would you recommend?

Maybe another one?

3 Likes

I believe there is a common term for this described technique, “Object Pooling.”
I’ve only read a little bit about it but perhaps looking into it and determining whether its pros and cons align with your goal can help you make a decision?

1 Like

Thank you for you answer!

I did a quick search and found this topic:

I understand the principle and it looks like Defold can handle it by default.
“This practice is not necessary in Defold. It’s automatically done for you.”

But in my case (option 2), I wouldn’t have a high number of “item lists” so this is not my core issue.

I’m pretty sure (and I hope) that I’m not the first one to create a screen with a “category selection” menu containing buttons (1 per category) that I click to “contextually” display such or such items (based on the selected category).

How do people design/create these “item lists” in Defold? (with Druid or not - not sure my question was really Druid-specific… Maybe there are more generic best practices)

How many items will you have in a single item list? I would start with a naive approach and each time an item category is selected I would delete existing item nodes and create new ones for the items in the category that was selected. If we’re talking about a small amount of items (maybe less than 100) it will not be measurable I think. If we’re talking a large amount of items per group it might be worthwhile to reuse the item nodes when switching category.

1 Like

In this specific case, the nb of items per item list is very limited (it’s a “battle preparation” menu where you choose the class and then a character in this class), so let’s say… 10-12 categories and 6-7 items (max) per category. It’s not a Shop (or similar) where you have fewer categories but potentially maaany items per category.

The “naive approach” was my first option indeed (consistent with my skill/experience :baby:), without considering the “performance” aspect. But happy to read it’s a reasonable approach in my situation.

But since there is no way (as far as I know) to determine which node has been automatically deleted by Druid (if off-“scrolling list zone”)… I don’t know how to target visible (non-deleted) nodes.

So I’m back to my initial problem, which was the lack of “node deleted” callback.

Anyway, I’ll start to implement the naive approach and pray for the callback in question :slight_smile: to make the feature 100% functional afterward.

I think this both options are good!

I usually using the option 2, but it depends from place to place. For example in my game in shop menu I created 3 data lists and have button to switch between them:

Also there is “only one selected” logic you asked before. Every component in data list subscribed on my “item changed” game event and react on this. II’ll add the example to Druid with data list + components to see how you can handle similar behaviour. (On_remove callback and other utilities stuff for Data list also will be added)

2 Likes

Good to know :slight_smile:

Oh man, this video is a compilation of what I’d like to do :scream:

Cool! Can’t wait for it :slight_smile:

1 Like

Just published the Druid 0.9.1 (without release, just a tagged version) The next release is in process :upside_down_face:

Update DataList and add the example with DataList + Custom component

Add two events to DataList: data_list.on_element_add and data_list.on_element_remove to have more ability to custom the behaviour
New functions:

  • data_list:get_data()
  • data_list:get_created_nodes()
  • data_list:get_created_components()

It’s also allow you to manage your nodes more :slight_smile:

Even the behaviour of ‘one selected’ can be implemented in several ways, choose the way you like more. DataList is more complicated than general scroll + grid components and it’s required more management. But if you wanna use this component, let’s learn the examples and source code.

Thanks for your feedback!

7 Likes

This, my friend, is EXACTLY what I needed! The missing piece!!
(just implemented it in my system and it works like a charm - I love the “control” I have over my nodes now)

Pretty sure this will be very useful to Defold users.

Thank you!

5 Likes

I would also like to thank for new example “DataList + Custom component”! Very useful feature for implementation in-game shops. Thanks a lot!

4 Likes

Hey @Insality !

EDIT: it’s ok, Britzl replied :slight_smile: but I leave this post in case someone has the same issue someday

I’m currently trying to divide my big list into sorted lists (based on categories), but I’m experiencing a really weird “resources” issue.

Here is my scrolling list with ALL my items (characters), before being split - everything is ok.

I add “category” buttons so the user can display only the characters of a given category
It works… to a certain extent.


Actually, it only works for the smaller lists (that have no “deleted” nodes).

When I want to replace a list with a long one… An issue occurs:


With the following error message:

I don’t know what these resources are (I had another issue related to these resources but I won’t mention it here):

“buffer is full (512)” => 512 of what? The only limitation set to 512 is the labels (in game.project)… I set it to 15000 (just out of curiosity) but nothing changed.

I obviously did something wrong, but I don’t know what. Maybe I didn’t clean the list as it should be?

Here is what I did:

	for i=1, #self.char_list_elements do -- I traverse my table of elements
		if self.char_list_elements[i].visible then -- only if the node is visible (not deleted)
			gui.delete_node(self.char_list_elements[i].btn_prefab) -- I delete the visibile nodes, one by one
		end
	end
	self.data_list_characters:clear(self) -- as I saw in the API documentation... not sure it's how I should use it

	-- and then I clean everything that can be cleaned :)
	self.char_list_elements = {}
	self.data_set_characters = {}
	self.btn_prefab_characters = nil
	self.data_list_characters = {}
	self.scroll_characters = {}
	self.grid_characters = {}
	self.data_list_characters = {}
	self.current_nodes = {}

Did I miss something crucial?

Maybe there is a best practice, a function etc. to super cleanly delete a datalist? (and replace it with a new one)

edit : maybe that the nodes deleted by Druid are still existing something (even though they’re not visible) and this “somewhere” needs to be cleaned?

2 Likes

Each .gui has a node limit that by default is 512 nodes. You can easily change this on a per gui component level by selecting the root of your gui in the outline and change the Max Nodes value in Properties (ie the same place where you assign a gui_script).

Also keep in mind that a deleted node lives for the entire duration of a frame. This means that if you delete 10 nodes and in the same frame create 10 new nodes you will have a total of 20 nodes during the frame.

1 Like

Oh, interesting. When I increase the limit, it fixes the issue indeed.

(but still, it’s weird to imagine than 2 categories alone (the previous one and the new one) have more nodes than the big whole list that is supposed to contained all the categories… it feels like something’s wrong somewhere - but maybe your second point will help me fix it)

Just out of curiosity: what are the reasons to NOT set this limit to… I don’t know, 5120 instead of 512? Memory or something like that?

Good to know as well!
(I did not have that in mind, while it’s a basic principle, not specific to this case)

I’ll give it a try by putting the “list deletion” part at the end of the script (instead of right before the creation), perhaps it’ll allow me to not increase the max nb of nodes.

edit: I just put the deletion after the creation in the script and it works fine now :slight_smile: (with 512 max nodes) thank you!

In Defold we try to allocate memory up front instead of dynamically. This helps with memory management and performance. Setting it to 5120 will use 10 times the amount of memory. Exactly how much memory each node takes would have to be measured by looking at the node implementation in the source code or measured using a profiler.

1 Like

Ok, thank you for the explanation!

Good to know even though, in this specific case, moving the deletion part in the script solved the problem (but I suppose that the principle remains the same for any increased limitation in Defold, ex: in game.project)


But since I will probably have to tweak such or such “max XXX” value in the future, I was wondering:

From a user perspective, what does it look like?

  • Longer loading times?
  • Lower FPS?
  • Device heating up?
    etc.

Primarily memory usage and to a very small extent impact on performance (ie higher CPU usage which also means more heat).

2 Likes

Hi @Insality !
(yeah it’s me… again :thinking:)

I would have another question about horizontal datalists:

How/where to define the number of rows of an horizontal datalist?

In the example, we can set the number of columns (= the number of elements in this case) :


image

But it’s like I can only create 1-row horizontal lists.

In the example, I tried to divide the number of columns/elements by 2 (so maybe the number of rows would automatically adjust and get multiplied by 2), but in the end, it just… reduces the nb of elements displayed (which is pretty logical).

It’s like something is missing or (more likely) I missed something.