Blender的插件開發-對象體系探索

按照python的說法一切皆對象,Blender中亦然。python

Blender的根對象是bpy,所以任何模塊都須要:shell

import bpy

注意:app

        Blender的腳本print("hello")函數是輸出信息到啓動的控制檯的,直接運行的時候看不到輸出的信息。ide

        能夠擴展出一個窗口,選擇「信息」,就能夠把當前全部操做的命令和執行結果都顯示在其中,很是方便。
函數

bpy.data

而後,任何對象其實都是數據,所以訪問blender的第一個關鍵對象是bpy.data。如今,咱們打開python的命令行窗口:spa

拖動3D視圖的右上角,向左下,擴展出一個窗口。
選擇左下角的立方體,選擇Python控制檯,而後就能夠輸入Python腳本了。

在其中輸入:插件

>>bpy.data.objects
<bpy_collection[4], BlendDataObjects>

    bpy_collection是一個python的詞典對象,顯示有四個對象(窗口初始是三個對象,我加了一個)。命令行

    想知道是哪幾個對象?很好辦。用一個遍歷,以下所示,列出了全部對象的名字:code

>>> for obj in bpy.data.objects:
...     print(obj.name)
...     
Camera
Cube
Lamp
融球

    經過這種方式,咱們能夠操做Blender的幾乎全部數據。orm

bpy.context

    bpy.context顧名思義就是運行的上下文環境,這個在腳本環境裏處處碰到了。知道了這個,呵呵!

>>> bpy.context.object
>>> bpy.context.selected_objects
>>> bpy.context.visible_bones

    這裏能夠看到,context也能夠訪問到object,這個是當前的環境可用的對象,其數據跟data裏是一致的。後面的ops還能夠來訪問和修改對象的屬性值。

    這是典型的python式的「面向對象」,數據按照對象來組織,可是訪問時倒是以函數方式出現的,從而適應腳本環境的運行須要。

bpy.ops

    bpy.ops是Operator(操做器)的簡寫,封裝了不少的對象操做在裏面,是Blender功能的核心了。

>>> bpy.ops.mesh.flip_normals()
{'FINISHED'}

>>> bpy.ops.mesh.hide(unselected=False)
{'FINISHED'}

>>> bpy.ops.object.scale_apply()
{'FINISHED'}

    一個操做器的完整例子:

import bpy

def 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"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}

def register():
    bpy.utils.register_class(SimpleOperator)

def unregister():
    bpy.utils.unregister_class(SimpleOperator)

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

     注意裏面的register/unregister,以及其中的class和poll、execute成員函數,這是一個典型的插件的實現結構。

    大部分插件照着上面這個結構依瓢畫葫蘆就能夠了。

bpy.types

    bpy.types不是python的type對象的簡單封裝,而是Blender各類「類」的集合,不要問我到底有啥區別哈,誰用誰知道啊。

   注意:Panel也是types裏面的東東啊。下面是定義Panel的插件:

import bpyclass HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        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")

        row = layout.row()
        row.operator("mesh.primitive_cube_add")

def register():
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)

if __name__ == "__main__":
    register()

    注意,這裏多了一些變量的聲明,這是插件的一些說明。

bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"

    全部插件原則上都應該包含上面這些信息,引號內的字符串能夠修改,變量名不能修改(不然就成本身的了)。這個插件信息聲明瞭這個panel是在對象的屬性面板中出現。

    bpy.types包含的一些對象以下:

bpy.types.Panel
bpy.types.Menu
bpy.types.Operator
bpy.types.PropertyGroup
bpy.types.KeyingSet
bpy.types.RenderEngine

    這裏再次了出現Operator對象,跟前面的bpy.ops是否是同樣的啊?

    我猜想應該是,考慮到type是python的基本對象,這個現象一點也不奇怪。要想一探究竟,很簡單,到python控制檯運行一下便可。

相關文章
相關標籤/搜索