HammerForge Data Portability¶
Last updated: September 2, 2026
This document describes how to move data in and out of HammerForge safely.
Source of Truth: .hflevel¶
.hflevelfiles are the canonical save format for brushes, paint layers, materials, entities, and settings.- When region streaming is enabled, per-region paint data is stored in a sibling
<level>.hfregions/folder. - Files include a version field and default missing keys on load for backward compatibility.
- Per-face UV data includes
uv_format_version(current: 1). Legacy data (version 0, pre-April 2026) used a different UV transform order (scale+offset before rotation). On load, legacy faces are auto-migrated: uniform-scale faces get their offset adjusted; non-uniform-scale faces with rotation are baked tocustom_uvs. No manual intervention is needed. - Per-face vertex winding includes
winding_version(current: 1). Legacy data (version 0, pre-April 2026) used CCW vertex winding for manually-created faces, which rendered inside-out under Godot 4's CW front-face convention. On load,apply_serialized_faces()detects v0 faces and runs a centroid-based migration: each face's normal is checked against the outward direction from the brush center, and faces pointing inward have their vertices reversed to CW. Mesh-extracted faces (already CW) are left unchanged. No manual intervention is needed. - Autosaves write to
res://.hammerforge/autosave.hflevelby default. - Store
.hflevelin version control for reliable recovery.
Entity I/O Serialization¶
- Entity I/O connections are stored per-entity in the
io_outputskey of each entity record. - Each connection is a Dictionary:
{output_name, target_name, input_name, parameter, delay, fire_once}. - Connections are captured by
capture_entity_info()and restored byrestore_entity_from_info(). - Missing
io_outputskey on load = no connections (backward-compatible).
Brush Entity Class Serialization¶
- Brush entity class (
func_detail,func_wall,trigger_once,trigger_multiple) is stored in thebrush_entity_classkey of each brush record. - Missing key on load = no entity class (standard structural brush).
.map Import / Export¶
- Use
.mapto exchange basic brush layouts with other editors. - Axis-aligned boxes use the optimized primitive path; tilted, clipped, and other non-axis-aligned convex brushes import and export as CUSTOM face geometry.
- Point-entity key/value properties and brush entity classes round-trip through the supported Classic Quake and Valve 220 adapters.
- Per-face materials and HammerForge surface-paint layers are not preserved, so
.hflevelremains the editable source of truth. - Treat
.mapas a blockout exchange format, not a full fidelity export. - Multi-format export: Classic Quake and Valve 220 format adapters are available via the format selector in the dock File section. Valve 220 includes UV texture axes from FaceData.
- Known limitation: quoted entity property values containing escaped quotes or backslashes do not yet round-trip reliably; follow #32 for that parser fix.
Import Vertex Welding¶
Legacy .map files from Hammer, TrenchBroom, and other editors often carry floating-point representation drift in vertex coordinates. Two vertices that should be coincident may differ by a fraction of a unit, producing micro-gaps or non-planar faces after import.
MapIO.parse_map_text() automatically welds near-coincident parsed vertices before constructing brush geometry. The tolerance is controlled by MapIO.import_weld_tolerance (default 0.01 units). Vertices within this distance are averaged to a shared position via BFS grouping over a spatial hash with 27-cell neighbor lookup, so pairs that straddle a snap-grid boundary are still caught.
To adjust the tolerance:
MapIO.import_weld_tolerance = 0.05 # increase for very noisy legacy files
MapIO.import_weld_tolerance = 0.0 # disable welding entirely
After import, run Check Only (Test tab) to detect any remaining non-planar faces or micro-gaps between brushes. The validation system offers auto-fix methods (weld_brush_vertices, fix_non_planar_faces) for post-import cleanup.
.glb Export¶
.glbexport writes the baked geometry only.- A successful bake is required before export.
- Use
Bake -> Export .glbwhen you need DCC or engine interoperability.
Material Library¶
- The material palette can be saved and loaded independently via
MaterialManager.save_library()/load_library(). - Library files are JSON containing material resource paths — portable across projects.
- The library path can be stored alongside
.hflevelsaves.
Prototype Textures¶
- HammerForge ships with 150 built-in SVG prototype textures at
addons/hammerforge/textures/prototypes/. - Click Refresh Prototypes in Paint tab → Materials section to batch-load all textures into the palette.
- Once loaded, prototype materials are serialized in
.hflevelsaves alongside custom materials. - Prototype textures are included in the plugin directory and travel with the project automatically.
Entity Definitions¶
- Entity types and brush entity classes are loaded from
entities.json(data-driven, not hardcoded). - Custom entity definitions can be added by creating or editing
res://addons/hammerforge/entities.json. - Definitions include
classname,description,color,is_brush_entity,properties, and optionalscene_path.
Prefabs: .hfprefab¶
.hfprefabfiles store reusable brush + entity groups as JSON.- Transforms are stored relative to the group centroid, so prefabs can be placed at any world position.
- Brush IDs and group IDs are stripped on capture; new ones are assigned on instantiation.
- Entity I/O connections are captured and remapped to new entity names when instantiated.
- Data encoding uses the same
HFLevelIO.encode_variant()/decode_variant()pipeline as.hflevel(handles Vector3, Transform3D, Basis, etc.). - Prefab files are saved to
res://prefabs/by default. The directory is created automatically on first save. - Prefabs are portable between projects — just copy
.hfprefabfiles to another project'sres://prefabs/folder.
Autosave Safety¶
- Autosave writes happen on a background thread.
- Saves first write a
.writingsidecar, then replace the destination. - If a write fails (e.g., disk full, permissions), the
autosave_failedsignal fires and the dock shows a red warning label. - The next autosave interval retries automatically.
- Manual save is always available via Test tab → File section.
- Current limitation: replacement removes an existing destination before renaming the sidecar, so interruption in that window is not fully crash-atomic (#33). Manual save can also report that work was queued before the background write completes (#51). Keep
.hflevelfiles in version control and treat the warning state—not the initial queued message—as the authoritative failure signal.
Recommended Pipeline¶
- Design and iterate in HammerForge.
- Save
.hflevelto preserve full fidelity editing data. - Bake when you need runtime geometry.
- Export
.glbfor downstream tools or external engines.