"""
Advanced Viewport Tools
Tools for controlling viewport display modes, overlays, and topology visualization.
"""
from mcp.server.fastmcp import Context, Image
import logging
import base64
logger = logging.getLogger("BlenderMCPServer")
def set_shading_mode(
ctx: Context,
blender_connection,
mode: str = "SOLID",
show_wireframe: bool = False,
show_xray: bool = False,
xray_alpha: float = 0.5
) -> str:
"""
Set the viewport shading mode and options.
Parameters:
- mode: Shading mode - "WIREFRAME", "SOLID", "MATERIAL", "RENDERED"
- show_wireframe: Show wireframe overlay on solid/material modes
- show_xray: Enable X-Ray mode for seeing through objects
- xray_alpha: X-Ray transparency (0.0-1.0)
Returns success status with applied settings.
"""
try:
result = blender_connection.send_command("set_shading_mode", {
"mode": mode,
"show_wireframe": show_wireframe,
"show_xray": show_xray,
"xray_alpha": xray_alpha
})
if "error" in result:
return f"Error: {result['error']}"
output = f"Shading mode set to: {result.get('mode')}\n"
output += f" Wireframe overlay: {result.get('wireframe_overlay')}\n"
output += f" X-Ray: {result.get('xray_enabled')} (alpha: {result.get('xray_alpha')})"
return output
except Exception as e:
logger.error(f"Error setting shading mode: {str(e)}")
return f"Error setting shading mode: {str(e)}"
def set_overlay_options(
ctx: Context,
blender_connection,
show_wireframe: bool = None,
show_face_orientation: bool = None,
show_normals: bool = None,
normals_length: float = 0.1,
show_stats: bool = None,
show_edge_seams: bool = None,
show_edge_sharp: bool = None
) -> str:
"""
Configure viewport overlay options for topology visualization.
Parameters:
- show_wireframe: Show wireframe overlay
- show_face_orientation: Show face orientation colors (blue=front, red=back)
- show_normals: Show vertex/face normals
- normals_length: Length of normal display lines
- show_stats: Show mesh statistics overlay
- show_edge_seams: Highlight UV seams
- show_edge_sharp: Highlight sharp edges
Returns list of applied settings.
"""
try:
params = {"normals_length": normals_length}
if show_wireframe is not None:
params["show_wireframe"] = show_wireframe
if show_face_orientation is not None:
params["show_face_orientation"] = show_face_orientation
if show_normals is not None:
params["show_normals"] = show_normals
if show_stats is not None:
params["show_stats"] = show_stats
if show_edge_seams is not None:
params["show_edge_seams"] = show_edge_seams
if show_edge_sharp is not None:
params["show_edge_sharp"] = show_edge_sharp
result = blender_connection.send_command("set_overlay_options", params)
if "error" in result:
return f"Error: {result['error']}"
applied = result.get('applied_settings', {})
output = "Overlay settings applied:\n"
for key, value in applied.items():
output += f" {key}: {value}\n"
return output
except Exception as e:
logger.error(f"Error setting overlay options: {str(e)}")
return f"Error setting overlay options: {str(e)}"
def get_topology_screenshot(
ctx: Context,
blender_connection,
show_wireframe: bool = True,
show_face_orientation: bool = False,
shading_mode: str = "SOLID",
max_size: int = 1024
) -> Image:
"""
Capture a screenshot with topology visualization enabled.
Temporarily enables wireframe/face orientation overlays,
captures the viewport, then restores original settings.
NOTE: Requires Blender running with GUI (not --background mode).
This tool uses bpy.ops.screen.screenshot which needs a window context.
Parameters:
- show_wireframe: Show wireframe overlay in screenshot
- show_face_orientation: Show face orientation colors
- shading_mode: Shading mode for screenshot
- max_size: Maximum dimension of the screenshot
Returns the screenshot as an Image with topology visible.
"""
try:
result = blender_connection.send_command("get_topology_screenshot", {
"show_wireframe": show_wireframe,
"show_face_orientation": show_face_orientation,
"shading_mode": shading_mode,
"max_size": max_size
})
if "error" in result:
raise Exception(result['error'])
image_data = result.get('image_data')
if image_data:
return Image(data=base64.b64decode(image_data), media_type="image/png")
else:
raise Exception("No image data received")
except Exception as e:
logger.error(f"Error capturing topology screenshot: {str(e)}")
raise