Setting camera position and taking screenshot of 3D view with Python API

The following function is an example of how to change the camera position and take a screenshot of the 3D view.

import XRendererUI
import XCore
from s4l_v1.model import Vec3
import numpy as np
import os

import pywintypes
import win32gui
import time

import random, string

def randomword(length):
   return ''.join(random.choice(string.lowercase) for i in range(length))

def camera(viewname, distance, target, theta):
	cam = XRendererUI.SaveCamera('')  # load or create a new camera setting
	cam.OrbitCenter.Value = Vec3(0,0,0)
	cam.Distance.Value = distance
	target.Normalize()

	cam.Orientation.Value = [np.cos(theta/2.)] + list(np.sin(theta/2)*target)  #quaternions 
	#print 'Cam: ', cam.Orientation.Value
	return cam

def set_camera(keyword, distance):
	if keyword == 'current':
		cam = XRendererUI.SaveCamera(randomword(20))  # create a new camera setting from current view settings
	elif keyword =='XY':
		cam = camera('XY', distance, Vec3(1,0,0), -np.pi/2.0)
	elif keyword =='XZ':
		cam = camera('XZ', distance, Vec3(0,1,0), np.pi/2.0)
	elif keyword =='YZ':
		cam = camera('YZ', distance, Vec3(0,0,1), np.pi/2.0)
	elif keyword =='ZXY':
		cam = camera('ZXY', distance, Vec3(1,1,1), np.pi)
	else:
		raise RuntimeError('Invalid option (%s) for camera setting' % keyword)
	return cam

def makeScreenshots(target_dir=None, distance=200.0, transparent_bg=True, delay=0.001,
					width=1024, height=1024, prefix='', suffix='',views='default'):

	if target_dir is None:
		target_dir = XCore.GetApp().Document.FileFolder
	assert os.path.exists(target_dir)

	if views=='default':
		viewnames = ['XY', 'XZ', 'YZ', 'ZXY']
	else:
		viewnames = views
	assert all([view in ['current', 'XY', 'XZ', 'YZ', 'ZXY'] for view in viewnames]), 'View not implemented'

	screenshot_paths = []
	for viewname in viewnames:
		cam = set_camera(viewname, distance)	
		XRendererUI.RestoreCamera(cam)
		
		time.sleep(delay)                 # wait for 3D rendering to complete
		win32gui.PumpWaitingMessages()  # update view

		filename = XCore.GetApp().Document.FileName
		if not prefix:
			prefix = os.path.splitext(filename)[0]
		screenshot_name = prefix + '_' + viewname
		
		# Workaround to remove counter
		# delete file if it already exists
		actual_screenshot_name = os.path.join(target_dir, screenshot_name + '-001.png')
		desired_screenshot_name = os.path.join(target_dir, screenshot_name + '.png')
		if os.path.isfile(desired_screenshot_name):
			os.remove(desired_screenshot_name)

		XRendererUI.SaveScreenCapture(width=width, height=height, output_folder=target_dir, output_prefix=screenshot_name, 
									  transparent_background=transparent_bg)
									  
		#actual_screenshot_name = os.path.join(target_dir, os.path.splitext(filename)[0] + '-001.png')
		os.rename(actual_screenshot_name, desired_screenshot_name)

		screenshot_paths.append(desired_screenshot_name)

	return screenshot_paths


# Example usage: 
# Take 4 screenshots at a distance of 200 units from 4 different view angles
# and place the pictures (PNG files) in the same folder as the project file.

if __name__=="__main__":
	makeScreenshots(distance=200.0, transparent_bg=True)