Skip to content

Commit d6c36f6

Browse files
authored
Merge pull request #102 from Simple-Robotics/expose-toggle-gui
Expose `Visualizer.toggleGui(value=None)`
2 parents 4af2bae + 43a6f85 commit d6c36f6

File tree

7 files changed

+27
-11
lines changed

7 files changed

+27
-11
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ci:
55
submodules: true
66
repos:
77
- repo: https://github.com/pre-commit/mirrors-clang-format
8-
rev: v20.1.8
8+
rev: v21.1.8
99
hooks:
1010
- id: clang-format
1111
types_or: []
@@ -30,12 +30,12 @@ repos:
3030
doc/doxygen-awesome.*
3131
)$
3232
- repo: https://github.com/astral-sh/ruff-pre-commit
33-
rev: 'v0.12.9'
33+
rev: 'v0.14.13'
3434
hooks:
3535
- id: ruff
3636
args: [--fix, --exit-non-zero-on-fix]
3737
- id: ruff-format
3838
- repo: https://github.com/BlankSpruce/gersemi
39-
rev: 0.22.1
39+
rev: 0.25.1
4040
hooks:
4141
- id: gersemi

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Expose `Visualizer.toggleGui(value=None)` (https://github.com/Simple-Robotics/candlewick/pull/102)
13+
1014
## [0.10.1] - 2026-01-19
1115

1216
## [0.10.0] - 2025-08-20

bindings/python/candlewick/async_visualizer.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ def send_models(sock: zmq.Socket, model_str, geom_str):
4949
return sock.recv()
5050

5151

52-
def send_state(sock: zmq.Socket, q: np.ndarray, v: np.ndarray | None = None):
53-
payload = _encoder.encode((q, v))
54-
sock.send_multipart([b"state_update", payload])
55-
56-
5752
def send_cam_pose(sock: zmq.Socket, M: np.ndarray):
5853
assert sock.socket_type == zmq.REQ
5954
assert M.shape == (4, 4)
@@ -114,7 +109,8 @@ def display(self, q: np.ndarray, v: Optional[np.ndarray] = None):
114109
assert q.size == self.model.nq
115110
if v is not None:
116111
assert v.size == self.model.nv
117-
send_state(self.publisher, q, v)
112+
payload = _encoder.encode((q, v))
113+
self.sync_sock.send_multipart([b"state_update", payload])
118114

119115
def clean(self):
120116
"""Clean the robot from the renderer. Equivalent to `viz.clean()` on the synchronous `Visualizer` class."""
@@ -127,6 +123,11 @@ def close(self):
127123
self.publisher.close()
128124
self.sync_sock.close()
129125

126+
def toggleGui(self):
127+
self.sync_sock.send_multipart([b"toggle_gui", b""])
128+
response = self.sync_sock.recv().decode()
129+
assert response == "ok"
130+
130131
def displayCollisions(self, visibility):
131132
raise NotImplementedError()
132133

bindings/python/src/expose-visualizer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ void exposeVisualizer() {
3030
eigenpy::OptionalConverter<ConstVectorRef, std::optional>::registration();
3131
eigenpy::OptionalConverter<Vector3, std::optional>::registration();
3232
eigenpy::OptionalConverter<float, std::optional>::registration();
33+
eigenpy::OptionalConverter<bool, std::optional>::registration();
3334
eigenpy::detail::NoneToPython<std::nullopt_t>::registration();
3435

3536
bp::class_<Visualizer::Config>("VisualizerConfig", bp::no_init)
@@ -50,6 +51,10 @@ void exposeVisualizer() {
5051
.def_readonly("renderer", &Visualizer::renderer)
5152
.def_readwrite("worldSceneBounds", &Visualizer::worldSceneBounds)
5253
.def("resetCamera", &Visualizer::resetCamera, ("self"_a))
54+
.def("toggleGui", &Visualizer::toggleGui,
55+
("self"_a, "value"_a = std::nullopt),
56+
"Toggle the GUI on and off. Passing no value will toggle. Passing a "
57+
"value will override.")
5358
.DEF_PROP_PROXY(device)
5459
.def(
5560
"takeScreenshot",

src/candlewick/multibody/Visualizer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class Visualizer final : public BaseVisualizer {
132132

133133
void processEvents();
134134

135+
void toggleGui(std::optional<bool> value = std::nullopt) noexcept {
136+
m_showGui = value.value_or(!m_showGui);
137+
}
138+
135139
[[nodiscard]] bool shouldExit() const noexcept { return m_shouldExit; }
136140

137141
void takeScreenshot(std::string_view filename);

src/candlewick/multibody/visualizer_gui.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include <imgui_impl_sdl3.h>
88
#include <magic_enum/magic_enum_flags.hpp>
99

10-
#include <string>
11-
1210
namespace candlewick::multibody {
1311
namespace core_gui = ::candlewick::gui;
1412
using namespace entt::literals;

src/candlewick/runtime/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ CANDLEWICK_RUNTIME_DEFINE_COMMAND(reset_camera);
3131
CANDLEWICK_RUNTIME_DEFINE_COMMAND(start_recording);
3232
CANDLEWICK_RUNTIME_DEFINE_COMMAND(stop_recording);
3333
CANDLEWICK_RUNTIME_DEFINE_COMMAND(clean);
34+
CANDLEWICK_RUNTIME_DEFINE_COMMAND(toggle_gui);
3435

3536
using RowMat4d = Eigen::Matrix<pin::context::Scalar, 4, 4, Eigen::RowMajor>;
3637

@@ -95,6 +96,9 @@ void pull_socket_router(Visualizer &viz, std::span<zmq::message_t, 2> msgs,
9596
} else if (header == CMD_clean) {
9697
viz.clean();
9798
sync_sock.send(zmq::str_buffer("ok"));
99+
} else if (header == CMD_toggle_gui) {
100+
viz.toggleGui();
101+
sync_sock.send(zmq::str_buffer("ok"));
98102
} else if (header == CMD_send_models) {
99103
sync_sock.send(
100104
zmq::str_buffer("error: visualizer already has models open."));

0 commit comments

Comments
 (0)