{ "sourceFile": "Project Notes/BLENDER_MATERIAL_MERGE_ADDON_PLAN.md", "activeCommit": 0, "commits": [ { "activePatchIndex": 0, "patches": [ { "date": 1745659279511, "content": "Index: \n===================================================================\n--- \n+++ \n" } ], "date": 1745659279511, "name": "Commit-0", "content": "# Blender Addon Plan: Material Merger\r\n\r\n**Version:** 1.1 (Includes Extensibility Consideration)\r\n\r\n**1. Goal:**\r\nCreate 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.\r\n\r\n**2. Core Functionality (Approach 2 - Node Copying):**\r\n\r\n* **Trigger:** User selects two materials in Blender and invokes an operator (e.g., via a button in the Shader Editor's UI panel).\r\n* **New Material Creation:** The addon creates a new Blender material, named appropriately (e.g., `MAT_Merged__`).\r\n* **Node Copying:**\r\n * For *each* selected source material:\r\n * Iterate through its node tree.\r\n * Copy all nodes *except* the `Material Output` node into the *new* material's node tree, attempting to preserve relative layout and offsetting subsequent copies.\r\n * **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.\r\n * 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).\r\n * In an already-merged material, these will be the outputs of its top-level `MaterialMerge` node group.\r\n * Store references to these final output nodes and their relevant sockets.\r\n* **MaterialMerge Node:**\r\n * **Link/Append** the `MaterialMerge` node group into the new material's node tree.\r\n * **Assumption:** This node group exists in `blender_files/utility_nodegroups.blend` relative to the addon's location.\r\n * **Assumption:** Socket names are `Shader A`, `Shader B`, `Displacement A`, `Displacement B` (inputs) and `BSDF`, `Displacement` (outputs).\r\n* **Connections:**\r\n * Connect the identified final BSDF output of the *first* source material's copied structure to the `MaterialMerge` node's `Shader A` input.\r\n * Connect the identified final Displacement output of the *first* source material's copied structure to the `MaterialMerge` node's `Displacement A` input.\r\n * Connect the identified final BSDF output of the *second* source material's copied structure to the `MaterialMerge` node's `Shader B` input.\r\n * Connect the identified final Displacement output of the *second* source material's copied structure to the `MaterialMerge` node's `Displacement B` input.\r\n * Connect the `MaterialMerge` node's `BSDF` output to the new material's `Material Output` node's `Surface` input.\r\n * Connect the `MaterialMerge` node's `Displacement` output to the new material's `Material Output` node's `Displacement` input.\r\n* **Layout:** Optionally, attempt a basic auto-layout (`node_tree.nodes.update()`) or arrange the key nodes logically.\r\n\r\n**3. User Interface (UI):**\r\n\r\n* A simple panel in the Blender Shader Editor (Properties region - 'N' panel).\r\n* Two dropdowns or search fields allowing the user to select existing materials from the current `.blend` file.\r\n* A button labeled \"Merge Selected Materials\".\r\n* Status messages/feedback (e.g., \"Merged material created: [Name]\", \"Error: Could not find required nodes in [Material Name]\").\r\n\r\n**4. Addon Structure (Python):**\r\n\r\n* `__init__.py`: Registers the addon, panel, and operator classes.\r\n* `operator.py`: Contains the `OT_MergeMaterials` operator class implementing the core logic.\r\n* `panel.py`: Contains the `PT_MaterialMergePanel` class defining the UI layout.\r\n* (Optional) `utils.py`: Helper functions for node finding, copying, linking, identifying final outputs, etc.\r\n\r\n**5. Error Handling:**\r\n\r\n* Check if two valid materials are selected.\r\n* Verify that the selected materials have node trees.\r\n* Handle cases where the expected final BSDF/Displacement output nodes cannot be reliably identified in one or both source materials.\r\n* Handle potential errors during node copying.\r\n* Handle errors if the `utility_nodegroups.blend` file or the `MaterialMerge` node group within it cannot be found/linked.\r\n\r\n**6. Assumptions to Verify (Based on User Feedback):**\r\n\r\n* **Node Identification:**\r\n * Base Material Handler: Node named `PBR_Handler`.\r\n * Base Material BSDF: Node named `PBR_BSDF`.\r\n * Merged Material Outputs: The `BSDF` and `Displacement` outputs of the top-level `MaterialMerge` node.\r\n* **`MaterialMerge` Node:**\r\n * Location: `blender_files/utility_nodegroups.blend` (relative path).\r\n * Input Sockets: `Shader A`, `Shader B`, `Displacement A`, `Displacement B`.\r\n * Output Sockets: `BSDF`, `Displacement`.\r\n\r\n**7. Future Extensibility - Recursive Merging:**\r\n\r\n* 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).\r\n\r\n**8. Mermaid Diagram of Node Flow:**\r\n\r\n```mermaid\r\ngraph TD\r\n subgraph New Merged Material\r\n subgraph Copied from Source A (Mat_A or Merge_A)\r\n %% Nodes representing the structure of Source A\r\n Structure_A[...]\r\n Final_BSDF_A[Final BSDF Output A]\r\n Final_Disp_A[Final Displacement Output A]\r\n Structure_A --> Final_BSDF_A\r\n Structure_A --> Final_Disp_A\r\n end\r\n\r\n subgraph Copied from Source B (Mat_B or Merge_B)\r\n %% Nodes representing the structure of Source B\r\n Structure_B[...]\r\n Final_BSDF_B[Final BSDF Output B]\r\n Final_Disp_B[Final Displacement Output B]\r\n Structure_B --> Final_BSDF_B\r\n Structure_B --> Final_Disp_B\r\n end\r\n\r\n Merge[MaterialMerge]\r\n Output[Material Output]\r\n\r\n Final_BSDF_A -- BSDF --> Merge -- Shader A --> Merge\r\n Final_Disp_A -- Displacement --> Merge -- Displacement A --> Merge\r\n Final_BSDF_B -- BSDF --> Merge -- Shader B --> Merge\r\n Final_Disp_B -- Displacement --> Merge -- Displacement B --> Merge\r\n\r\n Merge -- BSDF --> Output -- Surface --> Output\r\n Merge -- Displacement --> Output -- Displacement --> Output\r\n end" } ] }