Skip to main content 홈 크리에이터 johnnuwan eva_core blender-scripting-python
blender-scripting-python Scripting Python dans Blender — API bpy, add-ons, automation, batch processing, création d'outils personnalisés, panels, operators, UI, pipeline et intégration.
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill blender-scripting-python명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... name blender-scripting-python description Scripting Python dans Blender — API bpy, add-ons, automation, batch processing, création d'outils personnalisés, panels, operators, UI, pipeline et intégration. version 1.0.0 category creative tags ["blender","python","scripting","bpy","addon","automation","api","pipeline","3d"] prerequisites {"commands":["blender"]} setup {"help":"Blender installé. Python est intégré à Blender (bpy, bmesh, bpy_extras). Utiliser l'interpréteur Python de Blender ('blender --python script.py')."} metadata {"hermes":{"tags":["blender","python","scripting","bpy","addon","automation","api","pipeline"],"related_skills":["blender-modeling","blender-animation","blender-geometry-nodes"],"category":"creative"}}
Blender — Scripting Python
Guide complet du scripting Python dans Blender : API bpy, bmesh,
création d'add-ons, automation, batch processing, panels, operators,
et pipeline d'intégration.
Architecture Blender Python
┌─────────────────────────────────────────┐
│ bpy (module principal) │
│ ┌──────────────┐ ┌────────────────┐ │
│ │ bpy.data │ │ bpy.context │ │
│ │ (BDNA data) │ │ (contexte) │ │
│ └──────┬───────┘ └───────┬────────┘ │
│ │ │ │
│ ┌──────▼──────────────────▼────────┐ │
│ │ bpy.ops (operators) │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ bpy.types (classes) │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ bmesh (mesh editing) │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ bpy.app (timers, handlers) │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ mathutils (vectors, mats) │ │
│ └──────────────────────────────────┘ │
└─────────────────────────────────────────┘
bpy — Accès aux Données
bpy.data (Data Blocks)
bpy.data.objects["Cube" ]
bpy.data.objects["Camera" ]
bpy.data.objects["Light" ]
bpy.data.meshes["Cube.001" ]
bpy.data.meshes.new("MonMeshe" )
bpy.data.materials["Material" ]
bpy.data.materials.new("MonMat" )
bpy.data.images["render_output.png" ]
bpy.data.collections["Collection" ]
bpy.context (Contexte)
bpy.context.scene
bpy.context.view_layer
bpy.context.object
bpy.context.selected_objects
bpy.context.visible_objects
bpy.context.active_object
bpy.context.mode
bpy.context.area
bpy.context.space_data
bpy.ops (Operators) Appel des opérateurs Blender :
bpy.ops.mesh.primitive_cube_add(size=2 , location=(0 , 0 , 0 ))
bpy.ops.object .light_add(type ='POINT' , location=(1 , 1 , 5 ))
bpy.ops.object .select_all(action='DESELECT' )
bpy.data.objects["Cube" ].select_set(True )
bpy.ops.object .mode_set(mode='EDIT' )
bpy.ops.object .mode_set(mode='OBJECT' )
bpy.ops.object .mode_set(mode='SCULPT' )
bpy.ops.object .modifier_add(type ='SUBSURF' )
bpy.ops.object .modifier_apply(modifier="Subdivision" )
bpy.ops.wm.open_mainfile(filepath="scene.blend" )
bpy.ops.wm.save_mainfile()
bpy.ops.export_scene.fbx(filepath="output.fbx" )
bpy.app (Application) bpy.app.version
bpy.app.background
bpy.app.debug_value
bpy.app.handlers
bpy.app.timers.register()
bmesh — Edition de Maillage import bmesh
bm = bmesh.new()
v1 = bm.verts.new((0 , 0 , 0 ))
v2 = bm.verts.new((1 , 0 , 0 ))
v3 = bm.verts.new((1 , 1 , 0 ))
v4 = bm.verts.new((0 , 1 , 0 ))
face = bm.faces.new((v1, v2, v3, v4))
ret = bmesh.ops.extrude_face_region(bm, geom=[face])
extruded_verts = [v for v in ret['geom' ] if isinstance (v, bmesh.types.BMVert)]
for v in extruded_verts:
v.co.z += 1.0
mesh = bpy.data.meshes.new("Quad" )
bm.to_mesh(mesh)
bm.free()
Opérations bmesh bmesh.ops.subdivide_edges(bm, edges=bm.edges, cuts=2 )
bmesh.ops.bevel(bm, geom=bm.edges, offset=0.1 )
bmesh.ops.bridge_loops(bm, edges=[edge_list_a, edge_list_b])
bmesh.ops.remove_doubles(bm, dist=0.001 )
bmesh.ops.triangulate(bm, faces=bm.faces)
bmesh.ops.dissolve_limit(bm, angle_limit=5 , verts=bm.verts)
bmesh.ops.transform(bm, matrix=mat, verts=bm.verts)
mathutils — Vecteurs et Matrices import mathutils
from mathutils import Vector, Matrix, Euler, Quaternion
v = Vector((1 , 2 , 3 ))
v2 = Vector((4 , 5 , 6 ))
v.dot(v2)
v.cross(v2)
v.length
v.normalized()
mat = Matrix.Translation(Vector((0 , 0 , 1 )))
rot = Euler((0 , 0 , 1.57 ), 'XYZ' ).to_matrix().to_4x4()
scale = Matrix.Scale(2 , 4 )
transform = mat @ rot @ scale
q = Quaternion((1 , 0 , 0 , 0 ))
q2 = Quaternion((0.707 , 0.707 , 0 , 0 ))
Automatisation et Batch
Script Headless (mode --background) blender scene.blend --background --python mon_script.py
blender --background --python create_scene.py
blender --background --python batch_export.py
Exemple Batch Export FBX
import bpy
import os
import sys
input_dir = sys.argv[-2 ] if len (sys.argv) > 1 else "."
output_dir = sys.argv[-1 ] if len (sys.argv) > 2 else "exports"
os.makedirs(output_dir, exist_ok=True )
for filename in os.listdir(input_dir):
if filename.endswith(".blend" ):
path = os.path.join(input_dir, filename)
bpy.ops.wm.open_mainfile(filepath=path)
basename = os.path.splitext(filename)[0 ]
out_path = os.path.join(output_dir, f"{basename} .fbx" )
bpy.ops.export_scene.fbx(filepath=out_path)
print (f"Exported: {path} -> {out_path} " )
blender --background --python batch_export.py -- ./scenes ./exports
Add-ons (Modules)
Structure d'un Add-on mon_addon/
├── __init__.py # Metadata + register/unregister
├── operators.py # Classes d'opérateurs
├── ui.py # Panels et menus
├── properties.py # PropertyGroups
└── utils.py # Fonctions utilitaires
init .pybl_info = {
"name" : "Mon Addon" ,
"author" : "Moi" ,
"version" : (1 , 0 , 0 ),
"blender" : (4 , 0 , 0 ),
"location" : "View3D > Sidebar > Mon Tab" ,
"description" : "Description de l'addon" ,
"category" : "Object" ,
}
modules = ["operators" , "ui" , "properties" ]
def register ():
for m in modules:
exec (f"import {m} " )
exec (f"{m} .register()" )
def unregister ():
for m in reversed (modules):
exec (f"{m} .unregister()" )
Créer un Operator import bpy
class MES_OT_mon_operateur (bpy.types.Operator):
"""Description de l'opérateur"""
bl_idname = "mesh.mon_operateur"
bl_label = "Mon Opérateur"
bl_options = {'REGISTER' , 'UNDO' }
scale: bpy.props.FloatProperty(
name="Scale" ,
default=1.0 ,
min =0.1 ,
max =10.0 ,
)
@classmethod
def poll (cls, context ):
return context.active_object is not None
def execute (self, context ):
obj = context.active_object
obj.scale = (self .scale, self .scale, self .scale)
return {'FINISHED' }
Créer un Panel class MES_PT_mon_panel (bpy.types.Panel):
bl_label = "Mon Panel"
bl_idname = "MES_PT_mon_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Mon Outil"
def draw (self, context ):
layout = self .layout
layout.label(text="Paramètres" )
layout.prop(context.active_object, "scale" )
layout.operator("mesh.mon_operateur" )
Properties (PropertyGroup) class MonGroupeProprietes (bpy.types.PropertyGroup):
ma_prop: bpy.props.FloatProperty(
name="Ma Propriété" ,
default=1.0 ,
min =0.0 ,
max =100.0 ,
)
bpy.utils.register_class(MonGroupeProprietes)
bpy.types.Scene.mon_groupe = bpy.props.PointerProperty(
type =MonGroupeProprietes
)
bpy.context.scene.mon_groupe.ma_prop
Handlers et Timers
Handlers (Events) def mon_handler (scene ):
print (f"Frame changed: {scene.frame_current} " )
bpy.app.handlers.frame_change_pre.append(mon_handler)
bpy.app.handlers.render_post.append(mon_handler)
bpy.app.handlers.depsgraph_update_post.append(mon_handler)
Timers import bpy
def mon_timer ():
print ("Timer tick..." )
return 0.5
bpy.app.timers.register(mon_timer)
Types de Handlers Handler Quand frame_change_pre/postAvant/après changement de frame render_init/complete/cancelRendu load_pre/postChargement fichier .blend save_pre/postSauvegarde .blend depsgraph_update_pre/postMise à jour du graphe object_updatedObjet modifié version_updatedMise à jour de version
Exemples de Scripts Utiles
import bpy
for obj in bpy.context.scene.objects:
obj.select_set(True )
bpy.ops.object .transform_apply(location=False , rotation=True , scale=True )
import bpy, os
out = "exports/"
os.makedirs(out, exist_ok=True )
for obj in bpy.data.objects:
bpy.context.view_layer.objects.active = obj
bpy.ops.object .select_all(action='DESELECT' )
obj.select_set(True )
bpy.ops.wm.obj_export(filepath=f"{out} /{obj.name} .obj" )
import bpy, math
obj = bpy.context.active_object
for frame in range (0 , 100 ):
bpy.context.scene.frame_set(frame)
obj.rotation_euler.z = frame * math.radians(3.6 )
obj.keyframe_insert(data_path="rotation_euler" , index=2 )
Débogage
for prop in dir (bpy.context.object ):
if not prop.startswith('_' ):
print (f"{prop} : {getattr (bpy.context.object , prop)} " )
for collection in bpy.data.collections:
print (f"Collection: {collection.name} " )
for obj in collection.objects:
print (f" {obj.name} ({obj.type } )" )
print ([op for op in dir (bpy.ops) if not op.startswith('_' )])
print (bpy.ops.mesh.primitive_cube_add.get_rna().properties)
Pitfalls
bpy n'existe pas en dehors de Blender — tester avec blender --python
bpy.ops échoue en background — certains ops nécessitent un contexte (area)
Scale non uniforme + Modifier — object.scale = (1, 1, 1) avant modificateurs
BMesh non libéré — bm.free() ou fuite mémoire
Context incorrect — passer {'area': ...} ou utiliser override
Blender API changes — Python API change entre versions majeures
Redraw manuel — bpy.context.area.tag_redraw() après changement UI
Add-on non enregistré — bpy.utils.register_class() oublié
Voir Aussi
blender-modeling — Automatisation de modélisation
blender-animation — Scripts d'animation
blender-geometry-nodes — Scripts pour créer/modifier des GN