# Processing from Python

> Human Generator for Blender documentation. Web version: https://humgen3d.com/docs/process/python-api

> **Early access**
> The process system is new and only in the early access version of Human Generator. It replaces the process tab of version 4.0, which is deprecated. Details can still change; if something doesn't work or looks wrong, [let us know](https://humgen3d.com/feedback/process).

Everything the Process tab does is available from Python, through `human.process`. The settings of the tab are one object, [ExportSettings](https://humgen3d.com/docs/api/exportsettings), and one call processes a human with them, so a build step or a render farm can export characters without anyone clicking. This page walks through the common cases; the reference is on [ProcessSettings](https://humgen3d.com/docs/api/processsettings) and [ExportSettings](https://humgen3d.com/docs/api/exportsettings), and the [Python API guide](https://humgen3d.com/docs/api) covers the rest of the add-on.

## Run a recipe

```python
import bpy
from HumGen3D import ExportSettings, Human

human = Human.from_existing(bpy.context.object)

settings = ExportSettings.from_recipe("unity")   # "unity", "unreal", "godot", "mixamo", "generic", "blender"
settings.output.folder = "/path/to/MyGame/Assets/Characters"

result = human.process.run(settings)
print(result.files)        # ['/path/to/MyGame/Assets/Characters/Jake.fbx']
print(result.summary())    # what the popup shows, with the triangle count and warnings
```

`run` does exactly what the button does: the human is not changed, a processed copy is made per LOD level, written to the files and removed again. The [ExportResult](https://humgen3d.com/docs/api/exportresult) tells what was made: `files`, the processed `humans` left in the file, `warnings`, the `triangles` per level and the `seconds` it took.

Recipes of your own are loaded by their path inside the `process_templates` folder of the content folder, `ExportSettings.from_recipe("MyGame/Mobile characters.json")`, or by any absolute path.

## Change the settings

The settings mirror the sections of the tab. Every field has the same name and values as the [recipe file](https://humgen3d.com/docs/process/recipes):

```python
from HumGen3D import ExportSettings, QualitySettings

settings = ExportSettings.from_recipe("unreal")
settings.output.format = "glb"                 # see Output
settings.output.name = "Hero_{name}"
settings.lods = [QualitySettings.from_tier("high"), QualitySettings.from_tier("low")]
settings.meshes.remove_hidden_skin = False
settings.haircards.enabled = False
settings.skeleton.names = "humanoid"
settings.skeleton.rest_pose = "t_pose"
settings.shape_keys.body = "keep"
settings.textures.set_resolution_tier("1k")
settings.textures.workflow = "metallic_roughness"
```

Or start from the defaults with `ExportSettings()` and set what you need. The classes per section: [OutputSettings](https://humgen3d.com/docs/api/outputsettings), [QualitySettings](https://humgen3d.com/docs/api/qualitysettings), [MeshSettings](https://humgen3d.com/docs/api/meshsettings), [HaircardSettings](https://humgen3d.com/docs/api/haircardsettings), [SkeletonSettings](https://humgen3d.com/docs/api/skeletonsettings), [ShapeKeySettings](https://humgen3d.com/docs/api/shapekeysettings), [TextureBakeSettings](https://humgen3d.com/docs/api/texturebakesettings) and [ScriptsSettings](https://humgen3d.com/docs/api/scriptssettings). `settings.to_dict()` and `ExportSettings.from_dict()` turn them into plain data, `settings.save_recipe("MyGame", "Hero")` saves them as a recipe for the interface.

## Check before running

The tab's red and grey lines come from `preflight`. Use it to validate settings without changing anything:

```python
check = human.process.preflight(settings)
if not check.ok:
    print("\n".join(check.errors))     # these would make run() raise
for warning in check.warnings:
    print("warning:", warning)
```

`run` raises a `HumGenException` when the preflight finds an error. Without the [Export pack](https://humgen3d.com/docs/process#hg-export-pack-missing), `run`, `preflight`, `ExportSettings.from_recipe` and the single steps raise `ExportPackMissing`, a `HumGenException` that says what to download. When a step fails, its own exception comes through unchanged. In both cases the copies made so far are removed.

## Several humans

Every human in the scene, with the same settings:

```python
from HumGen3D.common import find_multiple_in_list

rigs = find_multiple_in_list(bpy.context.scene.objects)
for human in (Human.from_existing(rig) for rig in rigs):
    result = human.process.run(settings)
    print(human.name, result.files)
```

## Progress

`run` accepts a callback that gets the fraction done, for a progress bar of your own:

```python
result = human.process.run(settings, progress=lambda fraction: print(f"{fraction:.0%}"))
```

For a modal operator that must keep Blender responsive, `human.process.run_steps(settings)` gives the same work as a generator that yields the fraction after every short chunk; that is what the Process button uses.

## From the command line

Blender in background mode, for a build step or a render farm. The add-on must be enabled in the Blender preferences of the machine. Tested with Blender 5.1: the script below exports a dressed human with hair cards to glb in about a minute, textures baked included:

```bash
blender -b characters.blend --python export_characters.py
```

```python
# export_characters.py
import bpy
from HumGen3D import ExportSettings, Human
from HumGen3D.common import find_multiple_in_list

settings = ExportSettings.from_recipe("godot")
settings.output.folder = "/builds/characters"

for rig in find_multiple_in_list(bpy.context.scene.objects):
    human = Human.from_existing(rig)
    result = human.process.run(settings, context=bpy.context)
    print(result.summary())
```

> **Passing context**
> As everywhere in the API, `context` is optional and `bpy.context` is used when you leave it out. Inside an operator or an add-on of your own, pass the context you were given. See [Overview › Passing context](https://humgen3d.com/docs/api#passing-context).

> **Did it run in background mode?**
> The command, the Blender version and the console output, when it did not. [Tell us](https://humgen3d.com/feedback/process?page=python-api&step=command-line).

## The single steps

`run` is a sequence of steps, each a method of [ProcessSettings](https://humgen3d.com/docs/api/processsettings) that takes the matching section of the settings, or plain arguments. You can call them yourself, for example to make a game-ready copy without exporting it, or to insert something between two steps.

> **The steps change the human they are called on**
> They can't be undone, so call them on a `human.duplicate()`, never on the original.

```python
from HumGen3D import QualitySettings, SkeletonSettings

copy = human.duplicate()
copy.process.set_shape_keys(body="keep", face="bake", age="bake")
copy.process.convert_to_haircards("medium")
copy.process.bake_textures(settings.textures, folder="/path/to/textures")
copy.process.set_quality(QualitySettings.from_tier("medium"))
copy.process.convert_to_game_rig(settings=SkeletonSettings(names="humanoid", rest_pose="t_pose"))
copy.process.apply_names()
copy.export.write("/path/to/Jake", settings.output)  # a file format; "in_file" raises
# or, to keep it in the file as a frozen result:
copy.process.mark_as_processed(human)
```

The order is the one `run` uses, and it matters:

1. **set_shape_keys**: First, so the later steps carry only the keys that stay
2. **convert_to_haircards**: Hair cards, game eyes and teeth before baking, as they change the materials
3. **bake_textures**: Before the meshes are reduced
4. **set_quality**: After baking
5. **convert_to_game_rig**: After the meshes
6. **apply_names**: Last

The steps with a `has_*` or `was_*` property (hair cards, baking, the game rig, the T-pose) refuse to run twice; the other steps run again. For one file with several LOD levels, make one copy per level and join them with [ProcessSettings › merge_levels](https://humgen3d.com/docs/api/processsettings#merge_levels).

Two more steps exist for scripts: [ProcessSettings › apply_modifiers](https://humgen3d.com/docs/api/processsettings#apply_modifiers) applies modifiers while keeping the shape keys, which Blender itself refuses, and [ProcessSettings › remove_hidden_skin](https://humgen3d.com/docs/api/processsettings#remove_hidden_skin) deletes the body under the clothing. To write a human to a file without any processing, use [ExportBuilder](https://humgen3d.com/docs/api/exportbuilder) (`human.export.to_fbx`, `to_glb`, `to_gltf_separate`, `to_obj`, `to_abc`).

## Reading a processed human

```python
copy = Human.from_existing(bpy.context.object)
copy.process.is_processed        # True for a frozen result
copy.process.settings            # the ExportSettings it was made with, None otherwise
```

> **Scripts in the interface**
> If you want your code to run as part of a recipe that others use from the Process tab, write it as a [script](https://humgen3d.com/docs/process/scripts): a file with a `main(context, human)` function that runs at a stage of the process.

> **Something missing from the API?**
> A step you had to work around, or a setting the recipe cannot hold. [Tell us](https://humgen3d.com/feedback/process?page=python-api&step=api).

## Frequently asked questions

### Can I export Human Generator characters without opening Blender's interface?

Yes. Run Blender in background mode with a script that loads a recipe and calls `human.process.run` for every human in the file. The add-on has to be enabled in the Blender preferences of that machine.

### Can I process the humans the batch generator made?

Yes. Find them with `find_multiple_in_list` on the scene objects and run the same settings on each, or select them all in the Process tab and press the button once.
