Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca146ea2c1 |
@@ -0,0 +1,31 @@
|
||||
name: Build & Release Addon (Gitea)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Build Zip Package
|
||||
run: python package_addon.py
|
||||
|
||||
- name: Create Release
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: |
|
||||
releases/*.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Build & Release Addon (GitHub)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Build Zip Package
|
||||
run: python package_addon.py
|
||||
|
||||
- name: Create Release and Upload Asset
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
releases/*.zip
|
||||
draft: false
|
||||
prerelease: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -8,10 +8,10 @@ A Blender add-on that generates a continuously morphing parade of procedural [to
|
||||
|
||||
## Features
|
||||
|
||||
- **20 built-in shader presets** — Gloss Blue, Neon Glow, Metallic, Glass, Hologram, Lava, Iridescent, Matte Clay, Ghost, Car Paint, Chrome, Ruby Glass, Frosted Ice, Lichen Rough, Copper Patina, Zebra Stripes, Wood Veneer, Carbon Fiber, Pearlescent, Plasma Glow
|
||||
- **Playlist-based animation** — add, remove, reorder any number of knots; each entry controls its own topology, geometry, material, and animation rates
|
||||
- **Smooth transitions** — configurable per-knot morph windows with Linear, Quadratic In/Out, or Smoothstep easing
|
||||
- **Audio-reactive hooks** — drive the global Reactivity factor from a sound driver to pulse spin, height, and scale rates in sync with audio
|
||||
- **20 built-in shader presets** — Gloss Blue, Neon Glow, Metallic, Glass, Hologram, Lava, Iridescent, Matte Clay, Ghost, Car Paint, Chrome, Ruby Glass, Frosted Ice, Lichen Rough, Copper Patina, Zebra Stripes, Wood Veneer, Carbon Fiber, Pearlescent, Plasma Glow
|
||||
- **Random playlist generator** — configure min/max ranges for every parameter and generate an entire playlist in one click
|
||||
- **Bake & Export** — bake the procedural animation to a standalone `.blend` with per-frame mesh visibility keyframes; no addon required at render time; supports split-file export for SheepIt / distributed render farms
|
||||
- **Blender 5.0+ native** — uses the layered Action API (`action → layers → strips → channelbag → fcurves`) and Blender 5 Principled BSDF input names directly
|
||||
@@ -24,37 +24,74 @@ A Blender add-on that generates a continuously morphing parade of procedural [to
|
||||
|---|---|
|
||||
| Blender | **5.0** or later |
|
||||
| Blender built-in addon | **Add Curve: Extra Objects** (auto-enabled by the script) |
|
||||
|
||||
> **Note:** The single-file version (`knot_animation.py`) has no installation step — just open and run in the Text Editor.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
## Installation & Running
|
||||
|
||||
### Option A — Persistent Add-on (recommended)
|
||||
### Option A — Persistent Add-on (Recommended for Users)
|
||||
|
||||
1. Download or clone this repository.
|
||||
2. In Blender, go to **Edit → Preferences → Add-ons → Install…**
|
||||
3. Zip the `knot_animation/` folder and select the zip (Blender 5 requires a zip for local installs).
|
||||
4. Enable **"Pr3tz"** from the add-on list.
|
||||
5. Open the **3D Viewport → N-panel → Pr3tz** tab.
|
||||
1. Download a release zip (or run `package_addon.py` to build one).
|
||||
2. In Blender, go to **Edit → Preferences → Get Extensions → Add-ons** (or **Install from Disk...** from the top right gear menu).
|
||||
3. Select the zip file (e.g. `releases/pr3tz_v2.0.0.zip`).
|
||||
4. Enable **"Pr3tz"** from the list.
|
||||
5. Access the controls in the **3D Viewport → N-panel (sidebar) → Pr3tz** tab.
|
||||
|
||||
### Option B — Run as a Script (no installation)
|
||||
### Option B — Symlink (Recommended for Developers)
|
||||
|
||||
```
|
||||
# From inside Blender's Text Editor:
|
||||
# File → Open → knot_animation/__init__.py → Run Script (Alt+P)
|
||||
To test and develop with live code updates without having to reinstall the addon:
|
||||
1. Open your terminal as Administrator (on Windows) or with standard user permissions (on Linux/macOS).
|
||||
2. Run the appropriate command for your OS/shell to link the `pr3tz/` folder directly to Blender's local addons directory (replace path with your Blender version/path if needed):
|
||||
|
||||
# Or from the command line:
|
||||
"C:\Program Files\Blender Foundation\Blender 5.0\blender.exe" --python knot_animation/__init__.py
|
||||
**PowerShell (Windows):**
|
||||
```powershell
|
||||
New-Item -ItemType SymbolicLink -Path "$env:APPDATA\Blender Foundation\Blender\5.0\scripts\addons\pr3tz" -Value "$PWD\pr3tz"
|
||||
```
|
||||
|
||||
### Option C — Single-file version
|
||||
|
||||
`knot_animation_single_file.py` is a self-contained copy of the entire add-on in one file, useful for quick testing without touching Blender's add-on directory.
|
||||
|
||||
**CMD (Windows):**
|
||||
```cmd
|
||||
mklink /d "%APPDATA%\Blender Foundation\Blender\5.0\scripts\addons\pr3tz" "%CD%\pr3tz"
|
||||
```
|
||||
blender.exe --python knot_animation_single_file.py
|
||||
|
||||
**Bash (Linux):**
|
||||
```bash
|
||||
ln -s "$PWD/pr3tz" "$HOME/.config/blender/5.0/scripts/addons/pr3tz"
|
||||
```
|
||||
|
||||
**Bash (macOS):**
|
||||
```bash
|
||||
ln -s "$PWD/pr3tz" "$HOME/Library/Application Support/Blender/5.0/scripts/addons/pr3tz"
|
||||
```
|
||||
|
||||
3. Enable **"Pr3tz"** in Blender's Preferences.
|
||||
4. Press `F3` and search for **"Reload Scripts"** to reload changes instantly.
|
||||
|
||||
### Option C — Bootstrap Loader (No Installation)
|
||||
|
||||
Since Python relative imports fail when running individual module files directly, you can run the bootstrap script from the repository root:
|
||||
1. Open Blender.
|
||||
2. In the **Text Editor**, open [run_script.py](run_script.py).
|
||||
3. Click **Run Script** (or press `Alt+P`).
|
||||
|
||||
Alternatively, load it directly from the terminal:
|
||||
|
||||
**PowerShell (Windows):**
|
||||
```powershell
|
||||
& "C:\Program Files\Blender Foundation\Blender 5.0\blender.exe" --python run_script.py
|
||||
```
|
||||
|
||||
**CMD (Windows):**
|
||||
```cmd
|
||||
"C:\Program Files\Blender Foundation\Blender 5.0\blender.exe" --python run_script.py
|
||||
```
|
||||
|
||||
**Bash (Linux):**
|
||||
```bash
|
||||
blender --python run_script.py
|
||||
```
|
||||
|
||||
**Bash (macOS):**
|
||||
```bash
|
||||
/Applications/Blender.app/Contents/MacOS/Blender --python run_script.py
|
||||
```
|
||||
|
||||
---
|
||||
@@ -79,23 +116,24 @@ The **Bake & Export** button (bottom of the Pr3tz panel) converts the procedural
|
||||
4. Submit the resulting `.blend` file(s) to your render farm — no addon needed on the farm.
|
||||
|
||||
---
|
||||
|
||||
## Module Layout
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
knot_animation/
|
||||
├── __init__.py # Add-on entry point, bl_info, register/unregister
|
||||
├── constants.py # Default playlist configs, camera/light positions, name tags
|
||||
├── types.py # KnotConfig TypedDict (shared data contract)
|
||||
├── compat.py # Headless align_matrix fix and other Blender compat patches
|
||||
├── properties.py # Blender PropertyGroups (KnotItem, KnotGlobalSettings, …)
|
||||
├── operators.py # KNOT_OT_* operators (Add, Remove, Move, Generate, Fit…)
|
||||
├── ui.py # N-panel, UILists, draw_knot_properties()
|
||||
├── geometry.py # _make_torus_knot() — pure parametric NURBS, no bpy.context reads
|
||||
├── materials.py # 20 shader builders, material cache, blend/transition system
|
||||
├── handler.py # @persistent frame_change_post handler, easing, playlist timing
|
||||
├── scene_setup.py # setup_scene() — camera, area light, world, render settings
|
||||
└── bake_export.py # KNOT_OT_BakeExport — bake to standalone .blend
|
||||
├── pr3tz/ # Main add-on package folder
|
||||
│ ├── __init__.py # Add-on entry point, bl_info, register/unregister
|
||||
│ ├── constants.py # Default playlist configs, camera/light positions, name tags
|
||||
│ ├── types.py # KnotConfig TypedDict (shared data contract)
|
||||
│ ├── compat.py # Headless align_matrix fix and other Blender compat patches
|
||||
│ ├── properties.py # Blender PropertyGroups (KnotItem, KnotGlobalSettings, …)
|
||||
│ ├── operators.py # KNOT_OT_* operators (Add, Remove, Move, Generate, Fit…)
|
||||
│ ├── ui.py # N-panel, UILists, draw_knot_properties()
|
||||
│ ├── geometry.py # _make_torus_knot() — pure parametric NURBS, no bpy.context reads
|
||||
│ ├── materials.py # 20 shader builders, material cache, blend/transition system
|
||||
│ ├── handler.py # @persistent frame_change_post handler, easing, playlist timing
|
||||
│ ├── scene_setup.py # setup_scene() — camera, area light, world, render settings
|
||||
│ └── bake_export.py # KNOT_OT_BakeExport — bake to standalone .blend
|
||||
├── run_script.py # Bootstrap runner for Text Editor / CLI execution
|
||||
└── package_addon.py # Automated packaging tool to create release .zip files
|
||||
```
|
||||
|
||||
---
|
||||
@@ -157,6 +195,26 @@ knot_animation/
|
||||
| `PEARLESCENT` | Angle-dependent pearl sheen |
|
||||
| `PLASMA_GLOW` | High-energy plasma emission |
|
||||
|
||||
---
|
||||
## Release Packaging
|
||||
|
||||
We provide an automated script to pack the addon for release:
|
||||
|
||||
**PowerShell / CMD (Windows):**
|
||||
```cmd
|
||||
python package_addon.py
|
||||
```
|
||||
|
||||
**Bash (macOS/Linux):**
|
||||
```bash
|
||||
python3 package_addon.py
|
||||
```
|
||||
|
||||
This script:
|
||||
1. Parses the release version dynamically from `pr3tz/__init__.py`.
|
||||
2. Zips the `pr3tz/` directory into `releases/pr3tz_v<version>.zip`.
|
||||
3. Automatically excludes developer files (`__pycache__`, `.git`, `.pyc`, etc.) so that the release package remains clean.
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
@@ -165,13 +223,13 @@ Pull requests are welcome. For major changes please open an issue first.
|
||||
|
||||
### Development setup
|
||||
|
||||
```powershell
|
||||
# Clone
|
||||
To configure your workspace for active development:
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/pr3tz.git
|
||||
|
||||
# Run the syntax checker (no Blender needed)
|
||||
python check_syntax.py
|
||||
```
|
||||
2. Symlink the addon to Blender's addons folder as shown in **Option B** of the installation instructions.
|
||||
3. Use `run_script.py` to quickly test code changes from the CLI or Text Editor.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import os
|
||||
import re
|
||||
import zipfile
|
||||
|
||||
def get_addon_version():
|
||||
"""Reads pr3tz/__init__.py and extracts the bl_info version tuple."""
|
||||
init_path = os.path.join("pr3tz", "__init__.py")
|
||||
if not os.path.exists(init_path):
|
||||
raise FileNotFoundError(f"Could not find {init_path}")
|
||||
|
||||
with open(init_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# Search for the "version": (x, y, z) pattern in bl_info
|
||||
match = re.search(r'"version"\s*:\s*\(([^)]+)\)', content)
|
||||
if not match:
|
||||
raise ValueError("Could not parse version from bl_info in __init__.py")
|
||||
|
||||
version_str = match.group(1)
|
||||
# Parse numbers, e.g. "2, 0, 0" -> ["2", "0", "0"] -> "2.0.0"
|
||||
version_parts = [part.strip() for part in version_str.split(",")]
|
||||
return ".".join(version_parts)
|
||||
|
||||
def package_addon():
|
||||
"""Zips the pr3tz addon folder, excluding development artifacts."""
|
||||
try:
|
||||
version = get_addon_version()
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not parse version: {e}. Defaulting to 'unknown'.")
|
||||
version = "unknown"
|
||||
|
||||
release_dir = "releases"
|
||||
if not os.path.exists(release_dir):
|
||||
os.makedirs(release_dir)
|
||||
print(f"Created output directory: {release_dir}/")
|
||||
|
||||
zip_filename = f"pr3tz_v{version}.zip"
|
||||
zip_path = os.path.join(release_dir, zip_filename)
|
||||
|
||||
print(f"Packaging addon v{version} into {zip_path}...")
|
||||
|
||||
addon_dir = "pr3tz"
|
||||
ignored_dirs = {"__pycache__", ".git"}
|
||||
ignored_extensions = {".pyc", ".pyo", ".py.bak"}
|
||||
|
||||
added_count = 0
|
||||
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
for root, dirs, files in os.walk(addon_dir):
|
||||
# Prune directories in-place to prevent walking into them
|
||||
dirs[:] = [d for d in dirs if d not in ignored_dirs]
|
||||
|
||||
for file in files:
|
||||
_, ext = os.path.splitext(file)
|
||||
if ext in ignored_extensions:
|
||||
continue
|
||||
|
||||
file_path = os.path.join(root, file)
|
||||
# Ensure the path in the ZIP has "pr3tz/" as its root folder
|
||||
arcname = os.path.relpath(file_path, os.path.dirname(addon_dir))
|
||||
zipf.write(file_path, arcname)
|
||||
print(f" Added: {arcname}")
|
||||
added_count += 1
|
||||
|
||||
print(f"\nSuccess! Packaged {added_count} files into {zip_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
package_addon()
|
||||
+12
-10
@@ -1,6 +1,6 @@
|
||||
"""
|
||||
knot_animation/__init__.py
|
||||
--------------------------
|
||||
pr3tz/__init__.py
|
||||
-----------------
|
||||
Blender add-on entry-point for the Pr3tz procedural animation system.
|
||||
|
||||
What this add-on does
|
||||
@@ -42,16 +42,18 @@ How to use
|
||||
----------
|
||||
Requires Blender 5.0 or later.
|
||||
|
||||
Option A – Blender Text Editor:
|
||||
Open knot_animation/__init__.py, click Run Script (Alt+P).
|
||||
Option A – Persistent add-on:
|
||||
Zip the pr3tz/ folder (using package_addon.py) and install it from Preferences.
|
||||
Alternatively, copy or symlink the pr3tz/ folder to Blender's addons directory
|
||||
and enable it from Edit → Preferences → Add-ons.
|
||||
The panel appears under the "Pr3tz" tab in the 3-D viewport N-panel.
|
||||
|
||||
Option B – Command line:
|
||||
blender.exe --python knot_animation/__init__.py
|
||||
Option B – Run as a script (via bootstrap runner):
|
||||
Open run_script.py from the workspace root in Blender's Text Editor,
|
||||
and click Run Script (Alt+P).
|
||||
|
||||
Option C – Persistent add-on:
|
||||
Copy the knot_animation/ folder to Blender's addons directory and enable
|
||||
it from Edit → Preferences → Add-ons. The panel appears under the
|
||||
"Pr3tz" tab in the 3-D viewport N-panel.
|
||||
Option C – Command line:
|
||||
blender.exe --python run_script.py
|
||||
"""
|
||||
|
||||
if "bpy" in locals():
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import sys
|
||||
import os
|
||||
import bpy
|
||||
|
||||
# Get the directory of this script (workspace root) and append it to sys.path
|
||||
dir_path = os.path.dirname(os.path.abspath(__file__))
|
||||
if dir_path not in sys.path:
|
||||
sys.path.append(dir_path)
|
||||
|
||||
# Try to register the pr3tz module
|
||||
try:
|
||||
# If the module was already imported, reload it to pick up changes
|
||||
if "pr3tz" in sys.modules:
|
||||
import importlib
|
||||
import pr3tz
|
||||
# Trigger reload inside pr3tz to refresh its submodules
|
||||
importlib.reload(pr3tz)
|
||||
else:
|
||||
import pr3tz
|
||||
|
||||
# Unregister first to clean up any leftover handlers or UI components
|
||||
try:
|
||||
pr3tz.unregister()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Register the addon components
|
||||
pr3tz.register()
|
||||
|
||||
# Run the initial scene setup (creates camera, light, and default playlist)
|
||||
pr3tz.setup_scene()
|
||||
|
||||
# Generate the torus knot for the current frame immediately
|
||||
pr3tz.knot_frame_handler(bpy.context.scene)
|
||||
|
||||
print("[Pr3tz] Registered and scene set up successfully!")
|
||||
print("[Pr3tz] Scrub the timeline or press Space in the Viewport to animate.")
|
||||
except Exception as e:
|
||||
print(f"[Pr3tz] Failed to register: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
Reference in New Issue
Block a user