# Blender Addon Plan: Material Merger **Version:** 1.1 (Includes Extensibility Consideration) **1. Goal:** Create a standalone Blender addon that allows users to select two existing materials (generated by the Asset Processor Tool, or previously merged by this addon) and merge them into a new material. The merge should preserve their individual node structures (including custom tweaks) and combine their final outputs using a dedicated `MaterialMerge` node group. **2. Core Functionality (Approach 2 - Node Copying):** * **Trigger:** User selects two materials in Blender and invokes an operator (e.g., via a button in the Shader Editor's UI panel). * **New Material Creation:** The addon creates a new Blender material, named appropriately (e.g., `MAT_Merged__`). * **Node Copying:** * For *each* selected source material: * Iterate through its node tree. * Copy all nodes *except* the `Material Output` node into the *new* material's node tree, attempting to preserve relative layout and offsetting subsequent copies. * **Identify Final Outputs:** Determine the node providing the final BSDF shader output and the node providing the final Displacement output *before* the original `Material Output` node. * In a base material (from Asset Processor), these are expected to be the `PBR_BSDF` node group (BSDF output) and the `PBR_Handler` node group (Displacement output). * In an already-merged material, these will be the outputs of its top-level `MaterialMerge` node group. * Store references to these final output nodes and their relevant sockets. * **MaterialMerge Node:** * **Link/Append** the `MaterialMerge` node group into the new material's node tree. * **Assumption:** This node group exists in `blender_files/utility_nodegroups.blend` relative to the addon's location. * **Assumption:** Socket names are `Shader A`, `Shader B`, `Displacement A`, `Displacement B` (inputs) and `BSDF`, `Displacement` (outputs). * **Connections:** * Connect the identified final BSDF output of the *first* source material's copied structure to the `MaterialMerge` node's `Shader A` input. * Connect the identified final Displacement output of the *first* source material's copied structure to the `MaterialMerge` node's `Displacement A` input. * Connect the identified final BSDF output of the *second* source material's copied structure to the `MaterialMerge` node's `Shader B` input. * Connect the identified final Displacement output of the *second* source material's copied structure to the `MaterialMerge` node's `Displacement B` input. * Connect the `MaterialMerge` node's `BSDF` output to the new material's `Material Output` node's `Surface` input. * Connect the `MaterialMerge` node's `Displacement` output to the new material's `Material Output` node's `Displacement` input. * **Layout:** Optionally, attempt a basic auto-layout (`node_tree.nodes.update()`) or arrange the key nodes logically. **3. User Interface (UI):** * A simple panel in the Blender Shader Editor (Properties region - 'N' panel). * Two dropdowns or search fields allowing the user to select existing materials from the current `.blend` file. * A button labeled "Merge Selected Materials". * Status messages/feedback (e.g., "Merged material created: [Name]", "Error: Could not find required nodes in [Material Name]"). **4. Addon Structure (Python):** * `__init__.py`: Registers the addon, panel, and operator classes. * `operator.py`: Contains the `OT_MergeMaterials` operator class implementing the core logic. * `panel.py`: Contains the `PT_MaterialMergePanel` class defining the UI layout. * (Optional) `utils.py`: Helper functions for node finding, copying, linking, identifying final outputs, etc. **5. Error Handling:** * Check if two valid materials are selected. * Verify that the selected materials have node trees. * Handle cases where the expected final BSDF/Displacement output nodes cannot be reliably identified in one or both source materials. * Handle potential errors during node copying. * Handle errors if the `utility_nodegroups.blend` file or the `MaterialMerge` node group within it cannot be found/linked. **6. Assumptions to Verify (Based on User Feedback):** * **Node Identification:** * Base Material Handler: Node named `PBR_Handler`. * Base Material BSDF: Node named `PBR_BSDF`. * Merged Material Outputs: The `BSDF` and `Displacement` outputs of the top-level `MaterialMerge` node. * **`MaterialMerge` Node:** * Location: `blender_files/utility_nodegroups.blend` (relative path). * Input Sockets: `Shader A`, `Shader B`, `Displacement A`, `Displacement B`. * Output Sockets: `BSDF`, `Displacement`. **7. Future Extensibility - Recursive Merging:** * The core merging logic (copying nodes, identifying final outputs, connecting to a new `MaterialMerge` node) is designed to inherently support selecting an already-merged material as an input without requiring separate code paths initially. The identification of final BSDF/Displacement outputs needs to correctly handle both base materials and merged materials (checking for `PBR_BSDF`/`PBR_Handler` or the outputs of an existing `MaterialMerge` node). **8. Mermaid Diagram of Node Flow:** ```mermaid graph TD subgraph New Merged Material subgraph Copied from Source A (Mat_A or Merge_A) %% Nodes representing the structure of Source A Structure_A[...] Final_BSDF_A[Final BSDF Output A] Final_Disp_A[Final Displacement Output A] Structure_A --> Final_BSDF_A Structure_A --> Final_Disp_A end subgraph Copied from Source B (Mat_B or Merge_B) %% Nodes representing the structure of Source B Structure_B[...] Final_BSDF_B[Final BSDF Output B] Final_Disp_B[Final Displacement Output B] Structure_B --> Final_BSDF_B Structure_B --> Final_Disp_B end Merge[MaterialMerge] Output[Material Output] Final_BSDF_A -- BSDF --> Merge -- Shader A --> Merge Final_Disp_A -- Displacement --> Merge -- Displacement A --> Merge Final_BSDF_B -- BSDF --> Merge -- Shader B --> Merge Final_Disp_B -- Displacement --> Merge -- Displacement B --> Merge Merge -- BSDF --> Output -- Surface --> Output Merge -- Displacement --> Output -- Displacement --> Output end