Use serpent for LuaGuiElement names?

Place to post guides, observations, things related to modding that are not mods themselves.
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Use serpent for LuaGuiElement names?

Post 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?
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Use serpent for LuaGuiElement names?

Post by aubergine18 »

Even better if the Factorio API had .mod and .meta properties on gui elements themselves: viewtopic.php?f=28&t=31738
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
User avatar
Adil
Filter Inserter
Filter Inserter
Posts: 945
Joined: Fri Aug 15, 2014 8:36 pm
Contact:

Re: Use serpent for LuaGuiElement names?

Post 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
I do mods. Modding wiki is friend, it teaches how to mod. Api docs is friend too...
I also update mods, some of them even work.
Recently I did a mod tutorial.
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Use serpent for LuaGuiElement names?

Post by aubergine18 »

GUI elements already have a .player property to determine which player the GUI is related to.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
Post Reply

Return to “Modding discussion”