Skip to content

Commit 75fb1f9

Browse files
docs: v1.6.0 audit — changelog, readme, claude.md, version bump
204 tools, 32 categories. Added actor org, advanced alignment, sign tools, pcg scatter, camera-spawn dashboard entries to all docs.
1 parent d64553d commit 75fb1f9

4 files changed

Lines changed: 102 additions & 10 deletions

File tree

CLAUDE.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import sys; [sys.modules.pop(k) for k in list(sys.modules) if "UEFN_Toolbelt" in
6161
## What This Project Is
6262

6363
**UEFN Toolbelt** is a comprehensive Python automation framework for Unreal Editor for Fortnite (UEFN 40.00+, March 2026).
64-
It runs inside the editor and exposes 171 tools through:
64+
It runs inside the editor and exposes 204 tools through:
6565
- A persistent top-menu entry (`Toolbelt ▾`) in the UEFN editor bar
6666
- An 18-tab PySide6 dark-themed dashboard (`tb.launch_qt()`)
6767
- An MCP HTTP bridge so Claude Code can control UEFN directly
@@ -103,7 +103,7 @@ This file contains every registered tool with its full Python parameter signatur
103103
}
104104
}
105105
```
106-
All 171 tools (100%) return `{"status": "ok"/"error", ...}` structured dicts as of Phase 21. Zero `None` returns remain in the codebase — MCP callers can read every result directly without parsing log output.
106+
All 204 tools (100%) return `{"status": "ok"/"error", ...}` structured dicts as of Phase 21. Zero `None` returns remain in the codebase — MCP callers can read every result directly without parsing log output.
107107

108108
**Schema utility functions** (`schema_utils.py`):
109109
- `schema_utils.validate_property(class_name, prop)` — check if a property exists and is writable
@@ -460,12 +460,44 @@ tb.run("bulk_randomize", rot_range=360.0, randomize_rot=True, randomize_scale=Tr
460460

461461
---
462462

463+
### Advanced Alignment
464+
465+
| Tool | Key Params | What it does |
466+
|---|---|---|
467+
| `align_to_reference` | `axis="Z"`, `reference="first\|last"` | Snap axis to first or last selected actor's position |
468+
| `distribute_with_gap` | `axis="X"`, `gap=0.0` | Exact cm gap between bounding boxes (not pivot-to-pivot) |
469+
| `rotate_around_pivot` | `angle_deg=90`, `axis="Z"`, `pivot="center\|first"` | Orbit selection around center-of-bounds or first actor |
470+
| `align_to_surface` | `offset_z=0.0` | Snap selection to floor with optional Z offset |
471+
| `match_spacing` | `axis="X"` | Even pivot spacing between first and last (endpoints fixed) |
472+
| `align_to_grid_two_points` | `grid_size=100.0` | Local grid from two anchor actors, snap rest to it |
473+
474+
---
475+
476+
### Actor Organization
477+
478+
| Tool | Key Params | What it does |
479+
|---|---|---|
480+
| `actor_attach_to_parent` || Last selected becomes parent of all others (Maya-style) |
481+
| `actor_detach` || Detach selection from parent, preserve world transforms |
482+
| `actor_move_to_folder` | `folder_name` | Move selection to named World Outliner folder |
483+
| `actor_move_to_root` || Strip folder from selection, move to root |
484+
| `actor_rename_folder` | `old_folder`, `new_folder`, `dry_run=False` | Re-path all actors from one folder to another |
485+
| `actor_select_by_folder` | `folder_name` | Select all actors in a named folder |
486+
| `actor_select_same_folder` || Expand selection to all actors sharing the first actor's folder |
487+
| `actor_select_by_class` | `class_filter` | Select all level actors whose class name contains filter |
488+
| `actor_folder_list` || Full folder map with actor counts — great for auditing level structure |
489+
| `actor_match_transform` | `copy_location=True`, `copy_rotation=True`, `copy_scale=False` | Copy transform from first selected to all others |
490+
491+
---
492+
463493
### Foliage / Scatter
464494

465495
| Tool | Key Params | What it does |
466496
|---|---|---|
467-
| `scatter_props` | `asset_path`, `count`, `radius`, `folder="Scatter"` | Individual actor scatter |
468-
| `scatter_hism` | `asset_path`, `count`, `radius`, `folder="Scatter"` | HISM (use for 100+) |
497+
| `scatter_props` | `asset_path`, `count`, `radius`, `center`, `folder="Scatter"` | Individual actor scatter at center |
498+
| `scatter_hism` | `asset_path`, `count`, `radius`, `center`, `folder="Scatter"` | HISM (use for 100+) at center |
499+
| `scatter_avoid` | `asset_path`, `count`, `radius`, `center`, `avoid_class`, `avoid_radius` | Poisson scatter — skips positions within avoid_radius of matching actors |
500+
| `scatter_road_edge` | `asset_path`, `points=[[x,y,z],...]`, `edge_offset`, `spread` | Props along both shoulders of a path. Pass waypoints or select SplineActor |
469501
| `scatter_along_path` | `asset_path`, `points`, `count_per_point=3` | Along path points |
470502
| `scatter_export_manifest` || Export scatter data to JSON |
471503
| `scatter_clear` | `folder="Scatter"` | Remove all scattered actors |
@@ -598,13 +630,20 @@ tb.run("screenshot_focus_selection", width=1920, height=1080, name="prop_focus")
598630

599631
| Tool | Key Params | What it does |
600632
|---|---|---|
601-
| `text_place` | `text`, `location`, `color="#FFFFFF"`, `world_size=100.0` | Place 3D text actor |
633+
| `text_place` | `text`, `location`, `color="#FFFFFF"`, `world_size=100.0` | Place a single 3D text actor |
602634
| `text_label_selection` | `color`, `world_size` | Label each selected actor with its name |
603635
| `text_paint_grid` | `cols=4`, `rows=4`, `cell_size=2000.0` | A1–D4 coordinate grid |
604636
| `text_color_cycle` || Row of team/color labels |
605637
| `text_save_style` | `name`, `color`, `size` | Save a named text style |
606638
| `text_list_styles` || Print saved styles |
607639
| `text_clear_folder` || Delete all toolbelt text actors |
640+
| `sign_spawn_bulk` | `count`, `text`, `prefix`, `location`, `layout="row_x\|row_y\|grid"`, `spacing`, `cols`, `color`, `world_size` | Spawn N TextRenderActor signs in a row/grid. **Not Billboard devices.** |
641+
| `sign_batch_edit` | `text`, `color`, `world_size` | Edit selected signs — only fields you pass are changed |
642+
| `sign_batch_set_text` | `texts=[...]` | Assign individual text to each selected sign in order |
643+
| `sign_batch_rename` | `prefix`, `start=1`, `sync_text=False` | Rename selected signs sequentially |
644+
| `sign_list` | `folder=""` | List all TextRenderActors with their text |
645+
| `sign_clear` | `folder="Signs"`, `dry_run=False` | Delete signs in folder |
646+
| `label_attach` | `offset_z=150`, `yaw=0`, `color`, `world_size`, `use_actor_name=True` | Spawn floating label above each selected actor, parented so it follows. Great for NPC name tags. |
608647

609648
---
610649

@@ -725,7 +764,7 @@ tb.run("config_reset", key="all") # wipe all customisations
725764
|---|---|---|
726765
| `plugin_validate_all` || Validate all registered tools against schema |
727766
| `plugin_list_custom` || List all loaded third-party tools from `Saved/UEFN_Toolbelt/Custom_Plugins` |
728-
| `plugin_export_manifest` || Export `tool_manifest.json` — machine-readable index of all 171 tools with full parameter signatures (name, type, required, default) for AI-agent and automation use |
767+
| `plugin_export_manifest` || Export `tool_manifest.json` — machine-readable index of all 204 tools with full parameter signatures (name, type, required, default) for AI-agent and automation use |
729768

730769
**Online Plugin Hub** — the Plugin Hub dashboard tab fetches `registry.json` live from GitHub.
731770
- **Core Tools** (green/BUILT-IN): 10 flagship modules by Ocean Bennett, already built in

Content/Python/UEFN_Toolbelt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
# Single source of truth — used in audit logs, reload messages, and manifests.
3030
# Bump this when shipping a release so plugin_audit.json records which version
3131
# of the platform each plugin was loaded against.
32-
__version__ = "1.5.3"
32+
__version__ = "1.6.0"
3333

3434
# API contract version — plugins declare MIN_TOOLBELT_VERSION = "x.y.z" to
3535
# signal the oldest platform release they support. Checked at load time.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# UEFN TOOLBELT
2-
**179 Professional Tools for UEFN Python Integration.**
2+
**204 Professional Tools for UEFN Python Integration.**
33

44
> Built by **Ocean Bennett** — 2026
55
66
[![CI](https://github.com/undergroundrap/UEFN-TOOLBELT/actions/workflows/ci.yml/badge.svg)](https://github.com/undergroundrap/UEFN-TOOLBELT/actions/workflows/ci.yml)
77
[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)
8-
[![Version](https://img.shields.io/badge/version-1.5.6-green.svg)](docs/CHANGELOG.md)
8+
[![Version](https://img.shields.io/badge/version-1.6.0-green.svg)](docs/CHANGELOG.md)
99
[![Discussions](https://img.shields.io/badge/community-discussions-blueviolet)](https://github.com/undergroundrap/UEFN-TOOLBELT/discussions)
1010

1111
![UEFN Toolbelt Dashboard](docs/dashboard_hero.png)
@@ -37,7 +37,7 @@ Automate the tedious, script the impossible, and bridge the gap between Python a
3737
UEFN Toolbelt is a master utility designed to leverage the **2026 UEFN Python 3.11 Update**,
3838
allowing creators to manipulate actors, manage assets, and generate boilerplate Verse code
3939
through a high-level, developer-friendly interface — all from a single persistent menu entry
40-
in the UEFN editor bar. **179 registered tools** across 30 categories, complete AI-agent
40+
in the UEFN editor bar. **204 registered tools** across 32 categories, complete AI-agent
4141
readiness (100% structured dict returns), and a unified theme system so every window in the
4242
platform looks and feels identical.
4343

docs/CHANGELOG.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,59 @@ Format: `## [version] — date` · Types: `feat` · `fix` · `refactor` · `docs
55

66
---
77

8+
## [1.6.0] — 2026-03-23
9+
10+
### feat: actor organization, advanced alignment, sign tools, PCG scatter, camera-spawn
11+
12+
**New modules — 33 new tools (171 → 204):**
13+
14+
- **`sign_tools.py`** (7 tools) — TextRenderActor signs, NOT Fortnite Billboard devices.
15+
`sign_spawn_bulk`: spawn N signs in row/column/grid at camera. `sign_batch_edit`: change
16+
text/color/size on all selected signs at once. `sign_batch_set_text`: assign individual
17+
strings per sign. `sign_batch_rename`: sequential rename with optional text sync.
18+
`sign_list` / `sign_clear`: audit and cleanup. `label_attach`: floating text label above
19+
selected actor, parented so it follows — perfect for NPC name tags. Supports yaw rotation.
20+
21+
- **`actor_org_tools.py`** (10 tools) — Full actor organization suite.
22+
`actor_attach_to_parent`: last-selected becomes parent, Maya-style. `actor_detach`: detach
23+
preserving world transforms. `actor_move_to_folder` / `actor_move_to_root`: one-click folder
24+
management. `actor_rename_folder`: re-path all actors in a folder. `actor_select_by_folder` /
25+
`actor_select_same_folder` / `actor_select_by_class`: selection helpers. `actor_folder_list`:
26+
full folder map with actor counts. `actor_match_transform`: copy loc/rot/scale from first
27+
selected to all others.
28+
29+
- **`advanced_alignment.py`** (6 tools) — Beyond the basic bulk_align/bulk_distribute.
30+
`align_to_reference`: snap axis to first/last selected actor's position.
31+
`distribute_with_gap`: exact cm gap between bounding boxes (not pivot-to-pivot).
32+
`rotate_around_pivot`: orbit selection around center-of-bounds or first actor.
33+
`align_to_surface`: snap_objects_to_floor with Z offset. `match_spacing`: even pivot
34+
spacing between endpoints. `align_to_grid_two_points`: local grid from two anchor actors.
35+
36+
- **`foliage_tools.py`** additions (2 tools) — PCG-style scatter.
37+
`scatter_avoid`: Poisson scatter with obstacle rejection (avoid_class / avoid_radius filters).
38+
`scatter_road_edge`: place props along both shoulders of a path defined by waypoints or
39+
SplineActor — resamples at spacing intervals, offsets perpendicular to tangent.
40+
41+
**Dashboard improvements:**
42+
- All spawn/scatter/pattern buttons now read viewport camera position at click time
43+
- Fixed `lambda s=s:` bug: PySide6 `clicked(bool)` signal was overriding loop variable
44+
- Fixed pattern buttons: was passing `center=` but tools expect `origin=`
45+
- PCG Scatter group added to Procedural tab
46+
- Advanced Alignment + Actor Organization groups added to Bulk Ops tab
47+
- Sign Spawner, Sign Batch Edit, Floating Label Attach groups added to Text tab
48+
49+
**Fixes:**
50+
- `scatter_avoid` with no filter was treating all 2000 level actors as obstacles — now
51+
requires at least one filter to be set
52+
- `scatter_road_edge` rewritten to accept `points=[[x,y,z],...]` waypoint list — no
53+
SplineActor required
54+
- Arena buttons: `apply_team_colors=True` was landing as `size` arg due to signal bool —
55+
fixed with `lambda *_, s=s:`
56+
- `sign_tools` naming: all tools renamed from `billboard_*` to `sign_*` to avoid confusion
57+
with Fortnite Billboard devices (V2, not Python-controllable)
58+
59+
---
60+
861
## [1.5.3] — 2026-03-22
962

1063
### feat: online plugin hub, describe_tool mcp command, attribution

0 commit comments

Comments
 (0)