How to make node match the size of the button's texture and get input from pressing buttons (SOLVED)

I’m currently in the process of figuring out how to make clickable buttons in defold. I have a collection of my pngs, made a node, and chose which texture to use with it.

The problem right now is, my button is a circle and the pie node is an oval which is longer on the sides. If i change the shape of the node, the texture changes with it. It’s a minor problem I know (I’m sure I could have a playable game without it), but I wanted to know if there was a way to make it more 1:1.

(Also, if there is any tutorials or instructions on how to make and code clickable buttons, that would be nice).

I would recommend that you use a simple box node instead of a pie node (even though your button is round). A box node has a property called Size Mode which can either be Auto or Manual. If you set it to Auto it will adjust it’s size to that of the image.

If you want to get some inspiration for how to create buttons then perhaps you could take a look at Dirty Larry? The basics are:

  • Create a box node for the button background. Use 9-slicing to get nice corners that don’t stretch when you resize the button.

  • Optionally add a text node as a child

  • Optionally create the above node(s) as a GUI template for easy reuse

  • Create a gui script and make sure to acquire input focus

  • In on_input() do something like this:

      function on_input(self, action_id, action)
      	if action_id == hash("touch") then
      		if action.released then
      			if gui.pick_node(gui.get_node("myboxnode"), action.x, action.y) then
      				print("Button has been pressed")
      			end
      		end
      	end
      end
    

The above would be the bare minimum to deal with user input for a single button. You probably also want to check if the button is enabled (using gui.is_enabled). It’s also likely that you wish to change visual representation while the button is pressed. Do this either by changing graphics usign gui.play_flipbook() or perhaps using gui.set_color().

1 Like

Thanks. This really helps.

Quick thing, I’m having trouble opening up the Dirty Larry example you gave me and running it on my laptop. I’ve been trying to cop the master file over and replace it but it doesn’t seem to notice it. Is there a file in there I should be opening up or am I copying the files to the wrong place?

You don’t have to copy anything. Dirty Larry is a library project, meaning that it is intended to be included in other projects as a dependency. You should open your project’s game.project file, and in the dependencies field under the project section you add:

https://github.com/andsve/dirtylarry/archive/master.zip

Once this is done you can do Project->Fetch Libraries to get a read only version of Dirty Larry included in your project automatically.

Question about the code sample you gave me. I tried it out on my project. I changed the name from myboxnode to the ID of one of my nodes, changed the input to recongnize MOUSE_LEFT_BUTTON as touch, and tried to print “Button has been pressed” after clicking it but nothing happens. Thinking that maybe I wasn’t looking at the right place for printing, I changed the print to a set color instead using a color I know would look different (I tested the color in the editor and then copied the numbers) but it still does nothing when I click it. I have my script included in my gui. Is there anything I might have missed?

Also, where do things get printed to in defold? Is it the console?

Edit: I did create a gameobject to hold my gui in main.collection and the buttons show up on screen. They just don’t seem to do anything when I click.

Are there any input events coming in at all?
A common trick is to add a print inside the on_input:

function on_input(self, action_id, action)
    print(action_id)
    pprint(action)
end

If there are no events coming in, then perhaps the input focus wasn’t acquired (see @britzl’s link above)

I’m guessing that it is one of two things: either you haven’t acquired input focus (does on_input get called at all?) or you haven’t added the gui.script to your .gui scene.

Oh, so you just past it in here. That’s interesting





Print is supposed to appear under console right? I’m not getting anything when I click on the buttons.

1 Like

It looks mostly right to me, but it seems you are not acquiring input focus in your init function.
Try adding this to your buttons.gui_script:

function init(self)
    print("Acquiring input focus")
    msg.post(".", "acquire_input_focus")
end
2 Likes

Ay, it worked. Thanks.

1 Like

Good that we managed to sort it out! I encourage you to read the Input manual to also understand how the engine works when multiple scripts have acquired input focus and how it works when a collection that was loaded using a collection proxy has acquire input focus.

1 Like