{
    "sourceFile": "Project Notes/BLENDER_MATERIAL_CREATION_PLAN.md",
    "activeCommit": 0,
    "commits": [
        {
            "activePatchIndex": 2,
            "patches": [
                {
                    "date": 1745258705721,
                    "content": "Index: \n===================================================================\n--- \n+++ \n"
                },
                {
                    "date": 1745259611867,
                    "content": "Index: \n===================================================================\n--- \n+++ \n@@ -1,7 +1,7 @@\n # Blender Material Creation Script Plan\r\n \r\n-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 generated by `blenderscripts/create_nodegroups.py`. The script will also set the material's viewport properties using pre-calculated statistics from the metadata.\r\n+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.\r\n \r\n ## 1. Script Location and Naming\r\n \r\n *   Create a new file: `blenderscripts/create_materials.py`.\r\n@@ -19,36 +19,38 @@\n ## 3. Configuration Variables\r\n \r\n The script will include the following configuration variables in the `--- USER CONFIGURATION ---` section:\r\n \r\n-*   `PROCESSED_ASSET_LIBRARY_ROOT`: Path to the root output directory of the Asset Processor Tool (same as in `create_nodegroups.py`).\r\n+*   `PROCESSED_ASSET_LIBRARY_ROOT`: Path to the root output directory of the Asset Processor Tool (same as in `create_nodegroups.py`). This is used to find the `metadata.json` files and reference images for previews.\r\n+*   `PBRSET_ASSET_LIBRARY_NAME`: **NEW:** The name of the Blender Asset Library (configured in Blender Preferences) that contains the PBRSET node groups created by `create_nodegroups.py`.\r\n *   `TEMPLATE_MATERIAL_NAME`: Name of the required template material in the Blender file (e.g., \"Template_PBRMaterial\").\r\n *   `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\").\r\n *   `MATERIAL_NAME_PREFIX`: Prefix for the created materials (e.g., \"Mat_\").\r\n *   `PBRSET_GROUP_PREFIX`: Prefix used for the PBRSET node groups created by `create_nodegroups.py` (e.g., \"PBRSET_\").\r\n *   `REFERENCE_MAP_TYPES`: List of map types to look for to find a reference image for the material preview (e.g., `[\"COL\", \"COL-1\"]`).\r\n *   `REFERENCE_RESOLUTION_ORDER`: Preferred resolution order for the reference image (e.g., `[\"1K\", \"512\", \"2K\", \"4K\"]`).\r\n *   `IMAGE_FILENAME_PATTERN`: Assumed filename pattern for processed images (same as in `create_nodegroups.py`).\r\n *   `FALLBACK_IMAGE_EXTENSIONS`: Fallback extensions for finding image files (same as in `create_nodegroups.py`).\r\n-*   `VIEWPORT_COLOR_MAP_TYPES`: List of map types to check for viewport diffuse color stats (e.g., `[\"COL\", \"COL-1\", \"COL-2\"]`).\r\n-*   `VIEWPORT_ROUGHNESS_MAP_TYPES`: List of map types to check for viewport roughness stats (e.g., `[\"ROUGH\"]`).\r\n-*   `VIEWPORT_METALLIC_MAP_TYPES`: List of map types to check for viewport metallic stats (e.g., `[\"METAL\"]`).\r\n+*   `VIEWPORT_COLOR_MAP_TYPES`: List of map types to check in metadata's `image_stats_1k` for viewport diffuse color.\r\n+*   `VIEWPORT_ROUGHNESS_MAP_TYPES`: List of map types to check in metadata's `image_stats_1k` for viewport roughness.\r\n+*   `VIEWPORT_METALLIC_MAP_TYPES`: List of map types to check in metadata's `image_stats_1k` for viewport metallic.\r\n \r\n ## 4. Helper Functions\r\n \r\n The script will include the following helper functions:\r\n \r\n *   `find_nodes_by_label(node_tree, label, node_type=None)`: Reusable from `create_nodegroups.py` to find nodes in a node tree.\r\n *   `add_tag_if_new(asset_data, tag_name)`: Reusable from `create_nodegroups.py` to add asset tags.\r\n *   `reconstruct_image_path_with_fallback(...)`: Reusable from `create_nodegroups.py` to find image paths (needed for setting the custom preview).\r\n-*   `get_stat_value(stats_dict, map_type_list, stat_key)`: A new helper function to safely retrieve a specific statistic (e.g., 'mean') for a given list of map types from the `image_stats_1k` dictionary, handling potential missing keys or invalid data formats.\r\n+*   `get_stat_value(stats_dict, map_type_list, stat_key)`: A helper function to safely retrieve a specific statistic from the `image_stats_1k` dictionary.\r\n \r\n ## 5. Main Processing Logic (`process_library_for_materials`)\r\n \r\n The main function will perform the following steps:\r\n \r\n *   **Pre-run Checks:**\r\n     *   Verify `PROCESSED_ASSET_LIBRARY_ROOT` exists and is a directory.\r\n+    *   Verify the `PBRSET_ASSET_LIBRARY_NAME` exists in Blender's user preferences (`bpy.context.preferences.filepaths.asset_libraries`).\r\n     *   Verify the `TEMPLATE_MATERIAL_NAME` material exists and uses nodes.\r\n     *   Verify the `PLACEHOLDER_NODE_LABEL` Group node exists in the template material's node tree.\r\n *   **Scan for Metadata:**\r\n     *   Iterate through supplier directories within `PROCESSED_ASSET_LIBRARY_ROOT`.\r\n@@ -64,16 +66,18 @@\n         *   If it exists, use the existing material (update mode).\r\n         *   If it doesn't exist, copy the `TEMPLATE_MATERIAL_NAME` material and rename the copy to `target_material_name` (create mode). Handle potential copy failures.\r\n     *   **Find Placeholder Node:**\r\n         *   Find the node with `PLACEHOLDER_NODE_LABEL` in the target material's node tree using `find_nodes_by_label`. Handle cases where the node is not found or is not a Group node.\r\n-    *   **Find PBRSET Node Group:**\r\n-        *   Find the node group with the expected PBRSET name in `bpy.data.node_groups`. Handle cases where the node group is not found (this would indicate `create_nodegroups.py` hasn't been run or failed for this asset).\r\n-    *   **Link Node Group to Placeholder:**\r\n-        *   If both the placeholder node and the PBRSET node group are found, assign the PBRSET node group to the `node_tree` property of the placeholder node.\r\n+    *   **Find and Link PBRSET Node Group from Asset Library:**\r\n+        *   Get the path to the `.blend` file associated with the `PBRSET_ASSET_LIBRARY_NAME` from user preferences.\r\n+        *   Use `bpy.data.libraries.load(filepath, link=True)` to link the node group with `target_pbrset_group_name` from the external `.blend` file into the current file. Handle cases where the library or the node group is not found.\r\n+        *   Once linked, get the reference to the newly linked node group in `bpy.data.node_groups`.\r\n+    *   **Link Linked Node Group to Placeholder:**\r\n+        *   If both the placeholder node and the *newly linked* PBRSET node group are found, assign the linked node group to the `node_tree` property of the placeholder node.\r\n     *   **Mark Material as Asset:**\r\n         *   If the material is new or not already marked, call `material.asset_mark()`.\r\n     *   **Copy Asset Tags:**\r\n-        *   If both the material and the PBRSET node group have asset data, copy tags (supplier, archetype) from the node group to the material using `add_tag_if_new`.\r\n+        *   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`.\r\n     *   **Set Custom Preview:**\r\n         *   Find a suitable reference image path (e.g., lowest resolution COL map) using `reconstruct_image_path_with_fallback` and the `REFERENCE_MAP_TYPES` and `REFERENCE_RESOLUTION_ORDER` configurations.\r\n         *   If a reference image path is found, use `bpy.ops.ed.lib_id_load_custom_preview` to set the custom preview for the material. This operation requires overriding the context.\r\n     *   **Set Viewport Properties (using metadata stats):**\r\n@@ -81,14 +85,14 @@\n         *   **Diffuse Color:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_COLOR_MAP_TYPES`. If found and is a valid color list `[R, G, B]`, set `material.diffuse_color` to this value.\r\n         *   **Roughness:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_ROUGHNESS_MAP_TYPES`. If found, get the first value (for grayscale). Check if stats for `VIEWPORT_METALLIC_MAP_TYPES` exist. If metallic stats are *not* found, invert the roughness value (`1.0 - value`) before assigning it to `material.roughness`. Clamp the final value between 0.0 and 1.0.\r\n         *   **Metallic:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_METALLIC_MAP_TYPES`. If found, get the first value (for grayscale) and assign it to `material.metallic`. If metallic stats are *not* found, set `material.metallic` to 0.0.\r\n     *   **Error Handling and Reporting:**\r\n-        *   Include `try...except` blocks to catch errors during file reading, JSON parsing, Blender operations, etc.\r\n+        *   Include `try...except` blocks to catch errors during file reading, JSON parsing, Blender operations, linking, etc.\r\n         *   Print informative messages about progress, creation/update status, and errors.\r\n *   **Summary Report:**\r\n-    *   Print a summary of how many metadata files were processed, materials created/updated, errors encountered, etc.\r\n+    *   Print a summary of how many metadata files were processed, materials created/updated, node groups linked, errors encountered, etc.\r\n \r\n-## 6. Process Flow Diagram\r\n+## 6. Process Flow Diagram (Updated)\r\n \r\n ```mermaid\r\n graph TD\r\n     A[Start Script] --> B{Pre-run Checks Pass?};\r\n@@ -102,12 +106,12 @@\n     I -- No --> J[Log Error, Skip Asset];\r\n     I -- Yes --> K[Extract Asset Info & Stats];\r\n     K --> L[Find or Create Material];\r\n     L --> M[Find Placeholder Node in Material];\r\n-    M --> N[Find PBRSET Node Group];\r\n-    N --> O{Placeholder & NG Found?};\r\n+    M --> N[Find PBRSET NG in Library & Link];\r\n+    N --> O{Linking Successful?};\r\n     O -- No --> P[Log Error, Skip Asset];\r\n-    O -- Yes --> Q[Link PBRSET NG to Placeholder];\r\n+    O -- Yes --> Q[Link Linked NG to Placeholder];\r\n     Q --> R[Mark Material as Asset];\r\n     R --> S[Copy Asset Tags];\r\n     S --> T[Find Reference Image Path for Preview];\r\n     T --> U{Reference Image Found?};\r\n"
                },
                {
                    "date": 1745259690754,
                    "content": "Index: \n===================================================================\n--- \n+++ \n@@ -1,7 +1,7 @@\n # Blender Material Creation Script Plan\r\n \r\n-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.\r\n+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.\r\n \r\n ## 1. Script Location and Naming\r\n \r\n *   Create a new file: `blenderscripts/create_materials.py`.\r\n@@ -20,9 +20,9 @@\n \r\n The script will include the following configuration variables in the `--- USER CONFIGURATION ---` section:\r\n \r\n *   `PROCESSED_ASSET_LIBRARY_ROOT`: Path to the root output directory of the Asset Processor Tool (same as in `create_nodegroups.py`). This is used to find the `metadata.json` files and reference images for previews.\r\n-*   `PBRSET_ASSET_LIBRARY_NAME`: **NEW:** The name of the Blender Asset Library (configured in Blender Preferences) that contains the PBRSET node groups created by `create_nodegroups.py`.\r\n+*   `PBRSET_ASSET_LIBRARY_NAME`: The name of the Blender Asset Library (configured in Blender Preferences) that contains the PBRSET node groups created by `create_nodegroups.py`.\r\n *   `TEMPLATE_MATERIAL_NAME`: Name of the required template material in the Blender file (e.g., \"Template_PBRMaterial\").\r\n *   `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\").\r\n *   `MATERIAL_NAME_PREFIX`: Prefix for the created materials (e.g., \"Mat_\").\r\n *   `PBRSET_GROUP_PREFIX`: Prefix used for the PBRSET node groups created by `create_nodegroups.py` (e.g., \"PBRSET_\").\r\n@@ -62,9 +62,9 @@\n     *   Determine the expected PBRSET node group name: `f\"{PBRSET_GROUP_PREFIX}{asset_name}\"`.\r\n     *   Determine the target material name: `f\"{MATERIAL_NAME_PREFIX}{asset_name}\"`.\r\n     *   **Find or Create Material:**\r\n         *   Check if a material with the `target_material_name` already exists in `bpy.data.materials`.\r\n-        *   If it exists, use the existing material (update mode).\r\n+        *   If it exists, log a message indicating the asset is being skipped and move to the next metadata file.\r\n         *   If it doesn't exist, copy the `TEMPLATE_MATERIAL_NAME` material and rename the copy to `target_material_name` (create mode). Handle potential copy failures.\r\n     *   **Find Placeholder Node:**\r\n         *   Find the node with `PLACEHOLDER_NODE_LABEL` in the target material's node tree using `find_nodes_by_label`. Handle cases where the node is not found or is not a Group node.\r\n     *   **Find and Link PBRSET Node Group from Asset Library:**\r\n@@ -88,9 +88,9 @@\n     *   **Error Handling and Reporting:**\r\n         *   Include `try...except` blocks to catch errors during file reading, JSON parsing, Blender operations, linking, etc.\r\n         *   Print informative messages about progress, creation/update status, and errors.\r\n *   **Summary Report:**\r\n-    *   Print a summary of how many metadata files were processed, materials created/updated, node groups linked, errors encountered, etc.\r\n+    *   Print a summary of how many metadata files were processed, materials created/updated, node groups linked, errors encountered, and assets skipped.\r\n \r\n ## 6. Process Flow Diagram (Updated)\r\n \r\n ```mermaid\r\n@@ -105,24 +105,27 @@\n     H --> I{Metadata Valid?};\r\n     I -- No --> J[Log Error, Skip Asset];\r\n     I -- Yes --> K[Extract Asset Info & Stats];\r\n     K --> L[Find or Create Material];\r\n-    L --> M[Find Placeholder Node in Material];\r\n-    M --> N[Find PBRSET NG in Library & Link];\r\n-    N --> O{Linking Successful?};\r\n-    O -- No --> P[Log Error, Skip Asset];\r\n-    O -- Yes --> Q[Link Linked NG to Placeholder];\r\n-    Q --> R[Mark Material as Asset];\r\n-    R --> S[Copy Asset Tags];\r\n-    S --> T[Find Reference Image Path for Preview];\r\n-    T --> U{Reference Image Found?};\r\n-    U -- Yes --> V[Set Custom Material Preview];\r\n-    U -- No --> W[Log Warning (No Preview)];\r\n-    V --> X[Set Viewport Properties from Stats];\r\n-    W --> X;\r\n-    X --> Y[Increment Counters];\r\n-    Y --> G;\r\n-    G --> Z[Print Summary Report];\r\n-    Z --> AA[End Script];\r\n+    L --> M{Material Exists?};\r\n+    M -- Yes --> N[Log Skip, Continue Loop];\r\n+    M -- No --> O[Find Placeholder Node in Material];\r\n\\ No newline at end of file\n+    O --> P[Find PBRSET NG in Library & Link];\r\n+    P --> Q{Linking Successful?};\r\n+    Q -- No --> R[Log Error, Skip Asset];\r\n+    Q -- Yes --> S[Link Linked NG to Placeholder];\r\n+    S --> T[Mark Material as Asset];\r\n+    T --> U[Copy Asset Tags];\r\n+    U --> V[Find Reference Image Path for Preview];\r\n+    V --> W{Reference Image Found?};\r\n+    W -- Yes --> X[Set Custom Material Preview];\r\n+    W -- No --> Y[Log Warning (No Preview)];\r\n+    X --> Z[Set Viewport Properties from Stats];\r\n+    Y --> Z;\r\n+    Z --> AA[Increment Counters];\r\n+    AA --> G;\r\n+    G --> AB[Print Summary Report];\r\n+    AB --> AC[End Script];\r\n \r\n     J --> G;\r\n-    P --> G;\n+    N --> G;\r\n+    R --> G;\n\\ No newline at end of file\n"
                }
            ],
            "date": 1745258705721,
            "name": "Commit-0",
            "content": "# Blender Material Creation Script Plan\r\n\r\nThis 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 generated by `blenderscripts/create_nodegroups.py`. The script will also set the material's viewport properties using pre-calculated statistics from the metadata.\r\n\r\n## 1. Script Location and Naming\r\n\r\n*   Create a new file: `blenderscripts/create_materials.py`.\r\n\r\n## 2. Script Structure\r\n\r\nThe script will follow a similar structure to `blenderscripts/create_nodegroups.py`, including:\r\n\r\n*   Import statements (`bpy`, `os`, `json`, `pathlib`, `time`, `base64`).\r\n*   A `--- USER CONFIGURATION ---` section at the top.\r\n*   Helper functions.\r\n*   A main processing function (e.g., `process_library_for_materials`).\r\n*   An execution block (`if __name__ == \"__main__\":`) to run the main function.\r\n\r\n## 3. Configuration Variables\r\n\r\nThe script will include the following configuration variables in the `--- USER CONFIGURATION ---` section:\r\n\r\n*   `PROCESSED_ASSET_LIBRARY_ROOT`: Path to the root output directory of the Asset Processor Tool (same as in `create_nodegroups.py`).\r\n*   `TEMPLATE_MATERIAL_NAME`: Name of the required template material in the Blender file (e.g., \"Template_PBRMaterial\").\r\n*   `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\").\r\n*   `MATERIAL_NAME_PREFIX`: Prefix for the created materials (e.g., \"Mat_\").\r\n*   `PBRSET_GROUP_PREFIX`: Prefix used for the PBRSET node groups created by `create_nodegroups.py` (e.g., \"PBRSET_\").\r\n*   `REFERENCE_MAP_TYPES`: List of map types to look for to find a reference image for the material preview (e.g., `[\"COL\", \"COL-1\"]`).\r\n*   `REFERENCE_RESOLUTION_ORDER`: Preferred resolution order for the reference image (e.g., `[\"1K\", \"512\", \"2K\", \"4K\"]`).\r\n*   `IMAGE_FILENAME_PATTERN`: Assumed filename pattern for processed images (same as in `create_nodegroups.py`).\r\n*   `FALLBACK_IMAGE_EXTENSIONS`: Fallback extensions for finding image files (same as in `create_nodegroups.py`).\r\n*   `VIEWPORT_COLOR_MAP_TYPES`: List of map types to check for viewport diffuse color stats (e.g., `[\"COL\", \"COL-1\", \"COL-2\"]`).\r\n*   `VIEWPORT_ROUGHNESS_MAP_TYPES`: List of map types to check for viewport roughness stats (e.g., `[\"ROUGH\"]`).\r\n*   `VIEWPORT_METALLIC_MAP_TYPES`: List of map types to check for viewport metallic stats (e.g., `[\"METAL\"]`).\r\n\r\n## 4. Helper Functions\r\n\r\nThe script will include the following helper functions:\r\n\r\n*   `find_nodes_by_label(node_tree, label, node_type=None)`: Reusable from `create_nodegroups.py` to find nodes in a node tree.\r\n*   `add_tag_if_new(asset_data, tag_name)`: Reusable from `create_nodegroups.py` to add asset tags.\r\n*   `reconstruct_image_path_with_fallback(...)`: Reusable from `create_nodegroups.py` to find image paths (needed for setting the custom preview).\r\n*   `get_stat_value(stats_dict, map_type_list, stat_key)`: A new helper function to safely retrieve a specific statistic (e.g., 'mean') for a given list of map types from the `image_stats_1k` dictionary, handling potential missing keys or invalid data formats.\r\n\r\n## 5. Main Processing Logic (`process_library_for_materials`)\r\n\r\nThe main function will perform the following steps:\r\n\r\n*   **Pre-run Checks:**\r\n    *   Verify `PROCESSED_ASSET_LIBRARY_ROOT` exists and is a directory.\r\n    *   Verify the `TEMPLATE_MATERIAL_NAME` material exists and uses nodes.\r\n    *   Verify the `PLACEHOLDER_NODE_LABEL` Group node exists in the template material's node tree.\r\n*   **Scan for Metadata:**\r\n    *   Iterate through supplier directories within `PROCESSED_ASSET_LIBRARY_ROOT`.\r\n    *   Iterate through asset directories within each supplier directory.\r\n    *   Identify `metadata.json` files.\r\n*   **Process Each Metadata File:**\r\n    *   Load the `metadata.json` file.\r\n    *   Extract `asset_name`, `supplier_name`, `archetype`, `processed_map_resolutions`, `merged_map_resolutions`, `map_details`, and `image_stats_1k`.\r\n    *   Determine the expected PBRSET node group name: `f\"{PBRSET_GROUP_PREFIX}{asset_name}\"`.\r\n    *   Determine the target material name: `f\"{MATERIAL_NAME_PREFIX}{asset_name}\"`.\r\n    *   **Find or Create Material:**\r\n        *   Check if a material with the `target_material_name` already exists in `bpy.data.materials`.\r\n        *   If it exists, use the existing material (update mode).\r\n        *   If it doesn't exist, copy the `TEMPLATE_MATERIAL_NAME` material and rename the copy to `target_material_name` (create mode). Handle potential copy failures.\r\n    *   **Find Placeholder Node:**\r\n        *   Find the node with `PLACEHOLDER_NODE_LABEL` in the target material's node tree using `find_nodes_by_label`. Handle cases where the node is not found or is not a Group node.\r\n    *   **Find PBRSET Node Group:**\r\n        *   Find the node group with the expected PBRSET name in `bpy.data.node_groups`. Handle cases where the node group is not found (this would indicate `create_nodegroups.py` hasn't been run or failed for this asset).\r\n    *   **Link Node Group to Placeholder:**\r\n        *   If both the placeholder node and the PBRSET node group are found, assign the PBRSET node group to the `node_tree` property of the placeholder node.\r\n    *   **Mark Material as Asset:**\r\n        *   If the material is new or not already marked, call `material.asset_mark()`.\r\n    *   **Copy Asset Tags:**\r\n        *   If both the material and the PBRSET node group have asset data, copy tags (supplier, archetype) from the node group to the material using `add_tag_if_new`.\r\n    *   **Set Custom Preview:**\r\n        *   Find a suitable reference image path (e.g., lowest resolution COL map) using `reconstruct_image_path_with_fallback` and the `REFERENCE_MAP_TYPES` and `REFERENCE_RESOLUTION_ORDER` configurations.\r\n        *   If a reference image path is found, use `bpy.ops.ed.lib_id_load_custom_preview` to set the custom preview for the material. This operation requires overriding the context.\r\n    *   **Set Viewport Properties (using metadata stats):**\r\n        *   Check if `image_stats_1k` is present and valid in the metadata.\r\n        *   **Diffuse Color:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_COLOR_MAP_TYPES`. If found and is a valid color list `[R, G, B]`, set `material.diffuse_color` to this value.\r\n        *   **Roughness:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_ROUGHNESS_MAP_TYPES`. If found, get the first value (for grayscale). Check if stats for `VIEWPORT_METALLIC_MAP_TYPES` exist. If metallic stats are *not* found, invert the roughness value (`1.0 - value`) before assigning it to `material.roughness`. Clamp the final value between 0.0 and 1.0.\r\n        *   **Metallic:** Use the `get_stat_value` helper to get the 'mean' stat for map types in `VIEWPORT_METALLIC_MAP_TYPES`. If found, get the first value (for grayscale) and assign it to `material.metallic`. If metallic stats are *not* found, set `material.metallic` to 0.0.\r\n    *   **Error Handling and Reporting:**\r\n        *   Include `try...except` blocks to catch errors during file reading, JSON parsing, Blender operations, etc.\r\n        *   Print informative messages about progress, creation/update status, and errors.\r\n*   **Summary Report:**\r\n    *   Print a summary of how many metadata files were processed, materials created/updated, errors encountered, etc.\r\n\r\n## 6. Process Flow Diagram\r\n\r\n```mermaid\r\ngraph TD\r\n    A[Start Script] --> B{Pre-run Checks Pass?};\r\n    B -- No --> C[Abort Script];\r\n    B -- Yes --> D[Scan Processed Asset Root];\r\n    D --> E{Found metadata.json?};\r\n    E -- No --> F[Finish Script (No Assets)];\r\n    E -- Yes --> G[Loop through metadata.json files];\r\n    G --> H[Read metadata.json];\r\n    H --> I{Metadata Valid?};\r\n    I -- No --> J[Log Error, Skip Asset];\r\n    I -- Yes --> K[Extract Asset Info & Stats];\r\n    K --> L[Find or Create Material];\r\n    L --> M[Find Placeholder Node in Material];\r\n    M --> N[Find PBRSET Node Group];\r\n    N --> O{Placeholder & NG Found?};\r\n    O -- No --> P[Log Error, Skip Asset];\r\n    O -- Yes --> Q[Link PBRSET NG to Placeholder];\r\n    Q --> R[Mark Material as Asset];\r\n    R --> S[Copy Asset Tags];\r\n    S --> T[Find Reference Image Path for Preview];\r\n    T --> U{Reference Image Found?};\r\n    U -- Yes --> V[Set Custom Material Preview];\r\n    U -- No --> W[Log Warning (No Preview)];\r\n    V --> X[Set Viewport Properties from Stats];\r\n    W --> X;\r\n    X --> Y[Increment Counters];\r\n    Y --> G;\r\n    G --> Z[Print Summary Report];\r\n    Z --> AA[End Script];\r\n\r\n    J --> G;\r\n    P --> G;"
        }
    ]
}