Blender-MCP服务源码5-BlenderSocket插件安装

Blender-MCP服务源码5-BlenderSocket插件安装

上一篇讲述了Blender是基于Socket进行本地和远程进行通讯,现在尝试将BlenderSocket插件安装到Blender中进行功能调试


1-核心知识点

  • 将开发的BlenderSocket插件安装到Blender中

2-思路整理

  • 1)将SocketServer部署到Blender启动SocketServer
  • 2)本地使用SocketClient连接SocketServer尝试发送指令
  • 3)验证交互结果->如果该逻辑通->后续就可以完善MCP业务指令

3-参考网址

  • Blender-MCP-Github地址:https://github.com/ahujasid/blender-mcp
  • B站大佬开源Blender开发框架:https://github.com/xzhuah/BlenderAddonPackageTool
  • B站大佬开源Blender开发框架教程
  • 个人实现代码仓库1:https://gitee.com/enzoism/python_blender_socket
  • 个人实现代码仓库2:https://gitee.com/enzoism/python_blender_mcp

4-上手实操

1-部署Socket到Blender

代码地址:https://gitee.com/enzoism/python_blender_mcp

  • 部署Socket到Blender
  • 本地SocketClient与SocketServer通讯验证

2-本地项目调试

运行test.py文件即可

  • SocketClient代码

代码地址:https://gitee.com/enzoism/python_blender_socket

import json
import socketdef send_command(command):"""发送命令到服务器并接收响应"""sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建TCP套接字try:print("Connecting to server...")  # 连接到服务器sock.connect(('localhost', 9876))  # 连接到本地9876端口的服务器# 发送命令json_command = json.dumps(command).encode('utf-8')  # 将命令转换为JSON格式并编码为字节sock.sendall(json_command)  # 发送命令print(f"Sent command: {command}")  # 打印发送的命令# 接收响应sock.settimeout(10)  # 设置超时时间为10秒response_data = sock.recv(65536)  # 接收响应数据,最大长度为65536字节if response_data:  # 如果接收到数据response = json.loads(response_data.decode('utf-8'))  # 将响应数据解码为JSON格式return response  # 返回响应else:return {"status": "error", "result": "Empty response"}  # 如果没有接收到数据,返回错误信息except Exception as e:  # 捕获所有异常return {"status": "error", "result": str(e)}  # 返回异常信息finally:sock.close()  # 关闭套接字if __name__ == "__main__":# 测试ping命令ping_command = {"type": "ping","params": {}}response = send_command(ping_command)print("Server response:", response)  # 打印服务器响应

3-代码结构

  • 1)clazz类中业务类->比如创建一个Person类,有构造方法,有eat方法
  • 2)operator中放要clazz类中业务类的操作逻辑
  • 3)panels中放看板的点击Operator类->但是不要在这里也业务逻辑(解耦)
  • 4)panels中防止看板的判断属性->根据状态更换按钮文字和点击事件

  • 1)clazz代码示例
import json
import socket
import threading
import time# 添加自己的业务Operator
class BlenderMCPServer:def __init__(self, host='localhost', port=9876):self.host = hostself.port = portself.running = Falseself.socket = Noneself.client = Noneself.server_thread = Nonedef start(self):self.running = Trueself.server_thread = threading.Thread(target=self._run_server)self.server_thread.daemon = Trueself.server_thread.start()print(f"BlenderMCP server started on {self.host}:{self.port}")def stop(self):self.running = Falseif self.socket:self.socket.close()if self.client:self.client.close()print("BlenderMCP server stopped")def _run_server(self):self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)try:self.socket.bind((self.host, self.port))self.socket.listen(1)self.socket.settimeout(1.0)  # Add a timeout for acceptwhile self.running:try:self.client, address = self.socket.accept()print(f"Connected to client: {address}")while self.running:try:# Set a timeout for receiving dataself.client.settimeout(15.0)data = self.client.recv(4096)if not data:print("Empty data received, client may have disconnected")breaktry:print(f"Received data: {data.decode('utf-8')}")command = json.loads(data.decode('utf-8'))response = self.execute_command(command)print(f"Sending response: {json.dumps(response)[:100]}...")  # Truncate long responses in logself.client.sendall(json.dumps(response).encode('utf-8'))except json.JSONDecodeError:print(f"Invalid JSON received: {data.decode('utf-8')}")self.client.sendall(json.dumps({"status": "error","message": "Invalid JSON format"}).encode('utf-8'))except Exception as e:print(f"Error executing command: {str(e)}")import tracebacktraceback.print_exc()self.client.sendall(json.dumps({"status": "error","message": str(e)}).encode('utf-8'))except socket.timeout:print("Socket timeout while waiting for data")continueexcept Exception as e:print(f"Error receiving data: {str(e)}")breakself.client.close()self.client = Noneexcept socket.timeout:# This is normal - just continue the loopcontinueexcept Exception as e:print(f"Connection error: {str(e)}")if self.client:self.client.close()self.client = Nonetime.sleep(1)  # Prevent busy waitingexcept Exception as e:print(f"Server error: {str(e)}")finally:if self.socket:self.socket.close()def execute_command(self, command):"""Execute a Blender command received from the MCP server"""cmd_type = command.get("type")params = command.get("params", {})# Add a simple ping handlerif cmd_type == "ping":print("Handling ping command")return {"status": "success", "result": {"pong": True}}else:return {"status": "error","result": f"Unknown command type: {command.get('type')}"}

  • 2)operator代码示例
class BlenderMCPOperatorStart(bpy.types.Operator):'''BlenderMCPOperatorStart'''bl_idname = "object.blender_mcp_operator_start"bl_label = "Now_Stop_Click_Start"# 确保在操作之前备份数据,用户撤销操作时可以恢复bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context: bpy.types.Context):return context.active_object is not Nonedef execute(self, context: bpy.types.Context):scene = context.scene# 创建socket实例if not hasattr(bpy.types, "blender_mcp_server") or not bpy.types.blender_mcp_server:# Start the serverbpy.types.blender_mcp_server = BlenderMCPServer(port=9876)bpy.types.blender_mcp_server.start()print("---------------------Start MCP Server后重置状态")scene.blender_mcp_server_running = Truereturn {'FINISHED'}class BlenderMCPOperatorStop(bpy.types.Operator):'''BlenderMCPOperatorStop'''bl_idname = "object.blender_mcp_operator_stop"bl_label = "Now_Start_Click_Stop"@classmethoddef poll(cls, context: bpy.types.Context):return context.active_object is not Nonedef execute(self, context: bpy.types.Context):scene = context.scene# 销毁socket实例if hasattr(bpy.types, "blender_mcp_server") or bpy.types.blender_mcp_server:bpy.types.blender_mcp_server.stop()del bpy.types.blender_mcp_serverprint("---------------------Stop MCP Server后重置状态")scene.blender_mcp_server_running = Falsereturn {'FINISHED'}

  • 3)panels中Operator代码示例
@reg_order(0)
class ExampleAddonPanel2(BasePanel, bpy.types.Panel):bl_label = "Example Addon Side Bar Panel"bl_idname = "SCENE_PT_sample2"def draw(self, context: bpy.types.Context):layout = self.layoutlayout.label(text="BlenderMCP Panel")# 当前只是为了测试常驻按钮的点击测试-点击对图形缩小0.8layout.operator(StaticButtonOperator.bl_idname)# 测试服务器的装scene = context.sceneif not scene.blender_mcp_server_running:layout.operator(BlenderMCPOperatorStart.bl_idname)print("Start MCP Server")else:layout.operator(BlenderMCPOperatorStop.bl_idname)print("Stop MCP Server")

  • 4)panels中属性代码示例
import bpy# 添加属性到 Scene 类型
bpy.types.Scene.blender_mcp_server = bpy.props.BoolProperty(name="Blender MCP Server Running",default=False,description="Indicates whether the Blender MCP server is running."
)
bpy.types.Scene.blender_mcp_server_running = bpy.props.BoolProperty(name="Blender MCP Server Running",default=False,description="Indicates whether the Blender MCP server is running."
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34147.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Androidstudio实现一个app引导页(超详细)

文章目录 1. 功能需求2. 代码实现过程1. 创建布局文件2. 创建引导页的Adapter3. 实现引导页Activity4. 创建圆点指示器的Drawable5. 创建“立即体验”按钮的圆角背景 2.效果图 1. 功能需求 1、需要和原型图设计稿对应的元素保持一致的样式。 2、引导页需要隐藏导航栏&#xff…

蓝桥杯省赛真题C++B组-小球反弹

一、题目 有一长方形,长为 343720 单位长度,宽为 233333 单位长度。在其内部左上角顶点有一小球(无视其体积),其初速度如图所示且保持运动速率不变,分解到长宽两个方向上的速率之比为 dx:dy 15:17。小球碰到长方形的边框时会发生…

基于深度学习的多模态人脸情绪识别研究与实现(视频+图像+语音)

这是一个结合图像和音频的情绪识别系统,从架构、数据准备、模型实现、训练等。包括数据收集、预处理、模型训练、融合方法、部署优化等全流程。确定完整系统的组成部分:数据收集与处理、模型设计与训练、多模态融合、系统集成、部署优化、用户界面等。详…

AI 数字人短视频源码开发:开启虚拟世界的创意引擎

在当今数字化浪潮中,AI 数字人正以惊人的速度融入我们的生活,尤其是在短视频领域,AI 数字人凭借其独特的魅力吸引了无数目光。从虚拟偶像的舞台表演到智能客服的贴心服务,AI 数字人已成为推动短视频行业创新发展的重要力量。而这背…

Java 代理模式:从静态代理到动态代理

前言 代理模式是 Java 中常见的设计模式之一,它的核心思想是通过一个代理对象来控制对真实对象的访问。代理模式不仅可以扩展目标对象的功能,而且在不修改原目标对象的情况下,可以增加一些我们自定义的操作。 1. 代理模式简介 代理模式的核心…

PyCharm 2019.1.3使用python3.9创建虚拟环境setuptools-40.8.0报错处理

目录 前置: 一劳永逸方法(缺最后一步,没有成行) step one: 下载高版本的pip、setuptools、virtualenv的tar.gz包 step two: 进入PyCharm安装目录的 helpers 目录下 step three: 下载并安装grep和sed命令,然后执行 …

word处理控件Aspose.Words教程:使用 Python 删除 Word 中的空白页

Aspose.Words 是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理,并…

C++数据结构1——栈结构详解

一、栈的基本概念与特性 1. 栈的定义与特点 栈(Stack)是一种遵循后进先出(LIFO, Last In First Out)原则的线性数据结构,其核心特征包括: 单端操作:所有操作仅通过栈顶进行 动态存储&#xf…

77.HarmonyOS NEXT ImageViewerView 组件深度剖析: Swiper容器与懒加载深度解析

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT ImageViewerView 组件深度剖析: Swiper容器与懒加载深度解析 一、组件基础结构 Component export struct ImageViewe…

向量数据库对比以及Chroma操作

一、向量数据库与传统类型数据库 向量数据库(Vector Storage Engine)与传统类型的数据库如关系型数据库(MySQL)、文档型数据库(MongoDB)、键值存储(Redis)、全文搜索引擎&#xff0…

深入解析对象存储及工作原理

在现代信息技术发展中,存储是一个永恒的话题。从最初的磁带、硬盘到现在的云存储,存储技术不断推陈出新。而其中,“对象存储”作为近年来备受关注的存储技术之一,凭借其高可扩展性和灵活性,逐渐成为企业级存储方案的首…

ctfshow-xxs-316-333-wp

316.反射型 XSS(-326都是反射型) js恶意代码是存在于某个参数中,通过url后缀进行get传入,当其他用户点进这个被精心构造的url链接时,恶意代码就会被解析,从而盗取用户信息。 来看题,先简单测试…

easypoi导入Excel兼容日期和字符串格式的日期和时间

问题场景 在使用easypoi导入Excel时,涉及到的常用日期会有yyyy-MM-dd HH:mm:ss、yyyy-MM-dd和HH:mm:ss,但是Excel上面的格式可不止这些,用户总会输入一些其他格式,如 如果在定义verify时用下面这种格式定义,那么总会…

基于yolo11+flask打造一个精美登录界面和检测系统

这个是使用flask实现好看登录界面和友好的检测界面实现yolov11推理和展示,代码仅仅有2个html文件和一个python文件,真正做到了用最简洁的代码实现复杂功能。 测试通过环境: windows x64 anaconda3python3.8 ultralytics8.3.81 flask1.1.…

R语言零基础系列教程-01-R语言初识与学习路线

代码、讲义、软件回复【R语言01】获取。 R语言初识 R是一个开放的统计编程环境,是一门用于统计计算和作图的语言。“一切皆是对象”,数据、函数、运算符、环境等等都是对象。易学,代码像伪代码一样简洁,可读性高强大的统计和可视…

AI重塑视觉艺术:DeepSeek与蓝耘通义万相2.1的图生视频奇迹

云边有个稻草人-CSDN博客 近年来,深度学习、计算机视觉和生成模型在多个领域取得了突破性进展。其中,DeepSeek与蓝耘通义万相2.1图生视频的结合为图像生成与视频生成技术提供了新的发展方向。DeepSeek作为一个图像和视频生成的工具,能够利用深…

ELK+Filebeat+Kafka+Zookeeper安装部署

1.安装zookeeper zookpeer下载地址:apache-zookeeper-3.7.1-bin.tar.gzhttps://link.csdn.net/?targethttps%3A%2F%2Fwww.apache.org%2Fdyn%2Fcloser.lua%2Fzookeeper%2Fzookeeper-3.7.1%2Fapache-zookeeper-3.7.1-bin.tar.gz%3Flogin%3Dfrom_csdn 1.1解压安装zookeeper软件…

历年云南大学计算机复试上机真题

历年云南大学计算机复试机试真题 在线评测:传送门:pgcode.cn 喝饮料 题目描述 商店里有 n 中饮料,第 i 种饮料有 mi 毫升,价格为 wi。 小明现在手里有 x 元,他想吃尽量多的饮料,于是向你寻求帮助&#x…

怎么有效降低知网AIGC率

在学术创作日益规范且数字化检测技术不断发展的当下,知网 AIGC 检测成为了众多创作者关注的焦点。许多人苦恼于如何有效降低知网 AIGC 率,让自己的作品在通过检测的同时,彰显出真实的创作水平与独特性。接下来,我们就深入探讨降低…

代码随想录day17 二叉树part05

654.最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums …