0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Blenderスクリプト]ログを全消去するスクリプト

Last updated at Posted at 2025-08-30

はじめに

アドオン開発をしているとInfo(情報)ウインドウのログを全消去したいときがあるのですが、ワンボタンでできないのでスクリプトで実現しました。
記事後半にはボタンを実装したアドオン用コードもあります。

ウインドウではなくエリアと言った方がコード的に合っていますが、分かりやすさからウインドウを使っています。

テキストエディターから実行する場合

テキストエディターで実行してください。
import bpy

# 全ウインドウを調べて "INFO" (情報)ウインドウを見つける
# 全ウインドウを調べないと、INFOを独立ウインドウにしていた時に特定できない
for window in bpy.context.window_manager.windows:
    screen = window.screen
    for area in screen.areas:
        if area.type == 'INFO':
            # INFOの WINDOW(ログが表示される場所(region)) を対象とした処理
            # INFOを特定できれば region の指定が無くても動くが、あった方が堅牢
            for region in area.regions:
                if region.type == 'WINDOW':
                    # temp_override により一時的にコンテキストを切り替え
                    with bpy.context.temp_override(window=window, area=area, region=region):
                        # ログを全選択
                        bpy.ops.info.select_all(action='SELECT')
                        # 選択したログを削除
                        bpy.ops.info.report_delete()

オペレーター識別子の調べ方

bpy.ops.info.select_all(action='SELECT')bpy.ops.info.report_delete()は英語版のプリファレンスから調べられます。
bpy.ops.info.select_allは選択解除も兼ねているため、(action='SELECT')が必要というわけですね。

01.jpg

最初にINFO (情報)ウインドウを特定する理由

他の処理は無くしてbpy.ops.info.select_all(action='SELECT')bpy.ops.info.report_delete()だけを実行するシンプル処理で動きそうな気がしますがエラーが出ます。

RuntimeError: Operator bpy.ops.info.select_all.poll() failed, context is incorrect

bpy.ops.info.select_all(action='SELECT')bpy.ops.info.report_delete()area.type == 'INFO'でしか動きませんが、処理を実行するウインドウはテキストエディタなため、まずInfoで処理を進める工程が必要です。

アドオンとしてインストールしてボタン押下やショートカットキーで実行する場合

ディレクトリ構成

ディレクトリ構成(これらをzip化してインストール)
Info log Clear(任意のフォルダ名)
  ∟  __init__.py

アドオンのコード

__init__.py
bl_info = {
    "name": "Info log Clear 情報ログ全消去",
    "blender": (4, 0, 0),
    "description": "Info(情報)ログを全消去するボタン。ショートカット名は「Info(情報)ログ全消去」。",
    "category": "Interface",
}

import bpy
from bpy.types import Operator


# --- 共通ロジック ---
def _clear_reports():
    bpy.ops.info.select_all(action="SELECT")
    bpy.ops.info.report_delete()


def _info_window_region(area):
    for r in area.regions:
        if r.type == "WINDOW":
            return r


# --- ヘッダーボタン用 ---
class INFO_OT_clear_in_area(Operator):
    bl_idname = "info.clear_in_area"  # オペレーターID
    bl_label = "Info(情報)ログ全消去(Infoエリアのボタンから実行用)"  # ショートカットキーのラベル
    bl_description = "ログを全消去します"  # マウスホバーしたときに表示される説明

    # Infoかどうか確認
    @classmethod
    def poll(cls, context):
        return context.area and context.area.type == "INFO"

    # Infoのheader(上のメニューバー)のボタンから実行するため、全ウインドウからINFOを探す処理は割愛
    def invoke(self, context, _event=None):
        a = context.area
        r = _info_window_region(a)
        if not r:
            return {"CANCELLED"}
        with context.temp_override(window=context.window, area=a, region=r):
            _clear_reports()
        return {"FINISHED"}


# --- ショートカットキー用 ---
class WM_OT_info_clear_global(Operator):
    bl_idname = "wm.info_clear_global"
    bl_label = "Info(情報)ログ全消去"
    bl_description = "Info(情報)ログを全消去します"

    # グローバルで実行されるため、まず全ウインドウからINFOを探す処理を行う
    def execute(self, _):
        done = 0
        for w in bpy.context.window_manager.windows:
            for a in w.screen.areas:
                if a.type != "INFO":
                    continue
                r = _info_window_region(a)
                if not r:
                    continue
                with bpy.context.temp_override(window=w, area=a, region=r):
                    _clear_reports()
                    done += 1
        return {"CANCELLED"} if done == 0 else {"FINISHED"}


# --- ヘッダーにボタン追加 ---
def _draw_info_header(self, _ctx):
    layout = self.layout
    layout.separator_spacer()  # 右寄せ
    layout.operator(INFO_OT_clear_in_area.bl_idname, text="全消去", icon="TRASH")


# --- wm.info_clear_globalをショートカットキー登録(Ctrl+Alt+A) ---
_keymaps = []

# --- 登録 ---
def register():
    for c in (INFO_OT_clear_in_area, WM_OT_info_clear_global):
        bpy.utils.register_class(c)
    bpy.types.INFO_HT_header.append(_draw_info_header)

    kc = bpy.context.window_manager.keyconfigs.addon
    if kc:
        km = kc.keymaps.new(name="Window", space_type="EMPTY", region_type="WINDOW")
        kmi = km.keymap_items.new(
            "wm.info_clear_global", "A", "PRESS", ctrl=True, alt=True
        )
        _keymaps.append((km, kmi))


def unregister():
    kc = bpy.context.window_manager.keyconfigs.addon
    if kc:
        for km, kmi in _keymaps:
            km.keymap_items.remove(kmi)
        _keymaps.clear()

    # INFO_HT_header からの削除
    bpy.types.INFO_HT_header.remove(_draw_info_header)

    for c in (WM_OT_info_clear_global, INFO_OT_clear_in_area):
        bpy.utils.unregister_class(c)


if __name__ == "__main__":
    register()

Infoウインドウ特定処理の有無

Infoのヘッダーボタンから実行する場合は、保険としてInfoかどうか検証するものの、context.areaで処理を開始できます。
ショートカットキーの場合はどこで発動されても動くようにまずInfoを特定します。

ヘッダーボタン、ショートカットキー共にショートカットキー用処理を使っても負荷は無視できる範囲ですが、今回は分けてみました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?