MHMAT key system

February 21, 2026 · View on GitHub

Overview

The MHMAT key system is implemented across two source files that together form the parsing infrastructure used by MhMaterial:

  • mhmatkeytypes.py — defines a type hierarchy of key-parser classes. Each class knows how to detect its key name (by case-insensitive prefix match against an input line) and parse its value.
  • mhmatkeys.py — instantiates the complete catalog of MHMAT keys and builds the lookup dictionaries used at parse time.

See the MHMAT file format reference for the full format specification.

Pattern

Each MhMatKey subclass handles one logical value type. When MhMaterial reads a line, it looks up the key name in MHMAT_NAME_TO_KEY for O(1) dispatch, then calls the matching key object's parse (or parse_file) method to extract the typed value.

Key names are matched case-insensitively: every key object stores key_name_lower = key_name.lower() and line_matches_key compares against the lowercased input line.

Sources

  • src/mpfb/entities/material/mhmatkeytypes.py
  • src/mpfb/entities/material/mhmatkeys.py

Dependencies

DependencyUsage
reRegular-expression parsing of MHMAT line values (standard library only — no service imports)

Key type hierarchy

Defined in mhmatkeytypes.py:

ClassValue typeNotes
MhMatKey(abstract base)Provides line_matches_key, abstract parse, and default as_string
MhMatStringKeystrEverything after the key name on the line
MhMatFileKeystrPath resolved relative to the MHMAT/MHCLO file location; use parse_file(line, location) instead of parse
MhMatFloatKeyfloatSingle float; formatted to 4 decimal places by as_string
MhMatBooleanKeyboolAccepts "true", "t", or "1" as True; anything else as False
MhMatColorKeylist[float]Three space-separated floats (R G B)
MhMatStringShaderKeylist[str]"key subkey value" — returns [subkey, value]
MhMatBooleanShaderKeybool"key subkey boolvalue" — returns the parsed bool

MhMatKey public methods

MethodDescription
__init__(key_name, default_value=None, key_group="Various")Store the key name (and its lowercase form), default value, and group
line_matches_key(input_line)Return True if the lowercased line starts with key_name_lower
parse(input_line)Parse the value from the line; returns (key_name, value). Must be overridden by subclasses — base raises ValueError
as_string(value)Serialise a typed value back to a string for writing an MHMAT file; default returns str(value)

MhMatFileKey replaces parse with parse_file(input_line, location) where location is the directory containing the MHMAT file, used to resolve relative texture paths.

Module-level objects (mhmatkeys.py)

NameTypeDescription
MHMAT_KEY_GROUPSlist[str]Ordered category names: "Metadata", "Color", "Texture", "Intensity", "SSS", "Various"
MHMAT_KEYSlist[MhMatKey]Full ordered catalog of key instances, one per MHMAT key name
MHMAT_ALIASdict[str, str]Legacy/alternative name → canonical name (e.g. "albedoTexture""diffuseTexture")
MHMAT_NAME_TO_KEYdict[str, MhMatKey]Lowercase key name → key instance for O(1) lookup during parsing
MHMAT_SHADER_KEYSlist[MhMatKey]Separate list of shader-related key instances (shader, shaderParam litsphereTexture, shaderConfig *)

Key groups and representative keys

GroupRepresentative keys
Metadatatag, name, description, uuid, license, author
ColordiffuseColor, specularColor, emissiveColor, ambientColor
TexturediffuseTexture, normalmapTexture, bumpmapTexture, roughnessmapTexture, metallicmapTexture, …
IntensitydiffuseIntensity, normalmapIntensity, bumpmapIntensity, …
SSSsssEnabled, sssRScale, sssGScale, sssBScale
Variousroughness, opacity, metallic, transparent, backfaceCull, …

parse_alias(texture_name)

Map a legacy or alternative key name to its canonical form.

ArgumentTypeDescription
texture_namestrKey name to look up (case-insensitive)

Returns: The canonical key name as a str if an alias exists; otherwise the original texture_name unchanged.


Examples

Look up a key by name

from mpfb.entities.material.mhmatkeys import MHMAT_NAME_TO_KEY

key_obj = MHMAT_NAME_TO_KEY["diffusecolor"]
print(key_obj.key_name)        # "diffuseColor"
print(key_obj.default_value)   # [0.5, 0.5, 0.5]
print(key_obj.key_group)       # "Color"

Parse a single MHMAT line

from mpfb.entities.material.mhmatkeys import MHMAT_NAME_TO_KEY

line = "diffuseColor 0.8 0.6 0.4"
key_obj = MHMAT_NAME_TO_KEY["diffusecolor"]
name, value = key_obj.parse(line)
print(name, value)  # "diffuseColor" [0.8, 0.6, 0.4]

Iterate all keys by group

from mpfb.entities.material.mhmatkeys import MHMAT_KEY_GROUPS, MHMAT_NAME_TO_KEY

for group in MHMAT_KEY_GROUPS:
    print(f"\n=== {group} ===")
    for key_obj in MHMAT_NAME_TO_KEY.values():
        if key_obj.key_group == group:
            print(f"  {key_obj.key_name} (default: {key_obj.default_value})")

Resolve an alias

from mpfb.entities.material.mhmatkeys import parse_alias

canonical = parse_alias("albedoTexture")
print(canonical)  # "diffuseTexture"

unchanged = parse_alias("diffuseTexture")
print(unchanged)  # "diffuseTexture"