鷲獅子通信

about Blender and modeling

Add-on開発①_restoreWorkspace

業務Blender用にアドオンを作りました。
工数は6時間です。append, link以外で外部の.blendファイルのDataBlockにアクセスする方法が未だにわかりません。 github.com

機能

f:id:igogo:20200517142721p:plain
Add Workspace :現在のシーンにstartup.blendに保存されているWorkspaceを追加します。
Delete Others :現在activeになっている以外のWorkspaceをすべて削除します。

ソースコード

workspace_manager.py

bl_info = {
    "name": "Restore Layout",
    "author": "gogo",
    "version": (0, 0, 1),
    "blender": (2, 82, 0),
    "description": "Restore Layout from startup file.",
    "warning": "",
    "support": "TESTING",
    "wiki_url": "",
    "category": "Development"
}

import bpy
from bpy.props import (
    FloatProperty,
    BoolProperty,
    EnumProperty,
    PointerProperty,
    StringProperty,
)
import mathutils
import os


def get_armature_callback(scene, object):
    return object.type == 'ARMATURE'


def get_layout_list_callback(scene, context):
    items = []

    filepath = os.path.join(bpy.utils.resource_path('USER'), "config\\startup.blend")
    # link startup.file
    with bpy.data.libraries.load(filepath, link=True) as (data_from, data_to):
        data_to.workspaces = data_from.workspaces

    for wk in data_to.workspaces:
        items.append((wk, wk, ""))

    return items


class MYWORKSPACE_OT_restore(bpy.types.Operator):
    bl_idname = "myworkspace.restore"
    bl_label = "restore layout "
    bl_description = "restore layout"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        
        propGrp = context.scene.mywrkspc

        blendfile = os.path.join(bpy.utils.resource_path('USER'), "config\\startup.blend")
        section = "\\WorkSpace\\"
        wk = propGrp.sWorkspace_list

        filepath  = blendfile + section + wk
        directory = blendfile + section
        filename  = wk

        oldList = [ws.name for ws in bpy.data.workspaces]
        bpy.ops.wm.append(
            filepath=filepath, 
            filename=filename,
            directory=directory
        )
        newList = [ws.name for ws in bpy.data.workspaces]

        if propGrp.bSetActive:
            result = list(set(newList) - set(oldList))
            context.window.workspace = bpy.data.workspaces[result[0]]
        
        return {'FINISHED'}


class MYWORKSPACE_OT_delete(bpy.types.Operator):
    bl_idname = "myworkspace.delete"
    bl_label = "delete layouts "
    bl_description = "delete layouts"
    bl_options = {'REGISTER', 'UNDO'}
    
    
    def execute(self, context):
        propGrp = context.scene.mywrkspc
        bpy.ops.ed.undo_push()
        workspaces = [ws for ws in bpy.data.workspaces if ws != context.workspace]
        bpy.data.batch_remove(ids=workspaces)
        bpy.ops.ed.undo_push()
        
        return {'FINISHED'}


class MYWORKSPACE_PT_restore(bpy.types.Panel):
    bl_idname = "MYWORKSPACE_PT_restore"
    bl_label = "Restore Workspace"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Tool"

    def draw(self, context):
        layout = self.layout
        propGrp = context.scene.mywrkspc
        layout.prop(propGrp, property="sWorkspace_list", text="Layout")
        layout.prop(propGrp, property="bSetActive", text="Set Active")
        
        layout.operator(MYWORKSPACE_OT_restore.bl_idname, text="Restore")
        layout.operator(MYWORKSPACE_OT_delete.bl_idname, text="Delete Other Layout")


class MYWORKSPACE_Props(bpy.types.PropertyGroup):
    sWorkspace_list: EnumProperty(
        name="Handle Type",
        description="Handle Type",
        items=get_layout_list_callback,
    )
    bSetActive: BoolProperty(
        name="Set Active",
        description="Set the appended workspace active",
        default=True,
    )


classes = (
    MYWORKSPACE_Props,
    MYWORKSPACE_OT_restore,
    MYWORKSPACE_OT_delete,
    MYWORKSPACE_PT_restore,
)


def register():
    for i in classes:
        bpy.utils.register_class(i)
    
    bpy.types.Scene.mywrkspc = PointerProperty(type=MYWORKSPACE_Props)


def unregister():
    del bpy.types.Scene.mywrkspc
    for i in classes:
        bpy.utils.unregister_class(i)

公式の代替機能

  • File > Open... > Option_Load UI
  • Edit > Preferences > File > Load UI
  • Add Workspace...

課題

現在Add, DeleteともにUndo(Ctrl+Z)が効きません。 手動でAppendしたデータもUndoで消せないため、Blenderの仕様という認識です。