🦔

BlenderのAdd-on開発環境をdevcontainerで作る

2024/03/24に公開

概要

Blender の Add-on 開発環境を、 VSCode の devcontainer 機能で作ったら結構いい感じだったので紹介する。
ちなみにこの記事に記載するコードは、私が作った Thanos[1] という Add-on から抜粋している。もし全体を見たい場合は以下からどうぞ。

https://github.com/kitta65/thanos-blender

書くこと

  • Blender Add-on 開発に向けた devcontainer の設定方法
  • 併せて設定しておくと便利な Tips

書かないこと

結論

.devcontainer/devcontainer.json に以下を記載して、devcontainer を起動すると大体いい感じになるはず。 src/ 直下に Add-on の __init__.py がある想定。

.devcontainer/devcontainer.json
{
  "name": "blender",
  "workspaceFolder": "/config/${localWorkspaceFolderBasename}",
  "workspaceMount": "source=${localWorkspaceFolder},target=/config/${localWorkspaceFolderBasename},type=bind",
  "remoteUser": "kasm-user", // created by linuxserver/blender
  "image": "lscr.io/linuxserver/blender:4.0.2-ls99",
  "overrideCommand": false,
  "forwardPorts": [
    3000,
    3001
  ],
  "containerEnv": {
    // specify the same value as your local environement
    "PUID": "1000", // id -u
    "PGID": "1000", // id -g
    "TZ": "Etc/UTC" // cat /etc/timezone
  },
  "features": {
    "ghcr.io/devcontainers/features/git:1": {}
  },
  "postCreateCommand": "/blender/4.0/python/bin/python3.10 -m pip install fake-bpy-module-4.0 && sudo ln -s $(pwd)/src /blender/4.0/scripts/addons/myaddon",
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.black-formatter"
      ],
      "settings": {
        "python.defaultInterpreterPath": "/blender/4.0/python/bin/python3.10"
      }
    }
  }
}

以下ではこだわりポイントを抜粋して補足する。

linuxserver/blender

.devcontainer/devcontainer.json
{
  "image": "lscr.io/linuxserver/blender:4.0.2-ls99"
}

これが Blender を含む Docker イメージ。以下の二択で迷ったが、 v4 以降もサポートしていそうな前者を採用した。

devcontainer として起動した上で localhost:3000 をブラウザで開くと Blender を操作することができる。VSCode 上で Add-on をコーディングしながら、たまにブラウザ上の Blender で動作確認するのが基本的な開発サイクルになる。

ちなみにそもそも Docker を利用しようと思った動機は、気軽に壊せる Blender 環境がほしかったから。そういう意味では portable 版の Blender を使うという方向性も考えられた(スクショの .zip のやつ)。結局 Docker の方が便利という結論に至ったけれど。

補完の設定

.devcontainer/devcontainer.json
{
  "postCreateCommand": "/blender/4.0/python/bin/python3.10 -m pip install fake-bpy-module-4.0 && ... 略 ...",
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python"
      ],
      "settings": {
        "python.defaultInterpreterPath": "/blender/4.0/python/bin/python3.10"
      }
    }
  }
}

補完が効くかどうかって開発効率に大きく影響するので、上記でその設定をしている。

ms-python.python は VSCode で Python を書く人ならみんな使っている拡張機能だと思うので説明は省略。

fake-bpy-module というのが、Blender API まわりの補完を可能にする優れもの。

Add-on の install

.devcontainer/devcontainer.json
{
  "postCreateCommand": " ... 略 ... && sudo ln -s $(pwd)/src /blender/4.0/scripts/addons/myaddon",
}

Blender が Add-on を格納するディレクトリに、開発中の Add-on に向けたシンボリックリンクを張っている。これによって、開発中の Add-on が install された扱いになって便利。

注意点は、 Add-on の有効化まではされていないので preferences から手動でチェックする必要があること。

また、コードの変更を反映させたいときは Menu Search (F3) から reload script を忘れずに行うこと[2]

その他 Tips

以下では devcontainer.json 以外で設定しておくと便利なものを紹介する。

テストの設定

テスト用の Python ファイルを用意して .vscode/tasks.json に以下を記載しておくと便利。

.vscode/tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "e2e test",
      "type": "shell",
      "command": "blender",
      "args": [
        "--background",
        "--python",
        "./tests/e2e.py"
      ],
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

これは Blender に ./tests/e2e.py を実行させるタスクの定義。タスクを定義することによって、 VSCode のコマンドパレットから実行できるようになる。

e2e.py には、開発した Add-on のオペレータを実行して想定通りの結果か確認する、という処理を書いておく想定。 Thanos の場合は以下のような内容。

e2e.py
e2e.py
import bpy
import bmesh
import addon_utils

# 準備
addon_utils.enable("myaddon")  # Add-on有効化
bpy.ops.mesh.primitive_cube_add()  # テスト対象の立方体を追加
bpy.ops.object.mode_set(mode="EDIT")  # 編集モードへ
bpy.context.scene.tool_settings.mesh_select_mode = [True, False, False]  # 頂点選択モード
bpy.ops.mesh.select_all(action="SELECT")  # 全選択

# オペレータ実行
bpy.ops.thanos.snap_fingers()

# 結果を記録
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
expected = 4  # 頂点は4個(半分)になるのが期待値
actual = len(bm.verts)

# 後始末
bm.free()
bpy.ops.object.mode_set(mode="OBJECT")  # オブジェクトモードへ戻る
bpy.ops.object.delete()  # テスト対象の立方体を削除

# アサーション
if actual != expected:
    raise Exception(f"expected {expected}, actual {actual}")

タスクを定義するのは必須ではなくて、ターミナルで blender --background --python ./tests/e2e.py を実行しても構わない。もしくはスクショのように Blender でファイルを開いて実行することもできる。

ローカルでのテストに加えて、リモートに push する度に GitHub Actions などでもテストできるとよい。以下はその例。

.github/workflows/ci.yml
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: lscr.io/linuxserver/blender:4.0.2-ls99
    steps:
      - uses: actions/checkout@v4
      - run: ln -s $(pwd)/src /blender/4.0/scripts/addons/myaddon
      - run: blender --background --python-exit-code 1 --python tests/e2e.py

zip にまとめる設定

Add-on が複数ファイルからなる場合は、 zip にしないと Blender から install できない(devcontainer の外で動作確認したいときや配布したいときに困る)。 GitHub Actions で以下を設定しておくと push の度に zip が artifact として保存されて便利。

.github/workflows/ci.yml
on: [push]
jobs:
  artifact:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Blender から install しやすいようにディレクトリの深さを調整
      # src/ の直下に __init__.py がある想定
      - run: |
          mkdir -p artifact
          mv src artifact/thanos
      - uses: actions/upload-artifact@v4
        with:
          name: thanos
          path: artifact/

最後に

個人的には100点満点中、70点くらいの開発環境ができたなという印象。少し不満が残ったのは以下のような点。

  • Docker で起動した Blender の動作が若干もっさりしていたこと(動作確認程度なら問題ないが、がっつりモデリングするにはちょっと厳しそう)
  • debug 機能が充実していないこと(Blender Development という VSCode 拡張機能を使う場合と比べて)

とはいえ devcontainer は便利なので、しばらく Add-on の開発はこの構成でやってみようかなという気持ち。

脚注
  1. 選択中の頂点/辺/面を半分削除するクレイジーな Add-on (thanos-jsに触発されて作ってしまった) ↩︎

  2. __init__.py だけならこれで十分だが、複数ファイルからなる Add-on ではうまくいかないこともある(この辺が参考になった) ↩︎

Discussion