はじめてのBlenderアドオン開発
Last Update: 2023.3.1
Blender 2.7
はじめてのBlenderアドオン開発
Blender 2.7
Last Update: 2023.3.1
2-6. ショートカットキーを割り当てる
Blender本体の機能やアドオンの中には、ショートカットキーを割り当てることで頻繁に使う機能を素早く行えるようにできるものがあります。 例えば、[3Dビュー] エリアのメニューである [オブジェクト] > [トランスフォーム] > [移動] で実行される機能には [G] キーが割り当てられてます。 Blenderの機能と同様、個人で作成した機能にもショートカットキーを割り当てることができます。 本節では 2-4節 で紹介したサンプルを改良し、アドオンの機能にショートカットキーを割り当てる方法を紹介します。
1-5節 を参考にして以下のソースコードを入力し、ファイル名を sample_2_6.py
として保存してください。
import bpy
from bpy.props import FloatVectorProperty, EnumProperty
from mathutils import Vector
bl_info = {
"name": "サンプル2-6: オブジェクトを複製するアドオン",
"author": "Nutti",
"version": (2, 0),
"blender": (2, 75, 0),
"location": "3Dビュー > オブジェクト, Ctrl + Alt + R",
"description": "選択したオブジェクトを複製するアドオン",
"warning": "",
"support": "TESTING",
"wiki_url": "",
"tracker_url": "",
"category": "Object"
}
addon_keymaps = [] # 登録したショートカットキー一覧
# EnumPropertyで表示したい項目リストを作成する関数
def location_list_fn(scene, context):
items = [
('3D_CURSOR', "3Dカーソル", "3Dカーソル上に配置します"),
('ORIGIN', "原点", "原点に配置します")]
items.extend([
('OBJ_' + o.name, o.name, "オブジェクトに配置します")
for o in bpy.data.objects
])
return items
# 選択したオブジェクトを複製するアドオン
class ReplicateObject(bpy.types.Operator):
bl_idname = "object.replicate_object"
bl_label = "選択オブジェクトの複製"
bl_description = "選択中のオブジェクトを複製します"
bl_options = {'REGISTER', 'UNDO'}
location = EnumProperty(
name="配置位置",
description="複製したオブジェクトの配置位置",
items=location_list_fn
)
scale = FloatVectorProperty(
name="拡大率",
description="複製したオブジェクトの拡大率を設定します",
default=(1.0, 1.0, 1.0),
subtype='XYZ',
unit='LENGTH'
)
rotation = FloatVectorProperty(
name="回転角度",
description="複製したオブジェクトの回転角度を設定します",
default=(0.0, 0.0, 0.0),
subtype='AXISANGLE',
unit='ROTATION'
)
offset = FloatVectorProperty(
name="オフセット",
description="複製したオブジェクトの配置位置からのオフセットを設定します",
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION',
unit='LENGTH'
)
def execute(self, context):
# bpy.ops.object.duplicate()実行後に複製オブジェクトが選択されるため、選択中のオブジェクトを保存
src_obj_name = context.active_object.name
bpy.ops.object.duplicate()
active_obj = context.active_object
# 複製したオブジェクトを配置位置に移動
if self.location == '3D_CURSOR':
# Shallow copyを避けるため、copy()によるDeep copyを実行
active_obj.location = context.scene.cursor_location.copy()
elif self.location == 'ORIGIN':
active_obj.location = Vector((0.0, 0.0, 0.0))
elif self.location[0:4] == 'OBJ_':
objs = bpy.data.objects
active_obj.location = objs[self.location[4:]].location.copy()
# 複製したオブジェクトの拡大率を設定
active_obj.scale.x = active_obj.scale.x * self.scale[0]
active_obj.scale.y = active_obj.scale.y * self.scale[1]
active_obj.scale.z = active_obj.scale.z * self.scale[2]
# 複製したオブジェクトの回転角度を設定
rot_euler = active_obj.rotation_euler
active_obj.rotation_euler.x = rot_euler.x + self.rotation[0]
active_obj.rotation_euler.y = rot_euler.y + self.rotation[1]
active_obj.rotation_euler.z = rot_euler.z + self.rotation[2]
# 複製したオブジェクトの最終位置を設定
active_obj.location = active_obj.location + Vector(self.offset)
self.report({'INFO'}, "サンプル2-6: 「%s」を複製しました。" % (src_obj_name))
print("サンプル2-6: オペレーション「%s」が実行されました。" % (self.bl_idname))
return {'FINISHED'}
def menu_fn(self, context):
self.layout.separator()
self.layout.operator(ReplicateObject.bl_idname)
def register_shortcut():
wm = bpy.context.window_manager
kc = wm.keyconfigs.addon
if kc:
# 3Dビューのショートカットキーとして登録
km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
# ショートカットキーの登録
kmi = km.keymap_items.new(
idname=ReplicateObject.bl_idname,
type="R",
value="PRESS",
shift=False,
ctrl=True,
alt=True
)
# ショートカットキー一覧に登録
addon_keymaps.append((km, kmi))
def unregister_shortcut():
for km, kmi in addon_keymaps:
# ショートカットキーの登録解除
km.keymap_items.remove(kmi)
# ショートカットキー一覧をクリア
addon_keymaps.clear()
def register():
bpy.utils.register_module(__name__)
bpy.types.VIEW3D_MT_object.append(menu_fn)
register_shortcut()
print("サンプル2-6: アドオン「サンプル2-6」が有効化されました。")
def unregister():
unregister_shortcut()
bpy.types.VIEW3D_MT_object.remove(menu_fn)
bpy.utils.unregister_module(__name__)
print("サンプル2-6: アドオン「サンプル2-6」が無効化されました。")
if __name__ == "__main__":
register()
1-5節 を参考に作成したアドオンを有効化すると、コンソールウィンドウに以下の文字列が出力されます。
サンプル2-6: アドオン「サンプル2-6」が有効化されました。
[3Dビュー] エリア上でオブジェクトを選択し、[ctrl] + [alt] + [R] キーを押すと、[3Dビュー] エリアのメニューである [オブジェクト] > [選択オブジェクトの複製] を実行した時と同じく、選択されたオブジェクトが複製されます。
オブジェクト [Cube] を選択して [ctrl] + [alt] + [R] キーを押した時の様子を示しています。
1-5節 を参考にアドオンを無効化すると、コンソールウィンドウに以下の文字列が出力されます。
サンプル2-6: アドオン「サンプル2-6」が無効化されました。
ショートカットキーの割り当ては、register_shortcut
関数で行います。
def register_shortcut():
wm = bpy.context.window_manager
kc = wm.keyconfigs.addon
if kc:
# 3Dビューのショートカットキーとして登録
km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
# ショートカットキーの登録
kmi = km.keymap_items.new(
idname=ReplicateObject.bl_idname,
type="R",
value="PRESS",
shift=False,
ctrl=True,
alt=True
)
# ショートカットキー一覧に登録
addon_keymaps.append((km, kmi))
bpy.context.window_manager.keyconfigs.addon.keymaps
はアドオンに割り当てられているキーマップです。
keymaps.new
関数を実行することで、新たにキーマップを割り当てることができます。 本節のサンプルは keymaps.new
関数に、以下に示す引数を指定してキーマップを割り当てます。
引数 | 値の意味 |
---|---|
name |
キーマップ名 |
space_type |
キーマップを割り当てるエリア名 |
km.keymap_items.new
関数を使い、新しく割り当てたキーマップにショートカットキーを登録します。 km.keymap_items.new
関数に指定する引数は以下の通りです。
引数 | 値の意味 |
---|---|
idname |
イベント発生時に実行する処理を記述した、オペレータクラスの bl_idname |
type |
イベントを発生させるキーボードのキー |
value |
イベント発生の条件値 |
shift |
イベント発生のためにshiftキーが押されている必要がある時は True |
ctrl |
イベント発生のためにctrlキーが押されている必要がある時は True |
alt |
イベント発生のためにaltキーが押されている必要がある時は True |
本節のサンプルは、[shift] + [ctrl] + [R] キーが押された時にイベントを発生させ、オブジェクトの複製の処理をイベント発生時に実行するように引数を指定しています。 イベント発生時に引数 idname
に指定した処理を実行しますが、引数 value
には例えば以下のようなイベントを発生する時の条件値を指定できます。
イベント値 | 値の意味 |
---|---|
PRESS |
ボタンを押した時にイベントを発生させる |
RELEASE |
ボタンを離した時にイベントを発生させる |
ANY |
ボタンの状態に何かしら変更があった時にイベントを発生させる |
NOTHING |
イベントを発生させない |
最後に、割り当てたキーマップとショートカットキーのペアをグローバル変数 addon_keymaps
に保存します。 この変数はアドオン無効化時に、割り当ててたショートカットキーを削除するために必要になります。
アドオン内で登録したショートカットキーは、アドオン無効化時に割り当てを解除する必要があります。
ショートカットキーの割り当て解除は、unregister_shortcut
関数で行います。
def unregister_shortcut():
for km, kmi in addon_keymaps:
# ショートカットキーの登録解除
km.keymap_items.remove(kmi)
# ショートカットキー一覧をクリア
addon_keymaps.clear()
アドオン有効化時にグローバル変数 addon_keymaps
に保存したキーマップを、keymap_items.remove
関数の引数に指定して実行することで、ショートカットキーのペアを削除します。
そして最後に、キーマップとショートカットキーのペアを保存したグローバル変数 addon_keymaps
をクリアします。
Blenderでは既に多くの機能にショートカットキーが割当てられているため、単一のキーの中からショートカットキーとして何も割当たっていないキーを探すのは意外と大変です。 このため、ctrlキーやshiftキー、altキーとの組み合わせたショートカットキーを割り当てる ことも検討しましょう。 これらのキーと組み合わせることで、既に割り当てられているキーと被る可能性を低くすることができ、より簡単に空いているキーを見つけることができると思います。 本節のサンプルでも、ctrlキーやaltキーを組み合わせたショートカットキーを登録しています。
割り当てるショートカットキーは、ショートカットキーを割り当てる機能を簡単に推測できる ようなものにしましょう。 ショートカットキーを割り当てる機能であるオブジェクトの複製は英訳するとReplicate Objectになるため、本節のサンプルでは英訳の頭文字を取って [R] キーを割り当てています。
2-4節 を改造し、[3Dビュー] エリアのメニューである [オブジェクト] > [選択オブジェクトの複製] にショートカットキーを割り当て、ショートカットキーからアドオンの機能を実行できるようにしました。 ショートカットキーを機能に割り当てることで、ユーザが機能を素早く利用できるようになります。
頻繁に使う機能に対してショートカットキーを割り当てることは、アドオンの利便性の改善に繋がる可能性があります。 一方、ショートカットキーに設定できる組み合わせには限りがあるため、ショートカットキーを乱用してユーザが利用可能なショートカットキーを減らしてしまうことは良いとは言えません。
アドオンを様々な人に使ってもらうことを考えている場合は、ショートカットキーを設定することでユーザの利便性が本当に向上するのかを検討してから設定すべき です。 個人的に利用するアドオンではない限り、試しにショートカットキーを割り当てたとか、とりあえず割り当てとけば良い程度の判断でショートカットキーを設定すべきではありません。
bpy.context.window_manager.keyconfigs.addon.keymaps.new
関数を実行することにより割り当てることができるkm
に対して km.keymap_items.new
関数を実行することにより割り当てることができる