diff --git a/.specstory/history/2025-08-20_22-43Z-creating-a-blender-extension-for-asset-replacement.md b/.specstory/history/2025-08-20_22-43Z-creating-a-blender-extension-for-asset-replacement.md index 64f7729..7b804cb 100644 --- a/.specstory/history/2025-08-20_22-43Z-creating-a-blender-extension-for-asset-replacement.md +++ b/.specstory/history/2025-08-20_22-43Z-creating-a-blender-extension-for-asset-replacement.md @@ -10004,3 +10004,176 @@ This gets the addon preferences from the current context, which is needed to acc --- +_**User**_ + +sweet. at the top of the addon, we should draw a button that takes the user to the addon preferences. + +--- + +_**Assistant**_ + +Great idea! Let me add a button at the top of the main panel that takes users directly to the addon preferences. This will make it easy for users to access the search path settings: + + +--- + +
Edit file: ui.py + +undefined + +**Chunk 1** +Lines added: 4, lines removed: undefined + +```diff +@@ -121,4 +121,8 @@ + layout = self.layout + props = context.scene.dynamic_link_manager ++ ++ # Addon preferences button at the top ++ row = layout.row() ++ row.operator("preferences.addon_show", text="Addon Preferences", icon='PREFERENCES').module = __package__ + + # Main scan section (FMT-style) +``` + +
+ +--- + +Perfect! Now there's a convenient "Addon Preferences" button at the very top of the Dynamic Link Manager panel. This button: + +1. **Uses the `preferences.addon_show` operator** - This is Blender's built-in operator for opening addon preferences +2. **Sets the `module` parameter** to `__package__` - This ensures it opens the preferences for the current addon (Dynamic Link Manager) +3. **Has a clear label and icon** - "Addon Preferences" with the `PREFERENCES` icon for easy recognition +4. **Is positioned at the top** - Making it easily accessible before users dive into the main functionality + +Users can now quickly access the search path management and other addon settings without having to navigate through Blender's main preferences menu. This follows good UX practices by providing easy access to configuration options right where users need them. + +--- + +_**User**_ + +is there a way we can draw the button in the title of the main panel itself? + +--- + +_**Assistant**_ + +Yes! We can add a button directly in the panel title using the `bl_options` and custom drawing. However, there's an even better approach - we can use Blender's built-in panel header customization by overriding the `draw_header` method. + +Let me show you how to add a preferences button in the panel header: + + +--- + +The string to replace was not found in the file. + +--- + +Let me check the current structure and fix it properly: + + +--- + +Read file: ui.py + +--- + +Now I can see the current structure. Let me add the `draw_header` method and clean up the duplicate preferences button: + + +--- + +
Edit file: ui.py + +undefined + +**Chunk 1** +Lines added: 4, lines removed: 6 + +```diff +@@ -118,13 +118,11 @@ + bl_label = "Dynamic Link Manager" + ++ def draw_header(self, context): ++ layout = self.layout ++ layout.operator("preferences.addon_show", text="", icon='PREFERENCES', icon_only=True).module = __package__ ++ + def draw(self, context): + layout = self.layout + props = context.scene.dynamic_link_manager +- +- layout.operator("preferences.addon_show", text="", icon='PREFERENCES').module = __package__ +- +- # Addon preferences button at the top, right-justified +- row = layout.row() +- row.alignment = 'RIGHT' + + # Main scan section (FMT-style) +``` + +
+ +--- + +Perfect! Now the preferences button is integrated directly into the panel header. Here's what this accomplishes: + +1. **`draw_header` method**: This is a special method that Blender calls to draw content in the panel header (the title bar area) + +2. **Header integration**: The preferences button now appears in the panel header itself, right next to the "Dynamic Link Manager" title + +3. **Clean layout**: Removed the duplicate preferences button from the main content area, making the UI cleaner + +4. **Icon-only button**: Used `icon_only=True` to make it a compact gear icon that fits nicely in the header + +5. **Better UX**: Users can now access preferences directly from the panel header, which is a more intuitive location and follows Blender's UI patterns + +The preferences button will now appear as a small gear icon in the panel header, making it easily accessible while keeping the main content area focused on the core functionality. + +--- + +_**User**_ + +Python: Traceback (most recent call last): + File "C:\Program Files\Blender Foundation\Blender 4.5\portable\extensions\vscode_development\Dynamic-Link-Manager\ui.py", line 122, in draw_header + layout.operator("preferences.addon_show", text="", icon='PREFERENCES', icon_only=True).module = __package__ + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +TypeError: UILayout.operator(): was called with invalid keyword argument(s) (icon_only), expected (operator, text, text_ctxt, translate, icon, emboss, depress, icon_value, search_weight) + + +--- + +_**Assistant**_ + +I see the issue! The `icon_only` parameter is not valid for the `layout.operator()` method. Let me fix this by removing the invalid parameter: + + +--- + +
Edit file: ui.py + +undefined + +**Chunk 1** +Lines added: 1, lines removed: 1 + +```diff +@@ -120,5 +120,5 @@ + def draw_header(self, context): + layout = self.layout +- layout.operator("preferences.addon_show", text="", icon='PREFERENCES', icon_only=True).module = __package__ ++ layout.operator("preferences.addon_show", text="", icon='PREFERENCES').module = __package__ + + def draw(self, context): +``` + +
+ +--- + +Perfect! I've removed the invalid `icon_only=True` parameter. The `layout.operator()` method doesn't support that parameter. + +Now the preferences button should work correctly in the panel header. It will appear as a gear icon with no text, which will look clean and professional in the panel title bar. The button will still function the same way - clicking it will take users directly to the addon preferences. + +--- + diff --git a/ui.py b/ui.py index c030c90..3bf2450 100644 --- a/ui.py +++ b/ui.py @@ -111,11 +111,15 @@ class DynamicLinkManagerPreferences(AddonPreferences): # Remove button (FMT-style) row.operator("dlm.remove_search_path", text="", icon='REMOVE').index = i -class DYNAMICLINK_PT_main_panel(Panel): +class DLM_PT_main_panel(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'Dynamic Link Manager' - bl_label = "Asset Replacement" + bl_label = "Dynamic Link Manager" + + def draw_header(self, context): + layout = self.layout + layout.operator("preferences.addon_show", text="", icon='PREFERENCES').module = __package__ def draw(self, context): layout = self.layout @@ -241,7 +245,7 @@ def register(): bpy.utils.register_class(LinkedLibraryItem) bpy.utils.register_class(DynamicLinkManagerProperties) bpy.utils.register_class(DynamicLinkManagerPreferences) - bpy.utils.register_class(DYNAMICLINK_PT_main_panel) + bpy.utils.register_class(DLM_PT_main_panel) # Register properties to scene bpy.types.Scene.dynamic_link_manager = bpy.props.PointerProperty(type=DynamicLinkManagerProperties) @@ -250,7 +254,7 @@ def unregister(): # Unregister properties from scene del bpy.types.Scene.dynamic_link_manager - bpy.utils.unregister_class(DYNAMICLINK_PT_main_panel) + bpy.utils.unregister_class(DLM_PT_main_panel) bpy.utils.unregister_class(DynamicLinkManagerPreferences) bpy.utils.unregister_class(DynamicLinkManagerProperties) bpy.utils.unregister_class(LinkedLibraryItem)