Handledning för tillägg¶
Avsedd målgrupp¶
Denna handledning är utformad för att hjälpa tekniska konstnärer eller utvecklare att lära sig att utöka Blender. En förståelse för grunderna i Python förväntas för dem som arbetar genom denna handledning.
Förutsättningar¶
Innan du går igenom handledningen bör du …
Vara bekant med grunderna i att arbeta i Blender.
Vet hur man kör ett skript i Blenders textredigerare.
Ha en förståelse för Pythons primitiva typer (heltal, boolesk, sträng, lista, tupel, ordbok och set).
Känna till konceptet med Python-moduler.
Ha en grundläggande förståelse för klasser (objektorientering) i Python.
Föreslagen läsning innan du börjar med denna handledning.
Dyk in i Python avsnitt (1, 2, 3, 4 och 7).
Blender API Quickstart för att hjälpa dig att bli bekant med grunderna i Blender/Python.
För att på bästa sätt felsöka eventuella felmeddelanden som Python skriver ut när du skriver skript kör du Blender från en terminal. Se Använda terminalen.
Tips
Du kan aktivera Developer Extras i inställningarna för att aktivera funktioner som gör det enklare att utveckla tillägg.
Länkar till dokumentation¶
När du går igenom handledningen kanske du vill titta på vår referensdokumentation.
Blender API Översikt: Detta dokument är ganska detaljerat men användbart om du vill veta mer om ett ämne.
bpy.context
API-referens – Praktiskt att ha en lista över tillgängliga objekt som ditt skript kan arbeta med.bpy.types.Operator
– Följande tillägg definierar operatorer, dessa dokument ger detaljer och fler exempel på operatorer.
Vad är ett tillägg?¶
Ett tillägg är helt enkelt en Python-modul med några ytterligare krav så att Blender kan visa den i en lista med användbar information.
För att ge ett exempel, här är det enklaste möjliga tillägget:
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
är en ordbok som innehåller metadata för tillägg, t.ex. titel, version och författare, som ska visas i tilläggslistan i Inställningar. Den anger också den minsta Blender-version som krävs för att köra skriptet; äldre versioner kommer inte att visa tillägget i listan.
register
är en funktion som bara körs när tillägget aktiveras, vilket innebär att modulen kan laddas utan att tillägget aktiveras.
unregister
är en funktion för att avlasta allt som konfigurerats av register, denna anropas när tillägget inaktiveras.
Observera att detta tillägg inte gör något som är relaterat till Blender (modulen blender_api:bpy
importeras inte till exempel).
Detta är ett konstruerat exempel på ett tillägg som tjänar till att illustrera att de grundläggande kraven på ett tillägg är enkla.
Ett tillägg registrerar vanligtvis operatörer, paneler, menyalternativ etc., men det är värt att notera att alla skript kan göra detta, när de körs från textredigeraren eller till och med den interaktiva konsolen - det finns inget som är annorlunda med ett tillägg som gör att det kan integreras med Blender, sådan funktionalitet tillhandahålls bara av blender_api:bpy
-modulen som alla skript kan komma åt.
Så ett tillägg är bara ett sätt att kapsla in en Python-modul på ett sätt som en användare lätt kan använda.
Observera
Om du kör det här skriptet i textredigeraren skrivs ingenting ut, för att se utdata måste det installeras via inställningarna. Meddelanden kommer att skrivas ut när du aktiverar och inaktiverar.
Ditt första tillägg¶
Det enklaste möjliga tillägget ovan är användbart som ett exempel men inte mycket annat. Nästa tillägg är enkelt men visar hur man integrerar ett skript i Blender med hjälp av en Operator som är det typiska sättet att definiera ett verktyg som nås från menyer, knappar och kortkommandon.
I det första exemplet ska vi skapa ett skript som helt enkelt flyttar alla objekt i en scen.
Skriva manuset¶
Lägg till följande skript i textredigeraren i Blender:
import bpy
scene = bpy.context.scene
for obj in scene.objects:
obj.location.x += 1.0
Klicka på knappen Run Script, så flyttas alla objekt i den aktiva scenen med 1,0 enhet.
Skriv tillägget (enkelt)¶
Detta tillägg tar kroppen av skriptet ovan och lägger till det i en operatörs execute()
-funktion.
bl_info = {
"name": "Move X Axis",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectMoveX(bpy.types.Operator):
"""My Object Moving Script""" # Use this as a tooltip for menu items and buttons.
bl_idname = "object.move_x" # Unique identifier for buttons and menu items to reference.
bl_label = "Move X by One" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
def execute(self, context): # execute() is called when running the operator.
# The original script
scene = context.scene
for obj in scene.objects:
obj.location.x += 1.0
return {'FINISHED'} # Lets Blender know the operator finished successfully.
def menu_func(self, context):
self.layout.operator(ObjectMoveX.bl_idname)
def register():
bpy.utils.register_class(ObjectMoveX)
bpy.types.VIEW3D_MT_object.append(menu_func) # Adds the new operator to an existing menu.
def unregister():
bpy.utils.unregister_class(ObjectMoveX)
# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":
register()
Observera
bl_info är uppdelad på flera rader, detta är bara en stilkonvention som används för att lättare kunna lägga till objekt.
Observera
I stället för att använda bpy.context.scene använder vi argumentet context.scene som skickas till execute(). I de flesta fall kommer dessa att vara desamma. Men i vissa fall kommer operatörer att skickas ett anpassat sammanhang så skriptförfattare bör föredra argumentet context som skickas till operatörer.
För att testa skriptet kan du kopiera och klistra in det i Blenders textredigerare och köra det. Detta kommer att exekvera skriptet direkt och anropa register omedelbart.
Men att köra skriptet kommer inte att flytta några objekt. För detta måste du köra den nyligen registrerade operatören.

Meny för operatörssökning.¶
Öppna menyn Operator Search och skriv in ”Move X by One” (bl_label), sedan Return.
Objekten ska röra sig som tidigare.
Håll detta tillägg öppet i Blender för nästa steg - Installing.
Installera tillägget¶
När du har ditt tillägg i Blenders textredigerare vill du kunna installera det så att det kan aktiveras i inställningarna för att laddas vid start.
Även om tillägget ovan är ett test, går vi igenom stegen ändå så att du vet hur du ska göra det till senare.
För att installera Blender-texten som ett tillägg måste du först spara den på hårddisken. Var noga med att följa de namngivningsrestriktioner som gäller för Python-moduler och avsluta med tillägget .py.
När filen finns på hårddisken kan du installera den på samma sätt som ett tillägg som du laddar ner online.
Öppna
och välj filen.Nu kommer tillägget att listas och du kan aktivera det genom att trycka på kryssrutan, om du vill att det ska aktiveras vid omstart trycker du på Save as Default. Operatören kan köras på samma sätt som beskrivs i föregående avsnitt.
När tillägget är aktiverat exekverar Blender koden och kör funktionen register(). När tillägget är inaktiverat kör Blender funktionen unregister().
Observera
Tilläggets destination beror på din Blender-konfiguration. När du installerar ett tillägg skrivs käll- och destinationssökvägarna ut i konsolen. Du kan också hitta tilläggssökvägar genom att köra detta i Python-konsolen:
import addon_utils
print(addon_utils.paths())
Mer finns skrivet om detta ämne här: Directory Layout.
Ditt andra tillägg¶
I vårt andra tillägg kommer vi att fokusera på objektinstansiering - det vill säga att skapa länkade kopior av ett objekt på ett liknande sätt som du kanske har sett med Array-modifieraren.
Skriva manuset¶
Som tidigare kommer vi först att börja med ett skript, utveckla det och sedan konvertera det till ett tillägg:
import bpy
from bpy import context
# Get the current scene
scene = context.scene
# Get the 3D cursor location
cursor = scene.cursor.location
# Get the active object (assume we have one)
obj = context.active_object
# Now make a copy of the object
obj_new = obj.copy()
# The new object has to be added to a collection in the scene
scene.collection.objects.link(obj_new)
# Now we can place the object
obj_new.location = cursor
Försök nu att kopiera detta skript till Blender och kör det på standardkuben. Se till att du klickar för att flytta 3D-markören innan du kör eftersom duplikatet kommer att visas på markörens plats.
Efter körning, lägg märke till att när du går in i Redigera Mode för att ändra kuben - ändras alla kopior. I Blender kallas detta för Linked Duplicates.
Nu ska vi göra detta i en loop för att skapa en array av objekt mellan det aktiva objektet och markören.
import bpy
from bpy import context
scene = context.scene
cursor = scene.cursor.location
obj = context.active_object
# Use a fixed value for now, eventually make this user adjustable
total = 10
# Add 'total' objects into the scene
for i in range(total):
obj_new = obj.copy()
scene.collection.objects.link(obj_new)
# Now place the object in between the cursor
# and the active object based on 'i'
factor = i / total
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
Prova att köra det här skriptet med det aktiva objektet och markören på avstånd från varandra för att se resultatet.
Med det här skriptet kommer du att märka att vi gör lite matematik med objektets plats och markör, detta fungerar eftersom båda är 3D mathutils.Vector
-instanser, en bekväm klass som tillhandahålls av mathutils
-modulen som gör att vektorer kan multipliceras med siffror och matriser.
Om du är intresserad av detta område, läs in dig på mathutils.Vector
- det finns många praktiska funktioner som att få vinkeln mellan vektorer, korsprodukt, punktprodukter samt mer avancerade funktioner i mathutils.geometry
som Bézier spline interpolation och ray-triangle intersection.
För närvarande kommer vi att fokusera på att göra detta skript till ett tillägg, men det är bra att veta att denna 3D-matematikmodul finns tillgänglig och kan hjälpa dig med mer avancerad funktionalitet senare.
Skriv tillägget¶
Det första steget är att konvertera manuset som det är till ett tillägg:
bl_info = {
"name": "Cursor Array",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectCursorArray(bpy.types.Operator):
"""Object Cursor Array"""
bl_idname = "object.cursor_array"
bl_label = "Cursor Array"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
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 register():
bpy.utils.register_class(ObjectCursorArray)
def unregister():
bpy.utils.unregister_class(ObjectCursorArray)
if __name__ == "__main__":
register()
Allt här har täckts i de tidigare stegen, du kanske vill prova att köra tillägget fortfarande och överväga vad som kan göras för att göra det mer användbart.
De två mest uppenbara saknade sakerna är – att ha summan fixerad till 10 och att behöva komma åt operatören med Operatörssökning är inte särskilt bekvämt.
Båda dessa tillägg förklaras härnäst, och därefter följer det slutliga manuset.
Operatörens egendom¶
Det finns en mängd olika egenskapstyper som används för verktygsinställningar, vanliga egenskapstyper är: int, float, vector, color, boolean och string.
Dessa egenskaper hanteras annorlunda än typiska Python-klassattribut eftersom Blender måste visa dem i gränssnittet, lagra deras inställningar i keymaps och spara inställningar för återanvändning.
Även om detta hanteras på ett ganska pythonskt sätt, bör du vara medveten om att du faktiskt definierar verktygsinställningar som laddas in i Blender och nås av andra delar av Blender, utanför Python.
För att bli av med den bokstavliga 10 för total använder vi en operatöregenskap. Operatöregenskaper definieras via bpy.props-modulen, detta läggs till i klassens kropp:
# moved assignment from execute() to the body of the class...
total: bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
# and this is accessed on the class
# instance within the execute() function as...
self.total
Dessa egenskaper från bpy.props
hanteras speciellt av Blender när klassen registreras så att de visas som knappar i användargränssnittet. Det finns många argument som du kan skicka till egenskaper för att ställa in gränser, ändra standard och visa en verktygstips.
Se även
Detta dokument går inte in i detalj på hur man använder andra egenskapstyper. Länken ovan innehåller dock exempel på mer avancerad användning av egenskaper.
Inmatning > Tangentbordsmappningar¶
I Blender har tilläggsprogram sina egna keymaps för att inte störa Blenders inbyggda keymaps.
I exemplet nedan läggs ett nytt objektläge bpy.types.KeyMap
till, sedan läggs en bpy.types.KeyMapItem
till i tangentmappningen som refererar till vår nyligen tillagda operatör, med Shift-Ctrl-T som kortkommando för att aktivera den.
# store keymaps here to access after registration
addon_keymaps = []
def register():
# handle the keymap
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'T', 'PRESS', ctrl=True, shift=True)
kmi.properties.total = 4
addon_keymaps.append((km, kmi))
def unregister():
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
Lägg märke till att keymap-objektet kan ha en annan inställning för total än den standardinställning som anges av operatören, vilket gör att du kan ha flera tangenter som har åtkomst till samma operatör med olika inställningar.
Observera
Även om Shift-Ctrl-T inte är en standardtangentgenväg i Blender, är det svårt att se till att tilläggsprogram inte skriver över varandras tangentkartor. Var därför åtminstone försiktig när du tilldelar nycklar så att de inte står i konflikt med viktiga funktioner i Blender (se även is key free add-on).
API-dokumentation för de funktioner som anges ovan finns i:
Att föra samman allt¶
bl_info = {
"name": "Cursor Array",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
class ObjectCursorArray(bpy.types.Operator):
"""Object Cursor Array"""
bl_idname = "object.cursor_array"
bl_label = "Cursor Array"
bl_options = {'REGISTER', 'UNDO'}
total: bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
def execute(self, context):
scene = context.scene
cursor = scene.cursor.location
obj = context.active_object
for i in range(self.total):
obj_new = obj.copy()
scene.collection.objects.link(obj_new)
factor = i / self.total
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
return {'FINISHED'}
def menu_func(self, context):
self.layout.operator(ObjectCursorArray.bl_idname)
# store keymaps here to access after registration
addon_keymaps = []
def register():
bpy.utils.register_class(ObjectCursorArray)
bpy.types.VIEW3D_MT_object.append(menu_func)
# handle the keymap
wm = bpy.context.window_manager
# Note that in background mode (no GUI available), keyconfigs are not available either,
# so we have to check this to avoid nasty errors in background case.
kc = wm.keyconfigs.addon
if kc:
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'T', 'PRESS', ctrl=True, shift=True)
kmi.properties.total = 4
addon_keymaps.append((km, kmi))
def unregister():
# Note: when unregistering, it's usually good practice to do it in reverse order you registered.
# Can avoid strange issues like keymap still referring to operators already unregistered...
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
bpy.utils.unregister_class(ObjectCursorArray)
bpy.types.VIEW3D_MT_object.remove(menu_func)
if __name__ == "__main__":
register()

I menyn.¶
Kör skriptet (eller spara det och lägg till det via inställningarna som tidigare) så visas det i menyn Object.

Operatörens egendom.¶
När du har valt den i menyn kan du välja hur många instanser av kuben du vill skapa.
Observera
Om du kör skriptet direkt flera gånger kommer menyn att läggas till varje gång också. Även om det inte är ett användbart beteende finns det inget att oroa sig för eftersom tillägg inte kommer att registrera sig flera gånger när de aktiveras via inställningarna.
Slutsatser¶
Tillägg kan kapsla in viss funktionalitet på ett snyggt sätt för att skriva verktyg som förbättrar ditt arbetsflöde eller för att skriva verktyg som andra kan använda.
Även om det finns gränser för vad Python kan göra i Blender, finns det mycket som kan uppnås utan att behöva dyka in i Blenders C/C++-kod.
Exemplet som ges i handledningen är begränsat, men visar Blender API som används för vanliga uppgifter som du kan expandera på för att skriva dina egna verktyg.
Ytterligare läsning¶
Blender levereras med kommenterade mallar som är tillgängliga från Textredigerarens sidhuvud. Om du har specifika områden som du vill se exempelkod för är det här ett bra ställe att börja på.
Här är några webbplatser som du kanske vill besöka efter att ha slutfört den här handledningen.
Blender/Python API Overview – För mer bakgrundsinformation om Blender/Python-integration.
Hur man tänker som en datavetare – Bra information för dem som fortfarande lär sig Python.
Blender Development – Blender Development, allmän information och användbara länkar.
Blender Developer Forum – Forum där folk ställer frågor om Python-utveckling.