Skip to content

Commit

Permalink
Add Mouse Callback to VisualizerWithKeyCallback (#6760)
Browse files Browse the repository at this point in the history
---------
Co-authored-by: Sameer Sheorey <sameer.sheorey@intel.com>
  • Loading branch information
organic-nailer authored May 15, 2024
1 parent bf48b45 commit a1fb32c
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 7 deletions.
62 changes: 62 additions & 0 deletions cpp/open3d/visualization/visualizer/VisualizerWithKeyCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ void VisualizerWithKeyCallback::PrintVisualizerHelp() {
utility::LogInfo(
" The default functions of these keys will be overridden.");
utility::LogInfo("");

std::string mouse_callbacks = (mouse_move_callback_ ? "MouseMove, " : "");
mouse_callbacks += (mouse_scroll_callback_ ? "MouseScroll, " : "");
mouse_callbacks += (mouse_button_callback_ ? "MouseButton, " : "");
utility::LogInfo(" Custom mouse callbacks registered for: {}",
mouse_callbacks.substr(0, mouse_callbacks.size() - 2));
utility::LogInfo("");
}

void VisualizerWithKeyCallback::RegisterKeyCallback(
Expand All @@ -38,6 +45,21 @@ void VisualizerWithKeyCallback::RegisterKeyActionCallback(
key_action_to_callback_[key] = callback;
}

void VisualizerWithKeyCallback::RegisterMouseMoveCallback(
std::function<bool(Visualizer *, double, double)> callback) {
mouse_move_callback_ = callback;
}

void VisualizerWithKeyCallback::RegisterMouseScrollCallback(
std::function<bool(Visualizer *, double, double)> callback) {
mouse_scroll_callback_ = callback;
}

void VisualizerWithKeyCallback::RegisterMouseButtonCallback(
std::function<bool(Visualizer *, int, int, int)> callback) {
mouse_button_callback_ = callback;
}

void VisualizerWithKeyCallback::KeyPressCallback(
GLFWwindow *window, int key, int scancode, int action, int mods) {
auto action_callback = key_action_to_callback_.find(key);
Expand All @@ -63,6 +85,46 @@ void VisualizerWithKeyCallback::KeyPressCallback(
}
}

void VisualizerWithKeyCallback::MouseMoveCallback(GLFWwindow *window,
double x,
double y) {
if (mouse_move_callback_) {
if (mouse_move_callback_(this, x, y)) {
UpdateGeometry();
}
UpdateRender();
} else {
Visualizer::MouseMoveCallback(window, x, y);
}
}

void VisualizerWithKeyCallback::MouseScrollCallback(GLFWwindow *window,
double x,
double y) {
if (mouse_scroll_callback_) {
if (mouse_scroll_callback_(this, x, y)) {
UpdateGeometry();
}
UpdateRender();
} else {
Visualizer::MouseScrollCallback(window, x, y);
}
}

void VisualizerWithKeyCallback::MouseButtonCallback(GLFWwindow *window,
int button,
int action,
int mods) {
if (mouse_button_callback_) {
if (mouse_button_callback_(this, button, action, mods)) {
UpdateGeometry();
}
UpdateRender();
} else {
Visualizer::MouseButtonCallback(window, button, action, mods);
}
}

std::string VisualizerWithKeyCallback::PrintKeyToString(int key) {
if (key == GLFW_KEY_SPACE) { // 32
return std::string("Space");
Expand Down
44 changes: 44 additions & 0 deletions cpp/open3d/visualization/visualizer/VisualizerWithKeyCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class VisualizerWithKeyCallback : public Visualizer {
void PrintVisualizerHelp() override;
void RegisterKeyCallback(int key,
std::function<bool(Visualizer *)> callback);

/// Register callback function with access to GLFW key actions.
///
/// \param key GLFW key value, see [GLFW key
Expand All @@ -48,18 +49,61 @@ class VisualizerWithKeyCallback : public Visualizer {
void RegisterKeyActionCallback(
int key, std::function<bool(Visualizer *, int, int)> callback);

/// Register callback function with access to GLFW mouse actions.
///
/// \param callback The callback function. The callback function takes
/// `Visualizer *`, and the x and y mouse position inside the window and
/// returns a boolean indicating if `UpdateGeometry()` needs to be run. See
/// [GLFW mouse
/// position](https://www.glfw.org/docs/latest/input_guide.html#input_mouse)
/// for more details.
void RegisterMouseMoveCallback(
std::function<bool(Visualizer *, double, double)> callback);

/// Register callback function with access to GLFW mouse actions.
///
/// \param callback The callback function. The callback function takes
/// `Visualizer *`, and the x and y scroll values and returns a boolean
/// indicating if `UpdateGeometry()` needs to be run. A normal mouse only
/// provides a y scroll value. See [GLFW mouse
/// scrolling](https://www.glfw.org/docs/latest/input_guide.html#scrolling)
/// for more details.
void RegisterMouseScrollCallback(
std::function<bool(Visualizer *, double, double)> callback);

/// Register callback function with access to GLFW mouse actions.
///
/// \param callback The callback function. The callback function takes
/// `Visualizer *`, `button`, `action` and `mods` as input and returns a
/// boolean indicating UpdateGeometry() needs to be run. The `action` can be
/// one of GLFW_RELEASE (0), GLFW_PRESS (1) or GLFW_REPEAT (2), see [GLFW
/// input interface](https://www.glfw.org/docs/latest/group__input.html).
/// The `mods` specifies the modifier key, see [GLFW modifier
/// key](https://www.glfw.org/docs/latest/group__mods.html).
void RegisterMouseButtonCallback(
std::function<bool(Visualizer *, int, int, int)> callback);

protected:
void KeyPressCallback(GLFWwindow *window,
int key,
int scancode,
int action,
int mods) override;
void MouseMoveCallback(GLFWwindow *window, double x, double y) override;
void MouseScrollCallback(GLFWwindow *window, double x, double y) override;
void MouseButtonCallback(GLFWwindow *window,
int button,
int action,
int mods) override;
std::string PrintKeyToString(int key);

protected:
std::map<int, std::function<bool(Visualizer *)>> key_to_callback_;
std::map<int, std::function<bool(Visualizer *, int, int)>>
key_action_to_callback_;
std::function<bool(Visualizer *, double, double)> mouse_move_callback_;
std::function<bool(Visualizer *, double, double)> mouse_scroll_callback_;
std::function<bool(Visualizer *, int, int, int)> mouse_button_callback_;
};

} // namespace visualization
Expand Down
46 changes: 42 additions & 4 deletions cpp/pybind/visualization/visualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,48 @@ void pybind_visualizer(py::module &m) {
.def("register_key_action_callback",
&VisualizerWithKeyCallback::RegisterKeyActionCallback,
"Function to register a callback function for a key action "
"event. The callback function takes Visualizer, action and "
"mods as input and returns a boolean indicating if "
"UpdateGeometry() needs to be run.",
"key"_a, "callback_func"_a);
"event. The callback function takes `Visualizer`, `action` "
"and `mods` as input and returns a boolean indicating if "
"`UpdateGeometry()` needs to be run. The `action` can be one "
"of `GLFW_RELEASE` (0), `GLFW_PRESS` (1) or `GLFW_REPEAT` "
"(2), see `GLFW input interface "
"<https://www.glfw.org/docs/latest/group__input.html>`__. The "
"`mods` specifies the modifier key, see `GLFW modifier key "
"<https://www.glfw.org/docs/latest/group__mods.html>`__",
"key"_a, "callback_func"_a)

.def("register_mouse_move_callback",
&VisualizerWithKeyCallback::RegisterMouseMoveCallback,
"Function to register a callback function for a mouse move "
"event. The callback function takes Visualizer, x and y mouse "
"position inside the window as input and returns a boolean "
"indicating if UpdateGeometry() needs to be run. `GLFW mouse "
"position <https://www.glfw.org/docs/latest/"
"input_guide.html#input_mouse>`__ for more details.",
"callback_func"_a)

.def("register_mouse_scroll_callback",
&VisualizerWithKeyCallback::RegisterMouseScrollCallback,
"Function to register a callback function for a mouse scroll "
"event. The callback function takes Visualizer, x and y mouse "
"scroll offset as input and returns a boolean "
"indicating if UpdateGeometry() needs to be run. `GLFW mouse "
"scrolling <https://www.glfw.org/docs/latest/"
"input_guide.html#scrolling>`__ for more details.",
"callback_func"_a)

.def("register_mouse_button_callback",
&VisualizerWithKeyCallback::RegisterMouseButtonCallback,
"Function to register a callback function for a mouse button "
"event. The callback function takes `Visualizer`, `button`, "
"`action` and `mods` as input and returns a boolean "
"indicating `UpdateGeometry()` needs to be run. The `action` "
"can be one of GLFW_RELEASE (0), GLFW_PRESS (1) or "
"GLFW_REPEAT (2), see `GLFW input interface "
"<https://www.glfw.org/docs/latest/group__input.html>`__. "
"The `mods` specifies the modifier key, see `GLFW modifier "
"key <https://www.glfw.org/docs/latest/group__mods.html>`__.",
"callback_func"_a);

py::class_<VisualizerWithEditing, PyVisualizer<VisualizerWithEditing>,
std::shared_ptr<VisualizerWithEditing>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,45 @@ def animation_callback(vis):
vis.run()


def custom_mouse_action(pcd):

vis = o3d.visualization.VisualizerWithKeyCallback()
buttons = ['left', 'right', 'middle']
actions = ['up', 'down']
mods_name = ['shift', 'ctrl', 'alt', 'cmd']

def on_key_action(vis, action, mods):
print("on_key_action", action, mods)

vis.register_key_action_callback(ord("A"), on_key_action)

def on_mouse_move(vis, x, y):
print(f"on_mouse_move({x:.2f}, {y:.2f})")

def on_mouse_scroll(vis, x, y):
print(f"on_mouse_scroll({x:.2f}, {y:.2f})")

def on_mouse_button(vis, button, action, mods):
pressed_mods = " ".join(
[mods_name[i] for i in range(4) if mods & (1 << i)])
print(f"on_mouse_button: {buttons[button]}, {actions[action]}, " +
pressed_mods)

vis.register_mouse_move_callback(on_mouse_move)
vis.register_mouse_scroll_callback(on_mouse_scroll)
vis.register_mouse_button_callback(on_mouse_button)

vis.create_window()
vis.add_geometry(pcd)
vis.run()


if __name__ == "__main__":
ply_data = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_data.path)

print(
"Customized visualization with smooth key action (without keyboard repeat delay)"
)
print("Customized visualization with smooth key action "
"(without keyboard repeat delay). Press the space-bar.")
custom_key_action_without_kb_repeat_delay(pcd)
print("Customized visualization with mouse action.")
custom_mouse_action(pcd)

0 comments on commit a1fb32c

Please sign in to comment.