Skip to main content

Custom GUI Panels

Language:

GUI panels let you place your application's 2D interfaces into the shared 3D room: dashboards, settings pages, control surfaces. Panels are shared session state — every peer sees the same panel at the same place, live. Panel content is currently web content: the panel renders a URI, which makes any existing web UI immediately usable in the room.

The concepts (identity by common name, top-left-corner pose, size + content scale, per-peer visibility) are explained in The QAROS World and Coordinate Systems.

Creating a panel (idempotent)

Panels are identified by a stable common name; get_or_create returns the existing panel or creates it — safe to call on every app start:

QarGuiPanelInit init = qar_gui_panel_init_default();
init.common_name = "machine-status.myapp.example.com"; /* stable identity */
init.display_name = "Machine Status";

init.pose = qar_pose_default();
init.pose.position.y = 1.5f; /* top-left corner, room space, meters */
init.pose.position.z = -1.0f;

QarGuiPanelSize size = qar_gui_panel_size_default();
size.width_meters = 0.8f;
size.height_meters = 0.5f;
init.size = size;

QarGuiPanelId panel_id;
QarResult r = qar_gui_panels_get_or_create(session, &init, &panel_id);
qar_result_log_if_error(r);

qar_gui_panels_navigate_to_uri(
session, &panel_id, "https://myapp.local/status-dashboard");
info

The C# snippets on this page are illustrative — they track the Qar binding surface but are not yet compiled from a published sample project.

:::tip Choosing common names Use a DNS-style, application-scoped name (<panel>.<app>.<org>) and keep it constant across versions. The panel's ID is derived deterministically from it — restarting your app reattaches to the same panel instead of spawning duplicates. :::

Manipulating panels

All mutations go through the session and the panel ID:

qar_gui_panels_update_pose(session, &panel_id, &new_pose); /* move it */
qar_gui_panels_change_size(session, &panel_id, &new_size); /* resize */
qar_gui_panels_set_state(session, &panel_id, QAR_GUI_PANEL_STATE_MINIMIZED);
qar_gui_panels_navigate_to_uri(session, &panel_id, "https://...");
qar_gui_panels_close_panel(session, &panel_id); /* remove */

Panel states: VISIBLE, MINIMIZED, HIDDEN, CLOSED.

Per-peer visibility

By default a panel is visible to everyone. Restrict it by editing the visibility set — for example an operator-only control panel:

const QarPeerId* add[] = { &operator_peer_id };
qar_gui_panels_update_visible_to(
session, &panel_id,
add, 1, /* additions */
NULL, 0); /* removals */

Observing panels

Your app can react to panels changing — whether changed by another peer, another app, or a user grabbing the panel in the room:

  • qar_gui_panels_subscribe_updates(session, callback, state) — all panels,
  • qar_gui_panels_subscribe_panel_updates(session, &panel_id, callback, state) — one panel,
  • qar_query_gui_panels_count / qar_query_gui_panels — enumerate current panels (count-then-fetch),
  • per-panel getters: qar_gui_panel_get_display_name, _get_pose, _get_size, _get_state, _get_content_uri, _get_visible_to_peers.

Update callbacks arrive on library threads — see the callback rules.

Integration patterns

Expose your app's existing web UI. If your application already serves a web frontend (local status page, embedded HTTP server), a panel is a one-call integration: get_or_create + navigate_to_uri pointing at your server. Interaction happens directly in the room.

Drive app state from a panel. Host a small web page that calls back into your application (REST/WebSocket). The panel is shared, so any user in the room can press the buttons; your app sees the effect and updates its rendered content accordingly.

Attach a panel to your app volume. Panels don't parent to volumes automatically, but you can keep one docked: subscribe to your volume's pose updates and reposition the panel relative to it. Remember the differing conventions — panel pose is the top-left corner, volume pose is the center.

Compiled tutorial

This page is backed by the compiled example gui_panel_operations.c, covering panel create, move, navigate, and subscribe:

  • Source: qaros/qar-streaming-c/examples/gui_panel_operations.c
  • Example walkthrough: GUI Panel Operations