見出し画像

[Blender][スクリプト]ビューポートとレンダーの表示非表示を一致させる(240903修正)

サムネールの様にビューポートとレンダーの表示設定が違う時に一致させるスクリプト。
その様なアドオンは既にあるのですが。。

↑はちょっと問題があって、サイドバーから実行するとコレクションには効かない。アウトライナーのフィルター設定から実行するとコレクションにも効くけど、コレクションを含むコレクションには効かない。
なので効くものを。
ビューポートの表示設定が二つ(「ビューポートで隠す」、「ビューポートで無効」)あるので、ちょっとややこしいです。なんで二つあるんでしょうね?
因みにオブジェクトの場合、隠すと無効の違いは、
・「ビューポートで隠す」 キーが打てない。非表示にしても再生が軽くならない。
・「ビューポートで無効」キーが打てる。非表示にすると再生が軽くなる。
という感じでした。
コレクションの場合、いずれもキーが打てません。
なので何かしら自分なりにルールを決めて使わないとカオスになります。なりました。
で、こういったスクリプトが必要だと思いました。場合によって必要な仕様が違うので複数。
(240820)コレクションを含むコレクションには効かない事がある問題を修正

VはViewport。RはRender。
  • V to R:Off
    レンダーをビューポートに合わせてオフ。
    「ビューポートで隠す」と「ビューポートで無効」のどちらかがオフの時、もう一方と、「レンダーで無効」もオフにする。

  • V to R:On
    レンダーをビューポートに合わせてオン。
    「ビューポートで隠す」と「ビューポートで無効」のどちらかがオンの時、もう一方と、「レンダーで無効」もオンにする。

  • R to V:Off
    ビューポートをレンダーに合わせてオフ。
    「レンダーで無効」がオフの時、「ビューポートで隠す」と「ビューポートで無効」もオフにする。

  • R to V:On
    ビューポートをレンダーに合わせてオン。
    「レンダーで無効」がオンの時、「ビューポートで隠す」と「ビューポートで無効」もオンにする。

  • Either:Off
    「ビューポートで隠す」「ビューポートで無効」「レンダーで無効」のいずれかがオフになっていたら全てオフにする。

  • All Off
    全てオフ。
    シーン内の全オブジェクト、コレクションの「ビューポートで隠す」「ビューポートで無効」「レンダーで無効」をオフ。

  • All On
    全てオン。
    シーン内の全オブジェクト、コレクションの「ビューポートで隠す」「ビューポートで無効」「レンダーで無効」をオン。

import bpy

# スクリプト 1: V to R:Off
def run_script_1():
    def sync_viewport_with_render_for_object(obj):
        if obj.hide_get():  # ビューポートで隠す (Object)
            obj.hide_viewport = True  # ビューポートで無効 (Object)
            obj.hide_render = True  # レンダーで無効 (Object)

        if obj.hide_viewport:  # ビューポートで無効 (Object)
            obj.hide_set(True)  # ビューポートで隠す (Object)
            obj.hide_render = True  # レンダーで無効 (Object)
                        
    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if layer_collection.hide_viewport:  # ビューポートで隠す (Collection)
            collection.hide_viewport = True  # ビューポートで無効 (Collection)
            collection.hide_render = True  # レンダーで無効 (Collection)
    
        if collection.hide_viewport:  # ビューポートで無効 (Collection)
            layer_collection.hide_viewport = True  # ビューポートで隠す (Collection)
            collection.hide_render = True  # レンダーで無効 (Collection)
    
        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 2: V to R:On
def run_script_2():
    def sync_viewport_with_render_for_object(obj):
        if not obj.hide_get():  # ビューポートで隠す (Object)
            obj.hide_viewport = False  # ビューポートで無効 (Object)
            obj.hide_render = False  # レンダーで無効 (Object)

        if not obj.hide_viewport:  # ビューポートで無効 (Object)
            obj.hide_set(False)  # ビューポートで隠す (Object)
            obj.hide_render = False  # レンダーで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if not layer_collection.hide_viewport:  # ビューポートで隠す (Collection)
            collection.hide_viewport = False  # ビューポートで無効 (Collection)
            collection.hide_render = False  # レンダーで無効 (Collection)

        if not collection.hide_viewport:  # ビューポートで無効 (Collection)
            layer_collection.hide_viewport = False  # ビューポートで隠す (Collection)
            collection.hide_render = False  # レンダーで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 3: R to V:Off
def run_script_3():
    def sync_viewport_with_render_for_object(obj):
        if obj.hide_render:  # レンダーで無効 (Object)
            obj.hide_set(True)  # ビューポートで隠す (Object)
            obj.hide_viewport = True  # ビューポートで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if collection.hide_render:  # レンダーで無効 (Collection)
            layer_collection.hide_viewport = True  # ビューポートで隠す (Collection)
            collection.hide_viewport = True  # ビューポートで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 4: R to V:On
def run_script_4():
    def sync_viewport_with_render_for_object(obj):
        if not obj.hide_render:  # レンダーで無効 (Object)
            obj.hide_set(False)  # ビューポートで隠す (Object)
            obj.hide_viewport = False  # ビューポートで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if not collection.hide_render:  # レンダーで無効 (Collection)
            layer_collection.hide_viewport = False  # ビューポートで隠す (Collection)
            collection.hide_viewport = False  # ビューポートで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 5: Either:Off
def run_script_5():
    def disable_all_if_any_disabled_for_object(obj):
        if obj.hide_render or obj.hide_viewport or obj.hide_get():  # いずれかが無効
            obj.hide_set(True)  # ビューポートで隠す (Object)
            obj.hide_viewport = True  # ビューポートで無効 (Object)
            obj.hide_render = True  # レンダーで無効 (Object)

    def disable_all_if_any_disabled_for_collection(layer_collection):
        collection = layer_collection.collection
        if collection.hide_render or collection.hide_viewport or layer_collection.hide_viewport:  # いずれかが無効
            layer_collection.hide_viewport = True  # ビューポートで隠す (Collection)
            collection.hide_viewport = True  # ビューポートで無効 (Collection)
            collection.hide_render = True  # レンダーで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            disable_all_if_any_disabled_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        disable_all_if_any_disabled_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    disable_all_if_any_disabled_for_collection(root_layer_collection)

# オペレータークラス定義
class WM_OT_run_script_1(bpy.types.Operator):
    bl_idname = "wm.run_script_1"
    bl_label = "V to R:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 1")
        run_script_1()
        return {'FINISHED'}

class WM_OT_run_script_2(bpy.types.Operator):
    bl_idname = "wm.run_script_2"
    bl_label = "V to R:On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 2")
        run_script_2()
        return {'FINISHED'}

class WM_OT_run_script_3(bpy.types.Operator):
    bl_idname = "wm.run_script_3"
    bl_label = "R to V:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 3")
        run_script_3()
        return {'FINISHED'}

class WM_OT_run_script_4(bpy.types.Operator):
    bl_idname = "wm.run_script_4"
    bl_label = "R to V:On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 4")
        run_script_4()
        return {'FINISHED'}

class WM_OT_run_script_5(bpy.types.Operator):
    bl_idname = "wm.run_script_5"
    bl_label = "Either:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 5")
        run_script_5()
        return {'FINISHED'}

class WM_OT_enable_all(bpy.types.Operator):
    bl_idname = "wm.enable_all"
    bl_label = "All On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Enable All")
        for obj in bpy.context.view_layer.objects:
            obj.hide_set(False)
            obj.hide_viewport = False
            obj.hide_render = False

        root_layer_collection = bpy.context.view_layer.layer_collection
        enable_all_for_collection(root_layer_collection)
        return {'FINISHED'}

def enable_all_for_collection(layer_collection):
    collection = layer_collection.collection
    layer_collection.hide_viewport = False
    collection.hide_viewport = False
    collection.hide_render = False

    for child in layer_collection.children:
        enable_all_for_collection(child)

class WM_OT_disable_all(bpy.types.Operator):
    bl_idname = "wm.disable_all"
    bl_label = "All OFF"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Disable All")
        for obj in bpy.context.view_layer.objects:
            obj.hide_set(True)
            obj.hide_viewport = True
            obj.hide_render = True

        root_layer_collection = bpy.context.view_layer.layer_collection
        disable_all_for_collection(root_layer_collection)
        return {'FINISHED'}

def disable_all_for_collection(layer_collection):
    collection = layer_collection.collection
    layer_collection.hide_viewport = True
    collection.hide_viewport = True
    collection.hide_render = True

    for child in layer_collection.children:
        disable_all_for_collection(child)

# パネルクラス定義
class VIEW3D_PT_custom_panel(bpy.types.Panel):
    bl_label = "Visibility Match"
    bl_idname = "VIEW3D_PT_custom_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Custom'

    def draw(self, context):
        layout = self.layout
        layout.operator("wm.run_script_1")
        layout.operator("wm.run_script_2")
        layout.operator("wm.run_script_3")
        layout.operator("wm.run_script_4")
        layout.operator("wm.run_script_5")
        layout.operator("wm.enable_all")
        layout.operator("wm.disable_all")

# Blenderへの登録
def register():
    bpy.utils.register_class(WM_OT_run_script_1)
    bpy.utils.register_class(WM_OT_run_script_2)
    bpy.utils.register_class(WM_OT_run_script_3)
    bpy.utils.register_class(WM_OT_run_script_4)
    bpy.utils.register_class(WM_OT_run_script_5)
    bpy.utils.register_class(WM_OT_enable_all)
    bpy.utils.register_class(WM_OT_disable_all)
    bpy.utils.register_class(VIEW3D_PT_custom_panel)

def unregister():
    bpy.utils.unregister_class(WM_OT_run_script_1)
    bpy.utils.unregister_class(WM_OT_run_script_2)
    bpy.utils.unregister_class(WM_OT_run_script_3)
    bpy.utils.unregister_class(WM_OT_run_script_4)
    bpy.utils.unregister_class(WM_OT_run_script_5)
    bpy.utils.unregister_class(WM_OT_enable_all)
    bpy.utils.unregister_class(WM_OT_disable_all)
    bpy.utils.unregister_class(VIEW3D_PT_custom_panel)

if __name__ == "__main__":
    register()


(240903追加)ビューポートで隠すは対象外にしたもの

import bpy

# スクリプト 1: V to R:Off
def run_script_1():
    def sync_viewport_with_render_for_object(obj):
        if obj.hide_viewport:  # ビューポートで無効 (Object)
            obj.hide_render = True  # レンダーで無効 (Object)
                        
    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
    
        if collection.hide_viewport:  # ビューポートで無効 (Collection)
            collection.hide_render = True  # レンダーで無効 (Collection)
    
        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 2: V to R:On
def run_script_2():
    def sync_viewport_with_render_for_object(obj):
        if not obj.hide_viewport:  # ビューポートで無効 (Object)
            obj.hide_render = False  # レンダーで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection

        if not collection.hide_viewport:  # ビューポートで無効 (Collection)
            collection.hide_render = False  # レンダーで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 3: R to V:Off
def run_script_3():
    def sync_viewport_with_render_for_object(obj):
        if obj.hide_render:  # レンダーで無効 (Object)
            obj.hide_viewport = True  # ビューポートで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if collection.hide_render:  # レンダーで無効 (Collection)
            collection.hide_viewport = True  # ビューポートで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 4: R to V:On
def run_script_4():
    def sync_viewport_with_render_for_object(obj):
        if not obj.hide_render:  # レンダーで無効 (Object)
            obj.hide_viewport = False  # ビューポートで無効 (Object)

    def sync_viewport_with_render_for_collection(layer_collection):
        collection = layer_collection.collection
        if not collection.hide_render:  # レンダーで無効 (Collection)
            collection.hide_viewport = False  # ビューポートで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            sync_viewport_with_render_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        sync_viewport_with_render_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    sync_viewport_with_render_for_collection(root_layer_collection)

# スクリプト 5: Either:Off
def run_script_5():
    def disable_all_if_any_disabled_for_object(obj):
        if obj.hide_render or obj.hide_viewport or obj.hide_get():  # いずれかが無効
            obj.hide_viewport = True  # ビューポートで無効 (Object)
            obj.hide_render = True  # レンダーで無効 (Object)

    def disable_all_if_any_disabled_for_collection(layer_collection):
        collection = layer_collection.collection
        if collection.hide_render or collection.hide_viewport or layer_collection.hide_viewport:  # いずれかが無効
            collection.hide_viewport = True  # ビューポートで無効 (Collection)
            collection.hide_render = True  # レンダーで無効 (Collection)

        # 子コレクションを再帰的に処理
        for child in layer_collection.children:
            disable_all_if_any_disabled_for_collection(child)

    # シーン内の全てのオブジェクトとコレクションに対して適用
    for obj in bpy.context.view_layer.objects:
        disable_all_if_any_disabled_for_object(obj)

    root_layer_collection = bpy.context.view_layer.layer_collection
    disable_all_if_any_disabled_for_collection(root_layer_collection)

# オペレータークラス定義
class WM_OT_run_script_1(bpy.types.Operator):
    bl_idname = "wm.run_script_1"
    bl_label = "V to R:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 1")
        run_script_1()
        return {'FINISHED'}

class WM_OT_run_script_2(bpy.types.Operator):
    bl_idname = "wm.run_script_2"
    bl_label = "V to R:On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 2")
        run_script_2()
        return {'FINISHED'}

class WM_OT_run_script_3(bpy.types.Operator):
    bl_idname = "wm.run_script_3"
    bl_label = "R to V:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 3")
        run_script_3()
        return {'FINISHED'}

class WM_OT_run_script_4(bpy.types.Operator):
    bl_idname = "wm.run_script_4"
    bl_label = "R to V:On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 4")
        run_script_4()
        return {'FINISHED'}

class WM_OT_run_script_5(bpy.types.Operator):
    bl_idname = "wm.run_script_5"
    bl_label = "Either:Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Run Script 5")
        run_script_5()
        return {'FINISHED'}

class WM_OT_enable_all(bpy.types.Operator):
    bl_idname = "wm.enable_all"
    bl_label = "All On"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Enable All")
        for obj in bpy.context.view_layer.objects:
            obj.hide_viewport = False
            obj.hide_render = False

        root_layer_collection = bpy.context.view_layer.layer_collection
        enable_all_for_collection(root_layer_collection)
        return {'FINISHED'}

def enable_all_for_collection(layer_collection):
    collection = layer_collection.collection
    collection.hide_viewport = False
    collection.hide_render = False

    for child in layer_collection.children:
        enable_all_for_collection(child)

class WM_OT_disable_all(bpy.types.Operator):
    bl_idname = "wm.disable_all"
    bl_label = "All Off"

    def execute(self, context):
        bpy.ops.ed.undo_push(message="Disable All")
        for obj in bpy.context.view_layer.objects:
            obj.hide_viewport = True
            obj.hide_render = True

        root_layer_collection = bpy.context.view_layer.layer_collection
        disable_all_for_collection(root_layer_collection)
        return {'FINISHED'}

def disable_all_for_collection(layer_collection):
    collection = layer_collection.collection
    collection.hide_viewport = True
    collection.hide_render = True

    for child in layer_collection.children:
        disable_all_for_collection(child)

# パネルクラス定義
class VIEW3D_PT_custom_panel(bpy.types.Panel):
    bl_label = "Visibility Match"
    bl_idname = "VIEW3D_PT_custom_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Custom'

    def draw(self, context):
        layout = self.layout
        layout.operator("wm.run_script_1")
        layout.operator("wm.run_script_2")
        layout.operator("wm.run_script_3")
        layout.operator("wm.run_script_4")
        layout.operator("wm.run_script_5")
        layout.operator("wm.enable_all")
        layout.operator("wm.disable_all")

# Blenderへの登録
def register():
    bpy.utils.register_class(WM_OT_run_script_1)
    bpy.utils.register_class(WM_OT_run_script_2)
    bpy.utils.register_class(WM_OT_run_script_3)
    bpy.utils.register_class(WM_OT_run_script_4)
    bpy.utils.register_class(WM_OT_run_script_5)
    bpy.utils.register_class(WM_OT_enable_all)
    bpy.utils.register_class(WM_OT_disable_all)
    bpy.utils.register_class(VIEW3D_PT_custom_panel)

def unregister():
    bpy.utils.unregister_class(WM_OT_run_script_1)
    bpy.utils.unregister_class(WM_OT_run_script_2)
    bpy.utils.unregister_class(WM_OT_run_script_3)
    bpy.utils.unregister_class(WM_OT_run_script_4)
    bpy.utils.unregister_class(WM_OT_run_script_5)
    bpy.utils.unregister_class(WM_OT_enable_all)
    bpy.utils.unregister_class(WM_OT_disable_all)
    bpy.utils.unregister_class(VIEW3D_PT_custom_panel)

if __name__ == "__main__":
    register()

この記事が気に入ったらサポートをしてみませんか?