Druid - Component GUI Framework

Now it works! Thanks.

3 Likes

Hello @Insality!

I recently updated Druid from version 0.9.1 to 0.11.0, which was a huge leap, requiring a few adjustments here and there.

However, I just need confirmation about one thing:

1/ When using a data_list in the game, the following message was displayed in the console:

DEBUG:SCRIPT: [Druid]: The component data_list is extended component. You have to register it via druid.register to use it
DEBUG:SCRIPT: [Druid]: Use next code:
DEBUG:SCRIPT: local data_list = require("druid.extended.data_list")
DEBUG:SCRIPT: druid.register("data_list", data_list)

So I added the registration as mentioned:

	self.data_list_items = require("druid.extended.data_list") -- druid 0.11.0
	druid.register("data_list", self.data_list_items) -- druid 0.11.0

	self.data_list_items = self.druid:new_data_list(self.scroll_items, self.grid_items, create_item_list)
	self.data_list_items:set_data(self.data_set_items)

And it seems to be working.

However, Iā€™m still wondering if this was the correct thing to do, as there is no ā€œdruid.registerā€ in the provided examples (specifically, data_list > static_grid) for Druid 0.11.0 :man_shrugging: (and it works fine :face_with_monocle:)

Can you confirm that it is necessary to use the druid.register in this way?

Right, all ā€œextendedā€ components should be register first to include them in your build

In Druid examples I register all extended components here

Better to include this code in your bootstrap script to donā€™t register again them each time

Thanks for the feedback! I will try to figure out how to describe this better

5 Likes

Is their any sample project for understaning how to use custom components. Iā€™m not understanding spawning and registering parts.

Trying something small
Iā€™m trying to create custom button component for navigation into other scenes. This buttons will have different icons in differnet scenes.

Hello!
Probably you can check this example:
Live example, code

or custom component documentation

In this example the custom component for data list are used.

Basically, the custom component is your lua file, that in simplest way will look like this:

local component = require("druid.component")

local ButtonComponent = component.create("button_component")

---@param template string
---@param nodes table<hash, node>
function ButtonComponent:init(template, nodes)
	self:set_template(template)
	self:set_nodes(nodes)
	self.druid = self:get_druid()

	self.root = self:get_node("root")
	self.button = self.druid:new_button(self.root, self._on_click)
end

function ButtonComponent:_on_click()
	self.on_click:trigger(self)
end

return ButtonComponent

And later you will create your component with self.druid:new(ButtonComponent, template, nodes)

Registering components are not required, itā€™s just to make aliases.
Example:

-- Direct component creation
local ButtonComponent = require("example.examples.data_list.with_component.button_component.button_component")
local button = self.druid:new(ButtonComponent, "button_component", nodes)

----- or ------

-- Register only once:
local druid = require("druid.druid")
local ButtonComponent = require("example.examples.data_list.with_component.button_component.button_component")
druid.register(ButtomComponent, "button_component")

-- And create component in this way
self.druid:new_button_component(template, nodes)

Donā€™t know about all your requirements, but isnā€™t it easier to custom icons right inside GUI file and add button over this GUI node?

Iā€™m just playing around this to learn this stuff. Even I donā€™t have clear idea right now when to use and not. I just gone through reading How to GUI in defold. Trying best practices from start of the project.

1 Like

@Insality , hello!
Is there updated examples on LangText? Link to source here leads to 404.

Hello!
Just checked the link now - it works. There are no any updates in this example

@Insality Hey! Thanks for the amazing work. When I was checking the scroll example, like you see in the ss, when the buttons com top of eachother, even though the expected behavior is go back to menu, it acts like if I clicked on the node button beneath and ignores the menu button click. It happens only when two buttons are aligned like this, just wanted to share.

1 Like

Thanks for sharing this! Iā€™ll fix it :slight_smile:

Just checked the link now - it works. There are no any updates in this example

This is how it looks for me. I click ā€œcodeā€ and get 404

1 Like

Oh, my mistake! Confirm there is a typo in example link, thanks!

Is there a way to make the Scroll component work with a View node with an Adjust Mode set to stretch?

In the video below the content is no longer contained within the view node once the window has been resized. It looks like it uses the original size for bounds, rather than the actual size?

Minimal example: Archive.zip (39.0 KB)

1 Like

Druid doesnā€™t re-calculate node sizes in non-fit adjust modes, so there probably isnā€™t a one-line way to achieve this.

As an idea, you could update the size of the view node manually to fit the game screen (with FIT adjust mode) and run code to update the view node sizes.

I use the following code with the Scroll component to refresh the view node sizes:
(itā€™s not a part of library, you should add this code to your Scroll component in this case)

--- Refresh scroll view size
-- @tparam Scroll self @{Scroll}
function Scroll.update_view_size(self)
	self.view_size = helper.get_scaled_size(self.view_node)
	self.view_border = helper.get_border(self.view_node)
	self:_update_size()
end
2 Likes

I have buttons with child images, and I was hoping to work with styles to change the look of all the button nodes when pressed.

Iā€™ve implemented a style, but gui.get_tree(node) doesnā€™t return the children. Is this the wrong method to use?

This is the relevant code from my style


function M.get_children(node)
    if children_count == -1 then
        -- print(gui.get_id(node))
        -- print(table.concat(gui.get_tree(node))) -- print table content
        children = gui.get_tree(node) -- get the children
        children_count = #children
        print("got children : " .. tostring (children_count))
        for k, v in pairs(children) do
            if k ~= node then -- we have no interest in the root
                -- do something with children
            end
        end
    end
end

M["button"] = {
	NORMAL_COLOR = vmath.vector4(1, 1, 1, 1),
	HOVER_COLOR = vmath.vector4(0.8, 0.8, 0.8, 1),

	on_click = function(self, node)
		sound_playclick()
	end,

	on_set_enabled = function(self, node, state)
        M.get_children(node)
		if state then
		    gui.set_color(node, M.button.NORMAL_COLOR)
		else
		    gui.set_color(node, M.button.HOVER_COLOR)
		end
	end,

	on_hover = function(self, node, state)
        M.get_children(node)
		if state then
			gui.set_color(node, M.button.HOVER_COLOR)
		else
			gui.set_color(node, M.button.NORMAL_COLOR)
		end
	end,
}

use self:get_node("node") instead :slight_smile:

Thanks, but not liking that either. I must be missing the obvious.

The node passed in the style is already actually a node. You donā€™t need to call the druidā€™s self:get_node

The children_count = #children should return 0 since children is a key-value table, not a array. Also you can pprint children to see if it actually get all your nodes

1 Like

Worked perfectly, many thanks - Druid is immense.

Is there a way to ensure that the hover style only works on the button that is initially pressed?

Currently if I press one button the hover style changes, but if I continue pressing and move to another button then the hover style on that one activates.

Iā€™d like it so hover is exclusive to the first button pressed if possible.

1 Like