100 lines
5.0 KiB
Markdown
100 lines
5.0 KiB
Markdown
# Contributor and Agent Guide
|
|
|
|
This repository contains Blender extensions and standalone asset-pipeline tools.
|
|
For Blender work, start with [the extension authoring guide](docs/blender-extension-guide.md),
|
|
then use [the API notes](docs/blender-api-notes.md) and
|
|
[the testing and release guide](docs/testing-and-releasing.md) as needed.
|
|
|
|
## Repository map
|
|
|
|
- `blender/<extension_id>/`: one installable Blender extension per directory.
|
|
Each extension root contains `blender_manifest.toml` and `__init__.py`.
|
|
- `blender/tests/`: headless Blender smoke tests. These run inside Blender's
|
|
bundled Python, not ordinary system Python.
|
|
- `blender/scripts/`: focused helpers for the current extension.
|
|
- `tools/`: standalone tools that do not need to run inside Blender.
|
|
- `dist/`: generated extension ZIP packages. Do not hand-edit them.
|
|
- `build-all.sh`: discover and package every manifest under `blender/`.
|
|
- `install-all.sh` / `install-all.bat`: build, install, and enable every
|
|
extension for the current Blender user.
|
|
|
|
## Rules for Blender extensions
|
|
|
|
1. Use the Blender Extensions format introduced in Blender 4.2. Do not add a
|
|
legacy `bl_info` dictionary. Metadata belongs in `blender_manifest.toml`.
|
|
2. Keep each extension self-contained. Use relative imports inside its package.
|
|
Bundle third-party dependencies as wheels and list them in the manifest;
|
|
never run `pip` from an enabled extension.
|
|
3. Treat the installed extension directory as read-only. Persistent extension
|
|
data belongs under `bpy.utils.extension_path_user(__package__, ...)`.
|
|
4. Declare `files`, `network`, `clipboard`, `camera`, or `microphone`
|
|
permissions in the manifest whenever the extension uses them. Network code
|
|
must also respect `bpy.app.online_access`.
|
|
5. Register Blender classes in dependency order and unregister them in reverse.
|
|
Delete properties added to `bpy.types` during `unregister()` and remove every
|
|
handler, timer, menu callback, preview collection, and keymap item created by
|
|
`register()`.
|
|
6. Operators must have a useful `poll()`, use their passed `context`, report
|
|
actionable failures, and return `{'FINISHED'}` or `{'CANCELLED'}` correctly.
|
|
7. Prefer Blender's data API over `bpy.ops`. When an operator is necessary,
|
|
make its context, selection, active object, object mode, and render engine
|
|
requirements explicit.
|
|
8. Preserve user state. Snapshot and restore temporary selection, active object,
|
|
mode, render settings, material assignments, and temporary data in `finally`.
|
|
Do not rely on Undo to reverse file writes or external side effects.
|
|
9. Never mutate shared mesh or material data merely to simplify processing.
|
|
Copy it, operate on the copy, and clean it up unless a persistent result is
|
|
an explicit feature.
|
|
10. Avoid hard-coded repository namespaces such as `bl_ext.user_default`.
|
|
An extension may be installed from another repository; use `__package__`
|
|
and relative imports.
|
|
|
|
## Adding an extension
|
|
|
|
1. Create `blender/<extension_id>/blender_manifest.toml` and `__init__.py`.
|
|
2. Use a lowercase snake-case manifest `id`; keep operator IDs and registered
|
|
class names uniquely prefixed.
|
|
3. Set a truthful `blender_version_min`, semantic `version`, SPDX license, and
|
|
only the permissions actually required.
|
|
4. Add a deterministic smoke test under `blender/tests/`. It must create its own
|
|
scene data, exercise the public operator or API, assert the result, and check
|
|
that temporary data and global state are restored.
|
|
5. Add the test to `blender/scripts/test.sh` or replace that helper with a test
|
|
dispatcher when a second extension needs its own Blender process.
|
|
6. Document the user workflow in `README.md` or a focused file under `docs/`.
|
|
7. Run the completion checks below.
|
|
|
|
## Required completion checks
|
|
|
|
For any changed Blender extension, run checks proportional to the change. The
|
|
minimum for code changes is:
|
|
|
|
```bash
|
|
./blender/scripts/test.sh
|
|
blender --factory-startup --command extension validate blender/<extension_id>
|
|
./build-all.sh
|
|
blender --factory-startup --command extension validate dist/<id>-<version>.zip
|
|
```
|
|
|
|
For registration, packaging, dependency, or manifest changes, also test the
|
|
built package in an isolated Blender user profile and confirm the enabled
|
|
extension is loaded. See [Testing and releasing](docs/testing-and-releasing.md).
|
|
|
|
Before declaring success:
|
|
|
|
- Test both the successful path and at least one important validation/failure path.
|
|
- Confirm the original scene state is preserved unless the feature documents a
|
|
persistent change.
|
|
- Confirm no temporary objects, meshes, materials, images, handlers, or files
|
|
survive unexpectedly.
|
|
- Rebuild the ZIP after the final source edit; a previously built package is not
|
|
evidence for the current source.
|
|
- Bump the manifest version for a user-visible release.
|
|
|
|
## Standalone tools
|
|
|
|
Code under `tools/` runs in ordinary Python. Keep its dependencies in
|
|
`tools/requirements.txt`, provide a helpful error when a dependency is absent,
|
|
and test with `./tools/test.sh`. Standalone tools must not import `bpy`.
|
|
|