テキストベースでBlenderを操作する上で、便利な設定を盛り込んだ環境の初期化方法の一例を紹介します。
初期化後、マウスとショートカットを用いて操作することを前提にしてないので、実行毎に環境が全初期化される構成になっています。環境の全初期化が必要ない場合は必要な設定項目だけ抜き出しての使用を検討してみてください。
動作確認環境 : Blender 4.2
bpyを使い始める前のBlender設定項目
ここでは簡単にbpyを使い始める前のBlenderの設定方法についてまとめておきます。
少し調べたらたくさん出てくるので、こちらで把握できていないような便利な設定項目について調べてみてください。
【設定】
「Edit」→「Preferences」→「Interface」Display
- 「Line Width」→「Developer Extras」
- 「Tooltips」→「Python Tooltips」
3D View画面中の「Overlays」(上画像)「Statistics」のチェックマークを有効にする(必須ではない)
【Python実行用設定】
■ Text Editorの開き方
上記画像のようなエリアの左上隅にあるエリアタイプ選択メニュー(アイコン)をクリックし表示されるメニューから「Text Editor」を開く
【bpyコードと操作の対応確認】
bpyで操作に対応するAPIが分からなくなった場合、Infoエディタで操作を確認します。
■ Infoエディタ開き方
上記画像のようなエリアの左上隅にあるエリアタイプ選択メニュー(アイコン)をクリックし表示されるメニューから「Info」を開く
■ 設定を含めたBlenderの環境保存
色々設定したのちに、次回起動時に設定が残るように
「File」→「Defaults」→「Save Setup File」
テキストベース操作に便利な初期化設定(bpy)
bpyを用いていくつかの環境設定および初期化処理についてもテキストの形で残します。
ここで紹介する実装内で行っている処理は次のようになっています。
- 3D View表示設定
- オブジェクト削除
- コンテキスト削除
- テクスチャ削除
- マテリアル削除
- ファイル削除
- 操作設定
- 未使用アイテム削除
- Pythonの実行毎に毎回環境を初期化
- モデリング実行
- マテリアル&UV展開実行
実際の実装は以下です。便利な設定を見つけ次第機能を拡張していきます。
Python:
import bpy
import math
# Blender 環境初期化
def bpy_modeling_initialize_common():
override = get_override('VIEW_3D', 'WINDOW')
update_3d_view_overlay()
preferences_setting()
set_initial_dev()
set_3d_cursor_position()
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
# 拡大縮小時の視認距離設定
space.clip_start = 0.0001
return override
# Blender環境初期化
def set_initial_dev():
# アクティブオブジェクト確認
if bpy.context.active_object is None:
# オブジェクトがない場合->キューブ追加
bpy.ops.mesh.primitive_cube_add()
# モード切替
bpy.ops.object.mode_set(mode='OBJECT')
# ------------------------------------------------------------------
# - Delete all objects in the scene
# ------------------------------------------------------------------
# 全オブジェクト選択
bpy.ops.object.select_all(action='SELECT')
# 全オブジェクト削除
bpy.ops.object.delete(use_global=False)
# 全オブジェクト取得
all_objects = bpy.data.objects
# 非表示状態オブジェクト削除
for obj in all_objects:
bpy.data.objects.remove(obj)
# 未使用アイテム削除
rm_nonused_all_items()
# 全コレクション削除
for collection in bpy.data.collections:
bpy.data.collections.remove(collection)
# 初期状態整理
# デフォルトコレクション作成
new_collection = bpy.data.collections.new(name="Collection")
# コレクションをシーンにリンク
bpy.context.scene.collection.children.link(new_collection)
# カメラ追加
bpy.ops.object.camera_add(
location=(7, -7, 5)
, rotation=(math.radians(63), math.radians(0), math.radians(47))
, scale=(1, 1, 1)
)
# カメラに名前設定
bpy.context.object.name = "MyCamera_001"
# Light追加
bpy.ops.object.light_add(
type='POINT' # 'POINT':点光源 , 'SUN':平行光源, 'SPOT':スポットライト, 'AREA':面光源
, location=(4, 1, 6)
, scale=(1, 1, 1)
)
# ライトに名前設定
bpy.context.object.name = "MyPointLight_001"
# 全オブジェクトの選択解除
bpy.ops.object.select_all(action='DESELECT')
set_xray_view(key="OFF")
# コンテキストのオーバーライド用辞書取得
def get_override(area_type, region_type):
for area in bpy.context.screen.areas:
if area.type == area_type:
for region in area.regions:
if region.type == region_type:
override = {'area': area, 'region': region}
return override
# エラーメッセージ
raise RuntimeError(f"Wasn't able to find {region_type} in area {area_type}. Make sure it's open while executing script.")
# Blender設定
def update_3d_view_overlay():
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
space = area.spaces.active
area.spaces.active.show_gizmo_object_translate = True # 移動ギズモ表示
if space.type == 'VIEW_3D':
overlay = space.overlay # オーバーレイ設定取得
overlay.show_edge_crease = True # エッジのクリース(強調されたエッジ)表示
overlay.show_face_center = False # 面中心表示
overlay.show_face_normals = False # 面法線表示
overlay.show_vertex_normals = False # 頂点法線表示
overlay.show_edge_seams = True # エッジシーム(接合部表示)
overlay.show_extra_indices = True # インデックス表示
overlay.show_face_orientation = True# 面の向き表示
print("Overlay settings updated.")
return
print("No 3D View area found.")
# preference設定
def preferences_setting():
# Orbit Around Selection
bpy.context.preferences.inputs.use_rotate_around_active = True
# Depthオプション有効化
bpy.context.preferences.inputs.use_zoom_to_mouse = True
# Smooth View(スムースビュー)時間(ミリ秒単位)
bpy.context.preferences.view.smooth_view = 200
# ギズモの種類設定
# LOCAL / GLOBAL / NORMAL etc.
bpy.context.scene.transform_orientation_slots[1].type = 'NORMAL'
# Shift + C(カーソル位置初期化)
def set_3d_cursor_position(position_list=[0, 0, 0]):
# 3Dカーソル位置->原点
bpy.context.scene.cursor.location = (position_list[0], position_list[1], position_list[2])
# View更新
bpy.context.view_layer.update()
# 未使用/使用アイテム削除
def rm_nonused_all_items():
# 未使用メッシュデータブロック削除
for mesh in bpy.data.meshes:
if not mesh.users:
bpy.data.meshes.remove(mesh)
# 未使用テクスチャデータブロック削除
for texture in bpy.data.textures:
if not texture.users:
bpy.data.textures.remove(texture)
# 未使用テクスチャデータブロック削除
for texture in bpy.data.lights:
if not texture.users:
bpy.data.lights.remove(texture)
# 未使用テクスチャデータブロック削除
for texture in bpy.data.cameras:
if not texture.users:
bpy.data.cameras.remove(texture)
# 未使用マテリアル削除
for material in bpy.data.materials:
if not material.users:
bpy.data.materials.remove(material)
# 使用マテリアル削除
for material in bpy.data.materials:
bpy.data.materials.remove(material)
# 画像データ削除
for img in bpy.data.images:
bpy.data.images.remove(img)
# 透過ビューのON/OFF
def set_xray_view(key="ON"):
if (key == "ON"):
# 透過表示ON
# 3Dビューエリア取得
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
# 透過表示(X-ray)設定ON
space.shading.show_xray = True
# X-ray強度設定(デフォルト1.0)
space.shading.xray_alpha = 0.5
break
else:
# 透過表示オフ
# 3Dビューエリア取得
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
# 透過表示(X-ray)設定OFF
space.shading.show_xray = False
# X-ray強度設定(デフォルト1.0)
space.shading.xray_alpha = 0.5
break
Python:
# 実行方法
override = bpy_modeling_initialize_common()
この処理を実行すると、限りなく環境がまっさらな状態になりカメラとポイントライトだけがオブジェクトとして存在する状態になります。
初期化処理使用例
上で紹介した初期化処理を入れておくと、常に同じ初期状態からモデリングおよびマテリアル追加の処理が可能になるため、作業が進むごとに変化していく状態に対してコードを対応させる必要が無くなります。
以下が初期化処理を盛り込んだ実行例です。
何度「Run Script」ボタンを押しても、常に同じ状態から処理がスタートして立方体が3Dオブジェクトとして追加されることが分かるかと思います。
Python:
# bpy modeling env initialize
override = bpy_modeling_initialize_common()
# ==================================================================
# = Main Code
# ==================================================================
def Room_Base_create():
# Mode 切り替え
bpy.ops.object.mode_set(mode='OBJECT')
# 立方体生成
bpy.ops.mesh.primitive_cube_add(
size=1
, location=(0, 0, 0)
, scale=(1,1,1)
)
bpy.context.object.name = "MyCube_001"
Room_Base_create()
以上