How to wait until actual background color change?

Hi all.

In an “A” c# script component i’m using this:

this.RhinoDocument.RenderSettings.BackgroundColorTop = c;
this.RhinoDocument.RenderSettings.BackgroundColorBottom = c;
Rhino.ApplicationSettings.AppearanceSettings.ViewportBackgroundColor = c;
this.RhinoDocument.Views.Redraw();

then, “later” in the component flow in the same .gh script, i’m using in a “B” c# script component:
view.CaptureToBitmap();

“A” do expire the flow that feeds “B” , so every other part of the code is indeed properly executed in the order I need.
The geometries I’m handling are heavy, and the whole script is complex… I do see on screen color change, but that visual effect came too late, “B” script fully computed and the .CaptureToBitmap() already happened with the old background color.


How to make a c#/Rhinocommon code to “wait until all pending changes in the viewport are fully completed”?

EDIT:
putting all the code into a single c# script at the end of the process still have the same problem. Rhino.RhinoApp.Wait(); doesn’t help too.
Rhinocommon seems to just “throw” the background change request but then it continue instantly and capturetobitmap happens when the color is not yet updated.
All of this inside a c# script in grasshopper, this might also freeze the viewports until the component finishes, but that’s why I had the color change in another, prior, component…

Hi @maje90,

he problem isn’t timing — it’s that CaptureToBitmap() isn’t a screen grab.

Views.Redraw() only calls InvalidateRect, which posts a paint message. The frame gets drawn when Rhino’s message loop runs, which it can’t while your component owns the UI thread. So there’s nothing to wait on.

And CaptureToBitmap() doesn’t read the screen — it re-renders the view offscreen using the display attributes the pipeline was left holding after its last completed frame. No frame has been drawn since your color change, so you get the old attributes. Hence: screen right, bitmap wrong.

Rather than wait, just tell the capture what background to use:

using System.Drawing;
using Rhino.Display;

RhinoView view = this.RhinoDocument.Views.ActiveView;

// this is a copy - it won't alter the user's display mode
DisplayModeDescription mode = view.ActiveViewport.DisplayMode;
DisplayPipelineAttributes attrs = mode.DisplayAttributes;

attrs.SetFill(c);                 // or SetFill(top, bottom) for a gradient

Bitmap bmp = view.CaptureToBitmap(attrs);
mode.Dispose();

Synchronous, no redraw needed, and it doesn’t permanently change AppearanceSettings or the document’s RenderSettings the way your current code does.

One aside: RenderSettings.BackgroundColorTop/Bottom only affects Rendered mode with background set to “Use render settings”, while AppearanceSettings.ViewportBackgroundColor only affects display modes set to “Use application settings” — so only one of those two lines was ever doing anything for you.

– Dale

Thank you, Dale!

Sorry for late reply, I only managed some day ago to try your solution in the code.
Works correctly!

yeah, I was quite desperate… :sweat_smile: