The bearcad.ui.* namespace
Everything under bearcad.ui simulates a real user driving the GUI — mouse, keyboard,
camera, tools, panes, palette. Use it when the UI interaction itself is what you're
testing; for ordinary modeling use the declarative API.
Tools and synthetic input
bearcad.ui.tool("rectangle") -- select, line, circle, sketch, rectangle, ...
bearcad.ui.click_ground(0, 0) -- click on the active sketch plane, in millimetres
bearcad.ui.move_ground(80, 50)
bearcad.ui.click(x, y) -- viewport pixel coordinates instead
bearcad.ui.click_ground(20, -10, { shift = true }) -- Shift+click
bearcad.ui.click_ground(20, -10, { ctrl = true }) -- Ctrl+click: one edge, not its run
bearcad.ui.move(x, y)
bearcad.ui.key("enter")
bearcad.ui.type("12.5")
Camera
bearcad.ui.orbit(dx, dy)
bearcad.ui.pan(dx, dy)
bearcad.ui.wheel(scroll)
bearcad.ui.view("front") -- standard view; waits for the camera animation
bearcad.ui.view("edge", "front_top") -- a view-bear edge
bearcad.ui.view_home()
bearcad.ui.toggle_projection()
bearcad.ui.shading("solid_wireframe") -- "wireframe" | "transparent" | "solid" | "solid_wireframe"
bearcad.ui.ground("off") -- ground plane: "grid" | "solid" | "off"
Absolute camera control sets the pose instantly (no transition animation), which keeps
scripted screenshots deterministic; with no pose fields, camera{} is a pure read:
local c = bearcad.ui.camera{} -- { yaw, pitch, distance, target = {x, y, z},
-- projection = "perspective" | "orthographic" }
bearcad.ui.camera{ yaw = 1.0, distance = 200 } -- set any subset of the pose
bearcad.ui.camera{ target = {20, 15, 5}, pitch = 0.6 }
bearcad.ui.zoom_fit() -- frame the whole document (bodies + sketch geometry)
bearcad.ui.snapping(false) -- snapping while drawing and placing shapes
See Navigation for what these correspond to in the GUI, including the view bear's gear/shading-modes popup.
Panes and the command palette
bearcad.ui.pane("hierarchy", "hide") -- show / hide / toggle a pane
bearcad.ui.pane("view_bear", "show") -- panes: hierarchy, context, parameters, view_bear
bearcad.ui.palette("run", "view top") -- run a command palette entry by name
bearcad.ui.elements_view("graph") -- Elements-pane layout: "list" | "tree" | "graph"
Dragging constrained geometry
bearcad.ui.drag_vertex({ kind = "line", index = 0, ["end"] = "end" }, u, v)
bearcad.ui.drag_line({ kind = "line", index = 0 }, au, av, u, v)
bearcad.ui.focus_dim("length") -- focus a dimension input field
Waiting
Because scripts run in a coroutine, these calls yield until the condition is met rather than blocking the interpreter:
bearcad.ui.wait(5) -- wait 5 UI frames
bearcad.ui.wait_ms(100) -- wait 100 milliseconds
Help mode
Help → Help Mode in the OS menu (⌘/Ctrl+/) toggles it in the app; from scripts:
bearcad.ui.help(true) -- explain every Context-pane control
bearcad.ui.help(false)
bearcad.ui.help() -- toggle
With help mode on, each row of the Context pane gets a floating note beside it saying what it wants. A pane screenshot widens to include the notes, which is how the annotated pane pictures in the tool pages are made.
bearcad.ui.tool_mode("free") -- put the active tool in one of its modes
tool_mode names the mode a tool's Context pane offers — "snap"/"free" for Move,
"combine"/"cut"/"intersect"/"difference" for Combine — reaching mode rows that a
scripted click cannot.
Screenshots
bearcad.ui.screenshot() -- writes screenshot-bearcad.png
bearcad.ui.screenshot("out.png")
bearcad.ui.screenshot("out.png", true) -- the entire window
bearcad.ui.screenshot("out.png", "window") -- the same, named
bearcad.ui.screenshot("out.png", "context") -- just the Context pane
bearcad.ui.screenshot("out.png", "elements") -- just the Elements pane
By default, screenshot captures the 3D viewport only (the view bear is suppressed for
that frame). This is the mechanism behind BearCAD's visual regression testing: a script
drives an exact interactive flow and emits a screenshot to compare against a golden image
in CI.
The second argument picks the region: "viewport" (the default), "window", or a pane
name — "context", "elements", "parameters". A pane shot is cropped to the pane and
stops below its last control, so it is the controls rather than a tall empty column. The
docs' annotated pane pictures are made this way.
Whether an action arrives declaratively or through bearcad.ui.*, it lands as the same
committed document change.