Set a button's onclick function from anywhere

Trying to figure out the best way to change what a click on a particular button does anywhere in the code. Here’s what I have.

Let’s say I have a menu table full of button tables in my gui script, something like:

local menu = {
  button0 = {
    node = "button0",
    label = "Click me"   
  }
}

Here’s my use case. The player is presented with a text screen and a row of buttons with choice labels. Upon clicking a button, a function is called that changes the text field, the button labels, and the button functions to match new choices within that function. Basically a CYOA system.

I want to set what happens when I click this button with something like:

setButton(menu.button0, "New label", function)

I know I can’t put a function call into a table, nor can I pass a function directly through a message.

I can only think of three solutions right now:

  • Pass strings and convert them into functions, usually a bad idea.

  • Make a set of global variables to hold the function calls in the GUI script and have my on_input functions grab those, then set those variables through setButton. This seems to work but feels clunky.

  • FInd out something new about the messaging system I haven’t figured out yet. When all the function does is return a block of text, the messaging system works great but if things are halting after each function to wait for a further response that gets strange.

What’s the best Defold-oriented method of handling this situation?

I think I may have figured it out. I don’t need to pass the function, I need to pass an event and a URL held in the object and set up a message to kick off the next function. So something like:


-- GUI Script
menu = {
  button0 = {
    node = "button0",
    label = "Old Label",
    url = "/menus#mainMenus",
    event = "mainDisplay"
  }
}

--If button is chosen...
msg.post(menu.button0.url, menu.button0.event)

--mainMenus.script
if (message_id == hash("mainDisplay") then
  menu.button0.url = ...
  menu.button0.event =...  

I’ll make a nicer function to keep the menu object local, but I think this will work. I’ll have to play with it for a bit.