@@ -116,13 +116,27 @@ def _capture_renderer(obj, options, registry, render_passes, compute_passes):
116116
117117
118118def _export_theme (scene , registry ) -> dict :
119- """Find any renderer's buffer for theme color updates."""
120- from ..renderer import Renderer
119+ """Find renderer buffers that the engine should update on theme changes.
120+
121+ ``buffer_id`` is the (optional) colorbar background buffer. ``label_buffers``
122+ lists font-color targets for labels that left their color at the default, so
123+ the engine can pick a theme-appropriate text color (black on a light canvas,
124+ off-white on a dark one).
125+ """
126+ theme = {}
121127 for obj in scene .render_objects :
122128 buf_id = _find_theme_buffer (obj , registry )
123129 if buf_id :
124- return {"buffer_id" : buf_id }
125- return {}
130+ theme ["buffer_id" ] = buf_id
131+ break
132+
133+ label_targets = []
134+ seen = set ()
135+ for obj in scene .render_objects :
136+ _collect_theme_label_targets (obj , registry , label_targets , seen )
137+ if label_targets :
138+ theme ["label_buffers" ] = label_targets
139+ return theme
126140
127141
128142def _find_theme_buffer (obj , registry ) -> str | None :
@@ -137,6 +151,24 @@ def _find_theme_buffer(obj, registry) -> str | None:
137151 return None
138152
139153
154+ def _collect_theme_label_targets (obj , registry , out , seen ):
155+ """Recursively gather font-color targets for theme-defaulted labels."""
156+ if obj is None or id (obj ) in seen :
157+ return
158+ seen .add (id (obj ))
159+ if hasattr (obj , 'get_theme_label_target' ):
160+ target = obj .get_theme_label_target (registry )
161+ if target and target ["buffer_id" ] not in {t ["buffer_id" ] for t in out }:
162+ out .append (target )
163+ if hasattr (obj , 'render_objects' ):
164+ for child in obj .render_objects :
165+ _collect_theme_label_targets (child , registry , out , seen )
166+ if hasattr (obj , 'gpu_objects' ):
167+ for child in obj .gpu_objects :
168+ if child is not obj :
169+ _collect_theme_label_targets (child , registry , out , seen )
170+
171+
140172def _export_camera (camera , options , registry ) -> dict :
141173 """Export camera state and identify the camera buffer."""
142174 t = camera .transform
0 commit comments