"""
Camera and viewport tools for orthographic reference views.
Provides safe, parameterized tools for camera control and orthographic projection.
"""
from typing import Dict, Any, Optional
from mcp.server.fastmcp import Context
import logging
logger = logging.getLogger("BlenderMCPServer")
# ============================================================================
# ALIGN ACTIVE CAMERA TO VIEW
# ============================================================================
def align_active_camera_to_view(
ctx: Context,
blender_connection
) -> str:
"""
Align the active camera to match the current viewport view.
Positions and rotates the active camera to exactly match the current
3D viewport angle. Useful for setting up orthographic reference cameras.
Requires an active camera in the scene.
Returns status message with camera alignment result.
"""
try:
result = blender_connection.send_command("align_active_camera_to_view", {})
if "error" in result:
return f"Error: {result['error']}"
output = "Camera Aligned to View!\n\n"
if 'camera_name' in result:
output += f"Camera: {result['camera_name']}\n"
if 'location' in result:
loc = result['location']
output += f"Location: ({loc[0]:.2f}, {loc[1]:.2f}, {loc[2]:.2f})\n"
if 'rotation' in result:
rot = result['rotation']
output += f"Rotation: ({rot[0]:.2f}°, {rot[1]:.2f}°, {rot[2]:.2f}°)\n"
return output
except Exception as e:
logger.error(f"Error aligning camera to view: {str(e)}")
return f"Error aligning camera to view: {str(e)}"
# ============================================================================
# SET CAMERA PROJECTION
# ============================================================================
def set_camera_projection(
ctx: Context,
blender_connection,
projection_type: str = "ORTHO",
ortho_scale: float = 10.0
) -> str:
"""
Set the active camera's projection type and scale.
Changes the camera between perspective and orthographic projection.
Orthographic cameras have no perspective distortion, making them ideal
for technical references and orthographic views.
Parameters:
- projection_type: Camera type - 'PERSP' or 'ORTHO' (default: 'ORTHO')
- ortho_scale: For ORTHO cameras, the orthographic scale (default: 10.0)
Returns status message with camera projection settings.
"""
try:
valid_types = ['PERSP', 'ORTHO']
if projection_type not in valid_types:
return f"Error: Invalid projection_type '{projection_type}'. Must be 'PERSP' or 'ORTHO'."
if projection_type == 'ORTHO' and ortho_scale <= 0:
return f"Error: ortho_scale must be greater than 0."
result = blender_connection.send_command("set_camera_projection", {
"projection_type": projection_type,
"ortho_scale": ortho_scale
})
if "error" in result:
return f"Error: {result['error']}"
output = "Camera Projection Updated!\n\n"
if 'camera_name' in result:
output += f"Camera: {result['camera_name']}\n"
output += f"Projection: {projection_type}\n"
if projection_type == 'ORTHO':
output += f"Orthographic Scale: {ortho_scale}\n"
output += "\nℹ Camera is now orthographic - no perspective distortion.\n"
output += "Renders will show parallel lines without convergence.\n"
return output
except Exception as e:
logger.error(f"Error setting camera projection: {str(e)}")
return f"Error setting camera projection: {str(e)}"
# ============================================================================
# SET ACTIVE CAMERA
# ============================================================================
def set_active_camera(
ctx: Context,
blender_connection,
camera_name: str
) -> str:
"""
Set the specified camera as the active scene camera.
Makes the named camera the active render camera for the scene.
Useful when working with multiple reference cameras.
Parameters:
- camera_name: Name of the camera object to make active
Returns status message with active camera info.
"""
try:
result = blender_connection.send_command("set_active_camera", {
"camera_name": camera_name
})
if "error" in result:
return f"Error: {result['error']}"
output = "Active Camera Set!\n\n"
output += f"Camera: {camera_name}\n"
if 'projection_type' in result:
output += f"Projection: {result['projection_type']}\n"
return output
except Exception as e:
logger.error(f"Error setting active camera: {str(e)}")
return f"Error setting active camera: {str(e)}"