diff --git a/src/viser/_gui_api.py b/src/viser/_gui_api.py index cccb142d..1f59b254 100644 --- a/src/viser/_gui_api.py +++ b/src/viser/_gui_api.py @@ -342,6 +342,10 @@ def _set_container_id(self, container_id: str) -> None: """Set container ID associated with the current thread.""" self._target_container_from_thread_id[threading.get_ident()] = container_id + def reset(self) -> None: + """Reset the GUI.""" + self._websock_interface.queue_message(_messages.ResetGuiMessage()) + def set_panel_label(self, label: str | None) -> None: """Set the main label that appears in the GUI panel. diff --git a/src/viser/_messages.py b/src/viser/_messages.py index 21e23d0f..1e6d6517 100644 --- a/src/viser/_messages.py +++ b/src/viser/_messages.py @@ -478,6 +478,11 @@ class ResetSceneMessage(Message): """Reset scene.""" +@dataclasses.dataclass +class ResetGuiMessage(Message): + """Reset GUI.""" + + @tag_class("GuiAddComponentMessage") @dataclasses.dataclass class GuiAddFolderMessage(Message): diff --git a/src/viser/_viser.py b/src/viser/_viser.py index 675ceb1b..d6b57b17 100644 --- a/src/viser/_viser.py +++ b/src/viser/_viser.py @@ -533,6 +533,7 @@ def _(conn: infra.WebsockClientConnection) -> None: self.request_share_url() self.scene.reset() + self.gui.reset() self.gui.set_panel_label(label) def get_host(self) -> str: diff --git a/src/viser/client/src/ControlPanel/GuiState.tsx b/src/viser/client/src/ControlPanel/GuiState.tsx index 0d9db966..52481565 100644 --- a/src/viser/client/src/ControlPanel/GuiState.tsx +++ b/src/viser/client/src/ControlPanel/GuiState.tsx @@ -135,10 +135,15 @@ export function useGuiState(initialServer: string) { }), resetGui: () => set((state) => { + // This feels brittle, could be cleaned up... + state.theme = cleanGuiState.theme; + state.label = cleanGuiState.label; state.shareUrl = null; state.guiIdSetFromContainerId = {}; + state.modals = []; state.guiOrderFromId = {}; state.guiConfigFromId = {}; + state.uploadsInProgress = {}; }), updateUploadState: (state) => set((globalState) => { diff --git a/src/viser/client/src/MessageHandler.tsx b/src/viser/client/src/MessageHandler.tsx index a7f9330f..6111a4e0 100644 --- a/src/viser/client/src/MessageHandler.tsx +++ b/src/viser/client/src/MessageHandler.tsx @@ -60,6 +60,7 @@ function useMessageHandler() { const removeSceneNode = viewer.useSceneTree((state) => state.removeSceneNode); const resetScene = viewer.useSceneTree((state) => state.resetScene); const addSceneNode = viewer.useSceneTree((state) => state.addSceneNode); + const resetGui = viewer.useGui((state) => state.resetGui); const setTheme = viewer.useGui((state) => state.setTheme); const setShareUrl = viewer.useGui((state) => state.setShareUrl); const addGui = viewer.useGui((state) => state.addGui); @@ -892,6 +893,11 @@ function useMessageHandler() { viewer.backgroundMaterialRef.current!.uniforms.enabled.value = false; return; } + // Reset the GUI state. + case "ResetGuiMessage": { + resetGui(); + return; + } // Update props of a GUI component case "GuiUpdateMessage": { updateGuiProps(message.id, message.updates); diff --git a/src/viser/client/src/WebsocketMessages.tsx b/src/viser/client/src/WebsocketMessages.tsx index 192a443d..5155b6ab 100644 --- a/src/viser/client/src/WebsocketMessages.tsx +++ b/src/viser/client/src/WebsocketMessages.tsx @@ -380,6 +380,13 @@ export interface SceneNodeClickMessage { export interface ResetSceneMessage { type: "ResetSceneMessage"; } +/** Reset GUI. + * + * (automatically generated) + */ +export interface ResetGuiMessage { + type: "ResetGuiMessage"; +} /** GuiAddFolderMessage(order: 'float', id: 'str', label: 'str', container_id: 'str', expand_by_default: 'bool', visible: 'bool') * * (automatically generated) @@ -963,6 +970,7 @@ export type Message = | SetSceneNodeClickableMessage | SceneNodeClickMessage | ResetSceneMessage + | ResetGuiMessage | GuiAddFolderMessage | GuiAddMarkdownMessage | GuiAddProgressBarMessage