Druid - Component GUI Framework

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.

Hello! :upside_down_face:
No, the current grid implementation as I know is not allow you to setup nodes layout in other side (by y axis).
As workaround you can copy the grid component and change several posing functions, probably it will work for you.
edit: as another workaround you can make the one line of custom components, which contains a two inner elements in the column (it’s sounds good!)

Also you can add the issue for that in Github!

4 Likes

druid_logo

Druid 0.10.0 : Release Defold Druid v0.10.0 · Insality/druid · GitHub

Hello! Here is new Druid update. It’s brings to you two new components: Layout and Hotkey. Both components are “extended”, so to use it, you should register it first (when you try to use it, in console will be prompt with code you should use)

In general:

local layout =  require("druid.extended.layout")
druid.register("layout", layout)

The Drag component now knows about window scaling, so now it have more accuracy dx/dy values depends on the screen size. The scroll and other components should work better :slight_smile:

Now you can change the input priority of components temporary. For example while you interact with them (input fields, drag on select etc).

Also the update brings several bug fixes and now Druid have stencil_check mode enabled by default. It should be more easy to use input components with stencil nodes without manual set_click_zone functions.

And yeah, the new Druid logo is here! Have a good days!

Changelog 0.10.0


  • #133 [Hotkey] Add new extended component: Hotkey
    • It’s allow you set hotkeys to call callbacks
    • You should pass one action key and several modificator keys (left shift, right ctrl etc)
    • List of modificator keys ids setup via component style (you can change it)
    • You can add several hotkeys on one callback via hotkey:add_hotkey with additional params
  • #98 [Layout] Add new extended component: Layout
    • It’s allow you to extend standart Defold node adjust modes
    • Layout mode can be next:
      • const.LAYOUT_MODE.STRETCH_X - Stretch node only by X
      • const.LAYOUT_MODE.STRETCH_Y - Stretch node only by Y
      • const.LAYOUT_MODE.ZOOM_MIN - Zoom node by minimal stretch multiplier
      • const.LAYOUT_MODE.ZOOM_MAX - Zoom node by maximum stretch multiplier
      • const.LAYOUT_MODE.FIT - Usual Defold Fit mode
      • const.LAYOUT_MODE.STRETCH - Usual Defold Stretch Mode
    • The Layout changes the node size property. So it’s look much better if you use 9slice nodes
    • Works even the node parent is have Fit adjust mode
  • #200 [Scroll] Glitch if content size equals to scroll view size in runtime
  • #201 [DataList] Update DataList:
    • Add two events: on_element_add and on_element_remove
    • Add data_list:get_data() to access all current data in DataList
    • Add data_list:get_created_nodes() to access currently visual nodes in DataList
    • Add data_list:get_created_components() to access currenly visual component in DataList (if created)
  • #190 [Progress] Add progress:set_max_size function to change max size of progress bar
  • #188 [Drag] Add two values passed to on_drag callback. Now it is on_drag(self, dx, dy, total_x, total_y) to check the overral drag distance
  • #195 [Drag] Add drag:is_enabled and drag:set_enabled to enable/disable drag input component
  • #186 [Grid] Fix: Method set_in_row works incorrectly with IS_DYNAMIC_NODE_POSES style option
  • #185 [System] Add on_window_resized component interest. It will called on game window size changes
  • #189 [System] Add optional flag to component:set_input_priority to mark it as temporary. It will reset to default input priority after the component:reset_input_priority
  • #204 [System] Fix: wrong code example link, if open example from direct URL
  • #202 [System] Enabled stencil check to true by default. To disable this, use druid.no_stencil_check in game.project settings
  • [Examples] Add layout, layout fit, progress bar, data list + component examples
12 Likes

I only recently started using Druid, and I’d just like to say:

Wow. It’s such a powerful and elegant tool. I haven’t yet bumped into anything that I haven’t been able to do. It has allowed me to remove my old rustic hand-rolled solutions for grids and scrolling that never quite seem to do what I want them to.

Thanks for making it! :star_struck:

11 Likes

Agreed with the above - very impressive!

Question to Insality or anyone else that may be using Druid. Is there an elegant way to manage input using keyboard or gamepad? I’ve searched this thread and the documentation but can’t find anything.

I target desktop (where people might use keyboard) and also Switch & Steam Deck (gamepads), which means navigating UI elements with keyboard/gamepads is a necessity for me.

3 Likes

My approach for mobile/PC is to switch to the used method; if a keyboard key is pressed the game uses keyboard + mouse, if touches are used the game uses touch input.

Maybe you could do the same for keyboard and gamepad?

1 Like

Thanks! I do something like this already, yes, for my own janky system.

However - and pardon me if I’m being obtuse - but how does that relate to Druid? I am wondering about things like handling input that isn’t touch/click (e.g. “clicking” things with Space/Enter or A on a gamepad), or moving focus from button to button using arrow keys or joystick/dpad. Does Druid do all of that somehow? I tried the example and it didn’t, and I searched the docs and this thread with no luck.

1 Like