跳转到内容

Blender 3D:融入 Python/自定义数据块属性

来自 Wikibooks,开放世界开放书籍

添加对每个数据块属性提案的支持

[编辑 | 编辑源代码]

草案,提议添加用户定义的每个数据块属性。
这意味着任何具有 ID 的 Blender 数据类型都可以为其分配属性。
对象/网格/相机/超球/灯/格栅/文本/IPO/屏幕/场景/世界/波浪 - 目前不包括面或顶点。这可能会在稍后添加,但需要进一步的工作,并且超出了本提案的范围。


有一些领域我不够了解,并要求其他人扩展。

我鼓励那些可能从这项工作中受益的人阅读此页面,并查看是否有可以改进的地方(编辑,提供示例并讨论 :) ) - Ideasman


来自 Ton 的消息

关于属性系统,需要解决的问题是;

- 它如何影响 UI
- 层次结构如何精确地工作?(也用于 UI 访问)
- 是否有一种方法可以默认设置为属性集?意思是;
您可以设置自定义属性,以便默认情况下为 yafray、crystalspace 等添加。
这将节省大量麻烦,并会以这种方式创建良好的可访问 UI。


- 我很忙,现在没有时间做这些, - Ideasman



Reed Hedges 说

为了回答 Ton 上面的问题,以下是我认为的:在 UI 中,您需要在某个窗格中添加一些东西,该窗格与现有的游戏逻辑属性完全一样(名称、值、类型 {字符串、布尔值、整数、浮点数、向量等})。这可以是新的窗口类型,而不是游戏逻辑窗口,也可以是在按钮窗口中与对象级操作一起,也可以是概述视图的一部分。从我在下面读到的内容来看,层次结构命名主要是一种命名约定。这可以被 UI 用于显示为树,或者它们可以只是一个标准列表,其中“层次结构”仅在名称格式中。对我来说,默认属性没有用。但是,它们可以是用于单个对象的相同 gui 的另一种模式。

+-CUSTOM PROPERTIES -------------------------------------+ 
|                                                        |
| Selected Object: ME:Suzanne01               (Defauts)  |  <-- (Defaults) is a two-state toggle button
|                                                        |      to show default props instead of sel. object
| Name:               Type:    Value:               Del: |   
|  [Example.Prop....] (String) [This is my stri...] (X)  |  <-- Name is text field. Type is multivalue
|  [Another.example.] (Bool  ) (true)               (X)  |      dropdown. Value depends on type.
| (New)                                                  |  <-- (New) creates a new empty property above it.
+--------------------------------------------------------+

我还要求所有对象类型能够具有属性,包括场景/世界。(是的,场景和世界将具有,因为它们具有 ID - Ideasman42)


  1. 注释关于网格、对象或材料的注释可以存储为指向文本块的链接或字符串。其他元数据也可以添加到不同的项目中。
  2. 渲染设置外部渲染引擎的额外属性,其中许多可以添加到材质数据,全局渲染设置可以分配给场景数据块。这可能是迈向更好的 Renderman 集成的第一步!
  3. 游戏引擎许多游戏引擎特定的设置,例如对象的细节级别。人物的不同姿势状态。可以存储在这些设置中。
  4. Blender CAD许多属性可以添加到 BlenderCAD 项目中。(请扩展)
  5. 仿真仿真行业需要填补一个空白,许多人已经在使用 Blender 进行仿真,但是没有简单的方法添加仿真输出设置(主要是 OpenFlight 属性)
  6. 扩展数据一些内部功能可能需要存储值,同时又不想对所有数据块施加额外的权重,即使那些不需要它的人也是如此
    • 评论:允许用户使用内部功能访问的数据也是一个不好的主意。如果它对内部有用(我想不出我会更喜欢其他实现的情况),用户数据和 Blender 数据应该分开或访问受限(Blender 内容只读)。-- tbleicher
    • 对评论的回答 : 并不是因为你使用了属性机制,它就必须是用户可编辑的,甚至可以查看。这种情况下,当你需要在极少数情况下(比如整个网格上只有很小一部分边)添加大量数据时,它很有用。
    • (由 Ideasman 提出) 大家,我想解决这个问题,请随意不同意,但必须划定一个界限来确定该项目涵盖的功能。
      • 1)用户必须能够直接编辑属性,将有一个为此目的的界面。Blender 的内部工具也可以管理属性,但将有一个专门用于数据块属性的面板。
        您可能会争辩说,让用户接触它们会导致数据中出现可能的错误,但允许用户编辑属性的优势远远超过让 Python 脚本/Blender 正确处理各种数据的努力。
      • 2)属性不会分配给边、贝塞尔点、面、单独的骨骼等。这超出了本项目的范围。如果需要预网格面属性,例如,我们可以将其作为单独的添加来解决。现在,只有具有 ID 结构的数据将具有自定义属性。
  7. Blender BVH 运动捕捉关节名称可以分配为属性,以便不同运动捕捉装置之间的重复对象名称不会冲突。目前,我将所有关节名称设置为唯一,因为没有很好的方法来设置对象的关节名称。(Ideasman)

默认值

[编辑 | 编辑源代码]

对于默认设置,可以使用主目录中的文本文件,名为.Bprops
现有文件是.B.blend用于默认新文件,以及.Bfs用于文件选择器中的默认目录列表。

.Bprops文本文件将存储默认情况下显示的属性(无需手动添加到数据块)
DataBlockType:PropertyType:PropertyName=DefaultValue - 将使用以下格式。

Object:bool:CrystalSpace.staticObject=1
Material:Text:RenderMan.Shader=""
Scene:int:RenderMan.Quality=5
Lamp:bool:OpenFlight.LightString=0

注意从 b2cs (crystalspace 导出器) 的角度来看,不仅默认值有用,最小值、最大值以及可能每个属性的描述也很有用。

示例用法

[编辑 | 编辑源代码]

以下是一些可能直接受益于属性的项目,感谢作者的输入以及如何扩展这些项目可能带来的益处。这个提议是否满足您的需求?

  1. Blight(OpenFlight 兼容性 - 存储 OpenFlight 特定的注释)
  2. Make Human(Make Human,每个网格的 Human 设置...)
  3. Brad Blender/Radiance 导出器(材质设置...)
    • 材质:将描述保存为文本字符串;保存对其他定义的依赖项(“修饰符”)
    • 网格:使用道具作为“特殊”导出对象,而不是 meshobj 名称
    • 灯光:存储对灯具数据和使用的数据源的引用(db、fs)
    • 场景:渲染选项和后期处理信息(滤镜、图像转换)
  4. CrystalSpace 开源游戏引擎。
  5. RenderMan 将 RenderMan 支持添加到 Blender 中。
    • 着色器:为 RenderMan 着色器指定着色器名称和参数(表面、位移...)
    • 图元:为 RenderMan 导出器提供处理特定图元的提示。
    • 场景:为 RenderMan 导出器提供场景级渲染控制的提示。

在此处添加您的项目

属性结构

[编辑 | 编辑源代码]

属性将存储在层次结构中。每个数据块可以拥有任意数量的属性文件夹
(我建议不要使用根级别属性,以强制执行更好的设计)
使用属性的插件将在根目录中有一个文件夹,用于存放其所有设置 - 这将阻止它在 UI 中变得杂乱,并为每个插件保持命名空间分离。
示例结构。python 可以包装 C 数据,并作为字典或类进行访问,我们可以允许两者共存 ob.prop.foo 或 ob.prop['foo'] - Ideasman42),

object.prop.metadata.annotation = 'This is a building' # string
object.prop.metadata.timestamp = sys.time() # float
object.prop.crystalSpace.lod = Mathutils.Vector(0,50) # vec
object.prop.crystalSpace.shadowMap.used = True # bool
object.prop.crystalSpace.shadowMap.size = 512 # int

属性类型

[编辑 | 编辑源代码]

以下是插件可以使用的一些属性类型。

  1. 布尔值
  2. 整数
  3. 浮点数
  4. 字符串 大小可能有限制,对于大型多行文本,可以链接文本块。
  5. 向量 (2D, 3D, 4D)
  6. 数据块链接 允许您链接到另一个数据块 - 文本/对象/网格/曲线等。
  7. 数组 所有先前值(不是必需的,因为可以使用属性文件夹,可能有用)

用户界面

[编辑 | 编辑源代码]

OOps 视图可以扩展为包含一个面板,允许编辑每个数据块的属性。这也可以在大纲视图中查看,但 OOps 视图更适合,因为它只显示每个数据块一次,并且同时显示所有数据块。

Python API 接口

[编辑 | 编辑源代码]
  • 注释 1:对于脚本来说,比访问和编辑整个属性集更重要的是按名称/层次结构访问单个属性。对于 BPy,我希望有一个 __getitem__/__setitem__ 的实现(就像在字典中一样)。示例
    • amesh.prop["Radiance"]["export"]["smooth"] = True # 设置属性,布尔值
    • var= amesh.prop["Radiance"]["export"]["smooth"] # 获取属性
    • amesh.prop["Radiance"]["export"].keys() # 获取子属性列表。
      ["smooth", "emit_light"]
    • del amesh.prop["Radiance"]["export"]["smooth"]

KeyError 应该在指定不存在的键(或将现有键转换为“容器”)时引发。如何检查并做出反应是脚本的任务。

  • 注释 2:为了导入/导出属性集,一个通用的数据序列化方法将非常受欢迎。目前,我们必须使用 Python 标准库从注册表/文本对象/文本文件中存储/读取运行时数据。一种从 Python 对象创建/解析文本字符串的内置方法可以帮助脚本编写者加载和保存持久数据。这样,整个属性集就可以作为对象的字符串属性存储。

-- tbleicher

(注释:Python 的 pickle 模块提供了这个功能,但我不知道它将如何与 Blender 对象等交互。 -- sapir)

内部实现

[编辑 | 编辑源代码]

任何具有 ID 的 Blender 数据都可以拥有一个属性。(请扩展并添加如何实现 - 在 Blenders DNA 中)

用户数据是否已经为对象存在?

[编辑 | 编辑源代码]

抱歉,我刚刚在网上搜索时看到了这个页面,试图弄清楚如何在 Blender 中向对象添加用户数据。在搜索中没有找到任何内容,但最终从 API 文档中弄明白了某些东西。

在 Blender 的 Python 交互式控制台中尝试以下操作
cube = bpy.data.objects["Cube"]
cube.addProperty("myUserDataName", 1, 'INT')
dir(cube.getProperty("myUserDataName"))
var = cube.getProperty("myUserDataName").data
cube.getProperty("myUserDataName").setData(2)
cube.getAllProperties()
cube.removeProperty("myUserDataName")

华夏公益教科书