Using Lua to detect a combination of keyboard key

2019-08-02 04:20发布

问题:

I'm in the middle of writing a World of Warcraft addon and I want the addon to be able to perform certain functions based on a key press or a combination of key presses. Most of the key states are protected WoW API functions now but the following are still able to be used by addons:

IsAltKeyDown()
IsControlKeyDown()
IsShiftKeyDown()

What I'd like to be able to do is perform a function based on any one of those keys down or a combination there of.

This is what I've got working:

function KeyCombos()
    total = 0
    if IsShiftKeyDown() then
        total = total + 1
    end
    if IsControlKeyDown() then
        total = total + 2
    end
    if IsAltKeyDown() then
        total = total + 4
    end
end

Now my question isn't necessarily about Lua, as the above function is working as I can check if total equals 6 for example to see if Control and Alt are both pressed. My question is more of an algorithmic one. Is there a better way to perform this programmaticly?

回答1:

If you are going to use a table, in the general case it would be much better to keep the same table.

function KeyCombos()
    keys = keys or {}

    keys.shift = IsShiftKeyDown()
    keys.control = IsControlKeyDown()
    keys.alt = IsAltKeyDown()
end

or, if you rather

function KeyCombos()
    if not keys then
        keys = {}
    end

    keys.shift = IsShiftKeyDown()
    keys.control = IsControlKeyDown()
    keys.alt = IsAltKeyDown()
end

The original example in the question, however, is much more performant using integer math.


However these examples all create globals. So:

function GetKeyCombos()
    local keys = 0

    if IsShiftKeyDown() then
        keys = keys + 1
    end
    if IsControlKeyDown() then
        keys = keys + 2
    end
    if IsAltKeyDown() then
        keys = keys + 4
    end

    return keys
end

would be much better. In WoW all AddOns share the same global environment so its best to keep it clean.



回答2:

Seems pretty sound to me already.

As an alternative, however, you could use a table:

function KeyCombos()
    keys = {
        shift = IsShiftKeyDown(),
        control = IsControlKeyDown(),
        alt = IsAltKeyDown(),
    }
end

Then you could call keys.alt or keys["alt"] to see if it's pressed.

More readable? Probably. More efficient? Not likely. But I'm not very knowledgeable when it comes to Lua's performance.

I would just add a comment block above the KeyCombos function stating every possible combination and what it means.

As a side note, it's Lua, not LUA.