Hey #b3d peeps!!
ポーズモードで、選択したボーンの子ボーンをすべて選択します。 アウトライナーのツリー上で、[Ctrl]+[左クリック]して選択出来る機能と同等なので、あまり需要は無いか、と。
コードサンプルなので、「機能として既に存在するか」は気にしないことにします。(もしかしたら3Dビュー上で同じような機能があるのかもしれないのに見つけられていない、というパターンもあり得ます…)
これを使用するには、selectallchilds.py という名前で適当な場所に保存した上で、Add-onを追加、使用可能にする手順を行います。
#!BPY
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
import bpy
bl_info = {
"name": "select all childs bone recursively",
"author": "blugjp",
"blender": (2, 76, 0),
"location": "Command search (Space bar) > Select All Childs Bone",
"description": "Select All Childs Bone",
"warning": "",
"category": "Object",
}
#select all childs bone recursively
def selectchilds_recv(tree_dict,bone):
list = tree_dict[bone.name]
for x in list:
x.select = True
selectchilds_recv(tree_dict,x)
return
def selectallchilds():
arm = bpy.context.active_object
bones = arm.data.bones
#map bone to tree
tree_dict ={ x.name : [] for x in bones}
for x in bones:
p = x.parent
if p != None:
tree_dict[p.name].append(x)
# active_bone
abone = bpy.context.active_bone
#call def
selectchilds_recv(tree_dict,abone)
class DialogOperator(bpy.types.Operator):
bl_idname = "object.dialog_operator"
bl_label = "Information"
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text=bpy.context.scene.clatdialog_message)
class ChildsBoneOperator(bpy.types.Operator):
"""Select All Childs Bone"""
bl_label = "Select All Childs Bone"
bl_idname = "object.select_all_childs_bone"
def execute(self, context):
if bpy.context.mode == 'POSE':
selectallchilds()
else:
bpy.context.scene.clatdialog_message = "Please change the mode to Pose mode."
bpy.ops.object.dialog_operator('INVOKE_DEFAULT')
return {'CANCELLED'}
return {'FINISHED'}
# Registration
def register():
bpy.utils.register_class(ChildsBoneOperator)
bpy.utils.register_class(DialogOperator)
bpy.types.Scene.clatdialog_message =\
bpy.props.StringProperty(name="message", default='')
def unregister():
bpy.utils.unregister_class(ChildsBoneOperator)
bpy.utils.unregister_class(DialogOperator)
del bpy.types.Scene.clatdialog_message
if __name__ == "__main__":
register()
Add-onを有効にしたのち、3Dビュー上で以下の手順を実行します。
ポーズモードにします。
ボーンを選択します。
スペースキーのコマンド検索から”Select All Childs Bone”を検索し、実行します。
実行時、アクティブなボーンが選択状態でない場合(アクティブなボーンを[Shift]+[左クリック]で選択解除した場合等)には、アクティブなボーンは選択されません。 再帰関数を使用していることもあり、ボーンの数が多いとちょっと危ないかもしれません :P
def selectallchilds():
arm = bpy.context.active_object
bones = arm.data.bones
#map bone to tree
tree_dict ={ x.name : [] for x in bones}
for x in bones:
p = x.parent
if p != None:
tree_dict[p.name].append(x)
# active_bone
abone = bpy.context.active_bone
#call def
selectchilds_recv(tree_dict,abone)
Blenderのボーンオブジェクトは、親のボーンを参照出来ますが、子のボーンは参照出来ません。 そのため、親から子を参照する形のツリー構造の辞書型リストを作成します。
最初に選択しているArmatureオブジェクトに含まれるボーン名をキーとします。 それと同時に空の配列を値としてtree_dictに登録します。
全てのボーンについて、親ボーン名が存在する場合にはtree_dictの配列に追加します。
現在アクティブなボーンと作成した辞書型リストを引数にselectchilds_recv関数を呼び出します。
def selectchilds_recv(tree_dict,bone):
list = tree_dict[bone.name]
for x in list:
x.select = True
selectchilds_recv(tree_dict,x)
return
再帰的に選択したボーンの子の選択状態をTrueに変更する関数です。
子ボーンが存在する、すなわち tree_dict で指定ボーンに対応する配列があった場合、配列内のボーンオブジェクトの選択状態をTrueにし、さらにselectchilds_recv関数を呼びます。