Page 1 of 1

Use serpent for LuaGuiElement names?

Posted: Sun Aug 28, 2016 5:58 am
by aubergine18
I've been struggling a lot with GUI stuff recently, in particular trying to find a better way to accurately identify and process events triggered by LuaGuiElement. I'm working on a massive refactor of narc's EvoGUI - greatly extending the ability for mods to define sensors, but also adding things like a toolbar, custom HUDs, sidebar manager, options API, notification API, etc., and the GUI stuff is a major pain. Common tasks involve:

* Is the event-triggering element something to do with my mod?
* If so, where should I route the event to handle it?
* And what is the best way to associate metadata with an element?

One of the things I'm about to try (in the next week or two) is putting required data in a table, then using Serpent to serialise that information to something that can be used as an element .name. This way, when an event is fired, I can have Evo deserialise the .name and send a much more descriptive event that mods can handle without the usual jumping through hoops - in particular, I can send the event to a specific mod.

While this might sound like overkill, GUI events aren't triggering thousands of times a second - there's a very limited rate at which a user will be clicking or changing stuff in mod-generated GUI...

Here's a rough sketch of the mandatory stuff that would appear in tables:

Code: Select all

local name = {
  mod = 'my_mod_name';
  id = 'my_element_id';
  task = 'name_of_method_to_call';
}
When serialised, the GUI element name will look something like this:

Code: Select all

{mod='my_mod_name',id='my_element_id',task='name_of_method_to_call'}
To determine if an element is using a serialised object name, the deserialiser would check first char is a '{' and then simply 'loadstring()' it.

The method name could be a method in remote interface, thus Evo could potentially listen to all GUI events and when it detects a serialised name it does a remote.call() to the specific method in a mods remote interface. The mod itself would no longer need to listen to GUI events, it would simply have it's remote methods called when appropriate with the element and metadata passed in as properties of a table in the first parameter. IMO this would make code in mods a lot cleaner - their remote interface would be the gateway to handling GUI events through named methods, rather than crufty GUI event handlers and associated element classification that's currently required.

I'm just putting this here to see if anyone has better ideas, comments or observations?

Re: Use serpent for LuaGuiElement names?

Posted: Sun Aug 28, 2016 6:55 am
by aubergine18
Even better if the Factorio API had .mod and .meta properties on gui elements themselves: viewtopic.php?f=28&t=31738

Re: Use serpent for LuaGuiElement names?

Posted: Sun Aug 28, 2016 7:47 am
by Adil
Your data doesn't provide the means to identify which player's gui is clicked.
I've been using a wrapper over standard gui functions to provide the metadata. Most of it was lost due to accident, but to outline:

Whenever a gui was created, the following structure was associated with player:

Code: Select all

gui={
    metadata={},--anything goes here
    container={ --typically associated with frame\ flow\ table
        anchor=reference_associated_element,
        elements={ 
            {element = gui_element,callback=function(metadata)},--pairs of buttons and their callbacks with no closures
        },
        children={--other containers
        },
    }
}
This way the on_click identification was handled by simple recursive function:

Code: Select all

function click_handler(container, clicked_element, metadata )
    for _, e in pairs(container.elements) do
        if e.element == clicked_element then
            e.callback(metadata)
            return
        end
    end
    for _,c in pairs(container.children) do
        click_handler(c, clicked_element, metadata )
    end
end
It was mostly convenient as you could put callback functions next to creation of the elements themselves.
There's also this good idea viewtopic.php?f=28&t=14907&p=100952#p101572

Re: Use serpent for LuaGuiElement names?

Posted: Sun Aug 28, 2016 9:02 am
by aubergine18
GUI elements already have a .player property to determine which player the GUI is related to.