[mimgui] Проблема с HotKey'ями

Dmitriy Makarov

25.05.2021
Автор темы
Проверенный
2,500
1,130
Версия MoonLoader
.027.0-preview
Помогите. Может, вопрос немного глуповат и легче, чем мне кажется, но я не могу его решить..

Столкнулся с неприятной проблемой во время создания биндера. Проблема с HotKey'ями. Использую (эту) библиотеку.
Пользователь может создавать неогр. кол-во биндов, указывая в BeginPopupModal команаду/хоткей/задержку/текст, и бинд должен привязываться к ним, но я не могу так сделать с ХотКеем.
Lua:
local config = {}

-- main()
HotKey = hotkey.RegisterHotKey("##", false, (#config > 0 and config[1].bindKey or {}), function() -- Проблема в основном тут. Выполняется бинд всех ХотКеев, работает только один ХотКей.
    for k, v in pairs(config) do
      lua_thread.create(function()
         for line in v.bindText:gmatch('[^\n]+') do
            sampAddChatMessage(line, -1)
            wait(v.bindDelay * 1000)
         end
      end)
   end
end)


-- OnDrawFrame()
-- BeginPopupModal
HotKey:ShowHotKey(imgui.ImVec2(100, 20))
imgui.SameLine()
imgui.Text(u8"Клавиша")

if imgui.Button(u8"Создать", imgui.ImVec2(-1, 30)) then
    table.insert(config, {bindKey = HotKey:GetHotKey()})
    JSONSave()
    imgui.CloseCurrentPopup()
end

Я так понял, что это из-за одинаковых названий ХотКеев в main'е, но я не знаю, как там обойтись без цикла for. А с циклом for это, возможно, работало бы, как и команды, однако в OnDrawFrame отображение хоткея (18-я строка) ругается на то, что "attempt to index global 'HotKey' (a nil value)" (Это где main(), в 4-й строке).
Lua:
-- main()
for k, v in pairs(config) do
    HotKey = hotkey.RegisterHotKey("##"..k, false, {}, function() -- Вот так, я думаю, работало бы, ибо названия ХотКеев были бы разными. По отдельности работают.
        -- Тут отправка бинда, как выше.
    end)
end

-- Но в OnDrawFrame ShowHotKey ругается на "HotKey".

P.S: Убрал код с лишними элементами, чтобы не запутаться. Также внизу видеодемонстрация. (Поставил скрипт для отображения нажатых клавиш, чтобы наглядно было)
Видео:
JSON:
1697873294678.png

Пробовал такое замутить - не работает:
Lua:
-- Беск. цикл.
for i = 1, #config do
    if isKeyJustPressed(config[i]["bindKey"]) then -- decodeJson пробовал. Мне пишут что-то вроде "The document is empty".
        sampAddChatMessage(config[i]["bindName"], -1)
    end
end
Хотя вот так всё выводит:
Lua:
for i = 1, #config do
    sampAddChatMessage(config[i]["bindName"], -1)
end
 
Решение
В общем. Я это, вроде как, решил. По крайней мере, всё работает так, как мне нужно.

Взята была функция isKeysDown отсюда.
И функция string.split отсюда. (Т.к AnWu в сниппете выше не выложил её. Или я просмотрел)
Lua:
-- main
HotKey = hotkey.RegisterHotKey("##", false, {}, function() end)

-- Беск. цикл
for _, v in pairs(config) do
    if isKeysDown(table.concat(v.bindKey, " ")) then --
        lua_thread.create(function()
            for line in v.bindText:gmatch('[^\n]+') do
                sampAddChatMessage(line, -1)
                wait(v.bindDelay * 1000)
            end
        end)
    end
end


--

function string.split(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={} ...

Rice.

Известный
Модератор
1,752
1,606
Помогите. Может, вопрос немного глуповат и легче, чем мне кажется, но я не могу его решить..

Столкнулся с неприятной проблемой во время создания биндера. Проблема с HotKey'ями. Использую (эту) библиотеку.
Пользователь может создавать неогр. кол-во биндов, указывая в BeginPopupModal команаду/хоткей/задержку/текст, и бинд должен привязываться к ним, но я не могу так сделать с ХотКеем.
Lua:
local config = {}

-- main()
HotKey = hotkey.RegisterHotKey("##", false, (#config > 0 and config[1].bindKey or {}), function() -- Проблема в основном тут. Выполняется бинд всех ХотКеев, работает только один ХотКей.
    for k, v in pairs(config) do
      lua_thread.create(function()
         for line in v.bindText:gmatch('[^\n]+') do
            sampAddChatMessage(line, -1)
            wait(v.bindDelay * 1000)
         end
      end)
   end
end)


-- OnDrawFrame()
-- BeginPopupModal
HotKey:ShowHotKey(imgui.ImVec2(100, 20))
imgui.SameLine()
imgui.Text(u8"Клавиша")

if imgui.Button(u8"Создать", imgui.ImVec2(-1, 30)) then
    table.insert(config, {bindKey = HotKey:GetHotKey()})
    JSONSave()
    imgui.CloseCurrentPopup()
end

Я так понял, что это из-за одинаковых названий ХотКеев в main'е, но я не знаю, как там обойтись без цикла for. А с циклом for это, возможно, работало бы, как и команды, однако в OnDrawFrame отображение хоткея (18-я строка) ругается на то, что "attempt to index global 'HotKey' (a nil value)" (Это где main(), в 4-й строке).
Lua:
-- main()
for k, v in pairs(config) do
    HotKey = hotkey.RegisterHotKey("##"..k, false, {}, function() -- Вот так, я думаю, работало бы, ибо названия ХотКеев были бы разными. По отдельности работают.
        -- Тут отправка бинда, как выше.
    end)
end

-- Но в OnDrawFrame ShowHotKey ругается на "HotKey".

P.S: Убрал код с лишними элементами, чтобы не запутаться. Также внизу видеодемонстрация. (Поставил скрипт для отображения нажатых клавиш, чтобы наглядно было)

Пробовал такое замутить - не работает:
Lua:
-- Беск. цикл.
for i = 1, #config do
    if isKeyJustPressed(config[i]["bindKey"]) then -- decodeJson пробовал. Мне пишут что-то вроде "The document is empty".
        sampAddChatMessage(config[i]["bindName"], -1)
    end
end
Хотя вот так всё выводит:
Lua:
for i = 1, #config do
    sampAddChatMessage(config[i]["bindName"], -1)
end
Моё предположение, что config["bindKey"] у тебя сохраняется неправильно, из-за этого проверка ломается
 
  • Нравится
Реакции: Dmitriy Makarov

Dmitriy Makarov

25.05.2021
Автор темы
Проверенный
2,500
1,130
Моё предположение, что config["bindKey"] у тебя сохраняется неправильно, из-за этого проверка ломается
Ну хз, я сделал через for регистрацию ХотКеев и всё нормально работает до тех пор, пока не открою меню создания бинда, где у меня ХотКей стоит. Там уже, как я говорил, скрипт крашится с ошибкой:
"attempt to index global 'HotKey' (a nil value)"
Lua:
for k, v in pairs(config) do
    HotKey = hotkey.RegisterHotKey("##"..k, false, (#config > 0 and v.bindKey or {}), function()
        lua_thread.create(function()
            for line in v.bindText:gmatch('[^\n]+') do
                sampAddChatMessage(line, -1)
                wait(v.bindDelay * 1000)
            end
        end)
    end)
end
 

Musaigen

abobusnik
Проверенный
1,604
1,361
Код максимально странный. На одну переменную регается N биндов, а клавиша активации подтягивается с самого первого бинда (config[1].bindKey), ну и собственно при ее нажатии активируются вообще все имеющееся бинды в локальных таблицах библиотеки, используемой тобой.

Похоже, проблема как раз в config[1].bindKey
 
  • Нравится
Реакции: Dmitriy Makarov

Dmitriy Makarov

25.05.2021
Автор темы
Проверенный
2,500
1,130
Похоже, проблема как раз в config[1].bindKey
Ну я по-другому не знаю, как туда запихнуть N количество биндов из JSON'а, без цикла for. Если я оставлю просто {} там, у меня после перезагрузки клавиши работать не будут, так как ХотКей не берётся откуда-то.
Если цикл for добавить, то я не смогу создавать бинды, ибо HotKey:GetHotKey() с OnDrawFrame не будет видеть HotKey из цикла в main'е.
Вот в сообщении над твоим сообщением я сделал это нормально и всё работают клавиши, но я не могу создавать новые бинды.
 

Musaigen

abobusnik
Проверенный
1,604
1,361
Ну я по-другому не знаю, как туда запихнуть N количество биндов из JSON'а, без цикла for. Если я оставлю просто {} там, у меня после перезагрузки ничего работать не будет, так как ХотКей не берётся ни откуда.
Если цикл for добавить, то я не смогу создавать бинды, ибо HotKey:GetHotKey() с OnDrawFrame не будет видеть HotKey из цикла в main'е.
Вот в сообщении над твоим сообщением я сделал это нормально и всё работают клавиши, но я не могу создавать новые бинды.
в библиотеке можно отображать, редактировать бинды по их названию.

hotkey.ShowHotKey("##1")

Достаточно цикла for в OnShowFrame.
 
  • Нравится
Реакции: Dmitriy Makarov

Rice.

Известный
Модератор
1,752
1,606
Ну я по-другому не знаю, как туда запихнуть N количество биндов из JSON'а, без цикла for. Если я оставлю просто {} там, у меня после перезагрузки клавиши работать не будут, так как ХотКей не берётся откуда-то.
Если цикл for добавить, то я не смогу создавать бинды, ибо HotKey:GetHotKey() с OnDrawFrame не будет видеть HotKey из цикла в main'е.
Вот в сообщении над твоим сообщением я сделал это нормально и всё работают клавиши, но я не могу создавать новые бинды.
если срочно нужны бинды, то могу свои наработки скинуть
тг: @Xkelling
 
  • Нравится
Реакции: Dmitriy Makarov

Dmitriy Makarov

25.05.2021
Автор темы
Проверенный
2,500
1,130
В общем. Я это, вроде как, решил. По крайней мере, всё работает так, как мне нужно.

Взята была функция isKeysDown отсюда.
И функция string.split отсюда. (Т.к AnWu в сниппете выше не выложил её. Или я просмотрел)
Lua:
-- main
HotKey = hotkey.RegisterHotKey("##", false, {}, function() end)

-- Беск. цикл
for _, v in pairs(config) do
    if isKeysDown(table.concat(v.bindKey, " ")) then --
        lua_thread.create(function()
            for line in v.bindText:gmatch('[^\n]+') do
                sampAddChatMessage(line, -1)
                wait(v.bindDelay * 1000)
            end
        end)
    end
end


--

function string.split(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={} ; i=1
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        t[i] = str
        i = i + 1
    end
    return t
end

function isKeysDown(keylist)
    local tKeys = string.split(keylist, " ")
    local bool = false
    local isDownIndex = 0
    local key = #tKeys < 2 and tonumber(tKeys[1]) or tonumber(tKeys[2])
    local modified = tonumber(tKeys[1])
    if #tKeys < 2 then
        if not isKeyDown(VK_RMENU) and not isKeyDown(VK_LMENU) and not isKeyDown(VK_LSHIFT) and not isKeyDown(VK_RSHIFT) and not isKeyDown(VK_LCONTROL) and not isKeyDown(VK_RCONTROL) then
            if wasKeyPressed(key) then
                bool = true
            end
        end
    else
        if isKeyDown(modified) and not wasKeyReleased(modified) then
            if wasKeyPressed(key) then
                bool = true
            end
        end
    end
    if nextLockKey == keylist then
        bool = false
        nextLockKey = ""
    end
    return bool
end

Спасибо за то, что откликнулись и постарались помочь. <3
 
  • Нравится
Реакции: Rice.