忘却まとめ

Blenderの中級者・上級者向けの踏み込んだ情報や、アドオン・3DCGに関する情報を記事にします

メニューの作り方・様々なレイアウト要素の紹介【Blender / アドオン / Python】

Python

更新日:

アドオンで使うメニューの作り方を紹介する。
アドオン開発で得た知識をここにまとめる。

ダウンロード

gumroad

BOOTH

この記事では、上記の学習用に作ったアドオンを元に解説する。

  • アドオン内のメニューの場所
    • 3Dビュー → サイドバー(Nキー) → Tools → Layout Practice

さまざまなレイアウトの要素表

UILayout(bpy_struct) — Blender Python API

上記のUILayoutのAPIからすべてを見ることができるが、よく使うものは限られている。
この記事では主に、下記の表にある要素を紹介する。

基本的なレイアウト要素

レイアウト説明
labelテキスト
layout.label(text="hoge",icon="ADD")
separator空白
layout.separator()
row横並びにする
row = layout.row(align=True)
col縦表示にする
col = layout.column(align=True)
box要素を囲う
box = layout.box()
split横に2つに分割する
sp = layout.split(align=True,factor=0.9)
operatorオペレーターのメニュー
layout.operator("mesh.primitive_cube_add")
propプロパティのメニュー
layout.prop(bpy.context.objcet,"name")

レイアウトのオプション

レイアウト説明
scale_x / scale_y要素を大きさを変える
layout.scale_x = 1.2
alignment左・中央・右に整列する
layout.alignment = "LEFT"
alert警告表示する
layout.alert = True
embossエンボスを消す
layout.emboss= False
active暗く表示させる
layout.active = False
enabled暗く表示させる(一切操作できなくさせる)
layout.enabled= False

基本のレイアウト

label テキスト

#des labelは、文字列
layout.label(text="label 文字列")

単純な文字列を表示する。
メニューのタイトルやユーザーに伝えたい内容を書ける。

メニューはあくまで機能にアクセスするためのものなので、長文の説明を書きたい場合は他の場所でやる(アドオンのドキュメントやOperatorのbl_description・ポップアップ表示など)。

separator 空白

layout.label(text="separator 空白")
layout.separator()

単純な空白を作る。
メニュー要素の関係を分けたい時に使える。

factorオプションに数値を設定すれば大きな空白を作ることができる。

layout.separator(factor=3)

row 横並びにする

#des 横表示
row = layout.row(align=True)
row.label(text="row 横表示にする")
row.label(text="align=Trueで")
row.label(text="隙間詰め")

要素を横並びにする。
基本的なレイアウト要素。

rowやcol、splitなどは、align=Trueで隙間を詰めることができる。
自分は基本的に入れて、隙間を開けたい時はseparatorを入れている。

col 縦並びにする

要素を縦並びにする。
align=Trueを使えば通常の縦並びより隙間を詰めることができるのが便利。

#des 縦表示
col = layout.column(align=True)
col.label(text="col 縦表示にする")
col.label(text="col 縦表示にする")
col.label(text="col 縦表示にする")

box 要素を囲う

#des ボックス
box = layout.box()
box.label(text="囲うのはbox")
box.label(text="要素をまとめたい時に便利")

要素をボックスで囲う。
要素をまとめたい時に便利。

box内では 上のcol の align=True は反映されないので注意。

オペレーターのメニュー

operator オペレーターのメニュー

layout.label(text="operator オペレーターのメニュー",icon="DOT")
layout.operator("mesh.primitive_cube_add")

bpy.opsと()はいらないので注意。

textやiconで修飾できる

layout.label(text="textやiconで修飾できる",icon="DOT")
layout.operator("mesh.primitive_cube_add",text="CUBE",icon="MESH_CUBE")
layout.separator()

textで名前を設定できる。
これがない場合は、Operatorのbl_labelが表示される。
text=""のように値がないテキストを設定した場合は、アイコンのみが表示される。

iconでアイコンを設定できる。
使えるアイコンを調べるには、Blender内臓のicon viewerアドオンが便利。

オペレーターのプロパティは、末尾に~.〇〇のように書ける

layout.label(text="オペレーターのプロパティは、末尾に~.〇〇のように書ける",icon="DOT")
layout.label(text="3Dカーソルの位置に依存せず常にワールドの中心に配置")
layout.operator("mesh.primitive_cube_add",text="CUBE (location 0)",icon="MESH_CUBE").location=(0,0,0)
layout.separator()

オペレーターのプロパティをあらかじめ決めておきたい場合は、下記のように書く。

メニューから実行されたときにプロパティの値を固定したい場合は、あらかじめこのように設定しておく必要がある
Blenderのオペレーターは、プロパティが初期値のままならユーザーが事後設定メニューで切り替えた設定が優先されるため。

layout.operator("mesh.primitive_cube_add").location=(0,0,0)

代入することで複数のプロパティを書ける

layout.label(text="代入することで複数のプロパティを書ける",icon="DOT")
layout.label(text="回転X45度を追加")
op = layout.operator("mesh.primitive_cube_add",text="CUBE (location 0,rotation X45)",icon="MESH_CUBE")
op.location=(0,0,0)
op.rotation=(0.785,0,0)
layout.separator()

複数のプロパティの値を設定したい場合はOperator自体を代入して書くとよい。

様々なレイアウト要素

基本的にrowやcolなどのサブ要素を作ってそこに設定する。

レイアウトのオプションは設定したレイアウト要素全てに適用されるので 、直接layoutに設定するとそれ以下のメニュー全てに反映されてしまう。

scale_x / scale_y 要素を大きさを変える

layout.label(text="scale_x / scale_y 要素を大きさを変える",icon="DOT")
row = layout.row(align=True)
row.scale_x = 3
row.scale_y = 3
row.operator("mesh.primitive_cube_add")
layout.separator()

要素を大きくしたり小さくしたりする。
scale_xが横幅。
scale_yが縦幅。

メイン機能のオペレーターのボタンを少し大きめにすると、どれがメインボタンなのかわかりやすくてよい。

スカルプトやグリースペンシルなどのペンタブで扱うこと前提の機能の場合は、ボタンを大きくすると押しやすい。

split 分割する

layout.label(text="Split 分割する",icon="DOT")
sp = layout.split(align=True,factor=0.7)
sp.operator("mesh.primitive_cube_add")
sp.operator("mesh.primitive_cube_add")
layout.separator()

要素を分割する。
1行内に2つの要素を指定間隔で横並びしたいときに使える。

factorの値を0.0~1.0の間で指定する。

alignment 左・中央・右に整列する

layout.label(text="alignment 左・中央・右に整列する",icon="DOT")
row = layout.row(align=True)
row.alignment="LEFT"
row.operator("mesh.primitive_cube_add")
layout.separator()

メニューを整列する。
右端や左端に寄せたいときに使える。

LEFT, RIGHT, CENTER から選べる。

alert 警告表示する

layout.label(text="alert 警告表示する",icon="DOT")
row = layout.row(align=True)
row.alert=True
row.operator("mesh.primitive_cube_add")
layout.separator()

エンボスの色を赤に変える。
問題が発生していることを警告する時に使える。
テキストなら赤文字になる。

ちなみにBlenderのUIlayoutでは、メニューの色を細かく設定することはできない
開発者が扱えるのはalertの赤と、propのboolなどが有効な時の青だけ。

emboss エンボスを消す

layout.label(text="emboss エンボスを消す",icon="DOT")
row = layout.row(align=True)
row.operator("mesh.primitive_cube_add",emboss=False)
layout.separator()

operatorやpropのエンボスを消す。
あまり強調させたくない場合や、ボタンとしても押せるテキストを用意したい場合に使う。

labelにembossを付けることはできない。

active 暗く表示させる

layout.label(text="active ブラックアウトさせる",icon="DOT")
row = layout.row(align=True)
row.active = False
row.operator("mesh.primitive_cube_add")
layout.separator()

要素を暗く表示させる。
要素が使える状況ではないことをユーザーに知らせる事ができる。

enabled 暗く表示させる(一切操作できなくさせる)

layout.label(text="enabled ブラックアウトさせる(一切操作できなくさせる)",icon="DOT")
row = layout.row(align=True)
row.enabled = False
row.operator("mesh.primitive_cube_add")
layout.separator()

enabledは、activeのように暗く表示にさせる効果に加え、ボタンをクリックしても動作しなくなる。
絶対に動作させたくないときに使える

自分はなんらかの想定外の時にも一切操作できなくなるのが好きではないので、あまり使っていない。

また、一切使えないのであれば単純に非表示にした方がメニューがすっきりして見やすくなる場合もある。

prop プロパティ

props = bpy.context.scene.bktemp

box = layout.box()
col = box.column()
col.use_property_split = True #des プロパティエディターのようにメニューを分割表示する
col.use_property_decorate = False  #des キーフレームを打つアイコンを消す

col.prop(props,"Bool",text="真偽")
col.prop(props,"Int",text="整数")
col.prop(props,"String",text="文字列")
col.prop(props,"Float",text="小数点のある数値")
col.prop(props,"FloatVector",text="複数の小数点のある数値")
rows = col.row(align=True)
rows.prop(props,"Enum",text="複数の文字列",expand=True) 
col.prop(props,"Pointer",text="オブジェクトなどのBlenderのデータを格納できるプロパティ")

プロパティを表示する。

上記では、bpy.context.scene.bktemp 以下にあるBoolやIntなどのプロパティを表示するメニュー。

col.use_property_split = Trueを付けると、textとメニューが分けられて見やすくなる。
このプロパティにもtext・icon・embossなどを付けることができる。

  • enumのメニューを横並びにするには、rowとexpand=Trueが必要
  • IntやFloatの数値量を見やすくしたい時は、slider=Trueを付ける
    • ※ プロパティのminとmax(下限と上限)があらかじめ設定されている場合のみ

応用 - 開閉できるメニューを作る

ここまで掲載した要素を応用して、クリックしたらメニューが開き、ONの文字が表示されるメニューを作る。

開閉用メニューのプロパティの登録

  • window_managerに、あらかじめ「ui_layout」というメニュー開閉用のBoolプロパティを登録しておく
class BKTEMP_WindowManager(PropertyGroup):
	ui_layout : BoolProperty(name="基本のレイアウト")

classes = (
BKTEMP_WindowManager,
)

def register():
	for cls in classes:
		bpy.utils.register_class(cls)

	bpy.types.WindowManager.bktemp = PointerProperty(type=BKTEMP_WindowManager)


def unregister():
	for cls in reversed(classes):
		bpy.utils.unregister_class(cls)

	del bpy.types.WindowManager.bktemp

メニューを作成

wm = bpy.context.window_manager.bktemp

row = layout.row(align = True)
row.alignment = "LEFT"
row.prop(wm, "ui_layout", icon="TRIA_DOWN" if wm.ui_layout else "TRIA_RIGHT", emboss=False)

if wm.ui_layout:
	layout.label(text="ON",icon="NONE")
  • rowで、要素をまとめる
  • alignmentにより、プロパティの文字を左に寄せる
    • propのデフォルトはCENTERなので、中央によってしまい、文字が読みづらいためこれを設定する
  • row.prop(wm, "ui_layout")で開閉用プロパティメニューを作る
  • iconを設定する
    • アイコンにもif文を使うことができる
    • プロパティが有効なら▼になる
    • そうでないなら▶になる
  • embossで、エンボスを消して、あまり主張しすぎないようにする
  • if wm.ui_layout: のif文で、開閉用プロパティが有効ならメニューを表示するようにする

その他

EnumProperty

モディファイア追加メニューのように横並びにする

各列ごとのラベルは、下記のようにして他のアイテムと同じく並べると、選択できるアイテムにはならずにラベルにできる。

('', 'Modify', 'description', 'None', 0) ,




sp = layout.split()
for keyname, label, desc, icon_val, num  in tgt_mod_items:
	if keyname == "":
		col = sp.column(align=True)
		col.label(text=label,icon="NONE")
		continue
	op = col.operator("automirror.modifier_add", text=label, icon=icon_val)
	if act_obj.type == "GPENCIL":
		op.gp_mod_type = keyname
	else:
		op.mesh_mod_type = keyname

bpy.types.Menuのメニューは、splitで横並びのメニューにできる。

モディファイア追加メニューの作り方参考リンク
How to rebuild the Add Modifier Menu Layout? - Coding / Python Support - Blender Artists Community

複数選択できるEnumPropertyの作り方

FBXエクスポーターのオブジェクトタイプような、複数選択できるEnumPropertyの作り方。

通常のEnumでは単一のStringしか選択できないが、
options={"ENUM_FLAG"}を付けることで複数項目を設定できるPropertyにすることができる。

数字を右揃えにする

数字を普通に縦列表示すると左揃えされるので、桁数が多い数字の比較が見にくい。 zfillでゼロ埋めする方法もあるが、 alignment="RIGHT" で右揃えにして、 ui_units_x で固定幅を設定すると、きれいに並べることができる。

アドオンの制作依頼はこちら

-Python
-

Copyright© 忘却まとめ , 2024 All Rights Reserved Powered by STINGER.