multitheftauto / mtasa-blue

Multi Theft Auto is a game engine that incorporates an extendable network play element into a proprietary commercial single-player game.
https://multitheftauto.com
GNU General Public License v3.0
1.4k stars 432 forks source link

Expand addEventHandler's functionality to support css-like selectors #1564

Open Pirulax opened 4 years ago

Pirulax commented 4 years ago

Is your feature request related to a problem? Please describe. Well, kinda. If you have event handlers on root, with very common events(eg.: onClientElementDataChange) you can run into a bottleneck where calling the event handlers takes 10x the time of setting the data)

Describe the solution you'd like Add css-like selectors to element data, that pre-checks the arguments, eg.:

addEventHandler("onClientElementDataChange", "player[acc.id!=10]", handler, "dataName=acc.id;oldValue=10")

The event handler in this case the handler will be attached to all player elements that have an elementData called acc.id, and is not equal to 10. The handler is only called if dataName=acc.id, and oldValue=10. (by the current syntax after the handler function you have bPropagate, but having to type out true, "normal" every time would be ugly IMHO)

Describe alternatives you've considered Some kind of function factory that pre-filters things, and only calls the real handler if it matches the specifications. But that wouldn't solve the performance issues of the current implementation which this feature aims to improve. Also, it would improve code readability.

Additional context I'd like to implement some CSS selectors according to this document. Namely: Selector Example Example description
element type vehicle Selects all vehicle elements
[elementData=value] [acc.id=10] Selects all elements with the element data named acc.id equal to 10
[elementData] [loggedin] Selects all elements that have the element data loggedin (same as checking with hasElementData)

A complex selector: player[acc.id!=10, loggedin] This would select all players with acc.id not equal to 10 and with the element data loggedin

And such, you got the idea probably

Pirulax commented 4 years ago

the handler argument filtering is pretty stupid with argument names. it would be better, and easier to use, if it would be based on the position of the argument. Eg.: Instead of

addEventHandler("onClientElementDataChange", "player[acc.id!=10]", handler, "dataName=acc.id;oldValue=10")

this:

addEventHandler("onClientElementDataChange", "player[acc.id!=10]", handler, "acc.id, 10")

but now i the problem is how the user should skip arguments? Eg.: We only want to check the 2nd parameter, and the 4th. maybe [2]=10 could be used? (2 indicating the index, and 10 the value)

ds1-e commented 4 years ago

This sounds great. I had similar idea, but not sure if i should create feature request for it. Basically i'd love to see tables implemented into it. Excluding setElementParent due of:

For example:

local guiWindow = guiCreateWindow(...)
local guiText = guiCreateLabel(...)

function onClientGUIClick(...)
    print("Yay!")
end
addEventHandler("onClientGUIClick", {guiWindow, guiText}, onClientGUIClick)
qaisjp commented 4 years ago

This should already work (corrected for onClientResourceStart):

local guiWindow, guiText

function onClientGUIClick(...)
    print("Yay!")
end

addEventHandler("onClientResourceStart", resourceRoot, function()
    guiWindow = guiCreateWindow(...)
    guiText = guiCreateLabel(...)

    local parent = createElement("gui-parent")
    guiWindow.parent = parent
    guiText.parent = parent
    addEventHandler("onClientGUIClick", parent, onClientGUIClick)
end)
ds1-e commented 4 years ago

Well i tested and actually it doesn't work. I assume it's due of #314

local guiWindow = guiCreateWindow(100, 100, 100, 100, "test", false, nil)
local parent = createElement("gui-parent")

setElementParent(guiWindow, parent)

iprint(getElementChildrenCount(parent))

It returns 0. But anyways it might not be good choice to use setElementParent. Why? As i mentioned before, one element can only have one parent at same time. That is if i would be up to have certain element in parent A & B, it wouldn't be possible to have it in both groups.