按照python的說法一切皆對象,Blender中亦然。python
Blender的根對象是bpy,所以任何模塊都須要:shell
import bpy
注意:app
Blender的腳本print("hello")函數是輸出信息到啓動的控制檯的,直接運行的時候看不到輸出的信息。ide
能夠擴展出一個窗口,選擇「信息」,就能夠把當前全部操做的命令和執行結果都顯示在其中,很是方便。
函數
而後,任何對象其實都是數據,所以訪問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.object >>> bpy.context.selected_objects >>> bpy.context.visible_bones
這裏能夠看到,context也能夠訪問到object,這個是當前的環境可用的對象,其數據跟data裏是一致的。後面的ops還能夠來訪問和修改對象的屬性值。
這是典型的python式的「面向對象」,數據按照對象來組織,可是訪問時倒是以函數方式出現的,從而適應腳本環境的運行須要。
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不是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控制檯運行一下便可。