MakeSkinMaterial

February 21, 2026 · View on GitHub

Overview

MakeSkinMaterial extends MhMaterial and bridges the MHMAT format with Blender's node-based material system for the MakeSkin workflow.

See the MHMAT file format reference and Material settings for related format documentation.

Import direction (MHMAT → Blender)

apply_node_tree loads the makeskin.json node-tree template from the MPFB data directory, substitutes $variable placeholders with texture paths and colour values derived from the current MHMAT settings, and applies the resulting node tree to a Blender material using NodeService.

Export direction (Blender → MHMAT)

populate_from_object reads texture nodes and Principled BSDF socket values from an existing Blender object's node tree, populating _settings so that as_mhmat (inherited from MhMaterial) can serialise them. export_to_disk then writes the MHMAT file and optionally copies all referenced textures into the target directory with normalised names.

Source

src/mpfb/entities/material/makeskinmaterial.py

Dependencies

DependencyUsage
bpyNode tree access, image creation
MhMaterialBase class
MHMAT_KEYSFull key catalog for default values during populate_from_object
LogServiceLogging via LogService.get_logger("material.makeskinmaterial")
LocationServiceLocating the makeskin.json node-tree template and data directories
NodeServiceNode tree application, node lookup, UV map node creation
MaterialServiceEmpty material creation

Public API

__init__(importer_presets=None)

Initialise MakeSkinMaterial with optional importer preset values.

ArgumentTypeDefaultDescription
importer_presetsdict or NoneNonePreset dictionary from the importer UI; stored in self.presets

Returns: None.


apply_node_tree(blender_material, template_values=None)

Apply the makeskin.json node-tree template to a Blender material.

If template_values is None, the method builds the dict automatically by scanning self._settings for each texture type (diffuse, normal map, bump map, AO, roughness map, metallic map, etc.) and colour values. Placeholders of the form "$key" in the JSON template are replaced with the computed values before the JSON is parsed.

ArgumentTypeDefaultDescription
blender_materialbpy.types.MaterialThe Blender material whose node tree will be replaced
template_valuesdict or NoneNonePre-built substitution dict; if None, built automatically from self._settings

Returns: None.

Raises: ValueError if the JSON template cannot be parsed after variable substitution (indicates a malformed template value).


ensure_uvmap_node_for_texture_nodes(blender_object)

Add a ShaderNodeUVMap node upstream of any texture node in the material that does not already have a UV input connected.

The new UV Map node is positioned 300 units to the left and 200 units below the texture node and linked to the object's first UV layer.

ArgumentTypeDefaultDescription
blender_objectbpy.types.ObjectObject whose first material slot provides the node tree

Returns: None.


populate_from_object(blender_object)

Extract material settings from an existing Blender object's node tree and populate self._settings.

Scans all recognised texture node names to set file paths. Reads socket values from Principled BSDF (base colour, metallic, IOR, roughness) and from the diffuseIntensity mix node if present. Reads SSS radius from Principled BSDF and sss_enable from MakeSkinObjectProperties. Metadata and miscellaneous settings are read from MakeSkinObjectProperties on the object.

ArgumentTypeDefaultDescription
blender_objectbpy.types.ObjectObject whose first material slot is the source

Returns: None.


check_that_all_textures_are_saved(blender_object, mhmat_dir=None, mhmat_bn=None)

Validate that every texture node in the material has a saved image on disk.

If a texture node has an unsaved image and both mhmat_dir and mhmat_bn are provided, the image is automatically saved to <mhmat_dir>/<mhmat_bn>_<type>.png and the corresponding _settings entry is updated.

ArgumentTypeDefaultDescription
blender_objectbpy.types.ObjectObject whose first material slot is checked
mhmat_dirstr or NoneNoneTarget directory for auto-saving unsaved images
mhmat_bnstr or NoneNoneBase name prefix for auto-saved images

Returns: None if all textures are saved; otherwise an error message str describing the first problem found.


export_to_disk(mhmat_path, normalize_textures=True)

Write the material to disk as an MHMAT file, optionally normalising and copying all texture files.

When normalize_textures=True, each texture referenced in _settings is copied to the same directory as mhmat_path with a name derived from the MHMAT base name and texture type (e.g. myshirt_diffuse.png). The _settings entries are updated to the new basenames before serialisation.

ArgumentTypeDefaultDescription
mhmat_pathstrFull path of the output .mhmat file
normalize_texturesboolTrueIf True, copy and rename textures alongside the MHMAT file

Returns: None.


create_makeskin_template_material(blender_object, scene, name="MakeSkinMaterial") (static)

Create a new Blender material from the MakeSkin template, driven by MAKESKIN_PROPERTIES scene settings.

Scene properties control which texture slots are included (create_<type> flags) and the image resolution for new texture images. New blank images are created and assigned to the appropriate texture nodes for each enabled slot.

ArgumentTypeDefaultDescription
blender_objectbpy.types.ObjectObject that will receive the new material
scenebpy.types.SceneScene providing MAKESKIN_PROPERTIES configuration
namestr"MakeSkinMaterial"Name for the new Blender material

Returns: None.

Raises: ValueError if blender_object or scene is None.


Examples

Import: apply MHMAT to a Blender material

import bpy
from mpfb.entities.material.makeskinmaterial import MakeSkinMaterial

mat = MakeSkinMaterial()
mat.populate_from_mhmat("/path/to/skin.mhmat")

blender_material = bpy.data.materials.new(name="SkinMaterial")
blender_material.use_nodes = True

mat.apply_node_tree(blender_material)

Export: write a Blender material to an MHMAT file

import bpy
from mpfb.entities.material.makeskinmaterial import MakeSkinMaterial

obj = bpy.context.active_object
mat = MakeSkinMaterial()
mat.populate_from_object(obj)

error = mat.check_that_all_textures_are_saved(
    obj,
    mhmat_dir="/path/to/output",
    mhmat_bn="myshirt"
)
if error:
    print("Problem:", error)
else:
    mat.export_to_disk("/path/to/output/myshirt.mhmat")