[ocornut/imgui]修复更新光标位置时 GLFW_CURSOR_DISABLED 被忽略的问题

2024-05-09 158 views
1

GLFW 后端当前忽略光标已禁用(GLFW_CURSOR_DISABLED 由 glfwSetInputMode 设置)。这会导致不可见的光标,在移动鼠标时仍然突出显示新的 ImGui 元素,即使光标应保持静态并且仅突出显示在被禁用之前最后一次经过的元素。此 PR 添加了对标志的检查,并在 ImGuiIO 的位置​​更新之前从函数中返回。

当前的行为源于这样一个事实:当设置 GLFW_CURSOR_DISABLED 时,GLFW 仍然提供更新的光标位置。我不知道这是否是有意的(我认为文档对此有点不清楚)。

回答

4

你好,

感谢您的公关。

我认为我们是否希望后端尊重这个 GLFW 设置是有争议的。用户可能希望GLFW_CURSOR_DISABLED根据其底层应用程序的目的进行切换,并且仍然期望 Dear ImGui 可用(例如使用软件渲染的光标)。我同意这不太可能,但这样我们就可以让这成为不可能。不过,我可以合并它,因为我相信它会符合大多数人的期望,但如果有人出现该用例,我可能会恢复。

请注意,您可以设置io.ConfigFlags |= ImGuiConfigFlags_NoMouse相同的结果。

PR 从技术上讲缺少一些点(ImGui_ImplGlfw_CursorEnterCallback 不应提交事件,ImGui_ImplGlfw_UpdateMouseDatais_app_focused应用程序也不应提交事件,进入GLFW_CURSOR_DISABLED状态应向 imgui 提交鼠标禁用事件io.AddMousePosEvent(-FLT_MAX, -FLT_MAX),可能可以在 ImGui_ImplGlfw_UpdateMouseData() 中完成。然后需要验证支持对于多视口docking分支将很容易合并/修复(我可以做到)。

4

您好,至于您对您提到的第一个用例的担忧:我认为您忽略了一个事实(如果我错了,请纠正我):用户可以设置(这仍然可以像ImGui 的GLFW_CURSOR_HIDDEN一样工作)GLFW_CURSOR_NORMALside),然后渲染自定义光标。GLFW_CURSOR_DISABLED如果用户想要无限移动,则应设置唯一的时间并呈现自定义光标。然而,我看到你担心让某些事情变得不可能。然而,对于您的替代建议,仅设置ImGuiConfigFlags_NoMouse不足以实现无限制移动,这是GLFW_CURSOR_DISABLED的主要用例。用户必须在 ImGui 中设置这两者,才能像我所描述的那样运行。

2

我认为你忽略了这样一个事实(如果我错了,请纠正我):用户可以设置 GLFW_CURSOR_HIDDEN (这仍然像 ImGui 一侧的 GLFW_CURSOR_NORMAL 一样工作),然后渲染自定义光标。

好点子。

然而,对于您的替代建议,仅设置 ImGuiConfigFlags_NoMouse 不足以启用无限移动,这是 GLFW_CURSOR_DISABLED 的主要用例。用户必须在 ImGui 中设置这两者,才能像我所描述的那样运行。

的确。我最初建议你的设置ImGuiConfigFlags_NoMouse相当于合并此 PR。

但根据你上面的第一点,我同意我们应该合并这一点。如果您想完成 PR,请告诉我,否则我可以完成。

9

我可以完成 PR。对接的话需要单独开PR吗?

7

您建议的更改

ImGui_ImplGlfw_CursorEnterCallback 不应提交事件,ImGui_ImplGlfw_UpdateMouseData is_app_focused 应用程序也不应提交事件,进入 GLFW_CURSOR_DISABLED 状态应向 imgui 提交鼠标禁用事件 io.AddMousePosEvent(-FLT_MAX, -FLT_MAX) ,可能可以在 ImGui_ImplGlfw_UpdateMouseData() 中完成

现已实施。如果有什么遗漏请告诉我。如果没有,我会打开一个单独的 PR,对对接分支进行相同的更改。

2

在 master 上做 PR,我会看看是否很容易在对接上合并,我可以做那部分。谢谢。

0

在 master 上做 PR

抱歉,如果我误解了,但更改已在此 PR 中推送

4

现在合并为 5867a43。我进行了一些小调整,修复了未聚焦时清除鼠标数据的问题,并且它毫无问题地合并到对接中。

谢谢你!

作为参考,一个超小型测试台正在运行:

ImGui::GetIO()->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; = true;
static bool DISABLED = false;
ImGui::Checkbox("DISABLED", &DISABLED);
glfwSetInputMode(window, GLFW_CURSOR, DISABLED ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
8

如果用户想要无限移动,则唯一一次应该设置 GLFW_CURSOR_DISABLED 并呈现自定义光标。

那么我现在怎样才能准确地实现这种行为呢?我有一个支持全屏模式的查看器应用程序。在窗口化时,您可以按下鼠标按钮来拖动 3D 场景上的当前视图,这是通过 ImGUI 鼠标事件处理的。当进入全屏时,处理这些事件的组件将扩展到全屏。对于多屏幕系统,当鼠标从未离开当前屏幕并且光标仍然可以发送事件(即使它会碰到屏幕边框时)时,它非常有用。在该模式下我也不需要任何光标。将其想象为一个游戏编辑器,您可以通过按按钮切换到 FPS 模式。

但现在通过此更改,我无法再全屏接收鼠标事件。为了解决这个问题,我现在必须直接从 GLFW 获取鼠标事件,这打破了 ImGUI 的抽象。所以,对我来说,这个修复引入了一个新的错误。

那么为什么设置对于原始请求来说io.ConfigFlags |= ImGuiConfigFlags_NoMouse是不够的呢?GLFW_CURSOR_DISABLED为什么将两者的组合直接实施到 GLFW 后端而不选择退出?

6

那么为什么设置 io.ConfigFlags |= ImGuiConfigFlags_NoMouse 和 GLFW_CURSOR_DISABLED 不足以满足原始请求呢?为什么将两者的组合直接实施到 GLFW 后端而不选择退出?

重新开放似乎是一个合理的声明。如果你们两个能进一步调查此事,我将不胜感激!

5

但现在通过此更改,我无法再全屏接收鼠标事件。为了解决这个问题,我现在必须直接从 GLFW 获取鼠标事件,这打破了 ImGUI 的抽象。所以,对我来说,这个修复引入了一个新的错误。

那么为什么设置 io.ConfigFlags |= ImGuiConfigFlags_NoMouse 和 GLFW_CURSOR_DISABLED 不足以满足原始请求呢?为什么将两者的组合直接实施到 GLFW 后端而不选择退出?

你是对的,这是我在编写补丁时没有记住的事情。由于GLFW_CURSOR_DISABLED旨在将真实光标固定到位,同时仍然通过虚拟光标提供适当的增量移动,因此我认为可以公平地假设 ImGui 不会在其渲染/项目上下文中尊重光标(因此 ImGui 不会突出显示某些内容)它不应该是由于虚拟光标),而不需要用户指定另一个标志(io.ConfigFlags |= ImGuiConfigFlags_NoMouse),但仍然向对增量移动的虚拟光标坐标感兴趣的应用程序发送回调。

我正在考虑(以某种方式)拦截 ImGui 对坐标的消耗,而不是后端的发射,因此如果需要,仍然可以调用光标回调。

@ocornut 请随意恢复此提交(不幸的是,我目前无法),直到我提交此 PR 的重写,因为破坏功能可能比主要视觉问题更严重。

0

@pborsutzki 我刚刚打开了另一个 PR,它应该可以解决你的问题。你能否证实情况确实如此?

1

你好@scorpion-26,

感谢您的公关。我不确定我是否同意您在 #6609 中发布的任一解决方案

  • 其一:后端绝对不应该操纵 ConfigFlags
  • 对于另一个:它会起作用,但似乎没有必要。

由于用户/应用程序可以控制操纵 GLFW 光标状态,因此它可以自由设置/清除ImGuiConfigFlags_NoMouse自身吗?因此,基于这个逻辑,我们可能只想恢复初始提交。

这个策略总是有效的。

1

我只推送了恢复(e5977f0),目前我认为不需要其他任何东西。如果我错了请告诉我@scorpion-26?

我在https://github.com/ocornut/imgui/pull/5625#issuecomment-1234208675中动摇/确信,但我认为推理是错误的,因为它要求后端特定的解决方案,即 GLFW 中存在第三个变体。据我所知,您的应用程序中的设置ImGuiConfigFlags_NoMouse始终可以解决问题。