Scene-scoped alert / confirm / update_control — VizSceneHandle
now exposes alert(), confirm(), and update_control(), scoped to the
handle's scene (no scene_name= argument). Previously these were only
available on Visualizer, where they accept an explicit scene_name=.
VisualizerApp forwards add_default_axes / add_default_grid — the app
base class now accepts and forwards these two flags, matching Visualizer.
Visualizer.scene(name, add_axes=…, add_grid=…) — a named scene can opt
out of the default placeholder grid/axes at creation, so a
CoordinateSystem pane doesn't draw a duplicate grid/axes underneath its own.
fit_view2d(xlim, ylim, …) — a standalone helper that computes the
centred View2DConfig a CoordinateSystem would auto-fit, for embedding an
exact per-pane camera into a SceneView(..., camera=...) at layout time.
ActSceneObject.drag_anchor(ray_origin, ray_direction) ideal-drag hook —
interactive objects drag from a point on their ideal geometry (via the new
interaction:drag_anchor backend reply) instead of the raw mesh hit point;
ActPoint anchors on its centre, and the drag scale is re-anchored to the
same ideal point.
Removed Visualizer(port=…, host=…, open_browser=…) and
VisualizerApp(port=…, host=…, open_browser=…) — the deprecated constructor
parameters are gone. Configure the server via start_server(host=…, port=…),
show(host=…, port=…), or VisualizerApp.run(host=…, port=…).
Server lifecycle no longer corrupts global state — start_server() /
stop_server() (and the SDF viewer) no longer replace the caller's event
loop or the process SIGINT/SIGTERM handlers, and restore them on stop.
A busy port now reports a clear message (no traceback) instead of the
misleading 5-second timeout, and a failed boot is cleaned up.
Busy-port detection works on Windows — the "port already in use" check
now recognises the WinSock WSAEADDRINUSE (10048) code and its "only one
usage of each socket address" message in addition to POSIX EADDRINUSE, so
start_server() reports the clear message on Windows instead of a raw
OSError traceback.
VisualizerApp.run(timeout=…) is honoured — the timeout is threaded down
to the browser wait instead of being ignored.
show(layout=…) opens the layout URL — the default reconnect path now
opens the pending layout URL (/?view=<name>&token=…) instead of the plain
/?token=…, so split views render instead of a blank single scene (this
also fixes named-scene open_browser()).
update_entity re-applies rotation and other creation-only geometry —
the live viewer no longer silently drops rotation (and size, radii,
normal, axis, sides, startDirection, radiusU/radiusV,
point, pointA/pointB, origin) when a Box, Ellipsoid, Disk,
Ellipse, RegularPolygon, PartialDisk, Circle, or Plane is updated
in place; the same fix covers the Rotor, GeneralRotor, Motor,
Dilator, PointPair, and ReflectionPlane operators.
ReflectionPoint serializes its position — the operator now emits
center from ReflectionPoint.point (instead of a hardcoded
origin: [0, 0, 0]) and radius instead of extent, so it renders at the
reflection point rather than always at the origin.
Pointer interaction is independent per split-view pane — each pane now
owns its own interaction state (camera, canvas, controls, object registry),
so draggable ActPoints work in every pane instead of only one.
2D panes frame with their own aspect ratio — the 2D orthographic frustum
now uses the pane's aspect (not the whole window's), so CoordinateSystem
plots in a split view are scaled correctly.
ActPoint drags anchor on the ideal point, not the mesh surface —
XY/XZ/YZ-plane drags were anchored on the rendered sphere surface; the ideal
anchor now keeps the point on the constraint plane (no spurious out-of-plane
component).