Выровнять окно imgui по центру не имея его начальных размеров

Статус
В этой теме нельзя размещать новые ответы.

Belo4ka_belka

Известный
Автор темы
191
7
Здравствуйте, опишу проблему более подробно теперь. Имеется окно imgui которое берет данные из ини файла и их отображает. Текста может быть много а может быть мало, сейчас для генерации случайных значений использую АХК на подхвате, не суть. Задача: задать окну минимально и максимально возможные размеры а так же чтобы размер окна при этом зависел от количества текста (флаг 64 в begin) и создаваемое окно каждый раз выравнивалось по центру экрана (именно чтобы центр окна был в центре экрана а не его верхний левый угол). Приведенный мной код впринципе решает задачу, но есть проблемы, я опишу проблемы которые нашел и пути их решения которые я вижу. Начну с проблем:
1) Не столь критичная, но неприятная: использую команду SetWindowPos уже после begin т.к. мне неизвестен размер окна до того как я его создам (привет флагу 64) и поэтому на первом кадре окно создается хрен знает где, а уже на втором только оно выравнивается (а пользователь на экране видит телепортацию окна (5 секунда на видео).
2) При резком изменении размера окна в большую сторону по сравнению со стандартным значением заданным SetNextWindowSizeConstraints изменение размера окна (видимо под влиянием флага 64) происходит довольно медленно и плавно что недопустимо вовсе (8 секунда на видео). Кстати интересно почему окно так сильно потолстело если текст даже половины ширины не занял (строка инпута подгоняется под ширину окна после текста)?
3) При резком изменении размера окна в меньшую сторону (если до этого было активно окно большего размера) изменение размера происходит ещё более медленно и плавно что так же недопустимо (14 секунда на видео).
Теперь варианты решений которые я вижу:
1) Для пункта 1 хочу попытаться скрыть окно imgui на несколько кадров но чтобы процесс имгуи при этом был активен. Таким образом первые несколько кадров окно будет невидимым но все расчеты и центровки будут проходить, а как закончится пользователь увидит окно уже в своем готовом варианте. Возможно ли такое?
2) Для пункта 2 и 3 увеличить скорость изменения размера окна чтобы все происходило побыстрее что-ли, есть способ?
3) Для пункта 1, 2 и 3 непосредственно перед созданием окна высчитать его приблизительный размер к которому будет стремится флаг 64 и создать окно с таким размером уже заранее (у меня имеется текст который будет помещен в окно, за стилями и продвинутым форматированием текста я не гонюсь, потому можно использовать все параметры текста по умолчанию). Есть возможность просчитать такое?
4) Не уверен что поможет, но возможно для пункта 2 и 3 будет полезным создавать окно каждый раз с размером по умолчанию, а не тем, который был раньше (например если вы вручную расширяете окно на пол экрана а потом скрываете его, при следующем его отображении его размеры сохранятся - этого я хочу избежать). Есть такой вариант? Попытался флаг 256 в begin использовать - не помог.

Полное видео с демонстрацией всего что делает мой код (можно комплексно изучить ситуацию), длина видео - 1 минута:
.
Я представил проблемы и способы их решения, которые я вижу. От вас я прошу помочь мне с реализацией либо моих вариантов решения, либо тех вариантов, которые по вашему мнению смогут решить мои проблемы, либо же варианты, которые помогут мне достичь моих целей (их я описал в начале). Рассчитываю на вашу помощь. Код:
Код:
function imgui.OnDrawFrame()
    if show_main_window.v and MainIni.Status.Read == "READ" then
        isCorrectClose = false
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - wW  / 2, sh / 2 - wH  / 2), imgui.Cond.Always, imgui.ImVec2(0.5,0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowContentRegionWidth() / 2, sh / 2 - imgui.GetContentRegionAvailWidth() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    --    imgui.SetNextWindowPos(imgui.ImVec2(766, 509), imgui.Cond.FirstUseEver)
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 100), imgui.Cond.Always)
        sw, sh = getScreenResolution()
        imgui.SetNextWindowSizeConstraints(imgui.ImVec2(300, 0), imgui.ImVec2(sw / 2, sh / 2))
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 200), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - 150, sh / 2 - 100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.Begin(u8(MainIni.Require.Title), show_main_window, 4 + 2 + 256 + 64 + 32)
        imgui.SetWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.Always)
        imgui.ShowCursor = true
        textGui, StrCol = MainIni.Require.Text:gsub("<e>", "\n")
        StrCol = StrCol + 1
        TBegin = imgui.GetCursorPosY()
        --imgui.BeginChild("##1", imgui.ImVec2(0, 0) , false)
        imgui.Text(u8(textGui))
        imgui.PushItemWidth(-1.0)
        imgui.InputText(u8'##empty_field', moonimgui_text_buffer)
        imgui.PopItemWidth()
        if IsAppear then -- условие возвращает истину только один раз при открытии окна
            imgui.SetKeyboardFocusHere(-1)
            IsAppear = false
        end
        --imgui.EndChild()
        ButtonY = TBegin + imgui.GetTextLineHeight() * StrCol + 30
        --imgui.NewLine()
        --imgui.NewLine()
        imgui.PushItemWidth(50.0)
        imgui.SetCursorPos(imgui.ImVec2(imgui.GetWindowWidth() / 2 - 50.0, ButtonY)) --imgui.GetWindowHeight() - 30))
        if imgui.Button(u8(MainIni.Require.ButtonText)) then
            isCorrectClose = true
            show_main_window.v = false
        --pos = imgui.GetWindowPos()
        --print("W: " .. imgui.GetWindowWidth() .. "; H: " .. imgui.GetWindowHeight() .. "; Px: " .. pos.x .. "; Py: " .. pos.y .. "")
        end
        imgui.End()
    end
end

P.S. Хотел нормально ссылки дать с привязкой ко времени но тупой форум их автоматически в media преобразует :(.
 

Belo4ka_belka

Известный
Автор темы
191
7
Если все слишком сложно то хотя бы помогите с вариантом решения проблемы под пунктом 3 - уверен что это вполне возможно, а то что-то просмотров много да отвечать никто не хочет. Видимо я тут решил пентагон взломать на мунлоадере и требую от пользователей непонятно чего(
 

James Hawk

Известный
919
217
Текста слишком много и некоторые забивают читать и вникать. Если правильно понял задумку
Lua:
local sw, sh = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(размер_х, размер_у), imgui.Cond.FirstUseEver)
Окно выводится по центру экрана (всегда), а ширину и высоту поставь, как тебе удобно
 
  • Нравится
Реакции: Belo4ka_belka

Belo4ka_belka

Известный
Автор темы
191
7
Лучше мне кажется все подробно расписать, обозначить задачи и пути их достижения, чем сидеть догадываться что же хочет сделать ТС. Попытался использовать Ваш вариант, столкнулся с трудностями но нашел решение пока писал про них. Следующий код уже в целом можно считать достижением цели, но есть 2 косяка:
1) Никуда не делась телепортация окна, на первом кадре пока окно автоматически подгоняется под размеры, SetNextWindowPos не может идеально его выровнять, а на втором кадре, когда окно уже раздулось до нормального размера оно подгоняется. Пользователь видит в этот момент мерцание, телепортацию, как кому угодно назвать, окна (на видео в первом посте этот момент есть). Я понимаю что технически наверное будет невозможно избавится от этого, ибо размеры не знает окно, но есть ли способ скрыть окно на время первого кадра (или первых нескольких кадров), а уже после всех этих махинаций отобразить его?
2) Если окно до этого было расширено из-за большой длины текста, то в следующий раз, если текст стал короче, окно не сужается, а остается на заданной ширине (для высоты все нормально, как и для увеличения окна в размерах по сравнению с предыдущим). Вот скриншот окна с маленьким текстом, вот скриншот окна с большим текстом, а вот скриншот окна с тем самым маленьким текстом, но создано это окно было после окна, что на втором скрине (в этом предложении три кликабельные ссылки). Есть вариант это исправить (например запретить imgui сохранять размеры окна когда оно скрывается (ведь если вы например вручную увеличите размер созданного окна а потом скроете его, то при следующем отображении размер будет таким, каким его задали вы, расширив мышкой, а не таким, который записан в скрипте - об этом сохранении я говорил))?

Код:
function imgui.OnDrawFrame()
    if show_main_window.v and MainIni.Status.Read == "READ" then
        isCorrectClose = false
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - wW  / 2, sh / 2 - wH  / 2), imgui.Cond.Always, imgui.ImVec2(0.5,0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowContentRegionWidth() / 2, sh / 2 - imgui.GetContentRegionAvailWidth() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    --    imgui.SetNextWindowPos(imgui.ImVec2(766, 509), imgui.Cond.FirstUseEver)
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 100), imgui.Cond.Always)
        sw, sh = getScreenResolution()
        imgui.SetNextWindowSizeConstraints(imgui.ImVec2(300, 0), imgui.ImVec2(sw / 2, sh / 2))
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.Always, imgui.ImVec2(0.5, 0.5))
        if IsAppear then
            imgui.SetNextWindowSize(imgui.ImVec2(0.0, 0.0), imgui.Cond.Always)
        end
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 200), imgui.Cond.FirstUseEver)
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - 150, sh / 2 - 100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.Begin(u8(MainIni.Require.Title), show_main_window, 4 + 2 + 32)
        --imgui.SetWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.Always)
        imgui.ShowCursor = true
        textGui, StrCol = MainIni.Require.Text:gsub("<e>", "\n")
        StrCol = StrCol + 1
        TBegin = imgui.GetCursorPosY()
        --imgui.BeginChild("##1", imgui.ImVec2(0, 0) , false)
        imgui.Text(u8(textGui))
        imgui.PushItemWidth(-1.0)
        imgui.InputText(u8'##empty_field', moonimgui_text_buffer)
        imgui.PopItemWidth()
        if IsAppear then -- условие возвращает истину только один раз при открытии окна
            imgui.SetKeyboardFocusHere(-1)
            IsAppear = false
        end
        --imgui.EndChild()
        ButtonY = TBegin + imgui.GetTextLineHeight() * StrCol + 30
        --imgui.NewLine()
        --imgui.NewLine()
        imgui.PushItemWidth(50.0)
        imgui.SetCursorPos(imgui.ImVec2(imgui.GetWindowWidth() / 2 - 50.0, ButtonY)) --imgui.GetWindowHeight() - 30))
        if imgui.Button(u8(MainIni.Require.ButtonText)) then
            isCorrectClose = true
            show_main_window.v = false
        --pos = imgui.GetWindowPos()
        --print("W: " .. imgui.GetWindowWidth() .. "; H: " .. imgui.GetWindowHeight() .. "; Px: " .. pos.x .. "; Py: " .. pos.y .. "")
        end
        imgui.End()
    end
end
 
Последнее редактирование:

James Hawk

Известный
919
217
Лучше мне кажется все подробно расписать, обозначить задачи и пути их достижения, чем сидеть догадываться что же хочет сделать ТС. Попытался использовать Ваш вариант, столкнулся с трудностями но нашел решение пока писал про них. Следующий код уже в целом можно считать достижением цели, но есть 2 косяка:
1) Никуда не делась телепортация окна, на первом кадре пока окно автоматически подгоняется под размеры, SetNextWindowPos не может идеально его выровнять, а на втором кадре, когда окно уже раздулось до нормального размера оно подгоняется. Пользователь видит в этот момент мерцание, телепортацию, как кому угодно назвать, окна (на видео в первом посте этот момент есть). Я понимаю что технически наверное будет невозможно избавится от этого, ибо размеры не знает окно, но есть ли способ скрыть окно на время первого кадра (или первых нескольких кадров), а уже после всех этих махинаций отобразить его?
2) Если окно до этого было расширено из-за большой длины текста, то в следующий раз, если текст стал короче, окно не сужается, а остается на заданной ширине (для высоты все нормально, как и для увеличения окна в размерах по сравнению с предыдущим). Вот скриншот окна с маленьким текстом, вот скриншот окна с большим текстом, а вот скриншот окна с тем самым маленьким текстом, но создано это окно было после окна, что на втором скрине (в этом предложении три кликабельные ссылки). Есть вариант это исправить (например запретить imgui сохранять размеры окна когда оно скрывается (ведь если вы например вручную увеличите размер созданного окна а потом скроете его, то при следующем отображении размер будет таким, каким его задали вы, расширив мышкой, а не таким, который записан в скрипте - об этом сохранении я говорил))?

Код:
function imgui.OnDrawFrame()
    if show_main_window.v and MainIni.Status.Read == "READ" then
        isCorrectClose = false
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - wW  / 2, sh / 2 - wH  / 2), imgui.Cond.Always, imgui.ImVec2(0.5,0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowContentRegionWidth() / 2, sh / 2 - imgui.GetContentRegionAvailWidth() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    --    imgui.SetNextWindowPos(imgui.ImVec2(766, 509), imgui.Cond.FirstUseEver)
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 100), imgui.Cond.Always)
        sw, sh = getScreenResolution()
        imgui.SetNextWindowSizeConstraints(imgui.ImVec2(300, 0), imgui.ImVec2(sw / 2, sh / 2))
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.Always, imgui.ImVec2(0.5, 0.5))
        if IsAppear then
            imgui.SetNextWindowSize(imgui.ImVec2(0.0, 0.0), imgui.Cond.Always)
        end
        --imgui.SetNextWindowSize(imgui.ImVec2(300, 200), imgui.Cond.FirstUseEver)
        --imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - 150, sh / 2 - 100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.Begin(u8(MainIni.Require.Title), show_main_window, 4 + 2 + 32)
        --imgui.SetWindowPos(imgui.ImVec2(sw / 2 - imgui.GetWindowWidth() / 2, sh / 2 - imgui.GetWindowHeight() / 2), imgui.Cond.Always)
        imgui.ShowCursor = true
        textGui, StrCol = MainIni.Require.Text:gsub("<e>", "\n")
        StrCol = StrCol + 1
        TBegin = imgui.GetCursorPosY()
        --imgui.BeginChild("##1", imgui.ImVec2(0, 0) , false)
        imgui.Text(u8(textGui))
        imgui.PushItemWidth(-1.0)
        imgui.InputText(u8'##empty_field', moonimgui_text_buffer)
        imgui.PopItemWidth()
        if IsAppear then -- условие возвращает истину только один раз при открытии окна
            imgui.SetKeyboardFocusHere(-1)
            IsAppear = false
        end
        --imgui.EndChild()
        ButtonY = TBegin + imgui.GetTextLineHeight() * StrCol + 30
        --imgui.NewLine()
        --imgui.NewLine()
        imgui.PushItemWidth(50.0)
        imgui.SetCursorPos(imgui.ImVec2(imgui.GetWindowWidth() / 2 - 50.0, ButtonY)) --imgui.GetWindowHeight() - 30))
        if imgui.Button(u8(MainIni.Require.ButtonText)) then
            isCorrectClose = true
            show_main_window.v = false
        --pos = imgui.GetWindowPos()
        --print("W: " .. imgui.GetWindowWidth() .. "; H: " .. imgui.GetWindowHeight() .. "; Px: " .. pos.x .. "; Py: " .. pos.y .. "")
        end
        imgui.End()
    end
end
Зачем делать большой inputtext? Туда будут молитву латынью вписывать?

Можно же сделать одно значение ширины инпута и не нужно морочиться с авторесайзом окна
 

Belo4ka_belka

Известный
Автор темы
191
7
Стоп не понял. Виной тому что не уменьшается окно - инпут? Мне нужно чтобы оно было шириной на все окно, или же определенной ширины но по центру окна (с равными отступами от краев окна), так можно сделать?
 

James Hawk

Известный
919
217
Стоп не понял. Виной тому что не уменьшается окно - инпут? Мне нужно чтобы оно было шириной на все окно, или же определенной ширины но по центру окна (с равными отступами от краев окна), так можно сделать?
Вектор после увеличения размера окна запомнит размер и сохранит его

Предлагаю сделать размер окна фиксированным (в зависимости от максимального инпута). А инпут поменьше размещать по центру, например
Lua:
imgui.SetCursorPos(imgui.ImVec2(координата_х, координата_у), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
Координаты матем. путём или подбором
 

Belo4ka_belka

Известный
Автор темы
191
7
Так размер окна зависит не от инпута а от текста который записан в окне. Инпут я подгоняю после создания текстового элемента по ширине окна (imgui.PushItemWidth(-1.0)). Автоматический размер окна для меня обязательный ибо я не знаю насколько широким будет текст или насколько много строчек в нем будет. Или я что-то не так понял?
 

James Hawk

Известный
919
217
Так размер окна зависит не от инпута а от текста который записан в окне. Инпут я подгоняю после создания текстового элемента по ширине окна (imgui.PushItemWidth(-1.0)). Автоматический размер окна для меня обязательный ибо я не знаю насколько широким будет текст или насколько много строчек в нем будет. Или я что-то не так понял?
Под текст можно юзать multiline
 
Статус
В этой теме нельзя размещать новые ответы.