reorganize ui

This commit is contained in:
Nathan
2025-08-22 14:32:29 -06:00
parent 327f9b9c58
commit 856926869f
3 changed files with 759 additions and 47 deletions

View File

@@ -10970,3 +10970,723 @@ Now users can:
--- ---
_**User**_
Failed to reload libraries: Operator bpy.ops.outliner.lib_operation.poll() failed, context is incorrect
---
_**Assistant**_
The error indicates that the `outliner.lib_operation` operator requires a specific context that isn't available when called from the 3D View panel. Let me fix this by using the correct context and also provide a fallback approach.
Let me update the operators to handle this properly:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 7, lines removed: 2
```diff
@@ -527,6 +527,11 @@
def execute(self, context):
try:
- # Use Blender's built-in library reload operation
- bpy.ops.outliner.lib_operation(type='RELOAD')
+ # Set the correct context for the outliner operation
+ override = context.copy()
+ override['area'] = [area for area in context.screen.areas if area.type == 'OUTLINER'][0]
+ override['region'] = [region for region in override['area'].regions if region.type == 'WINDOW'][0]
+
+ # Use Blender's built-in library reload operation with proper context
+ bpy.ops.outliner.lib_operation(override, type='RELOAD')
self.report({'INFO'}, "Library reload operation completed")
except Exception as e:
```
</details>
---
Now let me also update the relocate libraries operator to use the same approach:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 7, lines removed: 2
```diff
@@ -511,6 +511,11 @@
def execute(self, context):
try:
- # Use Blender's built-in library relocate operation
- bpy.ops.outliner.lib_operation(type='RELOCATE')
+ # Set the correct context for the outliner operation
+ override = context.copy()
+ override['area'] = [area for area in context.screen.areas if area.type == 'OUTLINER'][0]
+ override['region'] = [region for region in override['area'].regions if region.type == 'WINDOW'][0]
+
+ # Use Blender's built-in library relocate operation with proper context
+ bpy.ops.outliner.lib_operation(override, type='RELOCATE')
self.report({'INFO'}, "Library relocation operation completed")
except Exception as e:
```
</details>
---
Perfect! I've fixed both operators to properly handle the context requirements. The changes:
## What I Fixed:
1. **Context Override**: Both operators now create a proper context override that includes the Outliner area and region
2. **Proper Context**: The `outliner.lib_operation` operator requires an Outliner context to work properly
3. **Error Handling**: Both operators still have proper error handling and user feedback
## How It Works:
- **`override = context.copy()`**: Creates a copy of the current context
- **`override['area']`**: Sets the area to the first Outliner area found on the screen
- **`override['region']`**: Sets the region to the WINDOW region within that Outliner area
- **`bpy.ops.outliner.lib_operation(override, type='RELOAD'/'RELOCATE')`**: Calls the operator with the proper context
Now both the "Relocate Libraries" and "Reload Libraries" buttons should work correctly without the context error. The operators will automatically find an Outliner area and use it for the library operations, even when called from the 3D View panel.
---
_**User**_
Failed to reload libraries: 1-2 args execution context is supported
---
_**Assistant**_
The error indicates that the `outliner.lib_operation` operator doesn't support the context override approach I used. Let me fix this by using a different method that's more compatible with Blender's operator system.
Let me update both operators to use a simpler approach:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 2, lines removed: 7
```diff
@@ -532,11 +532,6 @@
def execute(self, context):
try:
- # Set the correct context for the outliner operation
- override = context.copy()
- override['area'] = [area for area in context.screen.areas if area.type == 'OUTLINER'][0]
- override['region'] = [region for region in override['area'].regions if region.type == 'WINDOW'][0]
-
- # Use Blender's built-in library reload operation with proper context
- bpy.ops.outliner.lib_operation(override, type='RELOAD')
+ # Use Blender's built-in library reload operation
+ bpy.ops.outliner.lib_operation(type='RELOAD')
self.report({'INFO'}, "Library reload operation completed")
except Exception as e:
```
</details>
---
Now let me also update the relocate libraries operator:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 2, lines removed: 7
```diff
@@ -511,11 +511,6 @@
def execute(self, context):
try:
- # Set the correct context for the outliner operation
- override = context.copy()
- override['area'] = [area for area in context.screen.areas if area.type == 'OUTLINER'][0]
- override['region'] = [region for region in override['area'].regions if region.type == 'WINDOW'][0]
-
- # Use Blender's built-in library relocate operation with proper context
- bpy.ops.outliner.lib_operation(override, type='RELOCATE')
+ # Use Blender's built-in library relocate operation
+ bpy.ops.outliner.lib_operation(type='RELOAD')
self.report({'INFO'}, "Library relocation operation completed")
except Exception as e:
```
</details>
---
Wait, I made an error in the relocate operator - it should use 'RELOCATE' not 'RELOAD'. Let me fix that:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 1, lines removed: 1
```diff
@@ -512,5 +512,5 @@
try:
# Use Blender's built-in library relocate operation
- bpy.ops.outliner.lib_operation(type='RELOAD')
+ bpy.ops.outliner.lib_operation(type='RELOCATE')
self.report({'INFO'}, "Library relocation operation completed")
except Exception as e:
```
</details>
---
Now I've simplified both operators to use the basic approach without context overrides. However, if you're still getting context errors, we might need to use a different approach.
Let me provide an alternative solution that uses Blender's file operations instead:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 10, lines removed: 3
```diff
@@ -527,10 +527,17 @@
def execute(self, context):
try:
- # Use Blender's built-in library reload operation
+ # Try the outliner operation first
bpy.ops.outliner.lib_operation(type='RELOAD')
self.report({'INFO'}, "Library reload operation completed")
except Exception as e:
- self.report({'ERROR'}, f"Failed to reload libraries: {e}")
- return {'CANCELLED'}
+ # Fallback: manually reload libraries
+ try:
+ for library in bpy.data.libraries:
+ if library.filepath and os.path.exists(bpy.path.abspath(library.filepath)):
+ library.reload()
+ self.report({'INFO'}, "Libraries reloaded manually")
+ except Exception as e2:
+ self.report({'ERROR'}, f"Failed to reload libraries: {e2}")
+ return {'CANCELLED'}
return {'FINISHED'}
```
</details>
---
Now let me also add a fallback for the relocate operation:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 8, lines removed: 3
```diff
@@ -511,10 +511,15 @@
def execute(self, context):
try:
- # Use Blender's built-in library relocate operation
+ # Try the outliner operation first
bpy.ops.outliner.lib_operation(type='RELOCATE')
self.report({'INFO'}, "Library relocation operation completed")
except Exception as e:
- self.report({'ERROR'}, f"Failed to relocate libraries: {e}")
- return {'CANCELLED'}
+ # Fallback: use file.find_missing_files
+ try:
+ bpy.ops.file.find_missing_files()
+ self.report({'INFO'}, "Library relocation completed using file operations")
+ except Exception as e2:
+ self.report({'ERROR'}, f"Failed to relocate libraries: {e2}")
+ return {'CANCELLED'}
return {'FINISHED'}
```
</details>
---
Perfect! Now both operators have fallback mechanisms:
## **Reload Libraries Operator:**
1. **Primary**: Tries `bpy.ops.outliner.lib_operation(type='RELOAD')`
2. **Fallback**: If that fails, manually reloads each library using `library.reload()`
## **Relocate Libraries Operator:**
1. **Primary**: Tries `bpy.ops.outliner.lib_operation(type='RELOCATE')`
2. **Fallback**: If that fails, uses `bpy.ops.file.find_missing_files()` which is more reliable
## **Why This Approach:**
- **Context Issues**: The outliner operations might require specific UI contexts that aren't always available
- **Fallback Safety**: If the primary method fails, the fallback ensures the operation still works
- **User Experience**: Users get feedback about which method succeeded
- **Compatibility**: The fallback methods work from any context in Blender
Now try the buttons again. If the outliner operations still fail due to context issues, the fallback methods should work and provide the same functionality.
---
_**User**_
good, except relocate libraries should be merged into the "find libraries in these folders" operator
---
_**Assistant**_
Great idea! That makes more sense - after finding the libraries, we should automatically attempt to relocate them. Let me merge the relocate functionality into the "Find libraries in these folders" operator and remove the separate relocate button.
First, let me update the UI to remove the separate relocate button:
---
<details><summary>Edit file: ui.py</summary>
undefined
**Chunk 1**
Lines added: 1, lines removed: 2
```diff
@@ -199,10 +199,9 @@
row.operator("dlm.add_search_path", text="", icon='ADD')
- # Main action buttons
+ # Main action button
missing_count = sum(1 for lib in props.linked_libraries if lib.is_missing)
if missing_count > 0:
row = box.row()
row.operator("dlm.fmt_style_find", text="Find libraries in these folders", icon='VIEWZOOM')
- row.operator("dlm.relocate_libraries", text="Relocate Libraries", icon='FILE_REFRESH')
# Asset replacement section
```
</details>
---
Now let me update the "Find libraries in these folders" operator to include the relocate functionality:
---
Read file: operators.py
---
Now let me update the `DLM_OT_fmt_style_find` operator (which is the one actually called from the UI) to include the relocate functionality:
---
Read file: operators.py
---
I can see there are two similar operators. Let me find the `DLM_OT_fmt_style_find` operator that's actually called from the UI:
---
<details>
<summary>Grep search for "class DLM_OT_fmt_style_find" • **2** files</summary>
| File | Line | Match |
|------|------|-------|
| `file:///t%3A/Dynamic-Link-Manager/operators.py` | L199 | `class DLM_OT_fmt_style_find(Operator):` |
| `file:///t%3A/Dynamic-Link-Manager/operators.py` | L199 | `class DLM_OT_fmt_style_find(Operator):` |
</details>
---
Read file: operators.py
---
Perfect! Now I can see the `DLM_OT_fmt_style_find` operator. Let me update it to include the relocate functionality after finding the libraries:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 10, lines removed: 6
```diff
@@ -243,12 +243,16 @@
found_count += 1
break
-
-
-
- # FMT-style reporting
+
+ # After finding libraries, attempt to relocate them
if found_count > 0:
- self.report({'INFO'}, f"FMT-style search complete: Found {found_count} libraries")
+ self.report({'INFO'}, f"Found {found_count} libraries. Attempting to relocate...")
+ try:
+ # Try to relocate using Blender's built-in system
+ bpy.ops.file.find_missing_files()
+ self.report({'INFO'}, "Library relocation completed successfully")
+ except Exception as e:
+ self.report({'WARNING'}, f"Found libraries but relocation failed: {e}")
else:
- self.report({'WARNING'}, "FMT-style search: No libraries found in search paths")
+ self.report({'WARNING'}, "No libraries found in search paths")
return {'FINISHED'}
```
</details>
---
Now let me also remove the separate `DLM_OT_relocate_libraries` operator since it's no longer needed, and update the register/unregister functions:
---
Model failed to call the tool with correct arguments.
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: 1, lines removed: 20
```diff
@@ -507,24 +507,5 @@
return {'RUNNING_MODAL'}
- class DLM_OT_relocate_libraries(Operator):
- """Relocate missing libraries using Blender's built-in relocate operation"""
- bl_idname = "dlm.relocate_libraries"
- bl_label = "Relocate Libraries"
- bl_options = {'REGISTER'}
-
- def execute(self, context):
- try:
- # Try the outliner operation first
- bpy.ops.outliner.lib_operation(type='RELOCATE')
- self.report({'INFO'}, "Library relocation operation completed")
- except Exception as e:
- # Fallback: use file.find_missing_files
- try:
- bpy.ops.file.find_missing_files()
- self.report({'INFO'}, "Library relocation completed using file operations")
- except Exception as e2:
- self.report({'ERROR'}, f"Failed to relocate libraries: {e2}")
- return {'CANCELLED'}
- return {'FINISHED'}
+
class DLM_OT_reload_libraries(Operator):
```
</details>
---
Now let me update the register and unregister functions to remove the relocate libraries operator:
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: undefined, lines removed: 1
```diff
@@ -542,5 +542,4 @@
bpy.utils.register_class(DLM_OT_find_in_folders)
bpy.utils.register_class(DLM_OT_fmt_style_find)
- bpy.utils.register_class(DLM_OT_relocate_libraries)
bpy.utils.register_class(DLM_OT_reload_libraries)
```
</details>
---
<details><summary>Edit file: operators.py</summary>
undefined
**Chunk 1**
Lines added: undefined, lines removed: 1
```diff
@@ -554,5 +554,4 @@
bpy.utils.unregister_class(DLM_OT_scan_linked_assets)
bpy.utils.unregister_class(DLM_OT_replace_linked_asset)
- bpy.utils.unregister_class(DLM_OT_relocate_libraries)
bpy.utils.unregister_class(DLM_OT_reload_libraries)
```
</details>
---
Perfect! Now I've successfully merged the relocate functionality into the "Find libraries in these folders" operator. Here's what the updated workflow does:
## **Updated Workflow:**
1. **User clicks "Find libraries in these folders"**
2. **Operator searches all search paths** for missing libraries
3. **Reports how many libraries were found**
4. **Automatically attempts to relocate** the found libraries using `bpy.ops.file.find_missing_files()`
5. **Provides feedback** on whether relocation succeeded or failed
## **Benefits of This Approach:**
- **Streamlined UI**: One button instead of two
- **Better UX**: Users don't need to remember to click relocate after finding
- **Automatic workflow**: Finding and relocating happen in sequence
- **Cleaner code**: Removed duplicate functionality
- **Consistent behavior**: Always attempts relocation after finding
## **What Was Removed:**
- Separate "Relocate Libraries" button
- `DLM_OT_relocate_libraries` operator class
- Related register/unregister calls
Now when users click "Find libraries in these folders", they'll get a complete solution that finds the missing libraries and automatically attempts to reconnect them in one operation.
---
_**User**_
let's move this panel down to the bottom
---
_**Assistant**_
I'll move the "Selected" item details panel to the bottom of the Linked Libraries Analysis section. Let me update the UI:
---
<details><summary>Edit file: ui.py</summary>
undefined
**Chunk 1**
Lines added: undefined, lines removed: 15
```diff
@@ -164,19 +164,4 @@
row.operator("dlm.reload_libraries", text="Reload Libraries", icon='FILE_REFRESH')
- # Show details of selected item
- if props.linked_libraries and 0 <= props.linked_libraries_index < len(props.linked_libraries):
- selected_lib = props.linked_libraries[props.linked_libraries_index]
- info_box = box.box()
- info_box.label(text=f"Selected: {selected_lib.name}")
-
- if selected_lib.is_missing:
- info_box.label(text="Status: MISSING", icon='ERROR')
- elif selected_lib.has_indirect_missing:
- info_box.label(text=f"Status: INDIRECT MISSING ({selected_lib.indirect_missing_count} dependencies)", icon='ERROR')
- else:
- info_box.label(text="Status: OK", icon='FILE_BLEND')
-
- info_box.label(text=f"Path: {selected_lib.filepath}", icon='FILE_FOLDER')
-
# Search Paths Management - integrated into Linked Libraries Analysis
if props.linked_assets_count > 0:
```
</details>
---
_**User**_
this panel is vestigial. let's remove it.
---
_**Assistant**_
You're absolutely right! The Settings panel with the Asset Path field is not being used and just takes up space. Let me remove it:
---
Model failed to call the tool with correct arguments.
---
<details><summary>Edit file: ui.py</summary>
undefined
**Chunk 1**
Lines added: 1, lines removed: 5
```diff
@@ -218,9 +218,5 @@
box.label(text="No object selected")
- # Settings section
- box = layout.box()
- box.label(text="Settings")
- row = box.row()
- row.prop(props, "selected_asset_path", text="Asset Path")
+
def register():
```
</details>
---
Perfect! I've removed the unused Settings panel. Now the UI is cleaner and more focused on the core functionality:
1. **Linked Libraries Analysis** - with scan, library list, and search paths
2. **Asset Replacement** - for working with selected objects
The `selected_asset_path` property was likely a leftover from earlier development and wasn't serving any purpose. Removing it makes the interface more streamlined and removes visual clutter.
---
_**User**_
let's replace this third column here with a button that opens the blend.
---
_**Assistant**_
I can see you want to replace the third column (which shows the file path) with a button that opens the blend file. Let me update the UI to replace the path display with an "Open Blend" button:
---
The string to replace was not found in the file.
---
I see the issue - the selected item details section was already removed when we moved it. Let me add it back at the bottom of the Linked Libraries Analysis section, but with the Open Blend button instead of the path display:
---
<details><summary>Edit file: ui.py</summary>
undefined
**Chunk 1**
Lines added: 18, lines removed: 1
```diff
@@ -189,5 +189,22 @@
row = box.row()
row.operator("dlm.fmt_style_find", text="Find libraries in these folders", icon='VIEWZOOM')
-
+
+ # Show details of selected item at the bottom
+ if props.linked_libraries and 0 <= props.linked_libraries_index < len(props.linked_libraries):
+ selected_lib = props.linked_libraries[props.linked_libraries_index]
+ info_box = box.box()
+ info_box.label(text=f"Selected: {selected_lib.name}")
+
+ if selected_lib.is_missing:
+ info_box.label(text="Status: MISSING", icon='ERROR')
+ elif selected_lib.has_indirect_missing:
+ info_box.label(text=f"Status: INDIRECT MISSING ({selected_lib.indirect_missing_count} dependencies)", icon='ERROR')
+ else:
+ info_box.label(text="Status: OK", icon='FILE_BLEND')
+
+ # Replace path display with Open Blend button
+ row = info_box.row()
+ row.operator("dlm.open_linked_file", text="Open Blend", icon='FILE_BLEND').filepath = selected_lib.filepath
+
# Asset replacement section
box = layout.box()
```
</details>
---
Perfect! Now I've added the selected item details section back at the bottom of the Linked Libraries Analysis, but with the key change you requested:
## **What Changed:**
1. **Moved the details panel to the bottom** - After the search paths and action buttons
2. **Replaced the path display with an "Open Blend" button** - Instead of showing the long file path, users now get a direct button to open the selected blend file
3. **Cleaner layout** - The third column now contains a functional button instead of just text
## **New Layout:**
- **First column**: Selected library name
- **Second column**: Status (MISSING/INDIRECT MISSING/OK) with appropriate icons
- **Third column**: "Open Blend" button that directly opens the selected blend file
This makes the interface more functional and user-friendly, as users can now directly open blend files from the panel instead of just seeing the file path.
---

View File

@@ -242,14 +242,18 @@ class DLM_OT_fmt_style_find(Operator):
self.report({'INFO'}, f"Found {lib_filename} at: {new_path}") self.report({'INFO'}, f"Found {lib_filename} at: {new_path}")
found_count += 1 found_count += 1
break break
# FMT-style reporting # After finding libraries, attempt to relocate them
if found_count > 0: if found_count > 0:
self.report({'INFO'}, f"FMT-style search complete: Found {found_count} libraries") self.report({'INFO'}, f"Found {found_count} libraries. Attempting to relocate...")
try:
# Try to relocate using Blender's built-in system
bpy.ops.file.find_missing_files()
self.report({'INFO'}, "Library relocation completed successfully")
except Exception as e:
self.report({'WARNING'}, f"Found libraries but relocation failed: {e}")
else: else:
self.report({'WARNING'}, "FMT-style search: No libraries found in search paths") self.report({'WARNING'}, "No libraries found in search paths")
return {'FINISHED'} return {'FINISHED'}
@@ -502,21 +506,7 @@ class DLM_OT_browse_search_path(Operator):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'} return {'RUNNING_MODAL'}
class DLM_OT_relocate_libraries(Operator):
"""Relocate missing libraries using Blender's built-in relocate operation"""
bl_idname = "dlm.relocate_libraries"
bl_label = "Relocate Libraries"
bl_options = {'REGISTER'}
def execute(self, context):
try:
# Use Blender's built-in library relocate operation
bpy.ops.outliner.lib_operation(type='RELOCATE')
self.report({'INFO'}, "Library relocation operation completed")
except Exception as e:
self.report({'ERROR'}, f"Failed to relocate libraries: {e}")
return {'CANCELLED'}
return {'FINISHED'}
class DLM_OT_reload_libraries(Operator): class DLM_OT_reload_libraries(Operator):
"""Reload all libraries using Blender's built-in reload operation""" """Reload all libraries using Blender's built-in reload operation"""
@@ -526,12 +516,19 @@ class DLM_OT_reload_libraries(Operator):
def execute(self, context): def execute(self, context):
try: try:
# Use Blender's built-in library reload operation # Try the outliner operation first
bpy.ops.outliner.lib_operation(type='RELOAD') bpy.ops.outliner.lib_operation(type='RELOAD')
self.report({'INFO'}, "Library reload operation completed") self.report({'INFO'}, "Library reload operation completed")
except Exception as e: except Exception as e:
self.report({'ERROR'}, f"Failed to reload libraries: {e}") # Fallback: manually reload libraries
return {'CANCELLED'} try:
for library in bpy.data.libraries:
if library.filepath and os.path.exists(bpy.path.abspath(library.filepath)):
library.reload()
self.report({'INFO'}, "Libraries reloaded manually")
except Exception as e2:
self.report({'ERROR'}, f"Failed to reload libraries: {e2}")
return {'CANCELLED'}
return {'FINISHED'} return {'FINISHED'}
def register(): def register():
@@ -544,7 +541,6 @@ def register():
bpy.utils.register_class(DLM_OT_attempt_relink) bpy.utils.register_class(DLM_OT_attempt_relink)
bpy.utils.register_class(DLM_OT_find_in_folders) bpy.utils.register_class(DLM_OT_find_in_folders)
bpy.utils.register_class(DLM_OT_fmt_style_find) bpy.utils.register_class(DLM_OT_fmt_style_find)
bpy.utils.register_class(DLM_OT_relocate_libraries)
bpy.utils.register_class(DLM_OT_reload_libraries) bpy.utils.register_class(DLM_OT_reload_libraries)
def unregister(): def unregister():
@@ -557,5 +553,4 @@ def unregister():
bpy.utils.unregister_class(DLM_OT_open_linked_file) bpy.utils.unregister_class(DLM_OT_open_linked_file)
bpy.utils.unregister_class(DLM_OT_scan_linked_assets) bpy.utils.unregister_class(DLM_OT_scan_linked_assets)
bpy.utils.unregister_class(DLM_OT_replace_linked_asset) bpy.utils.unregister_class(DLM_OT_replace_linked_asset)
bpy.utils.unregister_class(DLM_OT_relocate_libraries)
bpy.utils.unregister_class(DLM_OT_reload_libraries) bpy.utils.unregister_class(DLM_OT_reload_libraries)

41
ui.py
View File

@@ -163,21 +163,6 @@ class DLM_PT_main_panel(Panel):
row.scale_x = 0.7 row.scale_x = 0.7
row.operator("dlm.reload_libraries", text="Reload Libraries", icon='FILE_REFRESH') row.operator("dlm.reload_libraries", text="Reload Libraries", icon='FILE_REFRESH')
# Show details of selected item
if props.linked_libraries and 0 <= props.linked_libraries_index < len(props.linked_libraries):
selected_lib = props.linked_libraries[props.linked_libraries_index]
info_box = box.box()
info_box.label(text=f"Selected: {selected_lib.name}")
if selected_lib.is_missing:
info_box.label(text="Status: MISSING", icon='ERROR')
elif selected_lib.has_indirect_missing:
info_box.label(text=f"Status: INDIRECT MISSING ({selected_lib.indirect_missing_count} dependencies)", icon='ERROR')
else:
info_box.label(text="Status: OK", icon='FILE_BLEND')
info_box.label(text=f"Path: {selected_lib.filepath}", icon='FILE_FOLDER')
# Search Paths Management - integrated into Linked Libraries Analysis # Search Paths Management - integrated into Linked Libraries Analysis
if props.linked_assets_count > 0: if props.linked_assets_count > 0:
# Get preferences for search paths # Get preferences for search paths
@@ -198,12 +183,28 @@ class DLM_PT_main_panel(Panel):
row.alignment = 'RIGHT' row.alignment = 'RIGHT'
row.operator("dlm.add_search_path", text="", icon='ADD') row.operator("dlm.add_search_path", text="", icon='ADD')
# Main action buttons # Main action button
missing_count = sum(1 for lib in props.linked_libraries if lib.is_missing) missing_count = sum(1 for lib in props.linked_libraries if lib.is_missing)
if missing_count > 0: if missing_count > 0:
row = box.row() row = box.row()
row.operator("dlm.fmt_style_find", text="Find libraries in these folders", icon='VIEWZOOM') row.operator("dlm.fmt_style_find", text="Find libraries in these folders", icon='VIEWZOOM')
row.operator("dlm.relocate_libraries", text="Relocate Libraries", icon='FILE_REFRESH')
# Show details of selected item at the bottom
if props.linked_libraries and 0 <= props.linked_libraries_index < len(props.linked_libraries):
selected_lib = props.linked_libraries[props.linked_libraries_index]
info_box = box.box()
info_box.label(text=f"Selected: {selected_lib.name}")
if selected_lib.is_missing:
info_box.label(text="Status: MISSING", icon='ERROR')
elif selected_lib.has_indirect_missing:
info_box.label(text=f"Status: INDIRECT MISSING ({selected_lib.indirect_missing_count} dependencies)", icon='ERROR')
else:
info_box.label(text="Status: OK", icon='FILE_BLEND')
# Replace path display with Open Blend button
row = info_box.row()
row.operator("dlm.open_linked_file", text="Open Blend", icon='FILE_BLEND').filepath = selected_lib.filepath
# Asset replacement section # Asset replacement section
box = layout.box() box = layout.box()
@@ -233,11 +234,7 @@ class DLM_PT_main_panel(Panel):
else: else:
box.label(text="No object selected") box.label(text="No object selected")
# Settings section
box = layout.box()
box.label(text="Settings")
row = box.row()
row.prop(props, "selected_asset_path", text="Asset Path")
def register(): def register():
bpy.utils.register_class(SearchPathItem) bpy.utils.register_class(SearchPathItem)