feat: add tool to get screenshot of viewport
This commit is contained in:
parent
972096e9dc
commit
093c756a9f
58
addon.py
58
addon.py
@ -197,6 +197,7 @@ class BlenderMCPServer:
|
||||
handlers = {
|
||||
"get_scene_info": self.get_scene_info,
|
||||
"get_object_info": self.get_object_info,
|
||||
"get_viewport_screenshot": self.get_viewport_screenshot,
|
||||
"execute_code": self.execute_code,
|
||||
"get_polyhaven_status": self.get_polyhaven_status,
|
||||
"get_hyper3d_status": self.get_hyper3d_status,
|
||||
@ -330,6 +331,63 @@ class BlenderMCPServer:
|
||||
|
||||
return obj_info
|
||||
|
||||
def get_viewport_screenshot(self, max_size=800, filepath=None, format="png"):
|
||||
"""
|
||||
Capture a screenshot of the current 3D viewport and save it to the specified path.
|
||||
|
||||
Parameters:
|
||||
- max_size: Maximum size in pixels for the largest dimension of the image
|
||||
- filepath: Path where to save the screenshot file
|
||||
- format: Image format (png, jpg, etc.)
|
||||
|
||||
Returns success/error status
|
||||
"""
|
||||
try:
|
||||
if not filepath:
|
||||
return {"error": "No filepath provided"}
|
||||
|
||||
# Find the active 3D viewport
|
||||
area = None
|
||||
for a in bpy.context.screen.areas:
|
||||
if a.type == 'VIEW_3D':
|
||||
area = a
|
||||
break
|
||||
|
||||
if not area:
|
||||
return {"error": "No 3D viewport found"}
|
||||
|
||||
# Take screenshot with proper context override
|
||||
with bpy.context.temp_override(area=area):
|
||||
bpy.ops.screen.screenshot_area(filepath=filepath)
|
||||
|
||||
# Load and resize if needed
|
||||
img = bpy.data.images.load(filepath)
|
||||
width, height = img.size
|
||||
|
||||
if max(width, height) > max_size:
|
||||
scale = max_size / max(width, height)
|
||||
new_width = int(width * scale)
|
||||
new_height = int(height * scale)
|
||||
img.scale(new_width, new_height)
|
||||
|
||||
# Set format and save
|
||||
img.file_format = format.upper()
|
||||
img.save()
|
||||
width, height = new_width, new_height
|
||||
|
||||
# Cleanup Blender image data
|
||||
bpy.data.images.remove(img)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"filepath": filepath
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
def execute_code(self, code):
|
||||
"""Execute arbitrary Blender Python code"""
|
||||
# This is powerful but potentially dangerous - use with caution
|
||||
|
||||
@ -4,6 +4,7 @@ import socket
|
||||
import json
|
||||
import asyncio
|
||||
import logging
|
||||
import tempfile
|
||||
from dataclasses import dataclass
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncIterator, Dict, Any, List
|
||||
@ -266,6 +267,47 @@ def get_object_info(ctx: Context, object_name: str) -> str:
|
||||
logger.error(f"Error getting object info from Blender: {str(e)}")
|
||||
return f"Error getting object info: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
def get_viewport_screenshot(ctx: Context, max_size: int = 800) -> Image:
|
||||
"""
|
||||
Capture a screenshot of the current Blender 3D viewport.
|
||||
|
||||
Parameters:
|
||||
- max_size: Maximum size in pixels for the largest dimension (default: 800)
|
||||
|
||||
Returns the screenshot as an Image.
|
||||
"""
|
||||
try:
|
||||
blender = get_blender_connection()
|
||||
|
||||
# Create temp file path
|
||||
temp_dir = tempfile.gettempdir()
|
||||
temp_path = os.path.join(temp_dir, f"blender_screenshot_{os.getpid()}.png")
|
||||
|
||||
result = blender.send_command("get_viewport_screenshot", {
|
||||
"max_size": max_size,
|
||||
"filepath": temp_path,
|
||||
"format": "png"
|
||||
})
|
||||
|
||||
if "error" in result:
|
||||
raise Exception(result["error"])
|
||||
|
||||
if not os.path.exists(temp_path):
|
||||
raise Exception("Screenshot file was not created")
|
||||
|
||||
# Read the file
|
||||
with open(temp_path, 'rb') as f:
|
||||
image_bytes = f.read()
|
||||
|
||||
# Delete the temp file
|
||||
os.remove(temp_path)
|
||||
|
||||
return Image(data=image_bytes, format="png")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error capturing screenshot: {str(e)}")
|
||||
raise Exception(f"Screenshot failed: {str(e)}")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user