見出し画像

[Blender][script]カメラ画角内に必要な情報を表示させる(250124更新)

出力するムービーにレンズ等の情報を入れる機能は標準でもありますが、これがまったく融通が効かないのでスクリプトで。

今回はフォーカルレングスとファイル名、カレントフレーム、スタートエンドフレームを自由な場所に入れる様にしました。

後述のスクリプトをテキストエディタで実行するとテキストオブジェクトが出るので、画角内に貼り付けます。
下記が貼り付ける方法。

これだけだとシーンを開きなおした時にフォーカルの自動更新がされなくなってしまうので、テキストエディタで実行するスクリプトの「登録」をオンにしておきます。

こうするとシーンを開きなおしてもフォーカルレングスが自動更新されます。

フォーカルレングスのテキストオブジェクトを作るスクリプト

import bpy
import os

# テキストオブジェクトの設定
def setup_text_overlay():
    # テキストオブジェクトを取得または新規作成
    if "FocalLengthText" not in bpy.data.objects:
        text_data = bpy.data.curves.new(name="FocalLengthText", type='FONT')
        text_obj = bpy.data.objects.new(name="FocalLengthText", object_data=text_data)
        bpy.context.collection.objects.link(text_obj)
        # 位置やスケールを初期化
        text_obj.scale = (0.1, 0.1, 0.1)
        text_obj.location = (0, 0, 5)  # カメラの正面など適切な位置に配置
    else:
        text_obj = bpy.data.objects["FocalLengthText"]

    return text_obj

# フレームごとにフォーカルレングスを更新
def update_text_overlay(scene):
    camera = scene.camera
    if not camera:
        return

    focal_length = camera.data.lens
    text_obj = bpy.data.objects.get("FocalLengthText")
    if text_obj:
        text_obj.data.body = f"{focal_length:.2f}mm"

# ハンドラを登録
def register_handlers():
    # すでに登録されていない場合のみ登録
    if update_text_overlay not in bpy.app.handlers.frame_change_pre:
        bpy.app.handlers.frame_change_pre.append(update_text_overlay)

# Blendファイルをロードしたときの処理
def on_load(dummy):
    # テキストオブジェクトをセットアップ
    setup_text_overlay()
    # ハンドラを再登録
    register_handlers()

# 初期設定
def initialize():
    # テキストオブジェクトをセットアップ
    setup_text_overlay()
    # ハンドラを登録
    register_handlers()
    # Blendファイルをロードしたときのハンドラを登録
    if on_load not in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.append(on_load)

# 実行
initialize()


今開いている.blendのファイル名をテキストオブジェクトにするスクリプト

import bpy
import os

# テキストオブジェクトをセットアップ
def setup_filename_overlay():
    # テキストオブジェクトを取得または新規作成
    if "FileNameText" not in bpy.data.objects:
        # 新しいテキストオブジェクトを作成
        text_data = bpy.data.curves.new(name="FileNameText", type='FONT')
        text_obj = bpy.data.objects.new(name="FileNameText", object_data=text_data)
        bpy.context.collection.objects.link(text_obj)
        # テキストオブジェクトの位置やスケールを調整
        text_obj.scale = (0.1, 0.1, 0.1)
        text_obj.location = (0, 0, 0)  # 必要に応じてカメラの正面に配置
    else:
        text_obj = bpy.data.objects["FileNameText"]

    # 初期テキストを設定
    update_filename_overlay()

# Blendファイル名を更新
def update_filename_overlay(dummy=None):
    # 現在のBlendファイル名を取得
    filepath = bpy.data.filepath
    filename = os.path.basename(filepath) if filepath else "Untitled.blend"

    # テキストオブジェクトに反映
    text_obj = bpy.data.objects.get("FileNameText")
    if text_obj:
        text_obj.data.body = f"{filename}"

# ハンドラを登録
def register_handlers():
    # 保存後の処理
    if update_filename_overlay not in bpy.app.handlers.save_post:
        bpy.app.handlers.save_post.append(update_filename_overlay)

    # ロード後の処理
    if update_filename_overlay not in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.append(update_filename_overlay)

# 初期設定
def initialize():
    # テキストオブジェクトのセットアップ
    setup_filename_overlay()
    # ハンドラの登録
    register_handlers()

# 実行
initialize()


カレントフレームのテキストオブジェクトを作るスクリプト

import bpy

# テキストオブジェクトをセットアップ
def setup_frame_overlay():
    # テキストオブジェクトを取得または新規作成
    if "FrameText" not in bpy.data.objects:
        # 新しいテキストオブジェクトを作成
        text_data = bpy.data.curves.new(name="FrameText", type='FONT')
        text_obj = bpy.data.objects.new(name="FrameText", object_data=text_data)
        bpy.context.collection.objects.link(text_obj)
        # テキストオブジェクトの位置やスケールを調整
        text_obj.scale = (0.1, 0.1, 0.1)
        text_obj.location = (1, 0, 0)  # 必要に応じてカメラの正面に配置
    else:
        text_obj = bpy.data.objects["FrameText"]

    # 初期テキストを設定
    update_frame_overlay()

# カレントフレームを更新
def update_frame_overlay(scene=None):
    # 現在のカレントフレームを取得
    current_frame = bpy.context.scene.frame_current

    # フレーム数を4桁にパディング
    padded_frame = str(current_frame).zfill(4)
 
    # テキストオブジェクトに反映
    text_obj = bpy.data.objects.get("FrameText")
    if text_obj:
        text_obj.data.body = f"F:{padded_frame}"

# ハンドラを登録
def register_frame_handler():
    # フレーム変更時の処理
    if update_frame_overlay not in bpy.app.handlers.frame_change_pre:
        bpy.app.handlers.frame_change_pre.append(update_frame_overlay)

# 初期設定
def initialize():
    # テキストオブジェクトのセットアップ
    setup_frame_overlay()
    # ハンドラの登録
    register_frame_handler()

# 実行
initialize()


スタートフレーム、エンドフレームのテキストオブジェクトを作るスクリプト

import bpy

# テキストオブジェクトをセットアップ
def setup_frame_range_overlay():
    # テキストオブジェクトを取得または新規作成
    if "FrameRangeText" not in bpy.data.objects:
        # 新しいテキストオブジェクトを作成
        text_data = bpy.data.curves.new(name="FrameRangeText", type='FONT')
        text_obj = bpy.data.objects.new(name="FrameRangeText", object_data=text_data)
        bpy.context.collection.objects.link(text_obj)
        # テキストオブジェクトの位置やスケールを調整
        text_obj.scale = (0.1, 0.1, 0.1)
        text_obj.location = (1, -1, 0)  # 必要に応じて位置を調整
    else:
        text_obj = bpy.data.objects["FrameRangeText"]

    # 初期テキストを設定
    update_frame_range_overlay()

# スタートフレームとエンドフレームの更新
def update_frame_range_overlay():
    # シーンのスタートフレームとエンドフレームを取得
    scene = bpy.context.scene
    start_frame = scene.frame_start
    end_frame = scene.frame_end

    # 4桁パディングにフォーマット
    start_frame_str = f"{start_frame:04}"
    end_frame_str = f"{end_frame:04}"

    # テキストオブジェクトに反映
    text_obj = bpy.data.objects.get("FrameRangeText")
    if text_obj:
        text_obj.data.body = f"[{start_frame_str}-{end_frame_str}]"

# デプスグラフの更新時にフレーム範囲を監視
def depsgraph_update_handler(scene):
    # フレーム範囲が変更された場合のみ更新
    start_frame = scene.frame_start
    end_frame = scene.frame_end

    # 前回の値と比較
    if not hasattr(depsgraph_update_handler, "previous_start"):
        depsgraph_update_handler.previous_start = start_frame
        depsgraph_update_handler.previous_end = end_frame

    if start_frame != depsgraph_update_handler.previous_start or end_frame != depsgraph_update_handler.previous_end:
        update_frame_range_overlay()
        depsgraph_update_handler.previous_start = start_frame
        depsgraph_update_handler.previous_end = end_frame

# ハンドラの登録
def register_handlers():
    if depsgraph_update_handler not in bpy.app.handlers.depsgraph_update_post:
        bpy.app.handlers.depsgraph_update_post.append(depsgraph_update_handler)

# 初期化関数
def initialize():
    # テキストオブジェクトのセットアップ
    setup_frame_range_overlay()
    # ハンドラの登録
    register_handlers()

# 実行
initialize()

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