ui: fix drag scrolling and imgui gl renderer. use imgui events
Missing call to KeepAliveID was preventing drag scrolling in empty areas. Also check for HoveredIdDisabled to allow scrolling by dragging disabled items and enable HoveredIdAllowOverlap. imgui gl renderer: use ImDrawCmd::IdxOffset instead of counting manually. Use correct alpha blending function. Use imgui events for all input. Simplify keyboard input by getting rid of modifiers. Enable flat navigation in content window. Add format string to OptionSlider.
This commit is contained in:
parent
c033a81eca
commit
08ac485eac
|
@ -109,10 +109,10 @@ protected:
|
|||
if (port >= 0 && port < (int)std::size(kb_shift))
|
||||
kb_shift[port] = _modifier_keys;
|
||||
|
||||
if (keycode != 0 && keycode < 0xE0)
|
||||
if (keycode != 0)
|
||||
{
|
||||
gui_keyboard_key(keycode, pressed, _modifier_keys);
|
||||
if (port >= 0 && port < (int)std::size(kb_key))
|
||||
gui_keyboard_key(keycode, pressed);
|
||||
if (keycode < 0xE0 && port >= 0 && port < (int)std::size(kb_key))
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
|
|
|
@ -145,7 +145,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glcache.Enable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glcache.Disable(GL_CULL_FACE);
|
||||
glcache.Disable(GL_DEPTH_TEST);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
|
@ -187,6 +187,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
}
|
||||
#endif
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
|
@ -199,12 +200,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
|
@ -228,12 +225,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
|
||||
// Bind texture, Draw
|
||||
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
|
||||
}
|
||||
}
|
||||
idx_buffer_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
// Make sure the state cache is coherent
|
||||
glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
#ifndef GLES2
|
||||
if (vao_handle != 0)
|
||||
glDeleteVertexArrays(1, &vao_handle);
|
||||
|
|
|
@ -152,8 +152,14 @@ static ImGuiKey keycodeToImGuiKey(u8 keycode)
|
|||
case 0x1B: return ImGuiKey_X;
|
||||
case 0x1C: return ImGuiKey_Y;
|
||||
case 0x1D: return ImGuiKey_Z;
|
||||
case 0xE0:
|
||||
case 0xE4:
|
||||
return ImGuiMod_Ctrl;
|
||||
case 0xE1:
|
||||
case 0xE5:
|
||||
return ImGuiMod_Shift;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
|
||||
void gui_initFonts()
|
||||
|
@ -295,19 +301,19 @@ void gui_keyboard_inputUTF8(const std::string& s)
|
|||
io.AddInputCharactersUTF8(s.c_str());
|
||||
}
|
||||
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers)
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed)
|
||||
{
|
||||
if (!inited)
|
||||
return;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiKey key = keycodeToImGuiKey(keyCode);
|
||||
if (key == ImGuiKey_None)
|
||||
return;
|
||||
if (!pressed && ImGui::IsKeyDown(key))
|
||||
{
|
||||
keysUpNextFrame[keyCode] = true;
|
||||
return;
|
||||
}
|
||||
io.KeyCtrl = (modifiers & (0x01 | 0x10)) != 0;
|
||||
io.KeyShift = (modifiers & (0x02 | 0x20)) != 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(key, pressed);
|
||||
}
|
||||
|
||||
|
@ -351,9 +357,9 @@ static void gui_newFrame()
|
|||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if (mouseX < 0 || mouseX >= settings.display.width || mouseY < 0 || mouseY >= settings.display.height)
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
else
|
||||
io.MousePos = ImVec2(mouseX, mouseY);
|
||||
io.AddMousePosEvent(mouseX, mouseY);
|
||||
static bool delayTouch;
|
||||
#if defined(__ANDROID__) || defined(TARGET_IPHONE)
|
||||
// Delay touch by one frame to allow widgets to be hovered before click
|
||||
|
@ -365,14 +371,14 @@ static void gui_newFrame()
|
|||
#endif
|
||||
if (io.WantCaptureMouse)
|
||||
{
|
||||
io.MouseWheel = -mouseWheel / 16;
|
||||
io.AddMouseWheelEvent(0, -mouseWheel / 16);
|
||||
mouseWheel = 0;
|
||||
}
|
||||
if (!delayTouch)
|
||||
io.MouseDown[ImGuiMouseButton_Left] = (mouseButtons & (1 << 0)) != 0;
|
||||
io.MouseDown[ImGuiMouseButton_Right] = (mouseButtons & (1 << 1)) != 0;
|
||||
io.MouseDown[ImGuiMouseButton_Middle] = (mouseButtons & (1 << 2)) != 0;
|
||||
io.MouseDown[3] = (mouseButtons & (1 << 3)) != 0;
|
||||
io.AddMouseButtonEvent(ImGuiMouseButton_Left, (mouseButtons & (1 << 0)) != 0);
|
||||
io.AddMouseButtonEvent(ImGuiMouseButton_Right, (mouseButtons & (1 << 1)) != 0);
|
||||
io.AddMouseButtonEvent(ImGuiMouseButton_Middle, (mouseButtons & (1 << 2)) != 0);
|
||||
io.AddMouseButtonEvent(3, (mouseButtons & (1 << 3)) != 0);
|
||||
|
||||
io.AddKeyEvent(ImGuiKey_GamepadFaceLeft, ((kcode[0] & DC_BTN_X) == 0));
|
||||
io.AddKeyEvent(ImGuiKey_GamepadFaceRight, ((kcode[0] & DC_BTN_B) == 0));
|
||||
|
@ -2496,7 +2502,7 @@ static void gui_display_content()
|
|||
scanner.fetch_game_list();
|
||||
|
||||
// Only if Filter and Settings aren't focused... ImGui::SetNextWindowFocus();
|
||||
ImGui::BeginChild(ImGui::GetID("library"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling);
|
||||
ImGui::BeginChild(ImGui::GetID("library"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling | ImGuiWindowFlags_NavFlattened);
|
||||
{
|
||||
const int itemsPerLine = std::max<int>(ImGui::GetContentRegionMax().x / (150 * settings.display.uiScale + ImGui::GetStyle().ItemSpacing.x), 1);
|
||||
const float responsiveBoxSize = ImGui::GetContentRegionMax().x / itemsPerLine - ImGui::GetStyle().FramePadding.x * 2;
|
||||
|
|
|
@ -35,7 +35,7 @@ void gui_refresh_files();
|
|||
void gui_cheats();
|
||||
void gui_keyboard_input(u16 wc);
|
||||
void gui_keyboard_inputUTF8(const std::string& s);
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers);
|
||||
void gui_keyboard_key(u8 keyCode, bool pressed);
|
||||
bool gui_keyboard_captured();
|
||||
bool gui_mouse_captured();
|
||||
void gui_set_mouse_position(int x, int y);
|
||||
|
|
|
@ -359,8 +359,16 @@ void scrollWhenDraggingOnVoid(ImGuiMouseButton mouse_button)
|
|||
bool held = false;
|
||||
ImGuiButtonFlags button_flags = (mouse_button == ImGuiMouseButton_Left) ? ImGuiButtonFlags_MouseButtonLeft
|
||||
: (mouse_button == ImGuiMouseButton_Right) ? ImGuiButtonFlags_MouseButtonRight : ImGuiButtonFlags_MouseButtonMiddle;
|
||||
if (g.HoveredId == 0) // If nothing hovered so far in the frame (not same as IsAnyItemHovered()!)
|
||||
ImGui::ButtonBehavior(window->Rect(), window->GetID("##scrolldraggingoverlay"), &hovered, &held, button_flags);
|
||||
// If nothing hovered so far in the frame (not same as IsAnyItemHovered()!) or item is disabled
|
||||
if (g.HoveredId == 0 || g.HoveredIdDisabled)
|
||||
{
|
||||
bool hoveredAllowOverlap = g.HoveredIdAllowOverlap;
|
||||
g.HoveredIdAllowOverlap = true;
|
||||
ImGuiID overlayId = window->GetID("##scrolldraggingoverlay");
|
||||
ImGui::ButtonBehavior(window->Rect(), overlayId, &hovered, &held, button_flags);
|
||||
ImGui::KeepAliveID(overlayId);
|
||||
g.HoveredIdAllowOverlap = hoveredAllowOverlap;
|
||||
}
|
||||
const ImVec2& delta = ImGui::GetIO().MouseDelta;
|
||||
if (held && delta != ImVec2())
|
||||
{
|
||||
|
@ -654,14 +662,14 @@ bool OptionCheckbox(const char *name, config::Option<bool, PerGameOption>& optio
|
|||
template bool OptionCheckbox(const char *name, config::Option<bool, true>& option, const char *help);
|
||||
template bool OptionCheckbox(const char *name, config::Option<bool, false>& option, const char *help);
|
||||
|
||||
bool OptionSlider(const char *name, config::Option<int>& option, int min, int max, const char *help)
|
||||
bool OptionSlider(const char *name, config::Option<int>& option, int min, int max, const char *help, const char *format)
|
||||
{
|
||||
bool valueChanged;
|
||||
{
|
||||
DisabledScope scope(option.isReadOnly());
|
||||
|
||||
int v = option;
|
||||
valueChanged = ImGui::SliderInt(name, &v, min, max);
|
||||
valueChanged = ImGui::SliderInt(name, &v, min, max, format);
|
||||
if (valueChanged)
|
||||
option.set(v);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ IMGUI_API const ImWchar* GetGlyphRangesChineseTraditionalOfficial();// Defaul
|
|||
void ShowHelpMarker(const char* desc);
|
||||
template<bool PerGameOption>
|
||||
bool OptionCheckbox(const char *name, config::Option<bool, PerGameOption>& option, const char *help = nullptr);
|
||||
bool OptionSlider(const char *name, config::Option<int>& option, int min, int max, const char *help = nullptr);
|
||||
bool OptionSlider(const char *name, config::Option<int>& option, int min, int max, const char *help = nullptr, const char *format = nullptr);
|
||||
template<typename T>
|
||||
bool OptionRadioButton(const char *name, config::Option<T>& option, T value, const char *help = nullptr);
|
||||
void OptionComboBox(const char *name, config::Option<int>& option, const char *values[], int count,
|
||||
|
|
|
@ -652,8 +652,8 @@ bool checkTryDebug()
|
|||
changeText = nil;
|
||||
if (textField.markedTextRange == nil) {
|
||||
// it wants to replace text with nothing, ie a delete
|
||||
gui_keyboard_key(0x2A, true, 0); // backspace
|
||||
gui_keyboard_key(0x2A, false, 0);
|
||||
gui_keyboard_key(0x2A, true); // backspace
|
||||
gui_keyboard_key(0x2A, false);
|
||||
}
|
||||
if (textField.text.length < 16) {
|
||||
textField.text = obligateForBackspace;
|
||||
|
@ -667,8 +667,8 @@ bool checkTryDebug()
|
|||
// Terminates the editing session
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
|
||||
{
|
||||
gui_keyboard_key(0x28, true, 0); // Return
|
||||
gui_keyboard_key(0x28, false, 0);
|
||||
gui_keyboard_key(0x28, true); // Return
|
||||
gui_keyboard_key(0x28, false);
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue