从零开始 blender插件开发

blender 插件开发

文章目录

  • blender 插件开发
    • 环境配置
      • 1. 偏好设置中开启相关功能
      • 2. 命令行打开
      • 运行脚本
    • API学习
      • 专有名词
      • 1. bpy.data 从当前打开的blend file中,加载数据。
      • 2. bpy.context 可用于获取活动对象、场景、工具设置以及许多其他属性。
      • 3. bpy.ops 用户通常通过按钮、菜单项或快捷键访问的工具。
    • 将脚本融入blender, 成为blender的一部分
      • 1. 通过添加ui
      • 2. 通过添加功能(operator)
    • 从脚本到add-on
      • 1. 组成部分
      • 2.示例
    • 资料

环境配置

1. 偏好设置中开启相关功能

打开blender, 快捷键ctrl+,, 打开偏好设置面板。进行下列相关设置(下图为设置好的状态)

设置好后, 鼠标浮动在会出现工具提示,右键可以展示相关的菜单。
在这里插入图片描述
在这里插入图片描述

2. 命令行打开

第一种方法:

  • 将blender.exe所在路径添加到环境变量中
  • 打开命令行,输入blender, 即可打开blender,命令行中会出现软件运行相关的信息, 包括python的print输出. 注意要先关掉软件,再关掉命令行。
    ps: 目前来看,命令行主要是用来展示信息,而不是输入命令。

第二种方法:

  • 打开blender之后,点击如下图所示。
    在这里插入图片描述

运行脚本

点击如下按钮。
在这里插入图片描述
之后,界面变为下图。
在这里插入图片描述

API学习

专有名词

  • context
    在这里插入图片描述

1. bpy.data 从当前打开的blend file中,加载数据。

2. bpy.context 可用于获取活动对象、场景、工具设置以及许多其他属性。

请注意,上下文是只读的,这意味着不能直接修改这些值。但是,可以通过运行 API 函数或使用数据 API 来更改它们。

3. bpy.ops 用户通常通过按钮、菜单项或快捷键访问的工具。

从用户的角度来看,它们是一个工具,但 Python 可以通过 bpy.ops 模块使用自己的设置运行这些。
许多工具(运算符)都有一个 “poll” 功能,用于检查光标是否在有效区域中,或者对象是否处于正确的模式(Edit Mode、Weight Paint Mode 等)。当运算符的 poll 函数在 Python 中失败时,会引发异常。

if bpy.ops.view3d.render_border.poll():bpy.ops.view3d.render_border()

将脚本融入blender, 成为blender的一部分

1. 通过添加ui

  • By defining menus, headers and panels.
    通过定义菜单、标题和面板。

  • By inserting new buttons into existing menus, headers and panels.
    通过将新按钮插入到现有菜单、标题和面板中。

import bpy  # 导入Blender的Python API模块# 定义一个自定义面板类 HelloWorldPanel,继承自 bpy.types.Panel
class HelloWorldPanel(bpy.types.Panel):"""创建一个面板,在 '对象属性' 窗口中显示"""# 面板的标签,会显示在Blender UI中bl_label = "Hello World Panel"# 面板的唯一ID,用于Blender内部识别bl_idname = "OBJECT_PT_hello"# 面板显示的空间类型,这里是 'PROPERTIES',即对象属性窗口bl_space_type = 'PROPERTIES'# 面板显示的区域类型,这里是 'WINDOW',表示在窗口区域显示bl_region_type = 'WINDOW'# 面板显示的上下文,这里是 'object',即与对象相关的上下文bl_context = "object"# 面板的绘制方法,这个方法会在面板中绘制UI元素def draw(self, context):layout = self.layout  # 获取面板的布局对象,用于在面板中添加控件obj = context.object  # 获取当前选中的活动对象# 创建一行(row),并在其中添加一个标签,显示 "Hello world!" 并使用 'WORLD_DATA' 图标row = layout.row()row.label(text="Hello world!", icon='WORLD_DATA')# 创建新的一行,显示当前活动对象的名称row = layout.row()row.label(text="Active object is: " + obj.name)# 创建新的一行,添加一个控件,让用户可以编辑活动对象的名称row = layout.row()row.prop(obj, "name")  # 添加一个属性控件,允许修改对象的 'name' 属性# 创建新的一行,添加一个操作按钮,点击时会添加一个立方体到场景中row = layout.row()row.operator("mesh.primitive_cube_add")  # 这个操作会添加一个立方体到当前场景# 注册类和面板的函数
def register():bpy.utils.register_class(HelloWorldPanel)  # 注册 HelloWorldPanel 面板类# 注销类和面板的函数
def unregister():bpy.utils.unregister_class(HelloWorldPanel)  # 注销 HelloWorldPanel 面板类# 这部分代码确保如果脚本直接执行时,面板会被注册
if __name__ == "__main__":register()  # 注册面板

在这里插入图片描述

2. 通过添加功能(operator)

import bpydef main(context):# 遍历当前场景中的所有对象for ob in context.scene.objects:print(ob)  # 打印每个对象的信息class SimpleOperator(bpy.types.Operator):"""Tooltip"""bl_idname = "object.simple_operator"  # 操作的唯一标识符bl_label = "Simple Object Operator"  # 操作的名称,显示在UI中@classmethoddef poll(cls, context):# 确保只有在有活跃对象时才允许执行该操作return context.active_object is not Nonedef execute(self, context):# 当操作被触发时,调用 main 函数打印所有对象信息main(context)return {'FINISHED'}  # 操作完成def menu_func(self, context):# 将操作添加到 Blender 对象菜单中self.layout.operator(SimpleOperator.bl_idname, text=SimpleOperator.bl_label)# 注册操作和菜单项
def register():bpy.utils.register_class(SimpleOperator)  # 注册 SimpleOperator 操作类bpy.types.VIEW3D_MT_object.append(menu_func)  # 将操作添加到对象菜单# 注销操作和菜单项
def unregister():bpy.utils.unregister_class(SimpleOperator)  # 注销 SimpleOperator 操作类bpy.types.VIEW3D_MT_object.remove(menu_func)  # 从对象菜单中移除操作if __name__ == "__main__":# 如果脚本直接执行,注册操作和菜单项register()# 测试调用 SimpleOperator 操作,打印场景中所有对象bpy.ops.object.simple_operator()

在这里插入图片描述

从脚本到add-on


附加组件,也就是我们说的插件 add-on。本质上就是对脚本的一种包装。

1. 组成部分

从一个最简单的示例看起

bl_info = {"name": "My Test Add-on","blender": (2, 80, 0),"category": "Object",
}
def register():print("Hello World")
def unregister():print("Goodbye World")

bl_info 添加插件的时候,显示的相关信息。包括插件名字,版本号等等。
registerenable插件的时候运行。
unregister disable插件的时候使用。

2.示例

接下来的示例将展示,一个python脚本如何包装为插件

python脚本如下

import bpyscene = bpy.context.scene
for obj in scene.objects:obj.location.x += 1.0
首先将脚本包装为一个函数, 将函数作为一个类的excute方法, 并添加相关属性:用作菜单项和按钮的提示信息。
class ObjectMoveX(bpy.types.Operator):"""My Object Moving Script"""      # 用作菜单项和按钮的提示信息。bl_idname = "object.move_x"        # 唯一标识符,用于按钮和菜单项引用。bl_label = "Move X by One"         # 显示在界面上的名称。bl_options = {'REGISTER', 'UNDO'}  # 启用撤销和注册功能。def execute(self, context):        # 执行操作时调用此方法。# 原始脚本scene = context.scene            # 获取当前场景for obj in scene.objects:        # 遍历场景中的所有对象obj.location.x += 1.0        # 将对象的X轴坐标加1.0return {'FINISHED'}              # 告诉Blender操作已成功完成。

接下来将这个功能添加到菜单中。先写一个添加到菜单的函数。

def menu_func(self, context):self.layout.operator(ObjectMoveX.bl_idname)  # 将操作按钮添加到菜单中。

接下来,根据插件的三大组成:信息+注册+注销
信息

bl_info = {"name": "Move X Axis",               # 插件名称"blender": (2, 80, 0),                # 兼容的Blender版本"category": "Object",                 # 插件所属分类
}

注册函数,注册分为两部分,一是功能注册,而是ui注册

def register():bpy.utils.register_class(ObjectMoveX)         # 注册操作类bpy.types.VIEW3D_MT_object.append(menu_func)  # 将新的操作添加到现有菜单中。

注销,注销只需要注销功能。

	def unregister():bpy.utils.unregister_class(ObjectMoveX)       # 注销操作类

很好,再看一示例。

先看python脚本

import bpy
from bpy import context# 获取当前场景
scene = context.scene# 获取 3D 游标的位置
cursor = scene.cursor.location# 获取当前激活的对象(假设我们有一个激活的对象)
obj = context.active_object# 现在复制这个对象
obj_new = obj.copy()# 新对象必须被添加到场景中的一个集合里
scene.collection.objects.link(obj_new)# 现在可以将新对象放置在 3D 游标的位置
obj_new.location = cursor

这段代码的功能是,将选中激活的物体,复制到cusor位置,代码执行前
在这里插入图片描述
代码执行后
在这里插入图片描述

接下来省级一下这个python脚本,实现从选中物体到光标之间复制多个物体.

import bpy
from bpy import contextscene = context.scene
cursor = scene.cursor.location
obj = context.active_object# 目前使用固定值,将来可以让用户调整这个值
total = 10# 在场景中添加 'total' 个对象
for i in range(total):obj_new = obj.copy()  # 复制对象scene.collection.objects.link(obj_new)  # 将新对象添加到场景的集合中# 根据 'i' 将新对象放置在游标和活动对象之间factor = i / total  # 计算当前对象的位置比例# 将新对象的位置设置为介于活动对象和游标之间obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))

代码执行前同上,代码执行后

在这里插入图片描述
接下来,我们将其变为一个插件.
第一步,依然是包装这个脚本为一个函数,包装这个函数为一个类中的excute方法. 并为这个类添加相关属性

class ObjectCursorArray(bpy.types.Operator):"""Object Cursor Array"""  # 操作符的描述bl_idname = "object.cursor_array"  # 操作符的 IDbl_label = "Cursor Array"  # 操作符的显示名称bl_options = {'REGISTER', 'UNDO'}  # 操作符的选项,包括注册和撤销支持def execute(self, context):# 获取当前场景scene = context.scene# 获取 3D 游标的位置cursor = scene.cursor.location# 获取当前激活的对象obj = context.active_object# 设置要创建的对象数量total = 10# 创建并定位对象for i in range(total):# 复制当前激活的对象obj_new = obj.copy()# 将新对象添加到场景的集合中scene.collection.objects.link(obj_new)# 计算新对象的位置,使其位于活动对象和游标之间factor = i / total# 将新对象的位置设置为活动对象和游标之间的插值位置obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))# 返回操作完成return {'FINISHED'}

第二步,将这个功能添加到菜单或者ui中.

def menu_func(self, context):self.layout.operator(ObjectCursorArray.bl_idname)

第三步,添加插件三部 信息+注册+注销

bl_info = {"name": "Cursor Array",  # 插件的名称"blender": (2, 80, 0),  # 支持的 Blender 版本"category": "Object",  # 插件类别
}
def register():bpy.utils.register_class(ObjectCursorArray)bpy.types.VIEW3D_MT_object.append(menu_func)
def unregister():bpy.utils.unregister_class(ObjectCursorArray)

合并之后,整体代码

bl_info = {"name": "Cursor Array",  # 插件的名称"blender": (2, 80, 0),  # 支持的 Blender 版本"category": "Object",  # 插件类别
}import bpyclass ObjectCursorArray(bpy.types.Operator):"""Object Cursor Array"""  # 操作符的描述bl_idname = "object.cursor_array"  # 操作符的 IDbl_label = "Cursor Array"  # 操作符的显示名称bl_options = {'REGISTER', 'UNDO'}  # 操作符的选项,包括注册和撤销支持def execute(self, context):# 获取当前场景scene = context.scene# 获取 3D 游标的位置cursor = scene.cursor.location# 获取当前激活的对象obj = context.active_object# 设置要创建的对象数量total = 10# 创建并定位对象for i in range(total):# 复制当前激活的对象obj_new = obj.copy()# 将新对象添加到场景的集合中scene.collection.objects.link(obj_new)# 计算新对象的位置,使其位于活动对象和游标之间factor = i / total# 将新对象的位置设置为活动对象和游标之间的插值位置obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))# 返回操作完成return {'FINISHED'}def menu_func(self, context):self.layout.operator(ObjectCursorArray.bl_idname)# 注册操作符
def register():bpy.utils.register_class(ObjectCursorArray)bpy.types.VIEW3D_MT_object.append(menu_func)# 注销操作符
def unregister():bpy.utils.unregister_class(ObjectCursorArray)# 如果是直接执行脚本,注册操作符
if __name__ == "__main__":register()

此外,官方还给出了一些示例,可以从这里打开
在这里插入图片描述
在这里插入图片描述

资料

官方给出了多个链接用于学习

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

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

相关文章

el-table 行列文字悬浮超出屏幕宽度不换行的问题

修改前的效果 修改后的效果 ui框架 element-plus 在网上找了很多例子都没找到合适的 然后这个东西鼠标挪走就不显示 控制台也不好调试 看了一下El-table的源码 他这个悬浮文字用的el-prpper 包着的 所以直接改 .el-table .el-propper 设置为max-width:1000px 就可以了 吐槽一…

Tcp中的流量控制,拥塞控制,超时重传时间的选择,都附带相应例子说明

端口号的了解 通常进行通信时,发送方使用任意端口,指定接收方为指定端口,因为接收方在接收到后的需要根据发送方指定的接收方端口号,来选择使用哪一个服务进程进行处理。 端口号还可以分类为两个大类: TCP和UDP报文的…

Nextflow最佳实践:如何在云上高效处理大规模数据集

1. Nextflow 软件架构介绍 Nextflow 是一个用于简化数据驱动计算流程的工具,可以在各种计算环境中轻松部署。它采用了分布式计算和容器技术,实现了高度模块化、可重复性和可扩展性。NextFlow 的软件架构主要包括以下几个部分: 用户界面&…

一文看懂ERP、SCM、SRM、WMS、TMS、进销存管理系统

经常有人来私信问我ERP、SCM、SRM、WMS、TMS、进销存管理系统等等,它们听起来都很专业,但到底各自是什么?承担着怎样的角色呢?它们具体都有哪些功能?相互之间又存在怎样的关联,对企业而言又意味着什么呢&am…

深度学习——优化算法、激活函数、归一化、正则化

文章目录 🌺深度学习面试八股汇总🌺优化算法方法梯度下降 (Gradient Descent, GD)动量法 (Momentum)AdaGrad (Adaptive Gradient Algorithm)RMSProp (Root Mean Square Propagation)Adam (Adaptive Moment Estimation)AdamW 优化算法总结 经验和实践建议…

YOLOv11实战宠物狗分类

本文采用YOLOv11作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv11以其高效的特征提取能力,在多个图像分类任务中展现出卓越性能。本研究针对5种宠物狗数据集进行训练和优化,该数据集包含丰富的宠物狗图像样本…

星期-时间范围选择器 滑动选择时间 最小粒度 vue3

星期-时间范围选择器 功能介绍属性说明事件说明实现代码使用范例 根据业务需要,实现了一个可选择时间范围的周视图。用户可以通过鼠标拖动来选择时间段,并且可以通过快速选择组件来快速选择特定的时间范围。 如图: 功能介绍 时间范围选择&…

云岚到家 秒杀抢购

目录 秒杀抢购业务特点 常用技术方案 抢券 抢券界面 进行抢券 我的优惠券列表 活动查询 系统设计 活动查询分析 活动查询界面显示了哪些数据? 面向高并发如何提高活动查询性能? 如何保证缓存一致性? 数据流 Redis数据结构设计 如…

JavaWeb常见注解

1.Controller 在 JavaWeb 开发中,Controller是 Spring 框架中的一个注解,主要用于定义控制器类(Controller),是 Spring MVC 模式的核心组件之一。它表示该类是一个 Spring MVC 控制器,用来处理 HTTP 请求并…

光伏储能微电网协调控制器

安科瑞 Acrel-Tu1990 1. 产品介绍 ACCU-100微电网协调控制器是一款专为微电网、分布式发电和储能系统设计的智能协调控制设备。该装置能够兼容包括光伏系统、风力发电、储能系统以及充电桩等多种设备的接入。它通过全天候的数据采集与分析,实时监控光伏、风能、储…

【C++课程学习】:继承:默认成员函数

🎁个人主页:我们的五年 🔍系列专栏:C课程学习 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 构造函数 🍩默认构造函数(这里指的是编译器生成的构造函数)&#…

泷羽sec学习打卡-Linux基础2

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于Linux的那些事儿-Base2 一、Linux-Base2linux有哪些目录呢?不同目录下有哪些具体的文件呢…

TCP拥塞控制

TCP拥塞控制(Congestion Control) 什么是拥塞控制? 拥塞控制(Congestion Control)主要针对整个网络中的数据传输速率进行调节,防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致于过载,以避免…

Unity教程(十八)战斗系统 攻击逻辑

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程(零)Unity和VS的使用相关内容 Unity教程(一)开始学习状态机 Unity教程(二)角色移动的实现 Unity教程(三)角色跳跃的实现 Unity教程&…

自动驾驶合集(更新中)

文章目录 车辆模型控制路径规划 车辆模型 车辆模型基础合集 控制 控制合集 路径规划 规划合集

网站架构知识之Ansible进阶(day022)

1.handler触发器 应用场景:一般用于分发配置文件时候,如果配置文件有变化,则重启服务,如果没有变化,则不重启服务 案列01:分发nfs配置文件,若文件发生改变则重启服务 2.when判断 用于给ans运…

整理5个优秀的微信小程序开源项目

​ 一、Bee GitHub: https://github.com/woniudiancang/bee Bee是一个餐饮点餐商城微信小程序,是针对餐饮行业推出的一套完整的餐饮解决方案,实现了用户在线点餐下单、外卖、叫号排队、支付、配送等功能,完美的使餐饮行业更高效便捷&#x…

微服务链路追踪skywalking安装

‌SkyWalking是一个开源的分布式追踪系统,主要用于监控和分析微服务架构下的应用性能。‌ 它提供了分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案,特别适用于微服务、云原生架构和基于容器的环境(如Docker、K8s、Mesos&…

5G的发展演进

5G发展的驱动力 什么是5G [远程会议,2020年7月10日] 在来自世界各地的政府主管部门、电信制造及运营企业、研究机构约200多名会议代表和专家们的共同见证下,ITU-R WP 5D#35e远程会议宣布3GPP 5G技术(含NB-IoT)满足IMT-2020 5G技…

matlab建模入门指导

本文以水池中鸡蛋温度随时间的变化为切入点,对其进行数学建模并进行MATLAB求解,以更为通俗地进行数学建模问题入门指导。 一、问题简述 一个煮熟的鸡蛋有98摄氏度,将它放在18摄氏度的水池中,五分钟后鸡蛋的温度为38摄氏度&#x…