Skip to content

Commit 1afb17e

Browse files
committed
Support distributing as Blender extension
1 parent 948af81 commit 1afb17e

File tree

11 files changed

+142
-104
lines changed

11 files changed

+142
-104
lines changed

.github/workflows/release.yml

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ jobs:
3131
strategy:
3232
matrix:
3333
os: [macos-13, macos-latest, windows-latest]
34+
include:
35+
- os: macos-13
36+
blender-install: |
37+
brew update
38+
brew install --cask blender
39+
filename-match: "dist/*-macos_x64.zip"
40+
- os: macos-latest
41+
blender-install: |
42+
brew update
43+
brew install --cask blender
44+
filename-match: "dist/*-macos_arm64.zip"
45+
- os: windows-latest
46+
blender-install: |
47+
choco install blender --version=4.2.2
48+
echo "C:\Program Files\Blender Foundation\Blender 4.2\" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
49+
filename-match: "dist/*-windows_x64.zip"
3450
fail-fast: false
3551
runs-on: ${{ matrix.os }}
3652

@@ -48,16 +64,19 @@ jobs:
4864
python -m pip install --upgrade pip
4965
pip install -r requirements-dev.txt
5066
- name: Build
51-
run: python setup.py bdist_blender_addon
52-
- name: Rename artifact
53-
shell: bash
54-
run: for filename in dist/*.zip; do mv "${filename}" "${filename%.zip}-${{ runner.os }}-${{ runner.arch }}.zip"; done;
67+
run: python setup.py build_rust --inplace --release
68+
- name: Install Blender
69+
run: ${{ matrix.blender-install }}
70+
- name: Package addon into Blender extension
71+
run: |
72+
mkdir -p dist
73+
blender --command extension build --source-dir ./plumber --output-dir ./dist --split-platforms
5574
- name: Release
5675
uses: softprops/action-gh-release@v2
5776
with:
5877
draft: true
5978
fail_on_unmatched_files: true
60-
files: dist/*.zip
79+
files: ${{ matrix.filename-match }}
6180

6281
build-manylinux:
6382
runs-on: ubuntu-latest
@@ -78,13 +97,20 @@ jobs:
7897
python -m pip install --upgrade pip
7998
pip install -r requirements-dev.txt
8099
- name: Build
81-
run: python setup.py bdist_blender_addon
82-
- name: Rename artifact
83-
shell: bash
84-
run: for filename in dist/*.zip; do mv "${filename}" "${filename%.zip}-${{ runner.os }}-${{ runner.arch }}.zip"; done;
100+
run: python setup.py build_rust --inplace --release
101+
- name: Install Blender
102+
run: |
103+
dnf install -y wget libXi
104+
wget https://download.blender.org/release/Blender4.2/blender-4.2.3-linux-x64.tar.xz
105+
tar -xf blender-4.2.3-linux-x64.tar.xz
106+
echo "$PWD/blender-4.2.3-linux-x64" >> $GITHUB_PATH
107+
- name: Package addon into Blender extension
108+
run: |
109+
mkdir -p dist
110+
blender --command extension build --source-dir ./plumber --output-dir ./dist --split-platforms
85111
- name: Release
86112
uses: softprops/action-gh-release@v2
87113
with:
88114
draft: true
89115
fail_on_unmatched_files: true
90-
files: dist/*.zip
116+
files: "dist/*-linux_x64.zip"

README.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Supported file types are `.vmf`, `.mdl`, `.vmt` and `.vtf`. For a more complete
3434

3535
## Requirements
3636
- OS: Windows recommended. Linux and macOS supported.
37-
- Blender: 2.90 or newer (tested up to 4.2).
37+
- Blender: 2.90 or newer (up to version 1.1.1), 4.2 or newer (version 1.1.2 onwards).
3838

3939
## Quick start
4040
- Make sure you are using Blender 2.90 or newer.
@@ -45,15 +45,29 @@ Supported file types are `.vmf`, `.mdl`, `.vmt` and `.vtf`. For a more complete
4545
You can also follow a video tutorial, such as [this one](https://www.youtube.com/watch?v=jOJJzqOudw8) by ItsJustChris.
4646
This tutorial is recorded using a beta version, but also applies to the current version.
4747

48+
### Blender 4.2 and above
49+
- Make sure you are using Blender 4.2 or newer.
50+
- Download the latest extension release from the [releases](https://github.com/lasa01/Plumber/releases) tab.
51+
Make sure you download a file starting with `plumber-1.x.x`, not the source code.
52+
- Do **not** extract the downloaded files.
53+
- Open Blender and install the extension by dragging and dropping the downloaded .zip file into the Blender window.
54+
55+
<details>
56+
<summary>Blender 4.1 and below</summary>
57+
4858
- Make sure you are using Blender 2.90 or newer.
49-
- Download the latest addon release from the [releases](https://github.com/lasa01/Plumber/releases) tab.
50-
Make sure you download a file starting with `plumber-v1.x.x`, not the source code.
59+
- Download the v1.1.1 addon release from the [releases](https://github.com/lasa01/Plumber/releases/tag/v1.1.1) tab.
60+
Make sure you download a file starting with `plumber-v1.1.1`, not the source code.
5161
Also make sure that you downloaded the correct version for your operating system.
5262
- Do **not** extract the downloaded files.
5363
- Open Blender and install the addon:
5464
![Install addon](img/install_addon.gif)
5565

56-
### Installing latest from source (very advanced users)
66+
</details>
67+
68+
<details>
69+
<summary>Installing latest from source (very advanced users)</summary>
70+
5771
Make sure the following dependencies for building the addon are installed.
5872
The links are for Windows, for other platforms you need to figure it out yourself.
5973
- [Python 3](https://www.python.org/downloads/) with "Add python to environment variables" selected in the installer
@@ -63,10 +77,15 @@ The links are for Windows, for other platforms you need to figure it out yoursel
6377
- [CMake](https://cmake.org/download/)
6478

6579
After installing the dependencies, follow the following steps:
66-
- Download the repository as a .zip from the green "Code" button in the top right corner and extract it somewhere (or alternatively, clone it).
80+
- Download the repository as a .zip from the green "Code" button in the top right corner and extract it somewhere (or alternatively, clone it). Make sure you get the master branch, not the default release branch, if you want the latest changes.
6781
- Run `pip install -r requirements-dev.txt` on a terminal.
68-
- Run `python setup.py bdist_blender_addon`.
69-
- The built addon will be in the `dist` directory.
82+
- Run `python setup.py build_rust --inplace --release`.
83+
- Figure out where your Blender is installed, and take note of the path of blender executable.
84+
- Create the `dist` directory.
85+
- Run `{path/to/blender} --command extension build --source-dir plumber --output-dir dist`
86+
- The built extension will be in the `dist` directory.
87+
88+
</details>
7089

7190
## Usage
7291

plumber/__init__.py

Lines changed: 45 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,48 @@
11
import platform
22
import os
33

4-
bl_info = {
5-
"name": "Plumber",
6-
"author": "Lassi Säike",
7-
"version": (1, 1, 1),
8-
"blender": (2, 90, 0),
9-
"location": "File > Import -> Plumber",
10-
"description": "Imports Source Engine assets.",
11-
"warning": "",
12-
"tracker_url": "https://github.com/lasa01/plumber",
13-
"category": "Import-Export",
14-
}
15-
16-
version = bl_info["version"]
17-
version_pre = bl_info["warning"]
18-
19-
version_str = ".".join(map(str, version))
20-
21-
if version_pre != "":
22-
version_str += f"-{version_pre}"
23-
24-
# check if imported by setup.py or actually running in Blender
25-
try:
26-
from bpy.app import version as bpy_version
27-
except ImportError:
28-
bpy_version = None
29-
30-
if bpy_version is not None:
31-
is_windows = platform.system() == "Windows"
32-
33-
def register():
34-
if is_windows:
35-
# Check if the extension module was renamed on the last unregister,
36-
# and either rename it back or delete it if the addon was updated with a newer extension module
37-
ext_path = os.path.join(os.path.dirname(__file__), "plumber.pyd")
38-
unloaded_ext_path = os.path.join(
39-
os.path.dirname(os.path.dirname(__file__)), "plumber.pyd.unloaded"
40-
)
41-
42-
if os.path.isfile(unloaded_ext_path):
43-
if os.path.isfile(ext_path):
44-
try:
45-
os.remove(unloaded_ext_path)
46-
except OSError:
47-
print(
48-
"[Plumber] [WARN] old files remaining, restart Blender to finish post-update clean up"
49-
)
50-
else:
51-
os.rename(unloaded_ext_path, ext_path)
52-
53-
from . import addon
54-
55-
addon.register()
56-
57-
def unregister():
58-
from . import addon
59-
60-
addon.unregister()
61-
62-
if is_windows:
63-
# Rename the extension module to allow updating the addon without restarting Blender,
64-
# since the extension module will stay open and can't be overwritten even if the addon is unloaded
65-
ext_path = os.path.join(os.path.dirname(__file__), "plumber.pyd")
66-
unloaded_ext_path = os.path.join(
67-
os.path.dirname(os.path.dirname(__file__)), "plumber.pyd.unloaded"
68-
)
69-
70-
try:
71-
os.rename(ext_path, unloaded_ext_path)
72-
except OSError:
73-
pass
4+
is_windows = platform.system() == "Windows"
5+
6+
7+
def register():
8+
if is_windows:
9+
# Check if the extension module was renamed on the last unregister,
10+
# and either rename it back or delete it if the addon was updated with a newer extension module
11+
ext_path = os.path.join(os.path.dirname(__file__), "plumber.pyd")
12+
unloaded_ext_path = os.path.join(
13+
os.path.dirname(os.path.dirname(__file__)), "plumber.pyd.unloaded"
14+
)
15+
16+
if os.path.isfile(unloaded_ext_path):
17+
if os.path.isfile(ext_path):
18+
try:
19+
os.remove(unloaded_ext_path)
20+
except OSError:
21+
print(
22+
"[Plumber] [WARN] old files remaining, restart Blender to finish post-update clean up"
23+
)
24+
else:
25+
os.rename(unloaded_ext_path, ext_path)
26+
27+
from . import addon
28+
29+
addon.register()
30+
31+
32+
def unregister():
33+
from . import addon
34+
35+
addon.unregister()
36+
37+
if is_windows:
38+
# Rename the extension module to allow updating the addon without restarting Blender,
39+
# since the extension module will stay open and can't be overwritten even if the addon is unloaded
40+
ext_path = os.path.join(os.path.dirname(__file__), "plumber.pyd")
41+
unloaded_ext_path = os.path.join(
42+
os.path.dirname(os.path.dirname(__file__)), "plumber.pyd.unloaded"
43+
)
44+
45+
try:
46+
os.rename(ext_path, unloaded_ext_path)
47+
except OSError:
48+
pass

plumber/addon.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import bpy
22
from bpy.types import Context, Menu
33

4-
from . import preferences, importer, tools, benchmark, version_str
4+
from . import preferences, importer, tools, benchmark
55
from .importer import ImportMdl, ImportVmf, ImportVmt, ImportVtf
66
from .tools import IMPORT_MT_plumber_browse
77

@@ -32,15 +32,6 @@ def menu_func_import(self: Menu, context: Context):
3232

3333

3434
def register():
35-
from . import plumber
36-
37-
rust_version = plumber.version()
38-
if rust_version != version_str:
39-
raise Exception(
40-
f"Native code version {rust_version} does not match Python code version {version_str}. "
41-
+ "Please restart Blender and reinstall the addon."
42-
)
43-
4435
preferences.register()
4536
importer.register()
4637
tools.register()

plumber/blender_manifest.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
schema_version = "1.0.0"
2+
3+
id = "plumber"
4+
version = "1.1.1"
5+
name = "Plumber"
6+
tagline = "Imports Source 1 engine maps, models, materials and textures"
7+
maintainer = "Lassi Säike <[email protected]>"
8+
type = "add-on"
9+
website = "https://github.com/lasa01/Plumber"
10+
tags = ["Import-Export"]
11+
blender_version_min = "4.2.0"
12+
license = ["SPDX:GPL-3.0-or-later"]
13+
platforms = ["windows-x64", "macos-x64", "macos-arm64", "linux-x64"]
14+
15+
[permissions]
16+
files = "Import/extract assets from/to disk, detect installed games"
17+
18+
[build]
19+
paths_exclude_pattern = ["__pycache__/", "/.git/", "/*.zip", "/*.pyi"]

plumber/preferences.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ class AddonPreferences(AddonPreferences):
377377
)
378378

379379
def update_enable_file_browser_panel(self, context: Context):
380-
from plumber.tools import GameFileBrowserPanel
380+
from .tools import GameFileBrowserPanel
381381

382382
if not self.enable_file_browser_panel:
383383
bpy.utils.unregister_class(GameFileBrowserPanel)
@@ -392,7 +392,7 @@ def update_enable_file_browser_panel(self, context: Context):
392392
)
393393

394394
def update_enable_benchmarking(self, context: Context):
395-
from plumber.benchmark import BenchmarkVmf
395+
from .benchmark import BenchmarkVmf
396396

397397
if not self.enable_benchmarking:
398398
bpy.utils.unregister_class(BenchmarkVmf)

plumber/tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
)
1313
import bpy
1414

15-
from plumber.importer import (
15+
from .importer import (
1616
DisableCommonPanel,
1717
GameFileImporterOperator,
1818
GameFileImporterOperatorProps,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[build-system]
2-
requires = ["setuptools", "setuptools-rust", "blender.distutils"]
2+
requires = ["setuptools", "setuptools-rust", "toml"]

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fake-bpy-module-2.82
22
setuptools
33
setuptools-rust
4-
blender.distutils
54
black
5+
toml

setup.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from setuptools import setup, find_packages, sic
22
from setuptools_rust import Binding, RustExtension
3+
import toml
34

4-
from plumber import version_str
5+
with open("plumber/blender_manifest.toml", "r") as f:
6+
manifest = toml.load(f)
7+
8+
version_str = manifest["version"]
59

610
rust_extension = RustExtension(
711
"plumber.plumber",

0 commit comments

Comments
 (0)