FPS-style level editor plugin for Godot 4.6+
Brush-based greyboxing and fast bake workflows inside the editor.
HammerForge brings classic brush workflows (Hammer / TrenchBroom style) into Godot. Draw draft brushes, preview quickly, and bake to optimized meshes only when needed.
| Concept | Description |
|---|---|
| DraftBrush | Lightweight, editable brush nodes |
| Bake | CSG used only at bake time for performance |
| Floor Paint | Grid-based tool that generates floors/walls with optional heightmap terrain |
| Face Materials | Per-face materials, UVs, and surface paint layers |
- Two-stage CAD drawing -- drag base, then click height
- Add / Subtract operations with pending cut staging
- Extrude Up / Down -- click a face and drag to extend brushes vertically
- Shape palette -- box, cylinder, sphere, cone, wedge, pyramid, prisms, ellipsoid, capsule, torus, and platonic solids
- Grid snapping with quick presets and axis locks
- Resize gizmo with full undo/redo support
- Materials palette (dock) with add/remove and per-face assignment
- 150 built-in prototype textures (15 patterns x 10 colors) -- one-click Load Prototypes in the Paint tab for instant greyboxing materials
- Face select mode for per-face material painting
- UV editor with per-vertex drag handles and reset-to-projection
- Face data persists in
.hflevelsaves
- Paint target switch: Floor or Surface
- Per-face splat layers with weight images
- Live preview on DraftBrushes (per-face composite)
- Per-layer texture picker and adjustable radius/strength
- Grid-based paint layers with chunked storage
- Tools: Brush, Erase, Rect, Line, Bucket, Blend
- Brush shape: Square or Circle
- Live preview while dragging
- Greedy-meshed floors and merged wall segments
- Stable IDs with scoped reconciliation (no node churn)
- Paint layers persist in
.hflevelsaves - Heightmaps: import PNG/EXR or generate procedural noise per layer
- Displaced meshes: per-vertex heightmap displacement via SurfaceTool
- Material blending: four-slot shader with per-cell blend weights (UV2 blend map, RGB = slots B/C/D)
- Region streaming: sparse loading of paint chunks for large worlds
- Auto-connectors: ramp and stair mesh generation between layers
- Foliage scatter: height/slope-filtered MultiMeshInstance3D placement
- Hollow (Ctrl+H) -- convert solid brushes to hollow rooms with configurable wall thickness
- Clip (Shift+X) -- split brushes along an axis-aligned plane into two pieces
- Brush Entity Classes -- Tie/Untie brushes as func_detail, func_wall, trigger volumes (color-coded viewport overlays)
- Entity I/O -- Source-style input/output connections (output → target.input with parameter, delay, fire-once)
- Move to Floor/Ceiling (Ctrl+Shift+F/C) -- snap brushes to nearest surface
- Numeric Input -- type exact dimensions during drag or extrude
- UV Justify -- fit/center/left/right/top/bottom alignment for selected faces
- Visgroups -- named visibility groups (e.g. "walls", "detail", "lighting") with per-group show/hide toggle
- Brush/Entity Grouping -- persistent groups that select/move together (Ctrl+G / Ctrl+U)
- Texture Lock -- UV alignment preserved automatically when moving or resizing brushes
- Cordon (Partial Bake) -- restrict bake to an AABB region with yellow wireframe visualization
- Sticky LevelRoot -- selecting other scene nodes no longer breaks viewport input
- 4-tab dock (Brush, Paint, Entities, Manage) with collapsible sections (separators, indented content, persisted state)
- Mode indicator banner -- color-coded banner shows current tool, gesture stage ("Step 1/2: Draw base"), and numeric input
- Toast notifications -- transient messages surface save/load/bake results and errors in the dock
- First-run welcome panel -- 5-step quick-start guide on first launch
- Context hints -- per-tab guidance labels that update based on scene state
- Shortcuts quick-reference -- "?" toolbar button shows all keybindings in a popup
- Face hover highlights -- extrude mode previews which face you'll select (green/red overlay)
- Contextual Selection Tools in Brush tab -- hollow, clip, move, tie, duplicator appear when brushes are selected
- Readable toolbar with icon + text labels (Draw, Select, Add, Sub, Paint, Ext Up, Ext Dn) and descriptive tooltips
- Inline disabled hints -- "Select a brush to use these tools" visible without hovering
- Instant sync -- paint layer, material, and surface paint changes reflected immediately (signal-driven)
- Context-sensitive shortcut HUD that updates based on current tool and mode
- Customizable keymaps -- all shortcuts data-driven via JSON; rebind any key
- User preferences -- grid defaults, recent files, collapsed sections, welcome state persist across sessions
- Tool poll system -- buttons gray out with inline hints when action can't run
- Paint tool shortcuts: B / E / R / L / K for Brush / Erase / Rect / Line / Bucket
- Extrude shortcuts: U (Extrude Up), J (Extrude Down)
- Brush tool shortcuts: Ctrl+H (Hollow), Shift+X (Clip), Ctrl+Shift+F/C (Floor/Ceiling)
- Group shortcuts: Ctrl+G (Group), Ctrl+U (Ungroup)
- Tooltips on all dock controls with shortcut hints
- Selection count in the status bar with clear (x) button
- Color-coded status bar (red errors, yellow warnings, auto-clear)
- Pending cuts visually distinct (orange-red glow) from applied cuts
- "No LevelRoot" banner guides users when no root node is found
- Editor theme parity, high-contrast grid with follow mode
- History panel (beta) and live brush count
- Entity palette with drag-and-drop placement
- Bake Dry Run and Validate Level actions
- Performance panel with brush, paint, and bake stats
- Settings export/import for editor preferences
- Bake draft brushes to meshes + collision
- Optional: merge meshes, LOD generation, UV2 unwrap, navmesh baking
- Optional: Use Face Materials (bake per-face materials without CSG)
- Heightmap floors bake directly (bypass CSG) with trimesh collision
- Chunked baking via
LevelRoot.bake_chunk_size - Cordon bake -- restrict bake to an AABB region (skip brushes outside the cordon)
- Bake progress bar with chunk status updates
- Playtest button -- bakes and runs with an FPS controller
LevelRootis a thin coordinator delegating to 10 subsystem classes (grid, entity, brush, drag, bake, paint, state, file, validation, visgroup)- Central signal registry -- 14 signals on LevelRoot for event-driven UI updates
- Batched signal emission -- multi-brush operations coalesce signals to prevent UI thrash
- Tag-based invalidation -- dirty tags on brushes/paint/chunks for selective reconciliation
- Command collation -- rapid operations (nudge, resize, paint) merge into single undo entries
- Transaction support -- atomic multi-step operations with rollback
- Customizable keymaps -- all shortcuts data-driven via
HFKeymap; rebind via JSON - User preferences -- persistent cross-session prefs separate from per-level settings
- Declarative tool settings -- external tools expose schema; dock auto-generates UI controls
- Tool poll system --
can_activate()/get_poll_fail_reason()for context-aware tool availability - Entity definitions -- data-driven entity types from JSON (extensible, not hardcoded)
- Material library persistence -- save/load material palettes with usage tracking
- Autosave failure notification -- threaded write errors surface to the UI
- Gesture tracker pattern -- base class for self-contained input tool gestures
- Explicit input state machine for drag/paint operations
- Type-safe inter-module calls (no duck-typing)
- Threaded .hflevel I/O with error handling
- CI: automated
gdformat+gdlintchecks and GUT unit tests (371 tests) on push/PR
1. Copy addons/hammerforge into your project
2. Enable the plugin: Project → Project Settings → Plugins → HammerForge
3. Open a 3D scene and click in the viewport to auto-create LevelRoot
For upgrade steps and cache reset help, see docs/HammerForge_Install_Upgrade.md.
| Step | Action |
|---|---|
| 1. Draw a brush | Tool = Draw, Mode = Add, Shape = Box -> drag base -> click height |
| 2. Extrude a wall | Tool = Extrude Up (U) -> click face -> drag up -> release |
| 3. Cut a door | Mode = Subtract -> draw brush -> Apply Cuts -> Bake |
| 4. Face materials | Paint tab -> Materials section -> Load Prototypes (or Add -> pick materials/test_mat.tres) -> Face Select Mode -> click faces -> Assign material |
| 5. Surface paint | Paint Mode -> Paint tab -> Surface Paint section -> Paint Target = Surface -> paint |
| 6. Bake | Manage tab -> Bake section -> Click Bake (or enable Use Face Materials) |
| Document | Description |
|---|---|
| User Guide | Complete usage documentation |
| MVP Guide | Minimum viable product scope |
| Install + Upgrade | Setup, upgrade, and cache reset |
| Design Constraints | Explicit tradeoffs and limits |
| Data Portability | .hflevel/.map/.glb workflow |
| Demo Clips | Clip list and naming scheme |
| Sample Levels | Minimal and stress test scenes |
| Texture + Materials | Face materials, UVs, and surface paint |
| Prototype Textures | Built-in 150 SVG textures for greyboxing |
| Development + Testing | Local setup and test checklist |
| Floor Paint Design | Grid paint system design |
| Spec | Technical specification |
| Changelog | Version history |
| Roadmap | Planned features |
| Contributing | Contribution guidelines |
See ROADMAP.md for planned work and priorities.
Capture exit-time errors (PowerShell)
Start-Process -FilePath "C:\Godot\Godot_v4.6-stable_win64.exe" `
-ArgumentList '--editor','--path','C:\hammerforge' `
-RedirectStandardOutput "C:\Godot\godot_stdout.log" `
-RedirectStandardError "C:\Godot\godot_stderr.log" `
-NoNewWindow
MIT License
Last updated: March 24, 2026
