最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python可擴(kuò)展的Blender 3D插件開(kāi)發(fā)匯總

 更新時(shí)間:2023年09月04日 09:19:25   作者:xiangzhihong  
這篇文章主要為大家介紹了python可擴(kuò)展的Blender 3D插件開(kāi)發(fā)匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Blender 3D 插件

成熟的 Blender 3D 插件是令人驚奇的事情。作為 Python 和 Blender 的新手,我經(jīng)常發(fā)現(xiàn)自己被社區(qū)中的人們創(chuàng)造的強(qiáng)大的東西弄得目瞪口呆。坦率地說(shuō),其中一些包看起來(lái)有點(diǎn)神奇,當(dāng)自我懷疑或冒名頂替綜合癥的嘮叨聲音被打破時(shí),很容易想到“如果有人能做出可以做xxx的東西就好了” 。

然后我記得,通過(guò)將好奇心和固執(zhí)與良好的文檔相結(jié)合,某人可以是任何人,X可以成為X、Y 和 Z。即使是困難的部分也可以弄清楚——尤其是因?yàn)樗泄虉?zhí)和好奇的人確保 Blender 的 Python文檔和stackexchange與它讓我們創(chuàng)建的 gee whiz 圖形一樣好。

同樣的方式,已經(jīng)存在的文檔和模型為從頭開(kāi)始編寫(xiě) Blender 插件奠定了平滑的基礎(chǔ),在開(kāi)始時(shí)為該插件提供可擴(kuò)展的結(jié)構(gòu)有助于展示 Python API 的各個(gè)部分如何更多地組合在一起清楚地。換句話說(shuō),它使新編寫(xiě)的代碼比原來(lái)更好,同時(shí)也使現(xiàn)有代碼更容易學(xué)習(xí)。

在本文的最后,我們將創(chuàng)建一個(gè)功能齊全且已安裝的插件,它提供了一個(gè)自定義 UI 元素來(lái)將Standoff 添加到 Blender 場(chǎng)景中,并帶有界面控件來(lái)調(diào)整創(chuàng)建的網(wǎng)格的直徑和高度。

一、文件結(jié)構(gòu)

本文末尾將存在的完整目錄和文件結(jié)構(gòu),我們可以使用mkdir和touch方式進(jìn)行創(chuàng)建,本示例是一個(gè)填空游戲。我正在調(diào)用項(xiàng)目DemoRack并將其設(shè)置為我用于 Python 項(xiàng)目的文件夾中的頂級(jí)目錄名稱(chēng):它不一定必須是 Blender 特定的任何地方。下面是DemoRack項(xiàng)目的文件結(jié)構(gòu):

DemoRack
|-- README.md 
|-- DemoRack.zip <-- will (re)compile via 'zip -r DemoRack.zip src'
|-- src
|-- |-- __init__.py
|-- |-- standoff_mesh.py <-- from Part 2, not modified in this post 
|-- |-- standoff_operator.py
|-- |-- standoff_panel.py
|-- |-- standoff_props.py

下面我們簡(jiǎn)單介紹下這些文件的作用:

  • DemoRack.zip:已編譯src,安裝在 Blender 中的文件。
  • __init__.py:為附加組件注冊(cè)所有必要的信息和類(lèi)。
  • standoff_mesh.py:用于生成目標(biāo)幾何/網(wǎng)格數(shù)據(jù)的模塊。
  • standoff_operator.py:將提供給 UI 使用的“do-er”。
  • standoff_panel.py:在 UI 元素上添加插件將......添加。
  • standoff_props.py:定義Panel 和 Operator所需的數(shù)據(jù)對(duì)象

簡(jiǎn)而言之,每個(gè)新standoff_模塊都將包含register()和unregister()函數(shù)。該__init__模塊將導(dǎo)入這些模塊,并將兩種類(lèi)型的函數(shù)捆綁到單個(gè)迭代器中。Blender Python 文檔描述了這些函數(shù)所扮演的角色:

二、__init__.py

有了這個(gè)背景,并且因?yàn)開(kāi)_init__模塊中的大部分代碼都與sys和importlib包有關(guān),所以我將在此處包含要點(diǎn),而不會(huì)試圖去描述 Python 模塊導(dǎo)入的雜草。Blender插件需要注意的具體事項(xiàng)是module_names列表,聲明要引入register和unregister函數(shù)的的文件名,以及打開(kāi)的bl_info字典。如官方插件介紹教程中所述,bl_info包含將在“首選項(xiàng)”窗格中找到的所有信息:

bl_info是包含附加元數(shù)據(jù)的字典,例如要顯示在首選項(xiàng)附加列表中的標(biāo)題、版本和作者。它還指定了運(yùn)行腳本所需的最低 Blender 版本;舊版本不會(huì)在列表中顯示加載項(xiàng)。 

下面是一段示例代碼:

bl_info = {
    "name": "DemoRack",
    "description": "Make Mini Rack Units Dynamically",
    "author": "Jim O'Connor <hello@ocommaj.com>",
    "version": (0, 0, 1),
    "blender": (2, 90, 1),
    "category": "3D View"
}
module_names = [ 'standoff_props', 'standoff_operator', 'standoff_panel' ]
import sys
import importlib
module_full_names = [ f"{__name__}.{module}" for module in module_names ]
for module in module_full_names:
    if module in sys.modules:
        importlib.reload(sys.modules[module])
    else:
        locals()[module] = importlib.import_module(module)
        setattr(locals()[module], 'module_names', module_full_names)
def register():
    for module in module_full_names:
        if module in sys.modules:
            if hasattr(sys.modules[module], 'register'):
                sys.modules[module].register()
def unregister():
    for module in module_full_names:
        if module in sys.modules:
            if hasattr(sys.modules[module], 'unregister'):
                sys.modules[module].unregister()

三、standoff_props.py

該模塊將是其中涉及最多的模塊,但它也為其他模塊提供了主干,并實(shí)現(xiàn)了一種可以廣泛重用的模式。它依賴(lài)于導(dǎo)入用于將一組屬性定義捆綁在一起的PropertyGroup類(lèi)型(文檔),bpy.props。一旦PropertyGroup在 Blender 中注冊(cè),它就在 Python 可腳本化數(shù)據(jù)對(duì)象的指針和底層 C 分配的內(nèi)存之間提供了一座橋梁,這些內(nèi)存完成了 Blender 的繁重工作。

我們需要在standoff_props.py類(lèi)中將定義、繼承bpy.types.PropertyGroup并跟蹤 3 個(gè)屬性:

  • metric_diameter: FloatProperty(**kwargs)
  • height: FloatProperty(**kwargs)
  • mesh: PointerProperty(type=Mesh)

其中,前兩個(gè)應(yīng)該是不言自明的,并且在實(shí)現(xiàn)中將有更多關(guān)于參數(shù)的細(xì)節(jié)。第3個(gè)PointerProperty指向內(nèi)存中的一個(gè)對(duì)象,并要求在定義時(shí)指定該對(duì)象的類(lèi)型,并且它是 PropertyGroup的子類(lèi)或bpy.struct.ID(即 Mesh)。這意味著任何將值設(shè)置為任何其他數(shù)據(jù)類(lèi)型的實(shí)例的嘗試(在這種情況下,任何非 bpy.types.Mesh)都將引發(fā)錯(cuò)誤,任何將值傳遞給期望任何其他數(shù)據(jù)的參數(shù)的嘗試也是如此類(lèi)型。

在這種情況下,mesh的 PointerProperty屬性將用于保存在Standoff.mesh()的返回值,并使用存儲(chǔ)在metric_diameter和height后面的值進(jìn)行實(shí)例化和修改。這三個(gè)屬性的完整定義如下所示:

class PG_Standoff(PropertyGroup):
    metric_diameter: FloatProperty(
        name="Inner Diameter (Metric)",
        min=2,
        max=5,
        step=50,
        precision=1,
        set=prop_methods("SET", "metric_diameter"),
        get=prop_methods("GET", "metric_diameter"),
        update=prop_methods("UPDATE"))
    height: FloatProperty(
        name="Standoff Height",
        min=2,
        max=6,
        step=25,
        precision=2,
        set=prop_methods("SET", "height"),
        get=prop_methods("GET", "height"),
        update=prop_methods("UPDATE"))
    mesh: PointerProperty(type=Mesh)
    

單獨(dú)的set 、 get和update參數(shù)都指向prop_methods函數(shù)的返回值。這些值必須是函數(shù),參數(shù)分別為(self, value)、(self)和(self, context)。這個(gè)閉包工廠可能看起來(lái)額外復(fù)雜,但它會(huì)顯著減少重復(fù),并為與PropertyGroup 的數(shù)據(jù)屬性交互提供更大的靈活性。

要理解的一個(gè)重要區(qū)別是,每當(dāng)屬性更改時(shí)都會(huì)調(diào)用update函數(shù)——它不是作為更新定義其屬性的一種方式來(lái)調(diào)用的。相反,它提供了一種將特定屬性的更改傳達(dá)給程序的其他部分的方法;這必須小心使用以避免副作用,并且因?yàn)闆](méi)有檢查來(lái)避免無(wú)限遞歸。

另一件需要注意的是,使用set和get函數(shù)意味著任何default值都必須通過(guò)顯式set調(diào)用(而不是  kwarg)來(lái)設(shè)置,但這也提供了在必要時(shí)掛鉤on_load方法的機(jī)會(huì)。最后,prop_methods函數(shù)必須在調(diào)用它的任何PropertyGroup類(lèi)之前定義。

prop_methods函數(shù)的骨架代碼如下所示:

def prop_methods(call, prop=None):
    def getter(self):
        # getter function must check if prop attr has a value yet
            # if no value, will throw error, so must set default
            # can hook on load here
        # and either way, return self[prop] value
    def setter(self, value):
        self[prop] = value
    def updater(self, context):
        self.update(context)
    methods = {
        "GET": getter,
        "SET": setter,
        "UPDATE": updater
        }
    return methods[call]

完整的實(shí)現(xiàn)如下所示:

def prop_methods(call, prop=None):
    def getter(self):
        try:
            value = self[prop]
        except:
            set_default = prop_methods("SET", prop)
            set_default(self, self.defaults[prop])
            if hasattr(self, "on_load"):
                self.on_load()
            value = self[prop]
        finally:
            return value
    def setter(self, value):
        self[prop] = value
            
    def updater(self, context):
        self.update(context)
    methods = {
        "GET": getter,
        "SET": setter,
        "UPDATE": updater,
        }
    return methods[call]

為此,任何具有調(diào)用prop_methods屬性的類(lèi)都需要一個(gè)名為defaults的字典對(duì)象和一個(gè)名為update的方法(該函數(shù)提供,但不需要on_load方法)。在PG_Standoff類(lèi)中,這些調(diào)用將用于附加Standoff.mesh()的返回值,以及無(wú)論何時(shí)修改metric_diameter或height屬性。PG_Standoff課程的其余部分可以寫(xiě)成:

class PG_Standoff(PropertyGroup):
    # ...
    defaults = { "metric_diameter": 2.5, "height": 3 }
    standoff = Standoff()
    def on_load(self):
        if self.height and self.metric_diameter:
            self.__set_mesh()
    def update(self, context):
        self.__set_mesh()
    def __set_mesh(self):
        self.mesh = self.standoff.mesh(
           self.height, self.metric_diameter)

僅留下import語(yǔ)句和register 、unregister函數(shù)。在 register 函數(shù)中,我們還將從 ointerProperty的實(shí)例中指向PG_PropertyGroup類(lèi),從 Blender 的Scene類(lèi)型的新屬性中引用,這將使從插件的其余部分訪問(wèn)變得簡(jiǎn)單。這將產(chǎn)生一個(gè)完整的standoff_props.py模塊,如下面的要點(diǎn)所示:

from bpy.props import PointerProperty, FloatProperty
from bpy.types import Mesh, PropertyGroup, Scene
from bpy.utils import register_class, unregister_class
from .standoff_mesh import Standoff
def prop_methods(call, prop=None):
    def getter(self):
        try:
            value = self[prop]
        except:
            set_default = prop_methods("SET", prop)
            set_default(self, self.defaults[prop])
            if hasattr(self, "on_load"):
                self.on_load()
            value = self[prop]
        finally:
            return value
    def setter(self, value):
        self[prop] = value
    def updater(self, context):
        self.update(context)
    methods = {
        "GET": getter,
        "SET": setter,
        "UPDATE": updater,
        }
    return methods[call]
class PG_Standoff(PropertyGroup):
    metric_diameter: FloatProperty(
        name="Inner Diameter (Metric)",
        min=2,
        max=5,
        step=50,
        precision=1,
        set=prop_methods("SET", "metric_diameter"),
        get=prop_methods("GET", "metric_diameter"),
        update=prop_methods("UPDATE"))
    height: FloatProperty(
        name="Standoff Height",
        min=2,
        max=6,
        step=25,
        precision=2,
        set=prop_methods("SET", "height"),
        get=prop_methods("GET", "height"),
        update=prop_methods("UPDATE"))
    mesh: PointerProperty(type=Mesh)
    defaults = { "metric_diameter": 2.5, "height": 3 }
    standoff = Standoff()
    def on_load(self):
        if self.height and self.metric_diameter:
            self.__set_mesh()
    def update(self, context):
        self.__set_mesh()
    def __set_mesh(self):
        self.mesh = self.standoff.mesh(self.height, self.metric_diameter)
def register():
    register_class(PG_Standoff)
    Scene.Standoff = PointerProperty(type=PG_Standoff)
def unregister():
    unregister_class(PG_Standoff)
    del Scene.Standoff

四、standoff_operator.py

最后兩個(gè)模塊都是短文件,實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,因?yàn)榻Y(jié)構(gòu)化和修改數(shù)據(jù)的繁重工作已經(jīng)以簡(jiǎn)化其與 Blender Python API 交互的方式完成。在standoff_operator模塊中,我們將定義(并注冊(cè))一個(gè)新bpy.types.Operator類(lèi),然后可以將其附加到任何 UI 按鈕。

如何定義一個(gè)新的Operator有一些要求,但這些都是有據(jù)可查且簡(jiǎn)單明了的,并且通過(guò)從 CLI 啟動(dòng) Blender,警告和錯(cuò)誤消息將立即顯現(xiàn)錯(cuò)誤配置的Operator類(lèi)有。手冊(cè)部分給出了新Operators的預(yù)期定義的詳細(xì)信息。下面腳本將定義docstring、bl_idname、bl_label和bl_options屬性的值。它還將定義一個(gè)execute方法,該方法需要self和context參數(shù),并包含將附加到任何 UI 按鈕調(diào)用注冊(cè)bl_idname 名下的Operator邏輯和事件。

import bpy
from bpy.types import Operator
from bpy.utils import register_class, unregister_class
class DEMORACK_OT_AddNewStandoff(Operator):
    """adds standoff to test add-on registered ok"""
    bl_idname = 'scene.add_new_standoff'
    bl_label = 'New Standoff'
    bl_options = { "REGISTER", "UNDO" }
    def execute(self, context):
        name = "Standoff"
        standoff = context.scene.Standoff # <- set in standoff_props.register()
        collection = context.scene.collection
        obj = bpy.data.objects.new(name, standoff.mesh)
        collection.objects.link(obj)
        obj.select_set(True)
        context.view_layer.objects.active = obj
        return { "FINISHED" }
def register():
    register_class(DEMORACK_OT_AddNewStandoff)
def unregister():
    unregister_class(DEMORACK_OT_AddNewStandoff)

五、standoff_panel.py

定義一個(gè)新Panel類(lèi)幾乎遵循與定義一個(gè)新Operator類(lèi)相同的模式,并且從概念上講,只需將execute最后一步中的draw方法換成這一步中的方法。相關(guān)的Panel 手冊(cè)部分提供了幾個(gè)有用的示例, UI 腳本 > 模板 > Python 菜單中包含更多示例。 在手冊(cè)bpy.types.UILayout部分中可以發(fā)現(xiàn)了更多可能性,該部分記錄了Panel對(duì)象的導(dǎo)入項(xiàng)。在draw方法中,它是一個(gè)簡(jiǎn)單(且非常開(kāi)放)的過(guò)程:

  • 訪問(wèn)context 中的相關(guān)數(shù)據(jù)對(duì)象
  • 為需要按鈕的任何Operator 調(diào)用創(chuàng)建layout.operator對(duì)象
  • 為用戶(hù)可寫(xiě)數(shù)據(jù)屬性創(chuàng)建layout.prop對(duì)象

當(dāng)然,在該模式以及更復(fù)雜的數(shù)據(jù)類(lèi)型中,還有很多擴(kuò)展和變化的空間。但在基礎(chǔ)上,這是另一個(gè)由 API 處理繁重工作的地方,并遵循bpy.props和bpy.types.PropertyGroup實(shí)例的內(nèi)置使用模式。由于這種簡(jiǎn)單性,這是另一個(gè)模塊,它足夠簡(jiǎn)單:

from bpy.types import Panel
from bpy.utils import register_class, unregister_class
class DemoRackPanel:
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "DemoRack"
class StandoffPanel(DemoRackPanel, Panel):
    bl_idname = "DEMORACK_PT_standoff_panel"
    bl_label = "Standoff"
    def draw(self, context):
        layout = self.layout
        standoff_data = context.scene.Standoff # <- set in standoff_props.register()
        layout.operator("scene.add_new_standoff") # <- registered in standoff_operator.py
        layout.prop(standoff_data, "metric_diameter")
        layout.prop(standoff_data, "height")
def register():
    register_class(StandoffPanel)
def unregister():
    unregister_class(StandoffPanel)

唯一的額外變化是 DemoRackPanel的類(lèi)定義,它與 bpy.types.Panel一起被StandoffPanel繼承。因?yàn)檫@不是DemoRack插件中的唯一Panel,它們都將位于 View 3D 側(cè)抽屜中的單個(gè)選項(xiàng)卡下,消除 3 行重復(fù)是一件簡(jiǎn)單的事情。layout.prop 的模式和相關(guān)函數(shù)中是將 Data 對(duì)象作為第一個(gè)參數(shù),并將該對(duì)象內(nèi)屬性的字符串標(biāo)識(shí)符作為第二個(gè)參數(shù)。

剩下要做的就是從DemoRack/src/目錄編譯DemoRack.zip文件,然后像其他任何文件一樣在編輯 > 首選項(xiàng) > 附加組件中安裝該本地文件。

原文鏈接:Build a Blender Add-on Ready to Scale

以上就是python可擴(kuò)展的Blender 3D插件開(kāi)發(fā)匯總的詳細(xì)內(nèi)容,更多關(guān)于python Blender 3D插件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python抓取通過(guò)Ajax加載數(shù)據(jù)的示例

    Python抓取通過(guò)Ajax加載數(shù)據(jù)的示例

    在網(wǎng)頁(yè)上,有一些內(nèi)容是通過(guò)執(zhí)行Ajax請(qǐng)求動(dòng)態(tài)加載數(shù)據(jù)渲染出來(lái)的,本文主要介紹了使用Python抓取通過(guò)Ajax加載數(shù)據(jù),感興趣的可以了解一下
    2023-05-05
  • Python?獲取md5值(hashlib)常用方法

    Python?獲取md5值(hashlib)常用方法

    這篇文章主要介紹了Python獲取md5值(hashlib)常用方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Python中常見(jiàn)路徑算法的原理與實(shí)現(xiàn)詳解

    Python中常見(jiàn)路徑算法的原理與實(shí)現(xiàn)詳解

    在計(jì)算機(jī)科學(xué)中,路徑算法是解決許多實(shí)際問(wèn)題的核心工具,本文介紹了Python中三種常見(jiàn)的路徑算法及其實(shí)現(xiàn),幫助讀者快速上手并理解這些算法的原理和應(yīng)用
    2026-04-04
  • python 字符串split的用法分享

    python 字符串split的用法分享

    python 字符串的split方法是用的頻率還是比較多的。比如我們需要存儲(chǔ)一個(gè)很長(zhǎng)的數(shù)據(jù),并且按照有結(jié)構(gòu)的方法存儲(chǔ),方便以后取數(shù)據(jù)進(jìn)行處理。當(dāng)然可以用json的形式。但是也可以把數(shù)據(jù)存儲(chǔ)到一個(gè)字段里面,然后有某種標(biāo)示符來(lái)分割
    2013-03-03
  • python提取照片坐標(biāo)信息的實(shí)例代碼

    python提取照片坐標(biāo)信息的實(shí)例代碼

    這篇文章主要介紹了python提取照片坐標(biāo)信息的實(shí)例代碼,文中給大家提到了Python利用exifread庫(kù)來(lái)解析照片的經(jīng)緯度,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 簡(jiǎn)單談?wù)凱ython的pycurl模塊

    簡(jiǎn)單談?wù)凱ython的pycurl模塊

    PycURl是一個(gè)C語(yǔ)言寫(xiě)的libcurl的python綁定庫(kù)。libcurl 是一個(gè)自由的,并且容易使用的用在客戶(hù)端的 URL 傳輸庫(kù)。它的功能很強(qiáng)大,PycURL 是一個(gè)非??焖伲▍⒖级嗖l(fā)操作)和豐富完整特性的,但是有點(diǎn)復(fù)雜的接口。
    2018-04-04
  • selenium+python自動(dòng)化測(cè)試之頁(yè)面元素定位

    selenium+python自動(dòng)化測(cè)試之頁(yè)面元素定位

    這篇文章主要介紹了selenium+python自動(dòng)化測(cè)試之頁(yè)面元素定位,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • python編程開(kāi)發(fā)之textwrap文本樣式處理技巧

    python編程開(kāi)發(fā)之textwrap文本樣式處理技巧

    這篇文章主要介紹了python編程開(kāi)發(fā)之textwrap文本樣式處理技巧,實(shí)例分析了Python中textwrap的常用方法與處理文本樣式的相關(guān)使用技巧,需要的朋友可以參考下
    2015-11-11
  • 一起來(lái)學(xué)習(xí)一下python的數(shù)字類(lèi)型

    一起來(lái)學(xué)習(xí)一下python的數(shù)字類(lèi)型

    這篇文章主要為大家詳細(xì)介紹了python的數(shù)字類(lèi)型,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • python 利用瀏覽器 Cookie 模擬登錄的用戶(hù)訪問(wèn)知乎的方法

    python 利用瀏覽器 Cookie 模擬登錄的用戶(hù)訪問(wèn)知乎的方法

    今天小編就為大家分享一篇python 利用瀏覽器 Cookie 模擬登錄的用戶(hù)訪問(wèn)知乎的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07

最新評(píng)論

呼和浩特市| 桃江县| 长治市| 延庆县| 海伦市| 宜兴市| 桐柏县| 翁源县| 菏泽市| 榆树市| 繁峙县| 阿图什市| 墨脱县| 浦北县| 靖宇县| 永吉县| 长葛市| 玛沁县| 资源县| 阿拉善盟| 阿克陶县| 峡江县| 阳曲县| 资源县| 平遥县| 安化县| 山阳县| 福清市| 榕江县| 西宁市| 苏州市| 平顶山市| 庐江县| 亚东县| 获嘉县| 泸定县| 甘德县| 宜君县| 河北省| 库尔勒市| 临沧市|