Гайд Фикс бага с фокусом в InputText (imgui)

Cosmo

Известный
Автор темы
Друг
653
2,724
Примеры: раз / два / три / четыре

bug.gif


Обычно её решают перезагрузкой скрипта, но есть варик получше, и даже почти не костыль!
Вызываете эту функцию вместе с открытием окна c потенциально-забагованным инпутом и дело в шляпе.
Её суть в том, что она "отжимает" все нажатые клавиши и баг пропадает.

Lua:
function resetIO()
    for i = 1, 512 do
        imgui:GetIO().KeysDown[i] = false
    end
    for i = 1, 5 do
        imgui:GetIO().MouseDown[i] = false
    end
    imgui:GetIO().KeyCtrl = false
    imgui:GetIO().KeyShift = false
    imgui:GetIO().KeyAlt = false
    imgui:GetIO().KeySuper = false     
end
Lua:
function resetIO()
    for i = 0, 511 do
        imgui.GetIO().KeysDown[i] = false
    end
    for i = 0, 4 do
        imgui.GetIO().MouseDown[i] = false
    end
    imgui.GetIO().KeyCtrl = false
    imgui.GetIO().KeyShift = false
    imgui.GetIO().KeyAlt = false
    imgui.GetIO().KeySuper = false
end
 
Последнее редактирование:

Gorskin

♥ Love Lua ♥
Проверенный
1,332
1,169
Причину бага этого знаешь? У меня был этот баг давно ещё когда я использовал закрытие окна на esc. Как ни странно решалось это так: при выполнении функции закрытия окна я ставил значение переменной окна например: renderWindow = imgui.new.bool(false)
А не писал renderWindow[0] = false или renderWindow[0] = not renderWindow[0]
 

Tema05

Известный
1,471
435
Так есть уже нормальный фикс этого через onWindowMessage, сделанный миллиард лет назад. Всю жизнь его использовал. Чем этот вариант интересен?
 
Последнее редактирование:

#Northn

Pears Project — уже запущен!
Всефорумный модератор
2,650
2,535
Lua:
addEventHandler("onWindowMessage", function(msg, wparam, lparam)
    if not canShowMainWindow() then
        return
    end
    if (msg == win.msg.WM_KEYDOWN or msg == win.msg.WM_SYSKEYDOWN) then
        if (wparam == vkeys.VK_ESCAPE and canShowMainWindow()) then
            consumeWindowMessage(true, false)
            return
        end
    elseif (msg == win.msg.WM_KEYUP or msg == win.msg.WM_SYSKEYUP) then
        if (wparam == vkeys.VK_ESCAPE and canShowMainWindow()) then
            showMainWindow = false
            return
        end
    end
end)
Вот такое решение используется здесь:
 

Cosmo

Известный
Автор темы
Друг
653
2,724
Причину бага этого знаешь?
Имгуи не успевает обработать KeyUP событие для клавиши и завершает imgui.Process с "зажатой" клавишей. Тем самым при следующем открытии окна имгуи думает что эта клавиша всё еще зажата и не даёт ничего сделать (объяснил как мог и сам понимаю)

Чем этот вариант интересен?
Когда много разных окон это может быть полезно. Не надо делать под каждую переменную условие в onWindowMessage
 

Andrinall

Известный
702
518

СоМиК

Известный
458
314
Даю небольшой лайфхак во избежание этого бага: если делаете закрытие окна по ESCAPE, отслеживайте не нажатие клавиши в OnWindowMessage, а отпускание, т.е KeyUP.

Космо выше указал всё верно, сам сталкивался с такой проблемой и интересовался у других людей.

Имгуи отлавливает нажатия при вкл. процессе, то есть при открытых окнах, если во время того, как все окна закрылись, был нажат эскейп (а как мы знаем и понимаем, если мы сделаем закрытие окна на нажатие, а не отпускание, то закрытие окна, а значит отключение имгуи процесса, обработается быстрее, чем человек отпустит клавишу и имгуи ее обработает). Соответственно баг также можно пофиксить и без перезагрузки скрипта, если просто успеть отпустить эскейп при повторном открытии окна. Тогда ImGUI поймает событие KeyUP и бага не будет.

Ну, конечно, этот лайфхак поможет только тем, кто не хочет сувать в свой код что-то вроде выше указанного костыля

Также, я думаю вы уже поняли, что раз инпуты перестают работать, значит имгуи закрывает их при активном KeyDown.

Так вот спроецируем ситуацию, пользователь открыл инпут, что то туда вписал, а теперь хочет закрыть его, отменив все действия. Для этого он нажмёт ESCAPE. Из за того, что имгуи по умолчанию закрывает инпут по событию KeyDown, то при срабатывании события KeyUP (когда мы опустим клавишу), наше окно просто напросто закроется. Но как же быть? Ведь мы просто хотели убрать фокус с инпута, отменив всё, что туда вписали, мы не хотели закрывать окно! И тут поможет очередной костыль. Просто добавляем какую нибудь переменную, которая будет сидеть где то в самом конце имгуишки и возвращать себе стейт любого фокуса (isAnyItemFocused или как то так). Теперь, благодаря этой переменной, строим необходимую проверку в onWindowMessage и в случае чего - просто ничего не делаем, не закрываем окно. Вуаля. Теперь, без всяких ResetIO и т.д, мы получаем рабочий фикс эскейпа + закрытие окна на эскейп + нормальную работу с фокусами
 

baligins

Участник
42
12
Примеры: раз / два / три / четыре

Посмотреть вложение 225137

Обычно её решают перезагрузкой скрипта, но есть варик получше, и даже почти не костыль!
Вызываете эту функцию вместе с открытием окна c потенциально-забагованным инпутом и дело в шляпе.
Её суть в том, что она "отжимает" все нажатые клавиши и баг пропадает.

Lua:
function resetIO()
    for i = 1, 512 do
        imgui:GetIO().KeysDown[i] = false
    end
    for i = 1, 5 do
        imgui:GetIO().MouseDown[i] = false
    end
    imgui:GetIO().KeyCtrl = false
    imgui:GetIO().KeyShift = false
    imgui:GetIO().KeyAlt = false
    imgui:GetIO().KeySuper = false    
end
Lua:
function resetIO()
    for i = 0, 511 do
        imgui.GetIO().KeysDown[i] = false
    end
    for i = 0, 4 do
        imgui.GetIO().MouseDown[i] = false
    end
    imgui.GetIO().KeyCtrl = false
    imgui.GetIO().KeyShift = false
    imgui.GetIO().KeyAlt = false
    imgui.GetIO().KeySuper = false
end
то что нужно, оценил