9.5 KiB
Blender Material Creation Script Plan
This document outlines the plan for creating a new Blender script (create_materials.py) in the blenderscripts/ directory. This script will scan the processed asset library output by the Asset Processor Tool, read the metadata.json files, and create or update Blender materials that link to the corresponding PBRSET node groups found in a specified Blender Asset Library. The script will also set the material's viewport properties using pre-calculated statistics from the metadata. The script will skip processing an asset if the corresponding material already exists in the current Blender file.
1. Script Location and Naming
- Create a new file:
blenderscripts/create_materials.py.
2. Script Structure
The script will follow a similar structure to blenderscripts/create_nodegroups.py, including:
- Import statements (
bpy,os,json,pathlib,time,base64). - A
--- USER CONFIGURATION ---section at the top. - Helper functions.
- A main processing function (e.g.,
process_library_for_materials). - An execution block (
if __name__ == "__main__":) to run the main function.
3. Configuration Variables
The script will include the following configuration variables in the --- USER CONFIGURATION --- section:
PROCESSED_ASSET_LIBRARY_ROOT: Path to the root output directory of the Asset Processor Tool (same as increate_nodegroups.py). This is used to find themetadata.jsonfiles and reference images for previews.PBRSET_ASSET_LIBRARY_NAME: The name of the Blender Asset Library (configured in Blender Preferences) that contains the PBRSET node groups created bycreate_nodegroups.py.TEMPLATE_MATERIAL_NAME: Name of the required template material in the Blender file (e.g., "Template_PBRMaterial").PLACEHOLDER_NODE_LABEL: Label of the placeholder Group node within the template material's node tree where the PBRSET node group will be linked (e.g., "PBRSET_PLACEHOLDER").MATERIAL_NAME_PREFIX: Prefix for the created materials (e.g., "Mat_").PBRSET_GROUP_PREFIX: Prefix used for the PBRSET node groups created bycreate_nodegroups.py(e.g., "PBRSET_").REFERENCE_MAP_TYPES: List of map types to look for to find a reference image for the material preview (e.g.,["COL", "COL-1"]).REFERENCE_RESOLUTION_ORDER: Preferred resolution order for the reference image (e.g.,["1K", "512", "2K", "4K"]).IMAGE_FILENAME_PATTERN: Assumed filename pattern for processed images (same as increate_nodegroups.py).FALLBACK_IMAGE_EXTENSIONS: Fallback extensions for finding image files (same as increate_nodegroups.py).VIEWPORT_COLOR_MAP_TYPES: List of map types to check in metadata'simage_stats_1kfor viewport diffuse color.VIEWPORT_ROUGHNESS_MAP_TYPES: List of map types to check in metadata'simage_stats_1kfor viewport roughness.VIEWPORT_METALLIC_MAP_TYPES: List of map types to check in metadata'simage_stats_1kfor viewport metallic.
4. Helper Functions
The script will include the following helper functions:
find_nodes_by_label(node_tree, label, node_type=None): Reusable fromcreate_nodegroups.pyto find nodes in a node tree.add_tag_if_new(asset_data, tag_name): Reusable fromcreate_nodegroups.pyto add asset tags.reconstruct_image_path_with_fallback(...): Reusable fromcreate_nodegroups.pyto find image paths (needed for setting the custom preview).get_stat_value(stats_dict, map_type_list, stat_key): A helper function to safely retrieve a specific statistic from theimage_stats_1kdictionary.
5. Main Processing Logic (process_library_for_materials)
The main function will perform the following steps:
- Pre-run Checks:
- Verify
PROCESSED_ASSET_LIBRARY_ROOTexists and is a directory. - Verify the
PBRSET_ASSET_LIBRARY_NAMEexists in Blender's user preferences (bpy.context.preferences.filepaths.asset_libraries). - Verify the
TEMPLATE_MATERIAL_NAMEmaterial exists and uses nodes. - Verify the
PLACEHOLDER_NODE_LABELGroup node exists in the template material's node tree.
- Verify
- Scan for Metadata:
- Iterate through supplier directories within
PROCESSED_ASSET_LIBRARY_ROOT. - Iterate through asset directories within each supplier directory.
- Identify
metadata.jsonfiles.
- Iterate through supplier directories within
- Process Each Metadata File:
- Load the
metadata.jsonfile. - Extract
asset_name,supplier_name,archetype,processed_map_resolutions,merged_map_resolutions,map_details, andimage_stats_1k. - Determine the expected PBRSET node group name:
f"{PBRSET_GROUP_PREFIX}{asset_name}". - Determine the target material name:
f"{MATERIAL_NAME_PREFIX}{asset_name}". - Find or Create Material:
- Check if a material with the
target_material_namealready exists inbpy.data.materials. - If it exists, log a message indicating the asset is being skipped and move to the next metadata file.
- If it doesn't exist, copy the
TEMPLATE_MATERIAL_NAMEmaterial and rename the copy totarget_material_name(create mode). Handle potential copy failures.
- Check if a material with the
- Find Placeholder Node:
- Find the node with
PLACEHOLDER_NODE_LABELin the target material's node tree usingfind_nodes_by_label. Handle cases where the node is not found or is not a Group node.
- Find the node with
- Find and Link PBRSET Node Group from Asset Library:
- Get the path to the
.blendfile associated with thePBRSET_ASSET_LIBRARY_NAMEfrom user preferences. - Use
bpy.data.libraries.load(filepath, link=True)to link the node group withtarget_pbrset_group_namefrom the external.blendfile into the current file. Handle cases where the library or the node group is not found. - Once linked, get the reference to the newly linked node group in
bpy.data.node_groups.
- Get the path to the
- Link Linked Node Group to Placeholder:
- If both the placeholder node and the newly linked PBRSET node group are found, assign the linked node group to the
node_treeproperty of the placeholder node.
- If both the placeholder node and the newly linked PBRSET node group are found, assign the linked node group to the
- Mark Material as Asset:
- If the material is new or not already marked, call
material.asset_mark().
- If the material is new or not already marked, call
- Copy Asset Tags:
- If both the material and the linked PBRSET node group have asset data, copy tags (supplier, archetype) from the node group to the material using
add_tag_if_new.
- If both the material and the linked PBRSET node group have asset data, copy tags (supplier, archetype) from the node group to the material using
- Set Custom Preview:
- Find a suitable reference image path (e.g., lowest resolution COL map) using
reconstruct_image_path_with_fallbackand theREFERENCE_MAP_TYPESandREFERENCE_RESOLUTION_ORDERconfigurations. - If a reference image path is found, use
bpy.ops.ed.lib_id_load_custom_previewto set the custom preview for the material. This operation requires overriding the context.
- Find a suitable reference image path (e.g., lowest resolution COL map) using
- Set Viewport Properties (using metadata stats):
- Check if
image_stats_1kis present and valid in the metadata. - Diffuse Color: Use the
get_stat_valuehelper to get the 'mean' stat for map types inVIEWPORT_COLOR_MAP_TYPES. If found and is a valid color list[R, G, B], setmaterial.diffuse_colorto this value. - Roughness: Use the
get_stat_valuehelper to get the 'mean' stat for map types inVIEWPORT_ROUGHNESS_MAP_TYPES. If found, get the first value (for grayscale). Check if stats forVIEWPORT_METALLIC_MAP_TYPESexist. If metallic stats are not found, invert the roughness value (1.0 - value) before assigning it tomaterial.roughness. Clamp the final value between 0.0 and 1.0. - Metallic: Use the
get_stat_valuehelper to get the 'mean' stat for map types inVIEWPORT_METALLIC_MAP_TYPES. If found, get the first value (for grayscale) and assign it tomaterial.metallic. If metallic stats are not found, setmaterial.metallicto 0.0.
- Check if
- Error Handling and Reporting:
- Include
try...exceptblocks to catch errors during file reading, JSON parsing, Blender operations, linking, etc. - Print informative messages about progress, creation/update status, and errors.
- Include
- Load the
- Summary Report:
- Print a summary of how many metadata files were processed, materials created/updated, node groups linked, errors encountered, and assets skipped.
6. Process Flow Diagram (Updated)
graph TD
A[Start Script] --> B{Pre-run Checks Pass?};
B -- No --> C[Abort Script];
B -- Yes --> D[Scan Processed Asset Root];
D --> E{Found metadata.json?};
E -- No --> F[Finish Script (No Assets)];
E -- Yes --> G[Loop through metadata.json files];
G --> H[Read metadata.json];
H --> I{Metadata Valid?};
I -- No --> J[Log Error, Skip Asset];
I -- Yes --> K[Extract Asset Info & Stats];
K --> L[Find or Create Material];
L --> M{Material Exists?};
M -- Yes --> N[Log Skip, Continue Loop];
M -- No --> O[Find Placeholder Node in Material];
O --> P[Find PBRSET NG in Library & Link];
P --> Q{Linking Successful?};
Q -- No --> R[Log Error, Skip Asset];
Q -- Yes --> S[Link Linked NG to Placeholder];
S --> T[Mark Material as Asset];
T --> U[Copy Asset Tags];
U --> V[Find Reference Image Path for Preview];
V --> W{Reference Image Found?};
W -- Yes --> X[Set Custom Material Preview];
W -- No --> Y[Log Warning (No Preview)];
X --> Z[Set Viewport Properties from Stats];
Y --> Z;
Z --> AA[Increment Counters];
AA --> G;
G --> AB[Print Summary Report];
AB --> AC[End Script];
J --> G;
N --> G;
R --> G;