Scripting API
Render Studio stills
from ArtisanPlugin.Scripting import RenderStudioApi as studio
One raytraced image, taken the way the ArtisanRenderAndAnimation panel’s Render button takes it: the document render settings are written, Rhino’s current renderer runs — Cycles unless the user changed it — and the result is saved from the render window to the path you gave. It renders the Rhino document through the real renderer, which is why it is slow and why it looks like the panel’s output; the Realtime Render viewer and its ViewerScreenshot are a different, much faster path with a different look.
Usage
path = studio.RenderStill(r"C:\out\ring.png")
path = studio.RenderStill(r"C:\out\ring.png", width = 2000, height = 1500, samples = 1200)
Returns the full path actually written, which is worth capturing rather than reusing your own string — the path is normalised on the way in.
Parameters
| Parameter | Default | Meaning |
|---|---|---|
path | required | Destination file. Resolved to a full path; ".png" is appended when it has no extension at all; the containing folder is created if missing. |
width | 0 | Image width in pixels. 0 keeps the tool default, 800. |
height | 0 | Image height in pixels. 0 keeps the tool default, 600. |
samples | 0 | Cycles passes. 0 keeps the tool default, 500. |
There is no -1 sentinel here, and no “use the viewport size” mode: any value at or below zero — including a negative — is treated as “keep the default”. To render at the viewport’s own size you have to read it yourself and pass the numbers.
samples is written as the document-samples override that Cycles reads. If the current renderer is something other than Cycles, the size still applies but the sample count is meaningless to it.
Where the file goes
Wherever path points. There is no output folder of the studio’s own, and no automatic naming — you name the file. Two details of the normalisation matter to a script:
- Relative paths resolve against Rhino’s working directory, not against the script’s folder. Always pass an absolute path.
- The extension you give decides the format, because the save goes through Rhino’s own
SaveRenderWindowAs..png,.jpgand.tifall work; the default.pngis only substituted when there is no extension at all. A path ending in a bare version number such asring.v2will be read as having the extension.v2and will not gain a.png. - An existing file at that path is overwritten.
What it changes, and how long it blocks
RenderStill renders; it does not add, remove or modify geometry, so there is nothing to undo in the usual sense and no Transaction is required. It is not, however, entirely read-only: the document render settings are written on every call — the fixed output size is turned on, the image size is set, and the Cycles document-samples override is set to your samples. Those settings persist in the document after the call and will be saved with it.
The call blocks until the render is finished and the file is on disk. At the defaults that is seconds; at 2000×1500 and a high sample count expect minutes, during which Rhino is busy. There is no progress callback and no asynchronous variant.
The render window is left open afterwards, exactly as the panel leaves it. A script that renders several stills in a row will keep reusing it; close it with _-CloseRenderWindow if you want it out of the way at the end.
Failures
InvalidOperationException: No active document.
ArgumentException: A destination file path is required.
InvalidOperationException: The render was cancelled or failed.
InvalidOperationException: The render image could not be saved.
The third is what you get when the user hits Escape or closes the render window mid-render — an unattended script should treat it as “no image was produced”. The licence check runs first and throws before any of these.
import rhinoscriptsyntax as rs
from ArtisanPlugin.Scripting import RenderStudioApi as studio
studio.ApplyEnvironment() # known-good studio lighting
for view in ("Perspective", "Top"):
rs.CurrentView(view)
print(studio.RenderStill(r"C:\out\ring-" + view + ".png", 1600, 1200, 800))