It sounds like the issue is that refreshing the view is asynchronous, and when you change the visibility of a lot of layers the pdf export starts before the refresh has completed. Ruby generally blocks the main SketchUp engine while it runs, and this makes it hard to assure completion of a side-effect such as redrawing the view before Ruby proceeds. You might try a View#refresh to force an immediate redraw, but be wary of the warnings about possible crashes in the API docs. Calling View#invalidate won’t help, as it just schedules the view for a redraw, it does not assure when that redraw will happen.
Here are a couple of ideas to speed up the crucial block of your code. They may or may not actually help with the issue (I don’t have a model on hand with enough layers to check).
- Don’t bother setting the model’s active_layer. It only affects what will be used by default for adding new geometry (same as checking the box at the left in the layers inspector window). It has no effect on what’s visible in the view. It’s a user GUI thing that is irrelevant to what you are doing.
- Try setting all layers visible to false before the start of your loop over the visible Array and adding a variable for last_layer initialized to nil (you could save the state of each layer and restore them when finished so that the user’s view isn’t altered). In the visible loop, simply fetch the current target layer by name (Layers#[ ]) instead of looping over all layers, which takes time. Save the prior layer in last_layer and turn off its visibility in the next pass.
Edit: another thought:
While turning off visibility of the layers, you could save the index into the Layers collection for each one in the visible array. Then use that index instead of the name when retrieving them in the loop. Retrieval by index is much faster than by name because there is no string compare required.