見出し画像

[Blender][Script]ドープシートでアクティブなチャンネルのキーを選択する

以前のスクリプトの拡張版です。

選択する対象がグリースペンシルレイヤーのみだったのを、アクティブなアクションチャンネルにも働く様にして、サイドバーにボタンを設けました。
アクティブなアクションチャンネル又はレイヤーのキー全部、カレントフレーム以前、以降を選択できます。(サムネール参照)
既に選択中のキーはそのままで追加選択するので、一旦クリアした方が良いかも?
あとグラフエディタにも対応させるかもしれません。

import bpy


class GPENCIL_OT_SelectKeys(bpy.types.Operator):
    """選択操作を実行"""
    bl_idname = "gpencil.select_keys"
    bl_label = "Select Keys"
    bl_options = {'REGISTER', 'UNDO'}

    mode: bpy.props.EnumProperty(
        items=[
            ('ALL', "All Keys", "すべてのキーを選択"),
            ('BEFORE', "Before Current Frame", "カレントフレーム以前のキーを選択"),
            ('AFTER', "After Current Frame", "カレントフレーム以降のキーを選択")
        ],
        name="Mode",
        default='ALL'
    )

    def execute(self, context):
        current_frame = context.scene.frame_current
        count_selected = 0

        # グリースペンシルレイヤーのキーを操作
        gpencil = context.active_object
        if gpencil and gpencil.type == 'GPENCIL':
            for layer in gpencil.data.layers:
                if layer.select:  # アクティブなチャンネルのみ対象
                    for frame in layer.frames:
                        if self.mode == 'ALL':
                            frame.select = True
                        elif self.mode == 'BEFORE' and frame.frame_number <= current_frame:
                            frame.select = True
                        elif self.mode == 'AFTER' and frame.frame_number >= current_frame:
                            frame.select = True
                        count_selected += 1

        # アクティブなアクションのチャンネル(Fカーブ)のキーを操作
        action = context.object.animation_data.action if context.object and context.object.animation_data else None
        if action:
            for fcurve in action.fcurves:
                if fcurve.select:  # 選択されているチャンネルのみ対象
                    for keyframe in fcurve.keyframe_points:
                        if self.mode == 'ALL':
                            keyframe.select_control_point = True
                        elif self.mode == 'BEFORE' and keyframe.co.x <= current_frame:
                            keyframe.select_control_point = True
                        elif self.mode == 'AFTER' and keyframe.co.x >= current_frame:
                            keyframe.select_control_point = True
                        count_selected += 1

        if count_selected > 0:
            self.report({'INFO'}, f"{count_selected} keys selected.")
        else:
            self.report({'WARNING'}, "対象のキーが見つかりませんでした。")

        return {'FINISHED'}


class GPENCIL_PT_SelectKeysPanel(bpy.types.Panel):
    """サイドバーのパネル"""
    bl_label = "Select Keys on Active Channel"
    bl_idname = "GPENCIL_PT_select_keys"
    bl_space_type = 'DOPESHEET_EDITOR'
    bl_region_type = 'UI'
    bl_category = "Custom"

    def draw(self, context):
        layout = self.layout
        row = layout.row(align=True)  # 横並びに配置
        row.scale_x = 5  # ボタン間の間隔を広げる
        row.operator("gpencil.select_keys", text="", icon="BACK").mode = 'BEFORE'
        row.operator("gpencil.select_keys", text="", icon="ARROW_LEFTRIGHT").mode = 'ALL'
        row.operator("gpencil.select_keys", text="", icon="FORWARD").mode = 'AFTER'


def register():
    bpy.utils.register_class(GPENCIL_OT_SelectKeys)
    bpy.utils.register_class(GPENCIL_PT_SelectKeysPanel)


def unregister():
    bpy.utils.unregister_class(GPENCIL_PT_SelectKeysPanel)
    bpy.utils.unregister_class(GPENCIL_OT_SelectKeys)


if __name__ == "__main__":
    register()


いいなと思ったら応援しよう!