import pymel.core as pmdef setup_camera_rig(): # Get the selected camera sel = pm.selected() if not sel: pm.error("Please select a camera!") camera = sel[0] # Check if the selected object is a camera shape if not isinstance(camera.getShape(), pm.nt.Camera): pm.error("Selected object is not a camera!") # Check if camera has locked attributes locked_attrs = [] for attr in ['translate', 'rotate', 'scale']: for axis in ['X', 'Y', 'Z']: if camera.attr(f'{attr}{axis}').isLocked(): locked_attrs.append(f'{attr}{axis}') if locked_attrs: pm.error(f"Camera has locked attributes: {', '.join(locked_attrs)}. Please unlock them before running the script.") # Get the camera's world position, rotation, scale, and forward direction cam_pos = pm.xform(camera, q=True, ws=True, t=True) cam_rot = pm.xform(camera, q=True, ws=True, ro=True) cam_scale = pm.xform(camera, q=True, s=True) cam_matrix = pm.xform(camera, q=True, ws=True, m=True) forward = pm.datatypes.Vector(cam_matrix[8], cam_matrix[9], cam_matrix[10]) * -1 # Reverse forward # Create move locator move = pm.spaceLocator(name='move') pm.xform(move, ws=True, t=cam_pos, ro=cam_rot, s=cam_scale) # Create aimpoint locator 6 units in front aimpoint = pm.spaceLocator(name='aimpoint') aim_pos = pm.datatypes.Vector(cam_pos) + (forward * 6) pm.xform(aimpoint, ws=True, t=aim_pos, ro=cam_rot, s=cam_scale) # Create twist circle twist = pm.circle(name='twist', normal=(0,1,0))[0] pm.xform(twist, ws=True, t=cam_pos, ro=cam_rot, s=cam_scale) pm.rotate(twist, (90, 0, 0), r=True, os=True, fo=True) twist.scale.set(0.5 * cam_scale[0], 0.5 * cam_scale[1], 0.5 * cam_scale[2]) # Create group for the camera rig camera_rig = pm.group(em=True, name='camera_rig') pm.xform(camera_rig, ws=True, t=cam_pos) # Build the hierarchy (important: parent twist first before freezing) pm.parent(aimpoint, camera_rig) pm.parent(move, camera_rig) pm.parent(twist, move) pm.parent(camera, twist) # Freeze twist transforms AFTER parenting pm.makeIdentity(twist, apply=True, t=True, r=True, s=True, n=0) # Create an aimConstraint on move locator pm.aimConstraint( aimpoint, move, name='move_aimConstraint1', aimVector=(1, 0, 0), upVector=(0, 1, 0), worldUpType='scene', maintainOffset=True ) # Freeze aimpoint transforms (only translate and rotate) pm.makeIdentity(aimpoint, apply=True, t=True, r=True, n=0) # Lock camera translate/rotate/scale but keep visible for attr in ['translate', 'rotate', 'scale']: for axis in ['X', 'Y', 'Z']: channel = camera.attr(f'{attr}{axis}') channel.lock() channel.setKeyable(True) # Select the camera rig pm.select(camera_rig) print("Camera rig created successfully!")# Executesetup_camera_rig()